blob: 238bb40ae09863629570ca6fbaedf58272247f75 [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 Verkuil1b8dac12009-02-07 11:18:05 -0300171 mxb->saa7111a = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa7115", "saa7111", I2C_SAA7111A);
172 mxb->tea6420_1 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_1);
173 mxb->tea6420_2 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6420", "tea6420", I2C_TEA6420_2);
174 mxb->tea6415c = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tea6415c", "tea6415c", I2C_TEA6415C);
175 mxb->tda9840 = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tda9840", "tda9840", I2C_TDA9840);
176 mxb->tuner = v4l2_i2c_new_subdev(&mxb->i2c_adapter, "tuner", "tuner", I2C_TUNER);
177 if (v4l2_i2c_new_subdev(&mxb->i2c_adapter, "saa5246a", "saa5246a", I2C_SAA5246A)) {
178 printk(KERN_INFO "mxb: found teletext decoder\n");
179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
181 /* check if all devices are present */
Al Viro5fa12472008-03-29 03:07:38 +0000182 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
183 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 printk("mxb: did not find all i2c devices. aborting\n");
185 i2c_del_adapter(&mxb->i2c_adapter);
186 kfree(mxb);
187 return -ENODEV;
188 }
189
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300190 /* all devices are present, probe was successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
192 /* we store the pointer in our private data field */
193 dev->ext_priv = mxb;
194
195 return 0;
196}
197
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300198/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 there are no specs available, so we simply use some init values */
200static struct {
201 int length;
202 char data[9];
203} mxb_saa7740_init[] = {
204 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
205 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
206 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
207 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
208 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
209 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
210 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
211 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
212 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
213 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
214 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
215 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
216 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
217 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
218 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
219 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
220 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
221 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
222 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
223 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
224 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
225 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
226 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
227 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
228 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
229 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
230 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
231 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
232 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
233 { 3, { 0x48, 0x00, 0x01 } },
234 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
235 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
236 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
237 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
238 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
239 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
240 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
241 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
242 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
243 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
244 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
245 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
246 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
247 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
248 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
249 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
250 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300251 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252};
253
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254/* bring hardware to a sane state. this has to be done, just in case someone
255 wants to capture from this device before it has been properly initialized.
256 the capture engine would badly fail, because no valid signal arrives on the
257 saa7146, thus leading to timeouts and stuff. */
258static int mxb_init_done(struct saa7146_dev* dev)
259{
260 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700262 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800263 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300264 struct v4l2_routing route;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
266 int i = 0, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
268 /* select video mode in saa7111a */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300269 saa7111a_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
271 /* select tuner-output on saa7111a */
272 i = 0;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300273 route.input = SAA7115_COMPOSITE0;
274 route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300275 saa7111a_call(mxb, video, s_routing, &route);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
277 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700278 tun_setup.mode_mask = T_ANALOG_TV;
279 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700280 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300281 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700282 /* tune in some frequency on tuner */
283 mxb->cur_freq.tuner = 0;
284 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
285 mxb->cur_freq.frequency = freq;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300286 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700287
Michael Hunold6acaba82006-03-13 21:20:41 -0800288 /* set a default video standard */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300289 tuner_call(mxb, core, s_std, std);
Michael Hunold6acaba82006-03-13 21:20:41 -0800290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 /* mute audio on tea6420s */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300292 tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]);
293 tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]);
294 tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[6][0]);
295 tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[6][1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300297 /* switch to tuner-channel on tea6415c */
298 route.input = 3;
299 route.output = 17;
300 tea6415c_call(mxb, video, s_routing, &route);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300302 /* select tuner-output on multicable on tea6415c */
303 route.input = 3;
304 route.output = 13;
305 tea6415c_call(mxb, video, s_routing, &route);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300306
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 /* the rest for mxb */
308 mxb->cur_input = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 mxb->cur_mute = 1;
310
311 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300314 on the mxb. if so, we must initialize it. due to lack of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 informations about the saa7740, the values were reverse
316 engineered. */
317 msg.addr = 0x1b;
318 msg.flags = 0;
319 msg.len = mxb_saa7740_init[0].length;
320 msg.buf = &mxb_saa7740_init[0].data[0];
321
Hans Verkuil26338122008-09-06 17:24:30 -0300322 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
323 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 /* the sound arena module is a pos, that's probably the reason
325 philips refuses to hand out a datasheet for the saa7740...
326 it seems to screw up the i2c bus, so we disable fast irq
327 based i2c transactions here and rely on the slow and safe
328 polling method ... */
329 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300330 for (i = 1; ; i++) {
331 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300334 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300336 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
337 if (err != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 DEB_D(("failed to initialize 'sound arena module'.\n"));
339 goto err;
340 }
341 }
342 INFO(("'sound arena module' detected.\n"));
343 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300344err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 /* the rest for saa7146: you should definitely set some basic values
346 for the input-port handling of the saa7146. */
347
348 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300349
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300351 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
352 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 /* some stuff is done via direct write to the registers */
355
356 /* this is ugly, but because of the fact that this is completely
357 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300358 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 saa7146_write(dev, DD1_INIT, 0x02000200);
360 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
361
362 return 0;
363}
364
365/* interrupt-handler. this gets called when irq_mask is != 0.
366 it must clear the interrupt-bits in irq_mask it has handled */
367/*
368void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
369{
370 struct mxb* mxb = (struct mxb*)dev->ext_priv;
371}
372*/
373
Hans Verkuilb9600742009-01-18 19:59:11 -0300374static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
375{
376 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
377 int i;
378
379 for (i = MAXCONTROLS - 1; i >= 0; i--) {
380 if (mxb_controls[i].id == qc->id) {
381 *qc = mxb_controls[i];
382 DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
383 return 0;
384 }
385 }
386 return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc);
387}
388
389static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
390{
391 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
392 struct mxb *mxb = (struct mxb *)dev->ext_priv;
393 int i;
394
395 for (i = MAXCONTROLS - 1; i >= 0; i--) {
396 if (mxb_controls[i].id == vc->id)
397 break;
398 }
399
400 if (i < 0)
401 return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc);
402
403 if (vc->id == V4L2_CID_AUDIO_MUTE) {
404 vc->value = mxb->cur_mute;
405 DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
406 return 0;
407 }
408
409 DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
410 return 0;
411}
412
413static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
414{
415 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
416 struct mxb *mxb = (struct mxb *)dev->ext_priv;
417 int i = 0;
418
419 for (i = MAXCONTROLS - 1; i >= 0; i--) {
420 if (mxb_controls[i].id == vc->id)
421 break;
422 }
423
424 if (i < 0)
425 return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc);
426
427 if (vc->id == V4L2_CID_AUDIO_MUTE) {
428 mxb->cur_mute = vc->value;
429 if (!vc->value) {
430 /* switch the audio-source */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300431 tea6420_1_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300432 &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300433 tea6420_2_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300434 &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
435 } else {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300436 tea6420_1_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300437 &TEA6420_line[6][0]);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300438 tea6420_2_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300439 &TEA6420_line[6][1]);
440 }
441 DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
442 }
443 return 0;
444}
445
446static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
447{
448 DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
449 if (i->index < 0 || i->index >= MXB_INPUTS)
450 return -EINVAL;
451 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
452 return 0;
453}
454
455static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
456{
457 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
458 struct mxb *mxb = (struct mxb *)dev->ext_priv;
459 *i = mxb->cur_input;
460
461 DEB_EE(("VIDIOC_G_INPUT %d.\n", *i));
462 return 0;
463}
464
465static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
466{
467 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
468 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Hans Verkuilb9600742009-01-18 19:59:11 -0300469 struct v4l2_routing route;
470 int i = 0;
471
472 DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
473
474 if (input < 0 || input >= MXB_INPUTS)
475 return -EINVAL;
476
477 mxb->cur_input = input;
478
479 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
480 input_port_selection[input].hps_sync);
481
482 /* prepare switching of tea6415c and saa7111a;
483 have a look at the 'background'-file for further informations */
484 switch (input) {
485 case TUNER:
486 i = SAA7115_COMPOSITE0;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300487 route.input = 3;
488 route.output = 17;
Hans Verkuilb9600742009-01-18 19:59:11 -0300489
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300490 if (tea6415c_call(mxb, video, s_routing, &route)) {
Hans Verkuilb9600742009-01-18 19:59:11 -0300491 printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n");
492 return -EFAULT;
493 }
494 /* connect tuner-output always to multicable */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300495 route.input = 3;
496 route.output = 13;
Hans Verkuilb9600742009-01-18 19:59:11 -0300497 break;
498 case AUX3_YC:
499 /* nothing to be done here. aux3_yc is
500 directly connected to the saa711a */
501 i = SAA7115_SVIDEO1;
502 break;
503 case AUX3:
504 /* nothing to be done here. aux3 is
505 directly connected to the saa711a */
506 i = SAA7115_COMPOSITE1;
507 break;
508 case AUX1:
509 i = SAA7115_COMPOSITE0;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300510 route.input = 1;
511 route.output = 17;
Hans Verkuilb9600742009-01-18 19:59:11 -0300512 break;
513 }
514
515 /* switch video in tea6415c only if necessary */
516 switch (input) {
517 case TUNER:
518 case AUX1:
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300519 if (tea6415c_call(mxb, video, s_routing, &route)) {
Hans Verkuilb9600742009-01-18 19:59:11 -0300520 printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n");
521 return -EFAULT;
522 }
523 break;
524 default:
525 break;
526 }
527
528 /* switch video in saa7111a */
529 route.input = i;
530 route.output = 0;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300531 if (saa7111a_call(mxb, video, s_routing, &route))
Hans Verkuilb9600742009-01-18 19:59:11 -0300532 printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n");
533
534 /* switch the audio-source only if necessary */
535 if (0 == mxb->cur_mute) {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300536 tea6420_1_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300537 &TEA6420_line[video_audio_connect[input]][0]);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300538 tea6420_2_call(mxb, audio, s_routing,
Hans Verkuilb9600742009-01-18 19:59:11 -0300539 &TEA6420_line[video_audio_connect[input]][1]);
540 }
541
542 return 0;
543}
544
545static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
546{
547 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
548 struct mxb *mxb = (struct mxb *)dev->ext_priv;
549
550 if (t->index) {
551 DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
552 return -EINVAL;
553 }
554
555 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
556
557 memset(t, 0, sizeof(*t));
Hans Verkuilb9600742009-01-18 19:59:11 -0300558 strlcpy(t->name, "TV Tuner", sizeof(t->name));
559 t->type = V4L2_TUNER_ANALOG_TV;
560 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
561 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
562 t->audmode = mxb->cur_mode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300563 return call_all(dev, tuner, g_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300564}
565
566static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
567{
568 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
569 struct mxb *mxb = (struct mxb *)dev->ext_priv;
570
571 if (t->index) {
572 DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n", t->index));
573 return -EINVAL;
574 }
575
576 mxb->cur_mode = t->audmode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300577 return call_all(dev, tuner, s_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300578}
579
580static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
581{
582 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
583 struct mxb *mxb = (struct mxb *)dev->ext_priv;
584
585 if (mxb->cur_input) {
586 DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
587 mxb->cur_input));
588 return -EINVAL;
589 }
590
591 *f = mxb->cur_freq;
592
593 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
594 return 0;
595}
596
597static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
598{
599 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
600 struct mxb *mxb = (struct mxb *)dev->ext_priv;
601 struct saa7146_vv *vv = dev->vv_data;
602
603 if (f->tuner)
604 return -EINVAL;
605
606 if (V4L2_TUNER_ANALOG_TV != f->type)
607 return -EINVAL;
608
609 if (mxb->cur_input) {
610 DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
611 return -EINVAL;
612 }
613
614 mxb->cur_freq = *f;
615 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
616
617 /* tune in desired frequency */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300618 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Hans Verkuilb9600742009-01-18 19:59:11 -0300619
620 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
621 spin_lock(&dev->slock);
622 vv->vbi_fieldcount = 0;
623 spin_unlock(&dev->slock);
624
625 return 0;
626}
627
628static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
629{
630 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
631 struct mxb *mxb = (struct mxb *)dev->ext_priv;
632
633 if (a->index < 0 || a->index > MXB_INPUTS) {
634 DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
635 return -EINVAL;
636 }
637
638 DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
639 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
640 return 0;
641}
642
643static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
644{
645 DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
646 return 0;
647}
648
649#ifdef CONFIG_VIDEO_ADV_DEBUG
650static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
651{
652 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300653
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300654 return call_all(dev, core, g_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300655}
656
657static int vidioc_s_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, s_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300662}
663#endif
664
665static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
666{
667 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
668 struct mxb *mxb = (struct mxb *)dev->ext_priv;
669
670 switch (cmd) {
671 case MXB_S_AUDIO_CD:
672 {
673 int i = *(int *)arg;
674
675 if (i < 0 || i >= MXB_AUDIOS) {
676 DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n", i));
677 return -EINVAL;
678 }
679
680 DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i));
681
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300682 tea6420_1_call(mxb, audio, s_routing, &TEA6420_cd[i][0]);
683 tea6420_2_call(mxb, audio, s_routing, &TEA6420_cd[i][1]);
Hans Verkuilb9600742009-01-18 19:59:11 -0300684
685 return 0;
686 }
687 case MXB_S_AUDIO_LINE:
688 {
689 int i = *(int *)arg;
690
691 if (i < 0 || i >= MXB_AUDIOS) {
692 DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n", i));
693 return -EINVAL;
694 }
695
696 DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i));
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300697 tea6420_1_call(mxb, audio, s_routing, &TEA6420_line[i][0]);
698 tea6420_2_call(mxb, audio, s_routing, &TEA6420_line[i][1]);
Hans Verkuilb9600742009-01-18 19:59:11 -0300699
700 return 0;
701 }
702 default:
703/*
704 DEB2(printk("does not handle this ioctl.\n"));
705*/
706 return -ENOIOCTLCMD;
707 }
708 return 0;
709}
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711static struct saa7146_ext_vv vv_data;
712
713/* this function only gets called when the probing was successful */
Hans Verkuil26338122008-09-06 17:24:30 -0300714static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
Hans Verkuil26338122008-09-06 17:24:30 -0300716 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300717
Hans Verkuil26338122008-09-06 17:24:30 -0300718 DEB_EE(("dev:%p\n", dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
720 /* checking for i2c-devices can be omitted here, because we
721 already did this in "mxb_vl42_probe" */
722
Hans Verkuila8327812008-07-25 10:31:23 -0300723 saa7146_vv_init(dev, &vv_data);
Hans Verkuilb9600742009-01-18 19:59:11 -0300724 vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
725 vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
726 vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
727 vv_data.ops.vidioc_enum_input = vidioc_enum_input;
728 vv_data.ops.vidioc_g_input = vidioc_g_input;
729 vv_data.ops.vidioc_s_input = vidioc_s_input;
730 vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
731 vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
732 vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
733 vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
734 vv_data.ops.vidioc_g_audio = vidioc_g_audio;
735 vv_data.ops.vidioc_s_audio = vidioc_s_audio;
736#ifdef CONFIG_VIDEO_ADV_DEBUG
737 vv_data.ops.vidioc_g_register = vidioc_g_register;
738 vv_data.ops.vidioc_s_register = vidioc_s_register;
739#endif
740 vv_data.ops.vidioc_default = vidioc_default;
Hans Verkuila8327812008-07-25 10:31:23 -0300741 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 ERR(("cannot register capture v4l2 device. skipping.\n"));
743 return -1;
744 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300745
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300747 if (MXB_BOARD_CAN_DO_VBI(dev)) {
748 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 ERR(("cannot register vbi v4l2 device. skipping.\n"));
750 }
751 }
752
Hans Verkuila8327812008-07-25 10:31:23 -0300753 printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 mxb_num++;
756 mxb_init_done(dev);
757 return 0;
758}
759
Hans Verkuil26338122008-09-06 17:24:30 -0300760static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761{
Hans Verkuil26338122008-09-06 17:24:30 -0300762 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
Hans Verkuil26338122008-09-06 17:24:30 -0300764 DEB_EE(("dev:%p\n", dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 saa7146_unregister_device(&mxb->video_dev,dev);
Hans Verkuil26338122008-09-06 17:24:30 -0300767 if (MXB_BOARD_CAN_DO_VBI(dev))
768 saa7146_unregister_device(&mxb->vbi_dev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 saa7146_vv_release(dev);
770
771 mxb_num--;
772
773 i2c_del_adapter(&mxb->i2c_adapter);
774 kfree(mxb);
775
776 return 0;
777}
778
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300779static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780{
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300781 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300783 if (V4L2_STD_PAL_I == standard->id) {
Michael Hunold6acaba82006-03-13 21:20:41 -0800784 v4l2_std_id std = V4L2_STD_PAL_I;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300785
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
787 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300788 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 /* unset the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300790 saa7111a_call(mxb, core, s_gpio, 0);
Hans Verkuilf41737e2009-04-01 03:52:39 -0300791 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 } else {
Michael Hunold6acaba82006-03-13 21:20:41 -0800793 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300794
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
796 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300797 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 /* set the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300799 saa7111a_call(mxb, core, s_gpio, 1);
Hans Verkuilf41737e2009-04-01 03:52:39 -0300800 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 }
802 return 0;
803}
804
805static struct saa7146_standard standard[] = {
806 {
807 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
808 .v_offset = 0x17, .v_field = 288,
809 .h_offset = 0x14, .h_pixels = 680,
810 .v_max_out = 576, .h_max_out = 768,
811 }, {
812 .name = "PAL-I", .id = V4L2_STD_PAL_I,
813 .v_offset = 0x17, .v_field = 288,
814 .h_offset = 0x14, .h_pixels = 680,
815 .v_max_out = 576, .h_max_out = 768,
816 }, {
817 .name = "NTSC", .id = V4L2_STD_NTSC,
818 .v_offset = 0x16, .v_field = 240,
819 .h_offset = 0x06, .h_pixels = 708,
820 .v_max_out = 480, .h_max_out = 640,
821 }, {
822 .name = "SECAM", .id = V4L2_STD_SECAM,
823 .v_offset = 0x14, .v_field = 288,
824 .h_offset = 0x14, .h_pixels = 720,
825 .v_max_out = 576, .h_max_out = 768,
826 }
827};
828
829static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300830 .ext_priv = "Multimedia eXtension Board",
831 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832};
833
834static struct pci_device_id pci_tbl[] = {
835 {
836 .vendor = PCI_VENDOR_ID_PHILIPS,
837 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
838 .subvendor = 0x0000,
839 .subdevice = 0x0000,
840 .driver_data = (unsigned long)&mxb,
841 }, {
842 .vendor = 0,
843 }
844};
845
846MODULE_DEVICE_TABLE(pci, pci_tbl);
847
848static struct saa7146_ext_vv vv_data = {
849 .inputs = MXB_INPUTS,
850 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
851 .stds = &standard[0],
852 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300853 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854};
855
856static struct saa7146_extension extension = {
857 .name = MXB_IDENTIFIER,
858 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300859
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 .pci_tbl = &pci_tbl[0],
861 .module = THIS_MODULE,
862
863 .probe = mxb_probe,
864 .attach = mxb_attach,
865 .detach = mxb_detach,
866
867 .irq_mask = 0,
868 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300869};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
871static int __init mxb_init_module(void)
872{
Hans Verkuil26338122008-09-06 17:24:30 -0300873 if (saa7146_register_extension(&extension)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 DEB_S(("failed to register extension.\n"));
875 return -ENODEV;
876 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300877
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 return 0;
879}
880
881static void __exit mxb_cleanup_module(void)
882{
883 saa7146_unregister_extension(&extension);
884}
885
886module_init(mxb_init_module);
887module_exit(mxb_cleanup_module);
888
889MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
890MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
891MODULE_LICENSE("GPL");