blob: 6a52b1d5f7ba36332e0a51a8ccf7cf6f45936823 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 mxb - v4l2 driver for the Multimedia eXtension Board
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -03003
Michael Hunold6acaba82006-03-13 21:20:41 -08004 Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005
6 Visit http://www.mihu.de/linux/saa7146/mxb/
7 for further details about this card.
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -03008
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#define DEBUG_VARIABLE debug
25
26#include <media/saa7146_vv.h>
27#include <media/tuner.h>
Michael Krufky5e453dc2006-01-09 15:32:31 -020028#include <media/v4l2-common.h>
Hans Verkuil707ecf42008-09-06 15:40:25 -030029#include <media/saa7115.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
31#include "mxb.h"
32#include "tea6415c.h"
33#include "tea6420.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Hans Verkuil1b8dac12009-02-07 11:18:05 -030035#define I2C_SAA5246A 0x11
36#define I2C_SAA7111A 0x24
37#define I2C_TDA9840 0x42
38#define I2C_TEA6415C 0x43
39#define I2C_TEA6420_1 0x4c
40#define I2C_TEA6420_2 0x4d
41#define I2C_TUNER 0x60
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030043#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
45/* global variable */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030046static int mxb_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030048/* initial frequence the tuner will be tuned to.
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 in verden (lower saxony, germany) 4148 is a
50 channel called "phoenix" */
51static int freq = 4148;
52module_param(freq, int, 0644);
53MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
54
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030055static int debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070056module_param(debug, int, 0644);
57MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
58
59#define MXB_INPUTS 4
60enum { TUNER, AUX1, AUX3, AUX3_YC };
61
62static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030063 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
65 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
66 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
67};
68
69/* this array holds the information, which port of the saa7146 each
70 input actually uses. the mxb uses port 0 for every input */
71static struct {
72 int hps_source;
73 int hps_sync;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030074} input_port_selection[MXB_INPUTS] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
76 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
77 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
78 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
79};
80
81/* this array holds the information of the audio source (mxb_audios),
82 which has to be switched corresponding to the video source (mxb_channels) */
83static int video_audio_connect[MXB_INPUTS] =
84 { 0, 1, 3, 3 };
85
Hans Verkuil1b8dac12009-02-07 11:18:05 -030086/* These are the necessary input-output-pins for bringing one audio source
87 (see above) to the CD-output. Note that gain is set to 0 in this table. */
88static struct v4l2_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
89 { { 1, 1 }, { 1, 1 } }, /* Tuner */
90 { { 5, 1 }, { 6, 1 } }, /* AUX 1 */
91 { { 4, 1 }, { 6, 1 } }, /* AUX 2 */
92 { { 3, 1 }, { 6, 1 } }, /* AUX 3 */
93 { { 1, 1 }, { 3, 1 } }, /* Radio */
94 { { 1, 1 }, { 2, 1 } }, /* CD-Rom */
95 { { 6, 1 }, { 6, 1 } } /* Mute */
96};
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Hans Verkuil1b8dac12009-02-07 11:18:05 -030098/* These are the necessary input-output-pins for bringing one audio source
99 (see above) to the line-output. Note that gain is set to 0 in this table. */
100static struct v4l2_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
101 { { 2, 3 }, { 1, 2 } },
102 { { 5, 3 }, { 6, 2 } },
103 { { 4, 3 }, { 6, 2 } },
104 { { 3, 3 }, { 6, 2 } },
105 { { 2, 3 }, { 3, 2 } },
106 { { 2, 3 }, { 2, 2 } },
107 { { 6, 3 }, { 6, 2 } } /* Mute */
108};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
110#define MAXCONTROLS 1
111static struct v4l2_queryctrl mxb_controls[] = {
112 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
113};
114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115struct mxb
116{
117 struct video_device *video_dev;
118 struct video_device *vbi_dev;
119
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300120 struct i2c_adapter i2c_adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300122 struct v4l2_subdev *saa7111a;
123 struct v4l2_subdev *tda9840;
124 struct v4l2_subdev *tea6415c;
125 struct v4l2_subdev *tuner;
126 struct v4l2_subdev *tea6420_1;
127 struct v4l2_subdev *tea6420_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
129 int cur_mode; /* current audio mode (mono, stereo, ...) */
130 int cur_input; /* current input */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 int cur_mute; /* current mute status */
Michael Hunold9d2599d2005-07-27 11:46:00 -0700132 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133};
134
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300135#define saa7111a_call(mxb, o, f, args...) \
136 v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
137#define tea6420_1_call(mxb, o, f, args...) \
138 v4l2_subdev_call(mxb->tea6420_1, o, f, ##args)
139#define tea6420_2_call(mxb, o, f, args...) \
140 v4l2_subdev_call(mxb->tea6420_2, o, f, ##args)
141#define tda9840_call(mxb, o, f, args...) \
142 v4l2_subdev_call(mxb->tda9840, o, f, ##args)
143#define tea6415c_call(mxb, o, f, args...) \
144 v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
145#define tuner_call(mxb, o, f, args...) \
146 v4l2_subdev_call(mxb->tuner, o, f, ##args)
147#define call_all(dev, o, f, args...) \
148 v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150static struct saa7146_extension extension;
151
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300152static int mxb_probe(struct saa7146_dev *dev)
Jean Delvare961f80f2008-01-27 18:14:51 +0100153{
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300154 struct mxb *mxb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155
Panagiotis Issaris74081872006-01-11 19:40:56 -0200156 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300157 if (mxb == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 DEB_D(("not enough kernel memory.\n"));
159 return -ENOMEM;
160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
Hans Verkuil9ebeae52008-09-07 08:32:44 -0300162 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
163
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300165 if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 DEB_S(("cannot register i2c-device. skipping.\n"));
167 kfree(mxb);
168 return -EFAULT;
169 }
170
Hans Verkuile6574f22009-04-01 03:57:53 -0300171 mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
172 "saa7115", "saa7111", I2C_SAA7111A);
173 mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
174 "tea6420", "tea6420", I2C_TEA6420_1);
175 mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
176 "tea6420", "tea6420", I2C_TEA6420_2);
177 mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
178 "tea6415c", "tea6415c", I2C_TEA6415C);
179 mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
180 "tda9840", "tda9840", I2C_TDA9840);
181 mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
182 "tuner", "tuner", I2C_TUNER);
183 if (v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
184 "saa5246a", "saa5246a", I2C_SAA5246A)) {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300185 printk(KERN_INFO "mxb: found teletext decoder\n");
186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
188 /* check if all devices are present */
Al Viro5fa12472008-03-29 03:07:38 +0000189 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
190 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 printk("mxb: did not find all i2c devices. aborting\n");
192 i2c_del_adapter(&mxb->i2c_adapter);
193 kfree(mxb);
194 return -ENODEV;
195 }
196
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300197 /* all devices are present, probe was successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198
199 /* we store the pointer in our private data field */
200 dev->ext_priv = mxb;
201
202 return 0;
203}
204
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300205/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 there are no specs available, so we simply use some init values */
207static struct {
208 int length;
209 char data[9];
210} mxb_saa7740_init[] = {
211 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
212 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
213 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
214 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
215 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
216 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
217 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
218 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
219 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
220 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
221 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
222 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
223 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
224 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
225 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
226 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
227 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
228 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
229 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
230 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
231 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
232 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
233 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
234 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
235 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
236 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
237 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
238 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
239 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
240 { 3, { 0x48, 0x00, 0x01 } },
241 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
242 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
243 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
244 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
245 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
246 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
247 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
248 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
249 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
250 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
251 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
252 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
253 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
254 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
255 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
256 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
257 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300258 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259};
260
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261/* bring hardware to a sane state. this has to be done, just in case someone
262 wants to capture from this device before it has been properly initialized.
263 the capture engine would badly fail, because no valid signal arrives on the
264 saa7146, thus leading to timeouts and stuff. */
265static int mxb_init_done(struct saa7146_dev* dev)
266{
267 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700269 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800270 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300271 struct v4l2_routing route;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
273 int i = 0, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
275 /* select video mode in saa7111a */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300276 saa7111a_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
278 /* select tuner-output on saa7111a */
279 i = 0;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300280 route.input = SAA7115_COMPOSITE0;
281 route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300282 saa7111a_call(mxb, video, s_routing, &route);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
284 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700285 tun_setup.mode_mask = T_ANALOG_TV;
286 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700287 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300288 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700289 /* tune in some frequency on tuner */
290 mxb->cur_freq.tuner = 0;
291 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
292 mxb->cur_freq.frequency = freq;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300293 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700294
Michael Hunold6acaba82006-03-13 21:20:41 -0800295 /* set a default video standard */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300296 tuner_call(mxb, core, s_std, std);
Michael Hunold6acaba82006-03-13 21:20:41 -0800297
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 /* mute audio on tea6420s */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300299 tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]);
300 tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]);
301 tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]);
302 tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300304 /* switch to tuner-channel on tea6415c */
305 route.input = 3;
306 route.output = 17;
307 tea6415c_call(mxb, video, s_routing, &route);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300309 /* select tuner-output on multicable on tea6415c */
310 route.input = 3;
311 route.output = 13;
312 tea6415c_call(mxb, video, s_routing, &route);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300313
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 /* the rest for mxb */
315 mxb->cur_input = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 mxb->cur_mute = 1;
317
318 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300319
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300321 on the mxb. if so, we must initialize it. due to lack of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 informations about the saa7740, the values were reverse
323 engineered. */
324 msg.addr = 0x1b;
325 msg.flags = 0;
326 msg.len = mxb_saa7740_init[0].length;
327 msg.buf = &mxb_saa7740_init[0].data[0];
328
Hans Verkuil26338122008-09-06 17:24:30 -0300329 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
330 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 /* the sound arena module is a pos, that's probably the reason
332 philips refuses to hand out a datasheet for the saa7740...
333 it seems to screw up the i2c bus, so we disable fast irq
334 based i2c transactions here and rely on the slow and safe
335 polling method ... */
336 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300337 for (i = 1; ; i++) {
338 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300341 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300343 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
344 if (err != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 DEB_D(("failed to initialize 'sound arena module'.\n"));
346 goto err;
347 }
348 }
349 INFO(("'sound arena module' detected.\n"));
350 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300351err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 /* the rest for saa7146: you should definitely set some basic values
353 for the input-port handling of the saa7146. */
354
355 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300356
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300358 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
359 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
361 /* some stuff is done via direct write to the registers */
362
363 /* this is ugly, but because of the fact that this is completely
364 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300365 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 saa7146_write(dev, DD1_INIT, 0x02000200);
367 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
368
369 return 0;
370}
371
372/* interrupt-handler. this gets called when irq_mask is != 0.
373 it must clear the interrupt-bits in irq_mask it has handled */
374/*
375void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
376{
377 struct mxb* mxb = (struct mxb*)dev->ext_priv;
378}
379*/
380
Hans Verkuilb9600742009-01-18 19:59:11 -0300381static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
382{
383 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
384 int i;
385
386 for (i = MAXCONTROLS - 1; i >= 0; i--) {
387 if (mxb_controls[i].id == qc->id) {
388 *qc = mxb_controls[i];
389 DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
390 return 0;
391 }
392 }
393 return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc);
394}
395
396static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
397{
398 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
399 struct mxb *mxb = (struct mxb *)dev->ext_priv;
400 int i;
401
402 for (i = MAXCONTROLS - 1; i >= 0; i--) {
403 if (mxb_controls[i].id == vc->id)
404 break;
405 }
406
407 if (i < 0)
408 return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc);
409
410 if (vc->id == V4L2_CID_AUDIO_MUTE) {
411 vc->value = mxb->cur_mute;
412 DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
413 return 0;
414 }
415
416 DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
417 return 0;
418}
419
420static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
421{
422 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
423 struct mxb *mxb = (struct mxb *)dev->ext_priv;
424 int i = 0;
425
426 for (i = MAXCONTROLS - 1; i >= 0; i--) {
427 if (mxb_controls[i].id == vc->id)
428 break;
429 }
430
431 if (i < 0)
432 return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc);
433
434 if (vc->id == V4L2_CID_AUDIO_MUTE) {
435 mxb->cur_mute = vc->value;
436 if (!vc->value) {
437 /* switch the audio-source */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300438 tea6420_1_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300439 &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300440 tea6420_2_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300441 &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
442 } else {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300443 tea6420_1_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300444 &TEA6420_line[6][0]);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300445 tea6420_2_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300446 &TEA6420_line[6][1]);
447 }
448 DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
449 }
450 return 0;
451}
452
453static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
454{
455 DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
456 if (i->index < 0 || i->index >= MXB_INPUTS)
457 return -EINVAL;
458 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
459 return 0;
460}
461
462static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
463{
464 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
465 struct mxb *mxb = (struct mxb *)dev->ext_priv;
466 *i = mxb->cur_input;
467
468 DEB_EE(("VIDIOC_G_INPUT %d.\n", *i));
469 return 0;
470}
471
472static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
473{
474 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
475 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Hans Verkuilb9600742009-01-18 19:59:11 -0300476 struct v4l2_routing route;
477 int i = 0;
478
479 DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
480
481 if (input < 0 || input >= MXB_INPUTS)
482 return -EINVAL;
483
484 mxb->cur_input = input;
485
486 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
487 input_port_selection[input].hps_sync);
488
489 /* prepare switching of tea6415c and saa7111a;
490 have a look at the 'background'-file for further informations */
491 switch (input) {
492 case TUNER:
493 i = SAA7115_COMPOSITE0;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300494 route.input = 3;
495 route.output = 17;
Hans Verkuilb9600742009-01-18 19:59:11 -0300496
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300497 if (tea6415c_call(mxb, video, s_routing, &route)) {
Hans Verkuilb9600742009-01-18 19:59:11 -0300498 printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n");
499 return -EFAULT;
500 }
501 /* connect tuner-output always to multicable */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300502 route.input = 3;
503 route.output = 13;
Hans Verkuilb9600742009-01-18 19:59:11 -0300504 break;
505 case AUX3_YC:
506 /* nothing to be done here. aux3_yc is
507 directly connected to the saa711a */
508 i = SAA7115_SVIDEO1;
509 break;
510 case AUX3:
511 /* nothing to be done here. aux3 is
512 directly connected to the saa711a */
513 i = SAA7115_COMPOSITE1;
514 break;
515 case AUX1:
516 i = SAA7115_COMPOSITE0;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300517 route.input = 1;
518 route.output = 17;
Hans Verkuilb9600742009-01-18 19:59:11 -0300519 break;
520 }
521
522 /* switch video in tea6415c only if necessary */
523 switch (input) {
524 case TUNER:
525 case AUX1:
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300526 if (tea6415c_call(mxb, video, s_routing, &route)) {
Hans Verkuilb9600742009-01-18 19:59:11 -0300527 printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n");
528 return -EFAULT;
529 }
530 break;
531 default:
532 break;
533 }
534
535 /* switch video in saa7111a */
536 route.input = i;
537 route.output = 0;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300538 if (saa7111a_call(mxb, video, s_routing, &route))
Hans Verkuilb9600742009-01-18 19:59:11 -0300539 printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n");
540
541 /* switch the audio-source only if necessary */
542 if (0 == mxb->cur_mute) {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300543 tea6420_1_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300544 &TEA6420_line[video_audio_connect[input]][0]);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300545 tea6420_2_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300546 &TEA6420_line[video_audio_connect[input]][1]);
547 }
548
549 return 0;
550}
551
552static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
553{
554 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
555 struct mxb *mxb = (struct mxb *)dev->ext_priv;
556
557 if (t->index) {
558 DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
559 return -EINVAL;
560 }
561
562 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
563
564 memset(t, 0, sizeof(*t));
Hans Verkuilb9600742009-01-18 19:59:11 -0300565 strlcpy(t->name, "TV Tuner", sizeof(t->name));
566 t->type = V4L2_TUNER_ANALOG_TV;
567 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
568 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
569 t->audmode = mxb->cur_mode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300570 return call_all(dev, tuner, g_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300571}
572
573static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
574{
575 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
576 struct mxb *mxb = (struct mxb *)dev->ext_priv;
577
578 if (t->index) {
579 DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n", t->index));
580 return -EINVAL;
581 }
582
583 mxb->cur_mode = t->audmode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300584 return call_all(dev, tuner, s_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300585}
586
587static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
588{
589 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
590 struct mxb *mxb = (struct mxb *)dev->ext_priv;
591
592 if (mxb->cur_input) {
593 DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
594 mxb->cur_input));
595 return -EINVAL;
596 }
597
598 *f = mxb->cur_freq;
599
600 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
601 return 0;
602}
603
604static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
605{
606 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
607 struct mxb *mxb = (struct mxb *)dev->ext_priv;
608 struct saa7146_vv *vv = dev->vv_data;
609
610 if (f->tuner)
611 return -EINVAL;
612
613 if (V4L2_TUNER_ANALOG_TV != f->type)
614 return -EINVAL;
615
616 if (mxb->cur_input) {
617 DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
618 return -EINVAL;
619 }
620
621 mxb->cur_freq = *f;
622 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
623
624 /* tune in desired frequency */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300625 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Hans Verkuilb9600742009-01-18 19:59:11 -0300626
627 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
628 spin_lock(&dev->slock);
629 vv->vbi_fieldcount = 0;
630 spin_unlock(&dev->slock);
631
632 return 0;
633}
634
635static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
636{
637 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
638 struct mxb *mxb = (struct mxb *)dev->ext_priv;
639
640 if (a->index < 0 || a->index > MXB_INPUTS) {
641 DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
642 return -EINVAL;
643 }
644
645 DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
646 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
647 return 0;
648}
649
650static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
651{
652 DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
653 return 0;
654}
655
656#ifdef CONFIG_VIDEO_ADV_DEBUG
657static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
658{
659 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300660
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300661 return call_all(dev, core, g_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300662}
663
664static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
665{
666 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300667
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300668 return call_all(dev, core, s_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300669}
670#endif
671
672static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
673{
674 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
675 struct mxb *mxb = (struct mxb *)dev->ext_priv;
676
677 switch (cmd) {
678 case MXB_S_AUDIO_CD:
679 {
680 int i = *(int *)arg;
681
682 if (i < 0 || i >= MXB_AUDIOS) {
683 DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n", i));
684 return -EINVAL;
685 }
686
687 DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i));
688
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300689 tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[i][0]);
690 tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[i][1]);
Hans Verkuilb9600742009-01-18 19:59:11 -0300691
692 return 0;
693 }
694 case MXB_S_AUDIO_LINE:
695 {
696 int i = *(int *)arg;
697
698 if (i < 0 || i >= MXB_AUDIOS) {
699 DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n", i));
700 return -EINVAL;
701 }
702
703 DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i));
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300704 tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[i][0]);
705 tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[i][1]);
Hans Verkuilb9600742009-01-18 19:59:11 -0300706
707 return 0;
708 }
709 default:
710/*
711 DEB2(printk("does not handle this ioctl.\n"));
712*/
713 return -ENOIOCTLCMD;
714 }
715 return 0;
716}
717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718static struct saa7146_ext_vv vv_data;
719
720/* this function only gets called when the probing was successful */
Hans Verkuil26338122008-09-06 17:24:30 -0300721static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722{
Hans Verkuil26338122008-09-06 17:24:30 -0300723 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300724
Hans Verkuil26338122008-09-06 17:24:30 -0300725 DEB_EE(("dev:%p\n", dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
727 /* checking for i2c-devices can be omitted here, because we
728 already did this in "mxb_vl42_probe" */
729
Hans Verkuila8327812008-07-25 10:31:23 -0300730 saa7146_vv_init(dev, &vv_data);
Hans Verkuilb9600742009-01-18 19:59:11 -0300731 vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
732 vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
733 vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
734 vv_data.ops.vidioc_enum_input = vidioc_enum_input;
735 vv_data.ops.vidioc_g_input = vidioc_g_input;
736 vv_data.ops.vidioc_s_input = vidioc_s_input;
737 vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
738 vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
739 vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
740 vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
741 vv_data.ops.vidioc_g_audio = vidioc_g_audio;
742 vv_data.ops.vidioc_s_audio = vidioc_s_audio;
743#ifdef CONFIG_VIDEO_ADV_DEBUG
744 vv_data.ops.vidioc_g_register = vidioc_g_register;
745 vv_data.ops.vidioc_s_register = vidioc_s_register;
746#endif
747 vv_data.ops.vidioc_default = vidioc_default;
Hans Verkuila8327812008-07-25 10:31:23 -0300748 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 ERR(("cannot register capture v4l2 device. skipping.\n"));
750 return -1;
751 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300752
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300754 if (MXB_BOARD_CAN_DO_VBI(dev)) {
755 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 ERR(("cannot register vbi v4l2 device. skipping.\n"));
757 }
758 }
759
Hans Verkuila8327812008-07-25 10:31:23 -0300760 printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
762 mxb_num++;
763 mxb_init_done(dev);
764 return 0;
765}
766
Hans Verkuil26338122008-09-06 17:24:30 -0300767static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768{
Hans Verkuil26338122008-09-06 17:24:30 -0300769 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
Hans Verkuil26338122008-09-06 17:24:30 -0300771 DEB_EE(("dev:%p\n", dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 saa7146_unregister_device(&mxb->video_dev,dev);
Hans Verkuil26338122008-09-06 17:24:30 -0300774 if (MXB_BOARD_CAN_DO_VBI(dev))
775 saa7146_unregister_device(&mxb->vbi_dev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 saa7146_vv_release(dev);
777
778 mxb_num--;
779
780 i2c_del_adapter(&mxb->i2c_adapter);
781 kfree(mxb);
782
783 return 0;
784}
785
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300786static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300788 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300790 if (V4L2_STD_PAL_I == standard->id) {
Michael Hunold6acaba82006-03-13 21:20:41 -0800791 v4l2_std_id std = V4L2_STD_PAL_I;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300792
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
794 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300795 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 /* unset the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300797 saa7111a_call(mxb, core, s_gpio, 0);
Hans Verkuilf41737e2009-04-01 03:52:39 -0300798 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 } else {
Michael Hunold6acaba82006-03-13 21:20:41 -0800800 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300801
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
803 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300804 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 /* set the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300806 saa7111a_call(mxb, core, s_gpio, 1);
Hans Verkuilf41737e2009-04-01 03:52:39 -0300807 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 }
809 return 0;
810}
811
812static struct saa7146_standard standard[] = {
813 {
814 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
815 .v_offset = 0x17, .v_field = 288,
816 .h_offset = 0x14, .h_pixels = 680,
817 .v_max_out = 576, .h_max_out = 768,
818 }, {
819 .name = "PAL-I", .id = V4L2_STD_PAL_I,
820 .v_offset = 0x17, .v_field = 288,
821 .h_offset = 0x14, .h_pixels = 680,
822 .v_max_out = 576, .h_max_out = 768,
823 }, {
824 .name = "NTSC", .id = V4L2_STD_NTSC,
825 .v_offset = 0x16, .v_field = 240,
826 .h_offset = 0x06, .h_pixels = 708,
827 .v_max_out = 480, .h_max_out = 640,
828 }, {
829 .name = "SECAM", .id = V4L2_STD_SECAM,
830 .v_offset = 0x14, .v_field = 288,
831 .h_offset = 0x14, .h_pixels = 720,
832 .v_max_out = 576, .h_max_out = 768,
833 }
834};
835
836static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300837 .ext_priv = "Multimedia eXtension Board",
838 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839};
840
841static struct pci_device_id pci_tbl[] = {
842 {
843 .vendor = PCI_VENDOR_ID_PHILIPS,
844 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
845 .subvendor = 0x0000,
846 .subdevice = 0x0000,
847 .driver_data = (unsigned long)&mxb,
848 }, {
849 .vendor = 0,
850 }
851};
852
853MODULE_DEVICE_TABLE(pci, pci_tbl);
854
855static struct saa7146_ext_vv vv_data = {
856 .inputs = MXB_INPUTS,
857 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
858 .stds = &standard[0],
859 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300860 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861};
862
863static struct saa7146_extension extension = {
864 .name = MXB_IDENTIFIER,
865 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300866
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 .pci_tbl = &pci_tbl[0],
868 .module = THIS_MODULE,
869
870 .probe = mxb_probe,
871 .attach = mxb_attach,
872 .detach = mxb_detach,
873
874 .irq_mask = 0,
875 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300876};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877
878static int __init mxb_init_module(void)
879{
Hans Verkuil26338122008-09-06 17:24:30 -0300880 if (saa7146_register_extension(&extension)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 DEB_S(("failed to register extension.\n"));
882 return -ENODEV;
883 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300884
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 return 0;
886}
887
888static void __exit mxb_cleanup_module(void)
889{
890 saa7146_unregister_extension(&extension);
891}
892
893module_init(mxb_init_module);
894module_exit(mxb_cleanup_module);
895
896MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
897MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
898MODULE_LICENSE("GPL");