blob: aa3d75c1e35115b04dd54931c5d5c465b01b3577 [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
Justin P. Mattock631dd1a2010-10-18 11:03:14 +02006 Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 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
Joe Perches44d0b802011-08-21 19:56:44 -030024#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#define DEBUG_VARIABLE debug
27
28#include <media/saa7146_vv.h>
29#include <media/tuner.h>
Michael Krufky5e453dc2006-01-09 15:32:31 -020030#include <media/v4l2-common.h>
Hans Verkuil707ecf42008-09-06 15:40:25 -030031#include <media/saa7115.h>
Paul Gortmaker7a707b82011-07-03 14:03:12 -040032#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#include "mxb.h"
35#include "tea6415c.h"
36#include "tea6420.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
Hans Verkuil1b8dac12009-02-07 11:18:05 -030038#define I2C_SAA7111A 0x24
39#define I2C_TDA9840 0x42
40#define I2C_TEA6415C 0x43
41#define I2C_TEA6420_1 0x4c
42#define I2C_TEA6420_2 0x4d
43#define I2C_TUNER 0x60
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030045#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47/* global variable */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030048static int mxb_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030050/* initial frequence the tuner will be tuned to.
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 in verden (lower saxony, germany) 4148 is a
52 channel called "phoenix" */
53static int freq = 4148;
54module_param(freq, int, 0644);
55MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
56
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030057static int debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058module_param(debug, int, 0644);
59MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
60
61#define MXB_INPUTS 4
62enum { TUNER, AUX1, AUX3, AUX3_YC };
63
64static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
Hans Verkuil657f2272010-12-29 14:29:55 -030065 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
66 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
Hans Verkuil6e65ca92012-04-29 16:47:47 -030067 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 8, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
68 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 8, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
Linus Torvalds1da177e2005-04-16 15:20:36 -070069};
70
71/* this array holds the information, which port of the saa7146 each
72 input actually uses. the mxb uses port 0 for every input */
73static struct {
74 int hps_source;
75 int hps_sync;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030076} input_port_selection[MXB_INPUTS] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
78 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
79 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
80 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
81};
82
83/* this array holds the information of the audio source (mxb_audios),
84 which has to be switched corresponding to the video source (mxb_channels) */
85static int video_audio_connect[MXB_INPUTS] =
86 { 0, 1, 3, 3 };
87
Hans Verkuil5325b422009-04-02 11:26:22 -030088struct mxb_routing {
89 u32 input;
90 u32 output;
91};
92
Hans Verkuil6e65ca92012-04-29 16:47:47 -030093/* these are the available audio sources, which can switched
94 to the line- and cd-output individually */
95static struct v4l2_audio mxb_audios[MXB_AUDIOS] = {
96 {
97 .index = 0,
98 .name = "Tuner",
99 .capability = V4L2_AUDCAP_STEREO,
100 } , {
101 .index = 1,
102 .name = "AUX1",
103 .capability = V4L2_AUDCAP_STEREO,
104 } , {
105 .index = 2,
106 .name = "AUX2",
107 .capability = V4L2_AUDCAP_STEREO,
108 } , {
109 .index = 3,
110 .name = "AUX3",
111 .capability = V4L2_AUDCAP_STEREO,
112 } , {
113 .index = 4,
114 .name = "Radio (X9)",
115 .capability = V4L2_AUDCAP_STEREO,
116 } , {
117 .index = 5,
118 .name = "CD-ROM (X10)",
119 .capability = V4L2_AUDCAP_STEREO,
120 }
121};
122
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300123/* These are the necessary input-output-pins for bringing one audio source
124 (see above) to the CD-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -0300125static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300126 { { 1, 1 }, { 1, 1 } }, /* Tuner */
127 { { 5, 1 }, { 6, 1 } }, /* AUX 1 */
128 { { 4, 1 }, { 6, 1 } }, /* AUX 2 */
129 { { 3, 1 }, { 6, 1 } }, /* AUX 3 */
130 { { 1, 1 }, { 3, 1 } }, /* Radio */
131 { { 1, 1 }, { 2, 1 } }, /* CD-Rom */
132 { { 6, 1 }, { 6, 1 } } /* Mute */
133};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300135/* These are the necessary input-output-pins for bringing one audio source
136 (see above) to the line-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -0300137static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300138 { { 2, 3 }, { 1, 2 } },
139 { { 5, 3 }, { 6, 2 } },
140 { { 4, 3 }, { 6, 2 } },
141 { { 3, 3 }, { 6, 2 } },
142 { { 2, 3 }, { 3, 2 } },
143 { { 2, 3 }, { 2, 2 } },
144 { { 6, 3 }, { 6, 2 } } /* Mute */
145};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147struct mxb
148{
149 struct video_device *video_dev;
150 struct video_device *vbi_dev;
151
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300152 struct i2c_adapter i2c_adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300154 struct v4l2_subdev *saa7111a;
155 struct v4l2_subdev *tda9840;
156 struct v4l2_subdev *tea6415c;
157 struct v4l2_subdev *tuner;
158 struct v4l2_subdev *tea6420_1;
159 struct v4l2_subdev *tea6420_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
161 int cur_mode; /* current audio mode (mono, stereo, ...) */
162 int cur_input; /* current input */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 int cur_mute; /* current mute status */
Michael Hunold9d2599d2005-07-27 11:46:00 -0700164 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165};
166
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300167#define saa7111a_call(mxb, o, f, args...) \
168 v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300169#define tda9840_call(mxb, o, f, args...) \
170 v4l2_subdev_call(mxb->tda9840, o, f, ##args)
171#define tea6415c_call(mxb, o, f, args...) \
172 v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
173#define tuner_call(mxb, o, f, args...) \
174 v4l2_subdev_call(mxb->tuner, o, f, ##args)
175#define call_all(dev, o, f, args...) \
176 v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
177
Hans Verkuil5325b422009-04-02 11:26:22 -0300178static inline void tea6420_route_cd(struct mxb *mxb, int idx)
179{
180 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
181 TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
182 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
183 TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
184}
185
186static inline void tea6420_route_line(struct mxb *mxb, int idx)
187{
188 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
189 TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
190 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
191 TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
192}
193
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static struct saa7146_extension extension;
195
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300196static int mxb_s_ctrl(struct v4l2_ctrl *ctrl)
197{
198 struct saa7146_dev *dev = container_of(ctrl->handler,
199 struct saa7146_dev, ctrl_handler);
200 struct mxb *mxb = dev->ext_priv;
201
202 switch (ctrl->id) {
203 case V4L2_CID_AUDIO_MUTE:
204 mxb->cur_mute = ctrl->val;
205 /* switch the audio-source */
206 tea6420_route_line(mxb, ctrl->val ? 6 :
207 video_audio_connect[mxb->cur_input]);
208 break;
209 default:
210 return -EINVAL;
211 }
212 return 0;
213}
214
215static const struct v4l2_ctrl_ops mxb_ctrl_ops = {
216 .s_ctrl = mxb_s_ctrl,
217};
218
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300219static int mxb_probe(struct saa7146_dev *dev)
Jean Delvare961f80f2008-01-27 18:14:51 +0100220{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300221 struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300222 struct mxb *mxb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300224 v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops,
225 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
226 if (hdl->error)
227 return hdl->error;
Panagiotis Issaris74081872006-01-11 19:40:56 -0200228 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300229 if (mxb == NULL) {
Joe Perches44d0b802011-08-21 19:56:44 -0300230 DEB_D("not enough kernel memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 return -ENOMEM;
232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300234
Hans Verkuil9ebeae52008-09-07 08:32:44 -0300235 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300238 if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
Joe Perches44d0b802011-08-21 19:56:44 -0300239 DEB_S("cannot register i2c-device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 kfree(mxb);
241 return -EFAULT;
242 }
243
Hans Verkuile6574f22009-04-01 03:57:53 -0300244 mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300245 "saa7111", I2C_SAA7111A, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300246 mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300247 "tea6420", I2C_TEA6420_1, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300248 mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300249 "tea6420", I2C_TEA6420_2, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300250 mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300251 "tea6415c", I2C_TEA6415C, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300252 mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300253 "tda9840", I2C_TDA9840, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300254 mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300255 "tuner", I2C_TUNER, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
257 /* check if all devices are present */
Al Viro5fa12472008-03-29 03:07:38 +0000258 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
259 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
Joe Perches44d0b802011-08-21 19:56:44 -0300260 pr_err("did not find all i2c devices. aborting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 i2c_del_adapter(&mxb->i2c_adapter);
262 kfree(mxb);
263 return -ENODEV;
264 }
265
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300266 /* all devices are present, probe was successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
268 /* we store the pointer in our private data field */
269 dev->ext_priv = mxb;
270
Hans Verkuild69f4a52012-04-29 18:59:38 -0300271 v4l2_ctrl_handler_setup(hdl);
272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 return 0;
274}
275
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300276/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 there are no specs available, so we simply use some init values */
278static struct {
279 int length;
280 char data[9];
281} mxb_saa7740_init[] = {
282 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
283 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
284 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
285 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
286 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
287 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
288 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
289 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
290 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
291 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
292 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
293 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
294 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
295 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
296 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
297 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
298 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
299 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
300 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
301 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
302 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
303 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
304 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
305 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
306 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
307 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
308 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
309 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
310 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
311 { 3, { 0x48, 0x00, 0x01 } },
312 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
313 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
314 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
315 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
316 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
317 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
318 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
319 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
320 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
321 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
322 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
323 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
324 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
325 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
326 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
327 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
328 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300329 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330};
331
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332/* bring hardware to a sane state. this has to be done, just in case someone
333 wants to capture from this device before it has been properly initialized.
334 the capture engine would badly fail, because no valid signal arrives on the
335 saa7146, thus leading to timeouts and stuff. */
336static int mxb_init_done(struct saa7146_dev* dev)
337{
338 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700340 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800341 v4l2_std_id std = V4L2_STD_PAL_BG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
343 int i = 0, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
345 /* select video mode in saa7111a */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300346 saa7111a_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
348 /* select tuner-output on saa7111a */
349 i = 0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300350 saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
Hans Verkuil340dde82010-02-20 08:07:51 -0300351 SAA7111_FMT_CCIR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
353 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700354 tun_setup.mode_mask = T_ANALOG_TV;
355 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700356 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300357 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700358 /* tune in some frequency on tuner */
359 mxb->cur_freq.tuner = 0;
360 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
361 mxb->cur_freq.frequency = freq;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300362 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700363
Michael Hunold6acaba82006-03-13 21:20:41 -0800364 /* set a default video standard */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300365 tuner_call(mxb, core, s_std, std);
Michael Hunold6acaba82006-03-13 21:20:41 -0800366
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 /* mute audio on tea6420s */
Hans Verkuil5325b422009-04-02 11:26:22 -0300368 tea6420_route_line(mxb, 6);
369 tea6420_route_cd(mxb, 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300371 /* switch to tuner-channel on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300372 tea6415c_call(mxb, video, s_routing, 3, 17, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300374 /* select tuner-output on multicable on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300375 tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 /* the rest for mxb */
378 mxb->cur_input = 0;
Hans Verkuild69f4a52012-04-29 18:59:38 -0300379 mxb->cur_mute = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
381 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300382
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300384 on the mxb. if so, we must initialize it. due to lack of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 informations about the saa7740, the values were reverse
386 engineered. */
387 msg.addr = 0x1b;
388 msg.flags = 0;
389 msg.len = mxb_saa7740_init[0].length;
390 msg.buf = &mxb_saa7740_init[0].data[0];
391
Hans Verkuil26338122008-09-06 17:24:30 -0300392 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
393 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 /* the sound arena module is a pos, that's probably the reason
395 philips refuses to hand out a datasheet for the saa7740...
396 it seems to screw up the i2c bus, so we disable fast irq
397 based i2c transactions here and rely on the slow and safe
398 polling method ... */
399 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300400 for (i = 1; ; i++) {
401 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300404 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300406 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
407 if (err != 1) {
Joe Perches44d0b802011-08-21 19:56:44 -0300408 DEB_D("failed to initialize 'sound arena module'\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 goto err;
410 }
411 }
Joe Perches44d0b802011-08-21 19:56:44 -0300412 pr_info("'sound arena module' detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300414err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 /* the rest for saa7146: you should definitely set some basic values
416 for the input-port handling of the saa7146. */
417
418 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300419
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300421 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
422 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
424 /* some stuff is done via direct write to the registers */
425
426 /* this is ugly, but because of the fact that this is completely
427 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300428 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 saa7146_write(dev, DD1_INIT, 0x02000200);
430 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
431
432 return 0;
433}
434
435/* interrupt-handler. this gets called when irq_mask is != 0.
436 it must clear the interrupt-bits in irq_mask it has handled */
437/*
438void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
439{
440 struct mxb* mxb = (struct mxb*)dev->ext_priv;
441}
442*/
443
Hans Verkuilb9600742009-01-18 19:59:11 -0300444static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
445{
Joe Perches44d0b802011-08-21 19:56:44 -0300446 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
Roel Kluin223ffe52009-05-02 16:38:47 -0300447 if (i->index >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300448 return -EINVAL;
449 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
450 return 0;
451}
452
453static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
454{
455 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
456 struct mxb *mxb = (struct mxb *)dev->ext_priv;
457 *i = mxb->cur_input;
458
Joe Perches44d0b802011-08-21 19:56:44 -0300459 DEB_EE("VIDIOC_G_INPUT %d\n", *i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300460 return 0;
461}
462
463static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
464{
465 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
466 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Hans Verkuil5325b422009-04-02 11:26:22 -0300467 int err = 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300468 int i = 0;
469
Joe Perches44d0b802011-08-21 19:56:44 -0300470 DEB_EE("VIDIOC_S_INPUT %d\n", input);
Hans Verkuilb9600742009-01-18 19:59:11 -0300471
Roel Kluinf14a2972009-10-23 07:59:42 -0300472 if (input >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300473 return -EINVAL;
474
475 mxb->cur_input = input;
476
477 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
478 input_port_selection[input].hps_sync);
479
480 /* prepare switching of tea6415c and saa7111a;
481 have a look at the 'background'-file for further informations */
482 switch (input) {
483 case TUNER:
484 i = SAA7115_COMPOSITE0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300485
Hans Verkuil5325b422009-04-02 11:26:22 -0300486 err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
487
Hans Verkuilb9600742009-01-18 19:59:11 -0300488 /* connect tuner-output always to multicable */
Hans Verkuil5325b422009-04-02 11:26:22 -0300489 if (!err)
490 err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300491 break;
492 case AUX3_YC:
493 /* nothing to be done here. aux3_yc is
494 directly connected to the saa711a */
495 i = SAA7115_SVIDEO1;
496 break;
497 case AUX3:
498 /* nothing to be done here. aux3 is
499 directly connected to the saa711a */
500 i = SAA7115_COMPOSITE1;
501 break;
502 case AUX1:
503 i = SAA7115_COMPOSITE0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300504 err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300505 break;
506 }
507
Hans Verkuil5325b422009-04-02 11:26:22 -0300508 if (err)
509 return err;
Hans Verkuilb9600742009-01-18 19:59:11 -0300510
511 /* switch video in saa7111a */
Hans Verkuil340dde82010-02-20 08:07:51 -0300512 if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
Joe Perches44d0b802011-08-21 19:56:44 -0300513 pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
Hans Verkuilb9600742009-01-18 19:59:11 -0300514
515 /* switch the audio-source only if necessary */
Hans Verkuil5325b422009-04-02 11:26:22 -0300516 if (0 == mxb->cur_mute)
517 tea6420_route_line(mxb, video_audio_connect[input]);
Hans Verkuilb9600742009-01-18 19:59:11 -0300518
519 return 0;
520}
521
522static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
523{
524 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
525 struct mxb *mxb = (struct mxb *)dev->ext_priv;
526
527 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300528 DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
529 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300530 return -EINVAL;
531 }
532
Joe Perches44d0b802011-08-21 19:56:44 -0300533 DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300534
535 memset(t, 0, sizeof(*t));
Hans Verkuilb9600742009-01-18 19:59:11 -0300536 strlcpy(t->name, "TV Tuner", sizeof(t->name));
537 t->type = V4L2_TUNER_ANALOG_TV;
538 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
539 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
540 t->audmode = mxb->cur_mode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300541 return call_all(dev, tuner, g_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300542}
543
544static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
545{
546 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
547 struct mxb *mxb = (struct mxb *)dev->ext_priv;
548
549 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300550 DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
551 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300552 return -EINVAL;
553 }
554
555 mxb->cur_mode = t->audmode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300556 return call_all(dev, tuner, s_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300557}
558
559static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
560{
561 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
562 struct mxb *mxb = (struct mxb *)dev->ext_priv;
563
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300564 if (f->tuner)
Hans Verkuilb9600742009-01-18 19:59:11 -0300565 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300566 *f = mxb->cur_freq;
567
Joe Perches44d0b802011-08-21 19:56:44 -0300568 DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300569 return 0;
570}
571
572static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
573{
574 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
575 struct mxb *mxb = (struct mxb *)dev->ext_priv;
576 struct saa7146_vv *vv = dev->vv_data;
577
578 if (f->tuner)
579 return -EINVAL;
580
581 if (V4L2_TUNER_ANALOG_TV != f->type)
582 return -EINVAL;
583
Joe Perches44d0b802011-08-21 19:56:44 -0300584 DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300585
586 /* tune in desired frequency */
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300587 tuner_call(mxb, tuner, s_frequency, f);
588 /* let the tuner subdev clamp the frequency to the tuner range */
589 tuner_call(mxb, tuner, g_frequency, f);
590 mxb->cur_freq = *f;
591
592 if (mxb->cur_input)
593 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300594
595 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
596 spin_lock(&dev->slock);
597 vv->vbi_fieldcount = 0;
598 spin_unlock(&dev->slock);
599
600 return 0;
601}
602
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300603static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
604{
605 if (a->index >= MXB_AUDIOS)
606 return -EINVAL;
607 *a = mxb_audios[a->index];
608 return 0;
609}
610
Hans Verkuilb9600742009-01-18 19:59:11 -0300611static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
612{
613 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
614 struct mxb *mxb = (struct mxb *)dev->ext_priv;
615
Roel Kluin223ffe52009-05-02 16:38:47 -0300616 if (a->index > MXB_INPUTS) {
Joe Perches44d0b802011-08-21 19:56:44 -0300617 DEB_D("VIDIOC_G_AUDIO %d out of range\n", a->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300618 return -EINVAL;
619 }
620
Joe Perches44d0b802011-08-21 19:56:44 -0300621 DEB_EE("VIDIOC_G_AUDIO %d\n", a->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300622 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
623 return 0;
624}
625
626static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
627{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300628 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
629 struct mxb *mxb = (struct mxb *)dev->ext_priv;
630
Joe Perches44d0b802011-08-21 19:56:44 -0300631 DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300632 if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index))
633 return 0;
634 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300635}
636
637#ifdef CONFIG_VIDEO_ADV_DEBUG
638static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
639{
640 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300641
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300642 return call_all(dev, core, g_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300643}
644
645static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
646{
647 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300648
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300649 return call_all(dev, core, s_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300650}
651#endif
652
Hans Verkuil99cd47bc2011-03-11 19:00:56 -0300653static long vidioc_default(struct file *file, void *fh, bool valid_prio,
654 int cmd, void *arg)
Hans Verkuilb9600742009-01-18 19:59:11 -0300655{
656 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
657 struct mxb *mxb = (struct mxb *)dev->ext_priv;
658
659 switch (cmd) {
660 case MXB_S_AUDIO_CD:
661 {
662 int i = *(int *)arg;
663
664 if (i < 0 || i >= MXB_AUDIOS) {
Joe Perches44d0b802011-08-21 19:56:44 -0300665 DEB_D("invalid argument to MXB_S_AUDIO_CD: i:%d\n", i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300666 return -EINVAL;
667 }
668
Joe Perches44d0b802011-08-21 19:56:44 -0300669 DEB_EE("MXB_S_AUDIO_CD: i:%d\n", i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300670
Hans Verkuil5325b422009-04-02 11:26:22 -0300671 tea6420_route_cd(mxb, i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300672 return 0;
673 }
674 case MXB_S_AUDIO_LINE:
675 {
676 int i = *(int *)arg;
677
678 if (i < 0 || i >= MXB_AUDIOS) {
Joe Perches44d0b802011-08-21 19:56:44 -0300679 DEB_D("invalid argument to MXB_S_AUDIO_LINE: i:%d\n",
680 i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300681 return -EINVAL;
682 }
683
Joe Perches44d0b802011-08-21 19:56:44 -0300684 DEB_EE("MXB_S_AUDIO_LINE: i:%d\n", i);
Hans Verkuil5325b422009-04-02 11:26:22 -0300685 tea6420_route_line(mxb, i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300686 return 0;
687 }
688 default:
689/*
Joe Perches44d0b802011-08-21 19:56:44 -0300690 DEB2(pr_err("does not handle this ioctl\n"));
Hans Verkuilb9600742009-01-18 19:59:11 -0300691*/
Hans Verkuild1c754a2012-04-19 12:36:03 -0300692 return -ENOTTY;
Hans Verkuilb9600742009-01-18 19:59:11 -0300693 }
694 return 0;
695}
696
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697static struct saa7146_ext_vv vv_data;
698
699/* this function only gets called when the probing was successful */
Hans Verkuil26338122008-09-06 17:24:30 -0300700static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
Hans Verkuil03b19302010-03-24 19:09:55 -0300702 struct mxb *mxb;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300703
Joe Perches44d0b802011-08-21 19:56:44 -0300704 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Hans Verkuila8327812008-07-25 10:31:23 -0300706 saa7146_vv_init(dev, &vv_data);
Hans Verkuil03b19302010-03-24 19:09:55 -0300707 if (mxb_probe(dev)) {
708 saa7146_vv_release(dev);
709 return -1;
710 }
711 mxb = (struct mxb *)dev->ext_priv;
712
Hans Verkuilb9600742009-01-18 19:59:11 -0300713 vv_data.ops.vidioc_enum_input = vidioc_enum_input;
714 vv_data.ops.vidioc_g_input = vidioc_g_input;
715 vv_data.ops.vidioc_s_input = vidioc_s_input;
716 vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
717 vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
718 vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
719 vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300720 vv_data.ops.vidioc_enumaudio = vidioc_enumaudio;
Hans Verkuilb9600742009-01-18 19:59:11 -0300721 vv_data.ops.vidioc_g_audio = vidioc_g_audio;
722 vv_data.ops.vidioc_s_audio = vidioc_s_audio;
723#ifdef CONFIG_VIDEO_ADV_DEBUG
724 vv_data.ops.vidioc_g_register = vidioc_g_register;
725 vv_data.ops.vidioc_s_register = vidioc_s_register;
726#endif
727 vv_data.ops.vidioc_default = vidioc_default;
Hans Verkuila8327812008-07-25 10:31:23 -0300728 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300729 ERR("cannot register capture v4l2 device. skipping.\n");
Hans Verkuil03b19302010-03-24 19:09:55 -0300730 saa7146_vv_release(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 return -1;
732 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300735 if (MXB_BOARD_CAN_DO_VBI(dev)) {
736 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300737 ERR("cannot register vbi v4l2 device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 }
739 }
740
Joe Perches44d0b802011-08-21 19:56:44 -0300741 pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
743 mxb_num++;
744 mxb_init_done(dev);
745 return 0;
746}
747
Hans Verkuil26338122008-09-06 17:24:30 -0300748static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749{
Hans Verkuil26338122008-09-06 17:24:30 -0300750 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
Joe Perches44d0b802011-08-21 19:56:44 -0300752 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
Hans Verkuild69f4a52012-04-29 18:59:38 -0300754 /* mute audio on tea6420s */
755 tea6420_route_line(mxb, 6);
756 tea6420_route_cd(mxb, 6);
757
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 saa7146_unregister_device(&mxb->video_dev,dev);
Hans Verkuil26338122008-09-06 17:24:30 -0300759 if (MXB_BOARD_CAN_DO_VBI(dev))
760 saa7146_unregister_device(&mxb->vbi_dev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 saa7146_vv_release(dev);
762
763 mxb_num--;
764
765 i2c_del_adapter(&mxb->i2c_adapter);
766 kfree(mxb);
767
768 return 0;
769}
770
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300771static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300773 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300775 if (V4L2_STD_PAL_I == standard->id) {
Michael Hunold6acaba82006-03-13 21:20:41 -0800776 v4l2_std_id std = V4L2_STD_PAL_I;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300777
Joe Perches44d0b802011-08-21 19:56:44 -0300778 DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300780 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 /* unset the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300782 saa7111a_call(mxb, core, s_gpio, 0);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300783 saa7111a_call(mxb, core, s_std, std);
784 if (mxb->cur_input == 0)
785 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 } else {
Michael Hunold6acaba82006-03-13 21:20:41 -0800787 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300788
Hans Verkuild69f4a52012-04-29 18:59:38 -0300789 if (mxb->cur_input)
790 std = standard->id;
Joe Perches44d0b802011-08-21 19:56:44 -0300791 DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300793 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 /* set the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300795 saa7111a_call(mxb, core, s_gpio, 1);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300796 saa7111a_call(mxb, core, s_std, std);
797 if (mxb->cur_input == 0)
798 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 }
800 return 0;
801}
802
803static struct saa7146_standard standard[] = {
804 {
805 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
806 .v_offset = 0x17, .v_field = 288,
807 .h_offset = 0x14, .h_pixels = 680,
808 .v_max_out = 576, .h_max_out = 768,
809 }, {
810 .name = "PAL-I", .id = V4L2_STD_PAL_I,
811 .v_offset = 0x17, .v_field = 288,
812 .h_offset = 0x14, .h_pixels = 680,
813 .v_max_out = 576, .h_max_out = 768,
814 }, {
815 .name = "NTSC", .id = V4L2_STD_NTSC,
816 .v_offset = 0x16, .v_field = 240,
817 .h_offset = 0x06, .h_pixels = 708,
818 .v_max_out = 480, .h_max_out = 640,
819 }, {
820 .name = "SECAM", .id = V4L2_STD_SECAM,
821 .v_offset = 0x14, .v_field = 288,
822 .h_offset = 0x14, .h_pixels = 720,
823 .v_max_out = 576, .h_max_out = 768,
824 }
825};
826
827static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300828 .ext_priv = "Multimedia eXtension Board",
829 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830};
831
832static struct pci_device_id pci_tbl[] = {
833 {
834 .vendor = PCI_VENDOR_ID_PHILIPS,
835 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
836 .subvendor = 0x0000,
837 .subdevice = 0x0000,
838 .driver_data = (unsigned long)&mxb,
839 }, {
840 .vendor = 0,
841 }
842};
843
844MODULE_DEVICE_TABLE(pci, pci_tbl);
845
846static struct saa7146_ext_vv vv_data = {
847 .inputs = MXB_INPUTS,
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300848 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 .stds = &standard[0],
850 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300851 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852};
853
854static struct saa7146_extension extension = {
855 .name = MXB_IDENTIFIER,
856 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300857
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 .pci_tbl = &pci_tbl[0],
859 .module = THIS_MODULE,
860
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 .attach = mxb_attach,
862 .detach = mxb_detach,
863
864 .irq_mask = 0,
865 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300866};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
868static int __init mxb_init_module(void)
869{
Hans Verkuil26338122008-09-06 17:24:30 -0300870 if (saa7146_register_extension(&extension)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300871 DEB_S("failed to register extension\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 return -ENODEV;
873 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300874
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 return 0;
876}
877
878static void __exit mxb_cleanup_module(void)
879{
880 saa7146_unregister_extension(&extension);
881}
882
883module_init(mxb_init_module);
884module_exit(mxb_cleanup_module);
885
886MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
887MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
888MODULE_LICENSE("GPL");