blob: a698c24bea20713ccdc61ef058aa14479dd0a835 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include "tea6415c.h"
35#include "tea6420.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
Hans Verkuil66804272012-04-30 04:58:27 -030037#define MXB_AUDIOS 6
38
Hans Verkuil1b8dac12009-02-07 11:18:05 -030039#define I2C_SAA7111A 0x24
40#define I2C_TDA9840 0x42
41#define I2C_TEA6415C 0x43
42#define I2C_TEA6420_1 0x4c
43#define I2C_TEA6420_2 0x4d
44#define I2C_TUNER 0x60
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030046#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
48/* global variable */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030049static int mxb_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030051/* initial frequence the tuner will be tuned to.
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 in verden (lower saxony, germany) 4148 is a
53 channel called "phoenix" */
54static int freq = 4148;
55module_param(freq, int, 0644);
56MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
57
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030058static int debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070059module_param(debug, int, 0644);
60MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
61
62#define MXB_INPUTS 4
63enum { TUNER, AUX1, AUX3, AUX3_YC };
64
65static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
Hans Verkuil66804272012-04-30 04:58:27 -030066 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 0x2f, 0,
67 V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },
68 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 0x2f, 0,
69 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
70 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x2f, 0,
71 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
72 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 0x2f, 0,
73 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
Linus Torvalds1da177e2005-04-16 15:20:36 -070074};
75
76/* this array holds the information, which port of the saa7146 each
77 input actually uses. the mxb uses port 0 for every input */
78static struct {
79 int hps_source;
80 int hps_sync;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030081} input_port_selection[MXB_INPUTS] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
83 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
84 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
85 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
86};
87
88/* this array holds the information of the audio source (mxb_audios),
89 which has to be switched corresponding to the video source (mxb_channels) */
90static int video_audio_connect[MXB_INPUTS] =
91 { 0, 1, 3, 3 };
92
Hans Verkuil5325b422009-04-02 11:26:22 -030093struct mxb_routing {
94 u32 input;
95 u32 output;
96};
97
Hans Verkuil6e65ca92012-04-29 16:47:47 -030098/* these are the available audio sources, which can switched
99 to the line- and cd-output individually */
100static struct v4l2_audio mxb_audios[MXB_AUDIOS] = {
101 {
102 .index = 0,
103 .name = "Tuner",
104 .capability = V4L2_AUDCAP_STEREO,
105 } , {
106 .index = 1,
107 .name = "AUX1",
108 .capability = V4L2_AUDCAP_STEREO,
109 } , {
110 .index = 2,
111 .name = "AUX2",
112 .capability = V4L2_AUDCAP_STEREO,
113 } , {
114 .index = 3,
115 .name = "AUX3",
116 .capability = V4L2_AUDCAP_STEREO,
117 } , {
118 .index = 4,
119 .name = "Radio (X9)",
120 .capability = V4L2_AUDCAP_STEREO,
121 } , {
122 .index = 5,
123 .name = "CD-ROM (X10)",
124 .capability = V4L2_AUDCAP_STEREO,
125 }
126};
127
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300128/* These are the necessary input-output-pins for bringing one audio source
129 (see above) to the CD-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -0300130static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300131 { { 1, 1 }, { 1, 1 } }, /* Tuner */
132 { { 5, 1 }, { 6, 1 } }, /* AUX 1 */
133 { { 4, 1 }, { 6, 1 } }, /* AUX 2 */
134 { { 3, 1 }, { 6, 1 } }, /* AUX 3 */
135 { { 1, 1 }, { 3, 1 } }, /* Radio */
136 { { 1, 1 }, { 2, 1 } }, /* CD-Rom */
137 { { 6, 1 }, { 6, 1 } } /* Mute */
138};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300140/* These are the necessary input-output-pins for bringing one audio source
141 (see above) to the line-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -0300142static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300143 { { 2, 3 }, { 1, 2 } },
144 { { 5, 3 }, { 6, 2 } },
145 { { 4, 3 }, { 6, 2 } },
146 { { 3, 3 }, { 6, 2 } },
147 { { 2, 3 }, { 3, 2 } },
148 { { 2, 3 }, { 2, 2 } },
149 { { 6, 3 }, { 6, 2 } } /* Mute */
150};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152struct mxb
153{
154 struct video_device *video_dev;
155 struct video_device *vbi_dev;
156
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300157 struct i2c_adapter i2c_adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300159 struct v4l2_subdev *saa7111a;
160 struct v4l2_subdev *tda9840;
161 struct v4l2_subdev *tea6415c;
162 struct v4l2_subdev *tuner;
163 struct v4l2_subdev *tea6420_1;
164 struct v4l2_subdev *tea6420_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
166 int cur_mode; /* current audio mode (mono, stereo, ...) */
167 int cur_input; /* current input */
Hans Verkuil66804272012-04-30 04:58:27 -0300168 int cur_audinput; /* current audio input */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 int cur_mute; /* current mute status */
Michael Hunold9d2599d2005-07-27 11:46:00 -0700170 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171};
172
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300173#define saa7111a_call(mxb, o, f, args...) \
174 v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300175#define tda9840_call(mxb, o, f, args...) \
176 v4l2_subdev_call(mxb->tda9840, o, f, ##args)
177#define tea6415c_call(mxb, o, f, args...) \
178 v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
179#define tuner_call(mxb, o, f, args...) \
180 v4l2_subdev_call(mxb->tuner, o, f, ##args)
181#define call_all(dev, o, f, args...) \
182 v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
183
Hans Verkuil66804272012-04-30 04:58:27 -0300184static inline void tea6420_route(struct mxb *mxb, int idx)
Hans Verkuil5325b422009-04-02 11:26:22 -0300185{
186 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
187 TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
188 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
189 TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
Hans Verkuil5325b422009-04-02 11:26:22 -0300190 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
191 TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
192 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
193 TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
194}
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196static struct saa7146_extension extension;
197
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300198static int mxb_s_ctrl(struct v4l2_ctrl *ctrl)
199{
200 struct saa7146_dev *dev = container_of(ctrl->handler,
201 struct saa7146_dev, ctrl_handler);
202 struct mxb *mxb = dev->ext_priv;
203
204 switch (ctrl->id) {
205 case V4L2_CID_AUDIO_MUTE:
206 mxb->cur_mute = ctrl->val;
207 /* switch the audio-source */
Hans Verkuil66804272012-04-30 04:58:27 -0300208 tea6420_route(mxb, ctrl->val ? 6 :
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300209 video_audio_connect[mxb->cur_input]);
210 break;
211 default:
212 return -EINVAL;
213 }
214 return 0;
215}
216
217static const struct v4l2_ctrl_ops mxb_ctrl_ops = {
218 .s_ctrl = mxb_s_ctrl,
219};
220
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300221static int mxb_probe(struct saa7146_dev *dev)
Jean Delvare961f80f2008-01-27 18:14:51 +0100222{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300223 struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300224 struct mxb *mxb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300226 v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops,
227 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
228 if (hdl->error)
229 return hdl->error;
Panagiotis Issaris74081872006-01-11 19:40:56 -0200230 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300231 if (mxb == NULL) {
Joe Perches44d0b802011-08-21 19:56:44 -0300232 DEB_D("not enough kernel memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 return -ENOMEM;
234 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300236
Hans Verkuil9ebeae52008-09-07 08:32:44 -0300237 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
238
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300240 if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
Joe Perches44d0b802011-08-21 19:56:44 -0300241 DEB_S("cannot register i2c-device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 kfree(mxb);
243 return -EFAULT;
244 }
245
Hans Verkuile6574f22009-04-01 03:57:53 -0300246 mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300247 "saa7111", I2C_SAA7111A, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300248 mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300249 "tea6420", I2C_TEA6420_1, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300250 mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300251 "tea6420", I2C_TEA6420_2, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300252 mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300253 "tea6415c", I2C_TEA6415C, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300254 mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300255 "tda9840", I2C_TDA9840, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300256 mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300257 "tuner", I2C_TUNER, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259 /* check if all devices are present */
Al Viro5fa12472008-03-29 03:07:38 +0000260 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
261 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
Joe Perches44d0b802011-08-21 19:56:44 -0300262 pr_err("did not find all i2c devices. aborting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 i2c_del_adapter(&mxb->i2c_adapter);
264 kfree(mxb);
265 return -ENODEV;
266 }
267
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300268 /* all devices are present, probe was successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
270 /* we store the pointer in our private data field */
271 dev->ext_priv = mxb;
272
Hans Verkuild69f4a52012-04-29 18:59:38 -0300273 v4l2_ctrl_handler_setup(hdl);
274
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 return 0;
276}
277
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300278/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 there are no specs available, so we simply use some init values */
280static struct {
281 int length;
282 char data[9];
283} mxb_saa7740_init[] = {
284 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
285 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
286 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
287 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
288 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
289 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
290 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
291 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
292 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
293 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
294 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
295 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
296 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
297 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
298 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
299 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
300 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
301 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
302 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
303 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
304 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
305 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
306 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
307 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
308 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
309 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
310 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
311 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
312 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
313 { 3, { 0x48, 0x00, 0x01 } },
314 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
315 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
316 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
317 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
318 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
319 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
320 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
321 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
322 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
323 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
324 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
325 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
326 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
327 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
328 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
329 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
330 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300331 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332};
333
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334/* bring hardware to a sane state. this has to be done, just in case someone
335 wants to capture from this device before it has been properly initialized.
336 the capture engine would badly fail, because no valid signal arrives on the
337 saa7146, thus leading to timeouts and stuff. */
338static int mxb_init_done(struct saa7146_dev* dev)
339{
340 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700342 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800343 v4l2_std_id std = V4L2_STD_PAL_BG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
345 int i = 0, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
347 /* select video mode in saa7111a */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300348 saa7111a_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350 /* select tuner-output on saa7111a */
351 i = 0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300352 saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
Hans Verkuil340dde82010-02-20 08:07:51 -0300353 SAA7111_FMT_CCIR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
355 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700356 tun_setup.mode_mask = T_ANALOG_TV;
357 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700358 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300359 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700360 /* tune in some frequency on tuner */
361 mxb->cur_freq.tuner = 0;
362 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
363 mxb->cur_freq.frequency = freq;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300364 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700365
Michael Hunold6acaba82006-03-13 21:20:41 -0800366 /* set a default video standard */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300367 tuner_call(mxb, core, s_std, std);
Michael Hunold6acaba82006-03-13 21:20:41 -0800368
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 /* mute audio on tea6420s */
Hans Verkuil66804272012-04-30 04:58:27 -0300370 tea6420_route(mxb, 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300372 /* switch to tuner-channel on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300373 tea6415c_call(mxb, video, s_routing, 3, 17, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300375 /* select tuner-output on multicable on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300376 tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 /* the rest for mxb */
379 mxb->cur_input = 0;
Hans Verkuil66804272012-04-30 04:58:27 -0300380 mxb->cur_audinput = video_audio_connect[mxb->cur_input];
Hans Verkuild69f4a52012-04-29 18:59:38 -0300381 mxb->cur_mute = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
383 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300384
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300386 on the mxb. if so, we must initialize it. due to lack of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 informations about the saa7740, the values were reverse
388 engineered. */
389 msg.addr = 0x1b;
390 msg.flags = 0;
391 msg.len = mxb_saa7740_init[0].length;
392 msg.buf = &mxb_saa7740_init[0].data[0];
393
Hans Verkuil26338122008-09-06 17:24:30 -0300394 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
395 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 /* the sound arena module is a pos, that's probably the reason
397 philips refuses to hand out a datasheet for the saa7740...
398 it seems to screw up the i2c bus, so we disable fast irq
399 based i2c transactions here and rely on the slow and safe
400 polling method ... */
401 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300402 for (i = 1; ; i++) {
403 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300406 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300408 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
409 if (err != 1) {
Joe Perches44d0b802011-08-21 19:56:44 -0300410 DEB_D("failed to initialize 'sound arena module'\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 goto err;
412 }
413 }
Joe Perches44d0b802011-08-21 19:56:44 -0300414 pr_info("'sound arena module' detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300416err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 /* the rest for saa7146: you should definitely set some basic values
418 for the input-port handling of the saa7146. */
419
420 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300421
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300423 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
424 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
426 /* some stuff is done via direct write to the registers */
427
428 /* this is ugly, but because of the fact that this is completely
429 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300430 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 saa7146_write(dev, DD1_INIT, 0x02000200);
432 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
433
434 return 0;
435}
436
437/* interrupt-handler. this gets called when irq_mask is != 0.
438 it must clear the interrupt-bits in irq_mask it has handled */
439/*
440void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
441{
442 struct mxb* mxb = (struct mxb*)dev->ext_priv;
443}
444*/
445
Hans Verkuilb9600742009-01-18 19:59:11 -0300446static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
447{
Joe Perches44d0b802011-08-21 19:56:44 -0300448 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
Roel Kluin223ffe52009-05-02 16:38:47 -0300449 if (i->index >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300450 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
Joe Perches44d0b802011-08-21 19:56:44 -0300461 DEB_EE("VIDIOC_G_INPUT %d\n", *i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300462 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 Verkuil5325b422009-04-02 11:26:22 -0300469 int err = 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300470 int i = 0;
471
Joe Perches44d0b802011-08-21 19:56:44 -0300472 DEB_EE("VIDIOC_S_INPUT %d\n", input);
Hans Verkuilb9600742009-01-18 19:59:11 -0300473
Roel Kluinf14a2972009-10-23 07:59:42 -0300474 if (input >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300475 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 Verkuilb9600742009-01-18 19:59:11 -0300487
Hans Verkuil5325b422009-04-02 11:26:22 -0300488 err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
489
Hans Verkuilb9600742009-01-18 19:59:11 -0300490 /* connect tuner-output always to multicable */
Hans Verkuil5325b422009-04-02 11:26:22 -0300491 if (!err)
492 err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300493 break;
494 case AUX3_YC:
495 /* nothing to be done here. aux3_yc is
496 directly connected to the saa711a */
497 i = SAA7115_SVIDEO1;
498 break;
499 case AUX3:
500 /* nothing to be done here. aux3 is
501 directly connected to the saa711a */
502 i = SAA7115_COMPOSITE1;
503 break;
504 case AUX1:
505 i = SAA7115_COMPOSITE0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300506 err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300507 break;
508 }
509
Hans Verkuil5325b422009-04-02 11:26:22 -0300510 if (err)
511 return err;
Hans Verkuilb9600742009-01-18 19:59:11 -0300512
513 /* switch video in saa7111a */
Hans Verkuil340dde82010-02-20 08:07:51 -0300514 if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
Joe Perches44d0b802011-08-21 19:56:44 -0300515 pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
Hans Verkuilb9600742009-01-18 19:59:11 -0300516
Hans Verkuil66804272012-04-30 04:58:27 -0300517 mxb->cur_audinput = video_audio_connect[input];
Hans Verkuilb9600742009-01-18 19:59:11 -0300518 /* switch the audio-source only if necessary */
Hans Verkuil5325b422009-04-02 11:26:22 -0300519 if (0 == mxb->cur_mute)
Hans Verkuil66804272012-04-30 04:58:27 -0300520 tea6420_route(mxb, mxb->cur_audinput);
Hans Verkuilb9600742009-01-18 19:59:11 -0300521
522 return 0;
523}
524
525static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
526{
527 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
528 struct mxb *mxb = (struct mxb *)dev->ext_priv;
529
530 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300531 DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
532 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300533 return -EINVAL;
534 }
535
Joe Perches44d0b802011-08-21 19:56:44 -0300536 DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300537
538 memset(t, 0, sizeof(*t));
Hans Verkuilb9600742009-01-18 19:59:11 -0300539 strlcpy(t->name, "TV Tuner", sizeof(t->name));
540 t->type = V4L2_TUNER_ANALOG_TV;
541 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
542 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
543 t->audmode = mxb->cur_mode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300544 return call_all(dev, tuner, g_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300545}
546
547static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
548{
549 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
550 struct mxb *mxb = (struct mxb *)dev->ext_priv;
551
552 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300553 DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
554 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300555 return -EINVAL;
556 }
557
558 mxb->cur_mode = t->audmode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300559 return call_all(dev, tuner, s_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300560}
561
562static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
563{
564 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
565 struct mxb *mxb = (struct mxb *)dev->ext_priv;
566
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300567 if (f->tuner)
Hans Verkuilb9600742009-01-18 19:59:11 -0300568 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300569 *f = mxb->cur_freq;
570
Joe Perches44d0b802011-08-21 19:56:44 -0300571 DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300572 return 0;
573}
574
575static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
576{
577 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
578 struct mxb *mxb = (struct mxb *)dev->ext_priv;
579 struct saa7146_vv *vv = dev->vv_data;
580
581 if (f->tuner)
582 return -EINVAL;
583
584 if (V4L2_TUNER_ANALOG_TV != f->type)
585 return -EINVAL;
586
Joe Perches44d0b802011-08-21 19:56:44 -0300587 DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300588
589 /* tune in desired frequency */
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300590 tuner_call(mxb, tuner, s_frequency, f);
591 /* let the tuner subdev clamp the frequency to the tuner range */
592 tuner_call(mxb, tuner, g_frequency, f);
593 mxb->cur_freq = *f;
594
595 if (mxb->cur_input)
596 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300597
598 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
599 spin_lock(&dev->slock);
600 vv->vbi_fieldcount = 0;
601 spin_unlock(&dev->slock);
602
603 return 0;
604}
605
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300606static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
607{
608 if (a->index >= MXB_AUDIOS)
609 return -EINVAL;
610 *a = mxb_audios[a->index];
611 return 0;
612}
613
Hans Verkuilb9600742009-01-18 19:59:11 -0300614static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
615{
616 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
617 struct mxb *mxb = (struct mxb *)dev->ext_priv;
618
Roel Kluin223ffe52009-05-02 16:38:47 -0300619 if (a->index > MXB_INPUTS) {
Joe Perches44d0b802011-08-21 19:56:44 -0300620 DEB_D("VIDIOC_G_AUDIO %d out of range\n", a->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300621 return -EINVAL;
622 }
623
Joe Perches44d0b802011-08-21 19:56:44 -0300624 DEB_EE("VIDIOC_G_AUDIO %d\n", a->index);
Hans Verkuil66804272012-04-30 04:58:27 -0300625 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_audinput]], sizeof(struct v4l2_audio));
Hans Verkuilb9600742009-01-18 19:59:11 -0300626 return 0;
627}
628
629static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
630{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300631 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
632 struct mxb *mxb = (struct mxb *)dev->ext_priv;
633
Joe Perches44d0b802011-08-21 19:56:44 -0300634 DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
Hans Verkuil66804272012-04-30 04:58:27 -0300635 if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) {
636 if (mxb->cur_audinput != a->index) {
637 mxb->cur_audinput = a->index;
638 tea6420_route(mxb, a->index);
639 }
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300640 return 0;
Hans Verkuil66804272012-04-30 04:58:27 -0300641 }
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300642 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300643}
644
645#ifdef CONFIG_VIDEO_ADV_DEBUG
646static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
647{
648 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300649
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300650 return call_all(dev, core, g_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300651}
652
653static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
654{
655 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300656
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300657 return call_all(dev, core, s_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300658}
659#endif
660
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661static struct saa7146_ext_vv vv_data;
662
663/* this function only gets called when the probing was successful */
Hans Verkuil26338122008-09-06 17:24:30 -0300664static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665{
Hans Verkuil03b19302010-03-24 19:09:55 -0300666 struct mxb *mxb;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300667
Joe Perches44d0b802011-08-21 19:56:44 -0300668 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
Hans Verkuila8327812008-07-25 10:31:23 -0300670 saa7146_vv_init(dev, &vv_data);
Hans Verkuil03b19302010-03-24 19:09:55 -0300671 if (mxb_probe(dev)) {
672 saa7146_vv_release(dev);
673 return -1;
674 }
675 mxb = (struct mxb *)dev->ext_priv;
676
Hans Verkuilb9600742009-01-18 19:59:11 -0300677 vv_data.ops.vidioc_enum_input = vidioc_enum_input;
678 vv_data.ops.vidioc_g_input = vidioc_g_input;
679 vv_data.ops.vidioc_s_input = vidioc_s_input;
680 vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
681 vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
682 vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
683 vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300684 vv_data.ops.vidioc_enumaudio = vidioc_enumaudio;
Hans Verkuilb9600742009-01-18 19:59:11 -0300685 vv_data.ops.vidioc_g_audio = vidioc_g_audio;
686 vv_data.ops.vidioc_s_audio = vidioc_s_audio;
687#ifdef CONFIG_VIDEO_ADV_DEBUG
688 vv_data.ops.vidioc_g_register = vidioc_g_register;
689 vv_data.ops.vidioc_s_register = vidioc_s_register;
690#endif
Hans Verkuila8327812008-07-25 10:31:23 -0300691 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300692 ERR("cannot register capture v4l2 device. skipping.\n");
Hans Verkuil03b19302010-03-24 19:09:55 -0300693 saa7146_vv_release(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 return -1;
695 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300696
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300698 if (MXB_BOARD_CAN_DO_VBI(dev)) {
699 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300700 ERR("cannot register vbi v4l2 device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 }
702 }
703
Joe Perches44d0b802011-08-21 19:56:44 -0300704 pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
706 mxb_num++;
707 mxb_init_done(dev);
708 return 0;
709}
710
Hans Verkuil26338122008-09-06 17:24:30 -0300711static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712{
Hans Verkuil26338122008-09-06 17:24:30 -0300713 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
Joe Perches44d0b802011-08-21 19:56:44 -0300715 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Hans Verkuild69f4a52012-04-29 18:59:38 -0300717 /* mute audio on tea6420s */
Hans Verkuil66804272012-04-30 04:58:27 -0300718 tea6420_route(mxb, 6);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 saa7146_unregister_device(&mxb->video_dev,dev);
Hans Verkuil26338122008-09-06 17:24:30 -0300721 if (MXB_BOARD_CAN_DO_VBI(dev))
722 saa7146_unregister_device(&mxb->vbi_dev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 saa7146_vv_release(dev);
724
725 mxb_num--;
726
727 i2c_del_adapter(&mxb->i2c_adapter);
728 kfree(mxb);
729
730 return 0;
731}
732
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300733static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734{
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300735 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300737 if (V4L2_STD_PAL_I == standard->id) {
Michael Hunold6acaba82006-03-13 21:20:41 -0800738 v4l2_std_id std = V4L2_STD_PAL_I;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300739
Joe Perches44d0b802011-08-21 19:56:44 -0300740 DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300742 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 /* unset the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300744 saa7111a_call(mxb, core, s_gpio, 0);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300745 saa7111a_call(mxb, core, s_std, std);
746 if (mxb->cur_input == 0)
747 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 } else {
Michael Hunold6acaba82006-03-13 21:20:41 -0800749 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300750
Hans Verkuild69f4a52012-04-29 18:59:38 -0300751 if (mxb->cur_input)
752 std = standard->id;
Joe Perches44d0b802011-08-21 19:56:44 -0300753 DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300755 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 /* set the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300757 saa7111a_call(mxb, core, s_gpio, 1);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300758 saa7111a_call(mxb, core, s_std, std);
759 if (mxb->cur_input == 0)
760 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 }
762 return 0;
763}
764
765static struct saa7146_standard standard[] = {
766 {
767 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
768 .v_offset = 0x17, .v_field = 288,
769 .h_offset = 0x14, .h_pixels = 680,
770 .v_max_out = 576, .h_max_out = 768,
771 }, {
772 .name = "PAL-I", .id = V4L2_STD_PAL_I,
773 .v_offset = 0x17, .v_field = 288,
774 .h_offset = 0x14, .h_pixels = 680,
775 .v_max_out = 576, .h_max_out = 768,
776 }, {
777 .name = "NTSC", .id = V4L2_STD_NTSC,
778 .v_offset = 0x16, .v_field = 240,
779 .h_offset = 0x06, .h_pixels = 708,
780 .v_max_out = 480, .h_max_out = 640,
781 }, {
782 .name = "SECAM", .id = V4L2_STD_SECAM,
783 .v_offset = 0x14, .v_field = 288,
784 .h_offset = 0x14, .h_pixels = 720,
785 .v_max_out = 576, .h_max_out = 768,
786 }
787};
788
789static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300790 .ext_priv = "Multimedia eXtension Board",
791 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792};
793
794static struct pci_device_id pci_tbl[] = {
795 {
796 .vendor = PCI_VENDOR_ID_PHILIPS,
797 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
798 .subvendor = 0x0000,
799 .subdevice = 0x0000,
800 .driver_data = (unsigned long)&mxb,
801 }, {
802 .vendor = 0,
803 }
804};
805
806MODULE_DEVICE_TABLE(pci, pci_tbl);
807
808static struct saa7146_ext_vv vv_data = {
809 .inputs = MXB_INPUTS,
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300810 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 .stds = &standard[0],
812 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300813 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814};
815
816static struct saa7146_extension extension = {
Hans Verkuil66804272012-04-30 04:58:27 -0300817 .name = "Multimedia eXtension Board",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 .pci_tbl = &pci_tbl[0],
821 .module = THIS_MODULE,
822
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 .attach = mxb_attach,
824 .detach = mxb_detach,
825
826 .irq_mask = 0,
827 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300828};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
830static int __init mxb_init_module(void)
831{
Hans Verkuil26338122008-09-06 17:24:30 -0300832 if (saa7146_register_extension(&extension)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300833 DEB_S("failed to register extension\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 return -ENODEV;
835 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300836
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 return 0;
838}
839
840static void __exit mxb_cleanup_module(void)
841{
842 saa7146_unregister_extension(&extension);
843}
844
845module_init(mxb_init_module);
846module_exit(mxb_cleanup_module);
847
848MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
849MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
850MODULE_LICENSE("GPL");