blob: 8ecda8dfbd04f85d518750def6e4c8b54a878df5 [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>
28#include <linux/video_decoder.h>
Michael Krufky5e453dc2006-01-09 15:32:31 -020029#include <media/v4l2-common.h>
Hans Verkuil707ecf42008-09-06 15:40:25 -030030#include <media/saa7115.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#include "mxb.h"
33#include "tea6415c.h"
34#include "tea6420.h"
35#include "tda9840.h"
36
37#define I2C_SAA7111 0x24
38
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030039#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41/* global variable */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030042static int mxb_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030044/* initial frequence the tuner will be tuned to.
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 in verden (lower saxony, germany) 4148 is a
46 channel called "phoenix" */
47static int freq = 4148;
48module_param(freq, int, 0644);
49MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
50
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030051static int debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052module_param(debug, int, 0644);
53MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
54
55#define MXB_INPUTS 4
56enum { TUNER, AUX1, AUX3, AUX3_YC };
57
58static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030059 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
61 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
62 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
63};
64
65/* this array holds the information, which port of the saa7146 each
66 input actually uses. the mxb uses port 0 for every input */
67static struct {
68 int hps_source;
69 int hps_sync;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030070} input_port_selection[MXB_INPUTS] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
72 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
73 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
74 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
75};
76
77/* this array holds the information of the audio source (mxb_audios),
78 which has to be switched corresponding to the video source (mxb_channels) */
79static int video_audio_connect[MXB_INPUTS] =
80 { 0, 1, 3, 3 };
81
82/* these are the necessary input-output-pins for bringing one audio source
83(see above) to the CD-output */
84static struct tea6420_multiplex TEA6420_cd[MXB_AUDIOS+1][2] =
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030085 {
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 {{1,1,0},{1,1,0}}, /* Tuner */
87 {{5,1,0},{6,1,0}}, /* AUX 1 */
88 {{4,1,0},{6,1,0}}, /* AUX 2 */
89 {{3,1,0},{6,1,0}}, /* AUX 3 */
90 {{1,1,0},{3,1,0}}, /* Radio */
91 {{1,1,0},{2,1,0}}, /* CD-Rom */
92 {{6,1,0},{6,1,0}} /* Mute */
93 };
94
95/* these are the necessary input-output-pins for bringing one audio source
96(see above) to the line-output */
97static struct tea6420_multiplex TEA6420_line[MXB_AUDIOS+1][2] =
98 {
99 {{2,3,0},{1,2,0}},
100 {{5,3,0},{6,2,0}},
101 {{4,3,0},{6,2,0}},
102 {{3,3,0},{6,2,0}},
103 {{2,3,0},{3,2,0}},
104 {{2,3,0},{2,2,0}},
105 {{6,3,0},{6,2,0}} /* Mute */
106 };
107
108#define MAXCONTROLS 1
109static struct v4l2_queryctrl mxb_controls[] = {
110 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
111};
112
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113struct mxb
114{
115 struct video_device *video_dev;
116 struct video_device *vbi_dev;
117
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300118 struct i2c_adapter i2c_adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
Hans Verkuil26338122008-09-06 17:24:30 -0300120 struct i2c_client *saa7111a;
121 struct i2c_client *tda9840;
122 struct i2c_client *tea6415c;
123 struct i2c_client *tuner;
124 struct i2c_client *tea6420_1;
125 struct i2c_client *tea6420_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127 int cur_mode; /* current audio mode (mono, stereo, ...) */
128 int cur_input; /* current input */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 int cur_mute; /* current mute status */
Michael Hunold9d2599d2005-07-27 11:46:00 -0700130 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131};
132
133static struct saa7146_extension extension;
134
Jean Delvare961f80f2008-01-27 18:14:51 +0100135static int mxb_check_clients(struct device *dev, void *data)
136{
Hans Verkuil26338122008-09-06 17:24:30 -0300137 struct mxb *mxb = data;
Jean Delvare961f80f2008-01-27 18:14:51 +0100138 struct i2c_client *client = i2c_verify_client(dev);
139
Hans Verkuil707ecf42008-09-06 15:40:25 -0300140 if (!client)
Jean Delvare961f80f2008-01-27 18:14:51 +0100141 return 0;
142
Hans Verkuil707ecf42008-09-06 15:40:25 -0300143 if (I2C_ADDR_TEA6420_1 == client->addr)
Jean Delvare961f80f2008-01-27 18:14:51 +0100144 mxb->tea6420_1 = client;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300145 if (I2C_ADDR_TEA6420_2 == client->addr)
Jean Delvare961f80f2008-01-27 18:14:51 +0100146 mxb->tea6420_2 = client;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300147 if (I2C_TEA6415C_2 == client->addr)
Jean Delvare961f80f2008-01-27 18:14:51 +0100148 mxb->tea6415c = client;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300149 if (I2C_ADDR_TDA9840 == client->addr)
Jean Delvare961f80f2008-01-27 18:14:51 +0100150 mxb->tda9840 = client;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300151 if (I2C_SAA7111 == client->addr)
Jean Delvare961f80f2008-01-27 18:14:51 +0100152 mxb->saa7111a = client;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300153 if (0x60 == client->addr)
Jean Delvare961f80f2008-01-27 18:14:51 +0100154 mxb->tuner = client;
155
156 return 0;
157}
158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159static int mxb_probe(struct saa7146_dev* dev)
160{
161 struct mxb* mxb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 int result;
163
Hans Verkuil707ecf42008-09-06 15:40:25 -0300164 result = request_module("saa7115");
165 if (result < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 printk("mxb: saa7111 i2c module not available.\n");
167 return -ENODEV;
168 }
Hans Verkuil707ecf42008-09-06 15:40:25 -0300169 result = request_module("tea6420");
170 if (result < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 printk("mxb: tea6420 i2c module not available.\n");
172 return -ENODEV;
173 }
Hans Verkuil707ecf42008-09-06 15:40:25 -0300174 result = request_module("tea6415c");
175 if (result < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 printk("mxb: tea6415c i2c module not available.\n");
177 return -ENODEV;
178 }
Hans Verkuil707ecf42008-09-06 15:40:25 -0300179 result = request_module("tda9840");
180 if (result < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 printk("mxb: tda9840 i2c module not available.\n");
182 return -ENODEV;
183 }
Hans Verkuil707ecf42008-09-06 15:40:25 -0300184 result = request_module("tuner");
185 if (result < 0) {
Michael Hunolda08cc442006-11-28 08:13:58 -0300186 printk("mxb: tuner i2c module not available.\n");
187 return -ENODEV;
188 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
Panagiotis Issaris74081872006-01-11 19:40:56 -0200190 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 if( NULL == mxb ) {
192 DEB_D(("not enough kernel memory.\n"));
193 return -ENOMEM;
194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195
196 mxb->i2c_adapter = (struct i2c_adapter) {
197 .class = I2C_CLASS_TV_ANALOG,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 };
199
Hans Verkuil9ebeae52008-09-07 08:32:44 -0300200 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
201
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
203 if(i2c_add_adapter(&mxb->i2c_adapter) < 0) {
204 DEB_S(("cannot register i2c-device. skipping.\n"));
205 kfree(mxb);
206 return -EFAULT;
207 }
208
209 /* loop through all i2c-devices on the bus and look who is there */
Jean Delvare961f80f2008-01-27 18:14:51 +0100210 device_for_each_child(&mxb->i2c_adapter.dev, mxb, mxb_check_clients);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
212 /* check if all devices are present */
Al Viro5fa12472008-03-29 03:07:38 +0000213 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
214 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 printk("mxb: did not find all i2c devices. aborting\n");
216 i2c_del_adapter(&mxb->i2c_adapter);
217 kfree(mxb);
218 return -ENODEV;
219 }
220
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300221 /* all devices are present, probe was successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
223 /* we store the pointer in our private data field */
224 dev->ext_priv = mxb;
225
226 return 0;
227}
228
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300229/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 there are no specs available, so we simply use some init values */
231static struct {
232 int length;
233 char data[9];
234} mxb_saa7740_init[] = {
235 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
236 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
237 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
238 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
239 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
240 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
241 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
242 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
243 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
244 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
245 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
246 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
247 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
248 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
249 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
250 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
251 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
252 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
253 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
254 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
255 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
256 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
257 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
258 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
259 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
260 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
261 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
262 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
263 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
264 { 3, { 0x48, 0x00, 0x01 } },
265 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
266 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
267 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
268 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
269 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
270 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
271 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
272 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
273 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
274 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
275 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
276 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
277 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
278 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
279 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
280 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
281 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300282 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283};
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285/* bring hardware to a sane state. this has to be done, just in case someone
286 wants to capture from this device before it has been properly initialized.
287 the capture engine would badly fail, because no valid signal arrives on the
288 saa7146, thus leading to timeouts and stuff. */
289static int mxb_init_done(struct saa7146_dev* dev)
290{
291 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700293 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800294 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300295 struct v4l2_routing route;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
297 int i = 0, err = 0;
Hans Verkuil26338122008-09-06 17:24:30 -0300298 struct tea6415c_multiplex vm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 /* select video mode in saa7111a */
Hans Verkuil707ecf42008-09-06 15:40:25 -0300301 mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_S_STD, &std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
303 /* select tuner-output on saa7111a */
304 i = 0;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300305 route.input = SAA7115_COMPOSITE0;
306 route.output = SAA7111_FMT_CCIR | SAA7111_VBI_BYPASS;
307 mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
309 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700310 tun_setup.mode_mask = T_ANALOG_TV;
311 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700312 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil707ecf42008-09-06 15:40:25 -0300313 mxb->tuner->driver->command(mxb->tuner, TUNER_SET_TYPE_ADDR, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700314 /* tune in some frequency on tuner */
315 mxb->cur_freq.tuner = 0;
316 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
317 mxb->cur_freq.frequency = freq;
318 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY,
319 &mxb->cur_freq);
320
Michael Hunold6acaba82006-03-13 21:20:41 -0800321 /* set a default video standard */
322 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 /* mute audio on tea6420s */
Hans Verkuil26338122008-09-06 17:24:30 -0300325 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[6][0]);
326 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[6][1]);
327 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[6][0]);
328 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[6][1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330 /* switch to tuner-channel on tea6415c*/
331 vm.out = 17;
332 vm.in = 3;
Hans Verkuil26338122008-09-06 17:24:30 -0300333 mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
335 /* select tuner-output on multicable on tea6415c*/
336 vm.in = 3;
337 vm.out = 13;
Hans Verkuil26338122008-09-06 17:24:30 -0300338 mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300339
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 /* the rest for mxb */
341 mxb->cur_input = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 mxb->cur_mute = 1;
343
344 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300345
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300347 on the mxb. if so, we must initialize it. due to lack of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 informations about the saa7740, the values were reverse
349 engineered. */
350 msg.addr = 0x1b;
351 msg.flags = 0;
352 msg.len = mxb_saa7740_init[0].length;
353 msg.buf = &mxb_saa7740_init[0].data[0];
354
Hans Verkuil26338122008-09-06 17:24:30 -0300355 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
356 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 /* the sound arena module is a pos, that's probably the reason
358 philips refuses to hand out a datasheet for the saa7740...
359 it seems to screw up the i2c bus, so we disable fast irq
360 based i2c transactions here and rely on the slow and safe
361 polling method ... */
362 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300363 for (i = 1; ; i++) {
364 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300367 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300369 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
370 if (err != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 DEB_D(("failed to initialize 'sound arena module'.\n"));
372 goto err;
373 }
374 }
375 INFO(("'sound arena module' detected.\n"));
376 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300377err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 /* the rest for saa7146: you should definitely set some basic values
379 for the input-port handling of the saa7146. */
380
381 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300382
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300384 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
385 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
387 /* some stuff is done via direct write to the registers */
388
389 /* this is ugly, but because of the fact that this is completely
390 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300391 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 saa7146_write(dev, DD1_INIT, 0x02000200);
393 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
394
395 return 0;
396}
397
398/* interrupt-handler. this gets called when irq_mask is != 0.
399 it must clear the interrupt-bits in irq_mask it has handled */
400/*
401void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
402{
403 struct mxb* mxb = (struct mxb*)dev->ext_priv;
404}
405*/
406
Hans Verkuilb9600742009-01-18 19:59:11 -0300407static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
408{
409 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
410 int i;
411
412 for (i = MAXCONTROLS - 1; i >= 0; i--) {
413 if (mxb_controls[i].id == qc->id) {
414 *qc = mxb_controls[i];
415 DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id));
416 return 0;
417 }
418 }
419 return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc);
420}
421
422static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
423{
424 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
425 struct mxb *mxb = (struct mxb *)dev->ext_priv;
426 int i;
427
428 for (i = MAXCONTROLS - 1; i >= 0; i--) {
429 if (mxb_controls[i].id == vc->id)
430 break;
431 }
432
433 if (i < 0)
434 return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc);
435
436 if (vc->id == V4L2_CID_AUDIO_MUTE) {
437 vc->value = mxb->cur_mute;
438 DEB_D(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
439 return 0;
440 }
441
442 DEB_EE(("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d.\n", vc->value));
443 return 0;
444}
445
446static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
447{
448 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
449 struct mxb *mxb = (struct mxb *)dev->ext_priv;
450 int i = 0;
451
452 for (i = MAXCONTROLS - 1; i >= 0; i--) {
453 if (mxb_controls[i].id == vc->id)
454 break;
455 }
456
457 if (i < 0)
458 return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc);
459
460 if (vc->id == V4L2_CID_AUDIO_MUTE) {
461 mxb->cur_mute = vc->value;
462 if (!vc->value) {
463 /* switch the audio-source */
464 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
465 &TEA6420_line[video_audio_connect[mxb->cur_input]][0]);
466 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
467 &TEA6420_line[video_audio_connect[mxb->cur_input]][1]);
468 } else {
469 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
470 &TEA6420_line[6][0]);
471 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
472 &TEA6420_line[6][1]);
473 }
474 DEB_EE(("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d.\n", vc->value));
475 }
476 return 0;
477}
478
479static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
480{
481 DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index));
482 if (i->index < 0 || i->index >= MXB_INPUTS)
483 return -EINVAL;
484 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
485 return 0;
486}
487
488static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
489{
490 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
491 struct mxb *mxb = (struct mxb *)dev->ext_priv;
492 *i = mxb->cur_input;
493
494 DEB_EE(("VIDIOC_G_INPUT %d.\n", *i));
495 return 0;
496}
497
498static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
499{
500 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
501 struct mxb *mxb = (struct mxb *)dev->ext_priv;
502 struct tea6415c_multiplex vm;
503 struct v4l2_routing route;
504 int i = 0;
505
506 DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
507
508 if (input < 0 || input >= MXB_INPUTS)
509 return -EINVAL;
510
511 mxb->cur_input = input;
512
513 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
514 input_port_selection[input].hps_sync);
515
516 /* prepare switching of tea6415c and saa7111a;
517 have a look at the 'background'-file for further informations */
518 switch (input) {
519 case TUNER:
520 i = SAA7115_COMPOSITE0;
521 vm.in = 3;
522 vm.out = 17;
523
524 if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
525 printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #1\n");
526 return -EFAULT;
527 }
528 /* connect tuner-output always to multicable */
529 vm.in = 3;
530 vm.out = 13;
531 break;
532 case AUX3_YC:
533 /* nothing to be done here. aux3_yc is
534 directly connected to the saa711a */
535 i = SAA7115_SVIDEO1;
536 break;
537 case AUX3:
538 /* nothing to be done here. aux3 is
539 directly connected to the saa711a */
540 i = SAA7115_COMPOSITE1;
541 break;
542 case AUX1:
543 i = SAA7115_COMPOSITE0;
544 vm.in = 1;
545 vm.out = 17;
546 break;
547 }
548
549 /* switch video in tea6415c only if necessary */
550 switch (input) {
551 case TUNER:
552 case AUX1:
553 if (mxb->tea6415c->driver->command(mxb->tea6415c, TEA6415C_SWITCH, &vm)) {
554 printk(KERN_ERR "VIDIOC_S_INPUT: could not address tea6415c #3\n");
555 return -EFAULT;
556 }
557 break;
558 default:
559 break;
560 }
561
562 /* switch video in saa7111a */
563 route.input = i;
564 route.output = 0;
565 if (mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_VIDEO_ROUTING, &route))
566 printk(KERN_ERR "VIDIOC_S_INPUT: could not address saa7111a #1.\n");
567
568 /* switch the audio-source only if necessary */
569 if (0 == mxb->cur_mute) {
570 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH,
571 &TEA6420_line[video_audio_connect[input]][0]);
572 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH,
573 &TEA6420_line[video_audio_connect[input]][1]);
574 }
575
576 return 0;
577}
578
579static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
580{
581 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
582 struct mxb *mxb = (struct mxb *)dev->ext_priv;
583
584 if (t->index) {
585 DEB_D(("VIDIOC_G_TUNER: channel %d does not have a tuner attached.\n", t->index));
586 return -EINVAL;
587 }
588
589 DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
590
591 memset(t, 0, sizeof(*t));
592 i2c_clients_command(&mxb->i2c_adapter, VIDIOC_G_TUNER, t);
593
594 strlcpy(t->name, "TV Tuner", sizeof(t->name));
595 t->type = V4L2_TUNER_ANALOG_TV;
596 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
597 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
598 t->audmode = mxb->cur_mode;
599 return 0;
600}
601
602static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
603{
604 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
605 struct mxb *mxb = (struct mxb *)dev->ext_priv;
606
607 if (t->index) {
608 DEB_D(("VIDIOC_S_TUNER: channel %d does not have a tuner attached.\n", t->index));
609 return -EINVAL;
610 }
611
612 mxb->cur_mode = t->audmode;
613 i2c_clients_command(&mxb->i2c_adapter, VIDIOC_S_TUNER, t);
614 return 0;
615}
616
617static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
618{
619 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
620 struct mxb *mxb = (struct mxb *)dev->ext_priv;
621
622 if (mxb->cur_input) {
623 DEB_D(("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
624 mxb->cur_input));
625 return -EINVAL;
626 }
627
628 *f = mxb->cur_freq;
629
630 DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", mxb->cur_freq.frequency));
631 return 0;
632}
633
634static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
635{
636 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
637 struct mxb *mxb = (struct mxb *)dev->ext_priv;
638 struct saa7146_vv *vv = dev->vv_data;
639
640 if (f->tuner)
641 return -EINVAL;
642
643 if (V4L2_TUNER_ANALOG_TV != f->type)
644 return -EINVAL;
645
646 if (mxb->cur_input) {
647 DEB_D(("VIDIOC_S_FREQ: channel %d does not have a tuner!\n", mxb->cur_input));
648 return -EINVAL;
649 }
650
651 mxb->cur_freq = *f;
652 DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", mxb->cur_freq.frequency));
653
654 /* tune in desired frequency */
655 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_FREQUENCY, &mxb->cur_freq);
656
657 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
658 spin_lock(&dev->slock);
659 vv->vbi_fieldcount = 0;
660 spin_unlock(&dev->slock);
661
662 return 0;
663}
664
665static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
666{
667 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
668 struct mxb *mxb = (struct mxb *)dev->ext_priv;
669
670 if (a->index < 0 || a->index > MXB_INPUTS) {
671 DEB_D(("VIDIOC_G_AUDIO %d out of range.\n", a->index));
672 return -EINVAL;
673 }
674
675 DEB_EE(("VIDIOC_G_AUDIO %d.\n", a->index));
676 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
677 return 0;
678}
679
680static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
681{
682 DEB_D(("VIDIOC_S_AUDIO %d.\n", a->index));
683 return 0;
684}
685
686#ifdef CONFIG_VIDEO_ADV_DEBUG
687static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
688{
689 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
690 struct mxb *mxb = (struct mxb *)dev->ext_priv;
691
692 i2c_clients_command(&mxb->i2c_adapter, VIDIOC_DBG_G_REGISTER, reg);
693 return 0;
694}
695
696static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
697{
698 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
699 struct mxb *mxb = (struct mxb *)dev->ext_priv;
700
701 i2c_clients_command(&mxb->i2c_adapter, VIDIOC_DBG_S_REGISTER, reg);
702 return 0;
703}
704#endif
705
706static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
707{
708 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
709 struct mxb *mxb = (struct mxb *)dev->ext_priv;
710
711 switch (cmd) {
712 case MXB_S_AUDIO_CD:
713 {
714 int i = *(int *)arg;
715
716 if (i < 0 || i >= MXB_AUDIOS) {
717 DEB_D(("illegal argument to MXB_S_AUDIO_CD: i:%d.\n", i));
718 return -EINVAL;
719 }
720
721 DEB_EE(("MXB_S_AUDIO_CD: i:%d.\n", i));
722
723 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_cd[i][0]);
724 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_cd[i][1]);
725
726 return 0;
727 }
728 case MXB_S_AUDIO_LINE:
729 {
730 int i = *(int *)arg;
731
732 if (i < 0 || i >= MXB_AUDIOS) {
733 DEB_D(("illegal argument to MXB_S_AUDIO_LINE: i:%d.\n", i));
734 return -EINVAL;
735 }
736
737 DEB_EE(("MXB_S_AUDIO_LINE: i:%d.\n", i));
738 mxb->tea6420_1->driver->command(mxb->tea6420_1, TEA6420_SWITCH, &TEA6420_line[i][0]);
739 mxb->tea6420_2->driver->command(mxb->tea6420_2, TEA6420_SWITCH, &TEA6420_line[i][1]);
740
741 return 0;
742 }
743 default:
744/*
745 DEB2(printk("does not handle this ioctl.\n"));
746*/
747 return -ENOIOCTLCMD;
748 }
749 return 0;
750}
751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752static struct saa7146_ext_vv vv_data;
753
754/* this function only gets called when the probing was successful */
Hans Verkuil26338122008-09-06 17:24:30 -0300755static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756{
Hans Verkuil26338122008-09-06 17:24:30 -0300757 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300758
Hans Verkuil26338122008-09-06 17:24:30 -0300759 DEB_EE(("dev:%p\n", dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
761 /* checking for i2c-devices can be omitted here, because we
762 already did this in "mxb_vl42_probe" */
763
Hans Verkuila8327812008-07-25 10:31:23 -0300764 saa7146_vv_init(dev, &vv_data);
Hans Verkuilb9600742009-01-18 19:59:11 -0300765 vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
766 vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
767 vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
768 vv_data.ops.vidioc_enum_input = vidioc_enum_input;
769 vv_data.ops.vidioc_g_input = vidioc_g_input;
770 vv_data.ops.vidioc_s_input = vidioc_s_input;
771 vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
772 vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
773 vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
774 vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
775 vv_data.ops.vidioc_g_audio = vidioc_g_audio;
776 vv_data.ops.vidioc_s_audio = vidioc_s_audio;
777#ifdef CONFIG_VIDEO_ADV_DEBUG
778 vv_data.ops.vidioc_g_register = vidioc_g_register;
779 vv_data.ops.vidioc_s_register = vidioc_s_register;
780#endif
781 vv_data.ops.vidioc_default = vidioc_default;
Hans Verkuila8327812008-07-25 10:31:23 -0300782 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 ERR(("cannot register capture v4l2 device. skipping.\n"));
784 return -1;
785 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300788 if (MXB_BOARD_CAN_DO_VBI(dev)) {
789 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 ERR(("cannot register vbi v4l2 device. skipping.\n"));
791 }
792 }
793
794 i2c_use_client(mxb->tea6420_1);
795 i2c_use_client(mxb->tea6420_2);
796 i2c_use_client(mxb->tea6415c);
797 i2c_use_client(mxb->tda9840);
798 i2c_use_client(mxb->saa7111a);
799 i2c_use_client(mxb->tuner);
800
Hans Verkuila8327812008-07-25 10:31:23 -0300801 printk("mxb: found Multimedia eXtension Board #%d.\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
803 mxb_num++;
804 mxb_init_done(dev);
805 return 0;
806}
807
Hans Verkuil26338122008-09-06 17:24:30 -0300808static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809{
Hans Verkuil26338122008-09-06 17:24:30 -0300810 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
Hans Verkuil26338122008-09-06 17:24:30 -0300812 DEB_EE(("dev:%p\n", dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
814 i2c_release_client(mxb->tea6420_1);
815 i2c_release_client(mxb->tea6420_2);
816 i2c_release_client(mxb->tea6415c);
817 i2c_release_client(mxb->tda9840);
818 i2c_release_client(mxb->saa7111a);
819 i2c_release_client(mxb->tuner);
820
821 saa7146_unregister_device(&mxb->video_dev,dev);
Hans Verkuil26338122008-09-06 17:24:30 -0300822 if (MXB_BOARD_CAN_DO_VBI(dev))
823 saa7146_unregister_device(&mxb->vbi_dev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 saa7146_vv_release(dev);
825
826 mxb_num--;
827
828 i2c_del_adapter(&mxb->i2c_adapter);
829 kfree(mxb);
830
831 return 0;
832}
833
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300834static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835{
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300836 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 int zero = 0;
838 int one = 1;
839
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300840 if (V4L2_STD_PAL_I == standard->id) {
Michael Hunold6acaba82006-03-13 21:20:41 -0800841 v4l2_std_id std = V4L2_STD_PAL_I;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300842
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 DEB_D(("VIDIOC_S_STD: setting mxb for PAL_I.\n"));
844 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300845 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 /* unset the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil707ecf42008-09-06 15:40:25 -0300847 mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &zero);
Michael Hunold6acaba82006-03-13 21:20:41 -0800848 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 } else {
Michael Hunold6acaba82006-03-13 21:20:41 -0800850 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300851
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 DEB_D(("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM.\n"));
853 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300854 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 /* set the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil707ecf42008-09-06 15:40:25 -0300856 mxb->saa7111a->driver->command(mxb->saa7111a, VIDIOC_INT_S_GPIO, &one);
Michael Hunold6acaba82006-03-13 21:20:41 -0800857 mxb->tuner->driver->command(mxb->tuner, VIDIOC_S_STD, &std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 }
859 return 0;
860}
861
862static struct saa7146_standard standard[] = {
863 {
864 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
865 .v_offset = 0x17, .v_field = 288,
866 .h_offset = 0x14, .h_pixels = 680,
867 .v_max_out = 576, .h_max_out = 768,
868 }, {
869 .name = "PAL-I", .id = V4L2_STD_PAL_I,
870 .v_offset = 0x17, .v_field = 288,
871 .h_offset = 0x14, .h_pixels = 680,
872 .v_max_out = 576, .h_max_out = 768,
873 }, {
874 .name = "NTSC", .id = V4L2_STD_NTSC,
875 .v_offset = 0x16, .v_field = 240,
876 .h_offset = 0x06, .h_pixels = 708,
877 .v_max_out = 480, .h_max_out = 640,
878 }, {
879 .name = "SECAM", .id = V4L2_STD_SECAM,
880 .v_offset = 0x14, .v_field = 288,
881 .h_offset = 0x14, .h_pixels = 720,
882 .v_max_out = 576, .h_max_out = 768,
883 }
884};
885
886static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300887 .ext_priv = "Multimedia eXtension Board",
888 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889};
890
891static struct pci_device_id pci_tbl[] = {
892 {
893 .vendor = PCI_VENDOR_ID_PHILIPS,
894 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
895 .subvendor = 0x0000,
896 .subdevice = 0x0000,
897 .driver_data = (unsigned long)&mxb,
898 }, {
899 .vendor = 0,
900 }
901};
902
903MODULE_DEVICE_TABLE(pci, pci_tbl);
904
905static struct saa7146_ext_vv vv_data = {
906 .inputs = MXB_INPUTS,
907 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
908 .stds = &standard[0],
909 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300910 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911};
912
913static struct saa7146_extension extension = {
914 .name = MXB_IDENTIFIER,
915 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300916
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 .pci_tbl = &pci_tbl[0],
918 .module = THIS_MODULE,
919
920 .probe = mxb_probe,
921 .attach = mxb_attach,
922 .detach = mxb_detach,
923
924 .irq_mask = 0,
925 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300926};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
928static int __init mxb_init_module(void)
929{
Hans Verkuil26338122008-09-06 17:24:30 -0300930 if (saa7146_register_extension(&extension)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 DEB_S(("failed to register extension.\n"));
932 return -ENODEV;
933 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300934
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 return 0;
936}
937
938static void __exit mxb_cleanup_module(void)
939{
940 saa7146_unregister_extension(&extension);
941}
942
943module_init(mxb_init_module);
944module_exit(mxb_cleanup_module);
945
946MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
947MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
948MODULE_LICENSE("GPL");