blob: 91369daad72285005c14701c9dd0052d2e6adece [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 Verkuil4894b702012-05-01 10:12:22 -030066 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030067 V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },
Hans Verkuil4894b702012-05-01 10:12:22 -030068 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030069 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
Hans Verkuil4894b702012-05-01 10:12:22 -030070 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030071 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
Hans Verkuil4894b702012-05-01 10:12:22 -030072 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030073 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 Verkuil4894b702012-05-01 10:12:22 -0300184static void mxb_update_audmode(struct mxb *mxb)
185{
186 struct v4l2_tuner t = {
187 .audmode = mxb->cur_mode,
188 };
189
190 tda9840_call(mxb, tuner, s_tuner, &t);
191}
192
Hans Verkuil66804272012-04-30 04:58:27 -0300193static inline void tea6420_route(struct mxb *mxb, int idx)
Hans Verkuil5325b422009-04-02 11:26:22 -0300194{
195 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
196 TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
197 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
198 TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
Hans Verkuil5325b422009-04-02 11:26:22 -0300199 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
200 TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
201 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
202 TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
203}
204
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205static struct saa7146_extension extension;
206
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300207static int mxb_s_ctrl(struct v4l2_ctrl *ctrl)
208{
209 struct saa7146_dev *dev = container_of(ctrl->handler,
210 struct saa7146_dev, ctrl_handler);
211 struct mxb *mxb = dev->ext_priv;
212
213 switch (ctrl->id) {
214 case V4L2_CID_AUDIO_MUTE:
215 mxb->cur_mute = ctrl->val;
216 /* switch the audio-source */
Hans Verkuil66804272012-04-30 04:58:27 -0300217 tea6420_route(mxb, ctrl->val ? 6 :
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300218 video_audio_connect[mxb->cur_input]);
219 break;
220 default:
221 return -EINVAL;
222 }
223 return 0;
224}
225
226static const struct v4l2_ctrl_ops mxb_ctrl_ops = {
227 .s_ctrl = mxb_s_ctrl,
228};
229
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300230static int mxb_probe(struct saa7146_dev *dev)
Jean Delvare961f80f2008-01-27 18:14:51 +0100231{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300232 struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300233 struct mxb *mxb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300235 v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops,
Hans Verkuil4894b702012-05-01 10:12:22 -0300236 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300237 if (hdl->error)
238 return hdl->error;
Panagiotis Issaris74081872006-01-11 19:40:56 -0200239 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300240 if (mxb == NULL) {
Joe Perches44d0b802011-08-21 19:56:44 -0300241 DEB_D("not enough kernel memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 return -ENOMEM;
243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300245
Hans Verkuil9ebeae52008-09-07 08:32:44 -0300246 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
247
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300249 if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
Joe Perches44d0b802011-08-21 19:56:44 -0300250 DEB_S("cannot register i2c-device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 kfree(mxb);
252 return -EFAULT;
253 }
254
Hans Verkuile6574f22009-04-01 03:57:53 -0300255 mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300256 "saa7111", I2C_SAA7111A, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300257 mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300258 "tea6420", I2C_TEA6420_1, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300259 mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300260 "tea6420", I2C_TEA6420_2, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300261 mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300262 "tea6415c", I2C_TEA6415C, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300263 mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300264 "tda9840", I2C_TDA9840, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300265 mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300266 "tuner", I2C_TUNER, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
268 /* check if all devices are present */
Al Viro5fa12472008-03-29 03:07:38 +0000269 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
270 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
Joe Perches44d0b802011-08-21 19:56:44 -0300271 pr_err("did not find all i2c devices. aborting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 i2c_del_adapter(&mxb->i2c_adapter);
273 kfree(mxb);
274 return -ENODEV;
275 }
276
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300277 /* all devices are present, probe was successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
279 /* we store the pointer in our private data field */
280 dev->ext_priv = mxb;
281
Hans Verkuild69f4a52012-04-29 18:59:38 -0300282 v4l2_ctrl_handler_setup(hdl);
283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 return 0;
285}
286
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300287/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 there are no specs available, so we simply use some init values */
289static struct {
290 int length;
291 char data[9];
292} mxb_saa7740_init[] = {
293 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
294 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
295 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
296 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
297 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
298 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
299 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
300 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
301 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
302 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
303 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
304 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
305 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
306 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
307 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
308 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
309 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
310 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
311 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
312 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
313 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
314 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
315 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
316 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
317 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
318 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
319 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
320 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
321 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
322 { 3, { 0x48, 0x00, 0x01 } },
323 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
324 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
325 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
326 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
327 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
328 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
329 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
330 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
331 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
332 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
333 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
334 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
335 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
336 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
337 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
338 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
339 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300340 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341};
342
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343/* bring hardware to a sane state. this has to be done, just in case someone
344 wants to capture from this device before it has been properly initialized.
345 the capture engine would badly fail, because no valid signal arrives on the
346 saa7146, thus leading to timeouts and stuff. */
347static int mxb_init_done(struct saa7146_dev* dev)
348{
349 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700351 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800352 v4l2_std_id std = V4L2_STD_PAL_BG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 int i = 0, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
Hans Verkuil4894b702012-05-01 10:12:22 -0300356 /* mute audio on tea6420s */
357 tea6420_route(mxb, 6);
358
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 /* select video mode in saa7111a */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300360 saa7111a_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
362 /* select tuner-output on saa7111a */
363 i = 0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300364 saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
Hans Verkuil340dde82010-02-20 08:07:51 -0300365 SAA7111_FMT_CCIR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700368 tun_setup.mode_mask = T_ANALOG_TV;
369 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700370 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300371 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700372 /* tune in some frequency on tuner */
373 mxb->cur_freq.tuner = 0;
374 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
375 mxb->cur_freq.frequency = freq;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300376 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700377
Michael Hunold6acaba82006-03-13 21:20:41 -0800378 /* set a default video standard */
Hans Verkuil4894b702012-05-01 10:12:22 -0300379 /* These two gpio calls set the GPIO pins that control the tda9820 */
380 saa7146_write(dev, GPIO_CTRL, 0x00404050);
381 saa7111a_call(mxb, core, s_gpio, 1);
382 saa7111a_call(mxb, core, s_std, std);
Hans Verkuilf41737e2009-04-01 03:52:39 -0300383 tuner_call(mxb, core, s_std, std);
Michael Hunold6acaba82006-03-13 21:20:41 -0800384
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300385 /* switch to tuner-channel on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300386 tea6415c_call(mxb, video, s_routing, 3, 17, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300388 /* select tuner-output on multicable on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300389 tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300390
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 /* the rest for mxb */
392 mxb->cur_input = 0;
Hans Verkuil66804272012-04-30 04:58:27 -0300393 mxb->cur_audinput = video_audio_connect[mxb->cur_input];
Hans Verkuil4894b702012-05-01 10:12:22 -0300394 mxb->cur_mute = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
396 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Hans Verkuil4894b702012-05-01 10:12:22 -0300397 mxb_update_audmode(mxb);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300398
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300400 on the mxb. if so, we must initialize it. due to lack of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 informations about the saa7740, the values were reverse
402 engineered. */
403 msg.addr = 0x1b;
404 msg.flags = 0;
405 msg.len = mxb_saa7740_init[0].length;
406 msg.buf = &mxb_saa7740_init[0].data[0];
407
Hans Verkuil26338122008-09-06 17:24:30 -0300408 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
409 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 /* the sound arena module is a pos, that's probably the reason
411 philips refuses to hand out a datasheet for the saa7740...
412 it seems to screw up the i2c bus, so we disable fast irq
413 based i2c transactions here and rely on the slow and safe
414 polling method ... */
415 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300416 for (i = 1; ; i++) {
417 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300420 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300422 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
423 if (err != 1) {
Joe Perches44d0b802011-08-21 19:56:44 -0300424 DEB_D("failed to initialize 'sound arena module'\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 goto err;
426 }
427 }
Joe Perches44d0b802011-08-21 19:56:44 -0300428 pr_info("'sound arena module' detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300430err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 /* the rest for saa7146: you should definitely set some basic values
432 for the input-port handling of the saa7146. */
433
434 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300435
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300437 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
438 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
440 /* some stuff is done via direct write to the registers */
441
442 /* this is ugly, but because of the fact that this is completely
443 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300444 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 saa7146_write(dev, DD1_INIT, 0x02000200);
446 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
447
448 return 0;
449}
450
451/* interrupt-handler. this gets called when irq_mask is != 0.
452 it must clear the interrupt-bits in irq_mask it has handled */
453/*
454void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
455{
456 struct mxb* mxb = (struct mxb*)dev->ext_priv;
457}
458*/
459
Hans Verkuilb9600742009-01-18 19:59:11 -0300460static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
461{
Joe Perches44d0b802011-08-21 19:56:44 -0300462 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
Roel Kluin223ffe52009-05-02 16:38:47 -0300463 if (i->index >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300464 return -EINVAL;
465 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
466 return 0;
467}
468
469static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
470{
471 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
472 struct mxb *mxb = (struct mxb *)dev->ext_priv;
473 *i = mxb->cur_input;
474
Joe Perches44d0b802011-08-21 19:56:44 -0300475 DEB_EE("VIDIOC_G_INPUT %d\n", *i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300476 return 0;
477}
478
479static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
480{
481 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
482 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Hans Verkuil5325b422009-04-02 11:26:22 -0300483 int err = 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300484 int i = 0;
485
Joe Perches44d0b802011-08-21 19:56:44 -0300486 DEB_EE("VIDIOC_S_INPUT %d\n", input);
Hans Verkuilb9600742009-01-18 19:59:11 -0300487
Roel Kluinf14a2972009-10-23 07:59:42 -0300488 if (input >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300489 return -EINVAL;
490
491 mxb->cur_input = input;
492
493 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
494 input_port_selection[input].hps_sync);
495
496 /* prepare switching of tea6415c and saa7111a;
497 have a look at the 'background'-file for further informations */
498 switch (input) {
499 case TUNER:
500 i = SAA7115_COMPOSITE0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300501
Hans Verkuil5325b422009-04-02 11:26:22 -0300502 err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
503
Hans Verkuilb9600742009-01-18 19:59:11 -0300504 /* connect tuner-output always to multicable */
Hans Verkuil5325b422009-04-02 11:26:22 -0300505 if (!err)
506 err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300507 break;
508 case AUX3_YC:
509 /* nothing to be done here. aux3_yc is
510 directly connected to the saa711a */
511 i = SAA7115_SVIDEO1;
512 break;
513 case AUX3:
514 /* nothing to be done here. aux3 is
515 directly connected to the saa711a */
516 i = SAA7115_COMPOSITE1;
517 break;
518 case AUX1:
519 i = SAA7115_COMPOSITE0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300520 err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300521 break;
522 }
523
Hans Verkuil5325b422009-04-02 11:26:22 -0300524 if (err)
525 return err;
Hans Verkuilb9600742009-01-18 19:59:11 -0300526
527 /* switch video in saa7111a */
Hans Verkuil340dde82010-02-20 08:07:51 -0300528 if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
Joe Perches44d0b802011-08-21 19:56:44 -0300529 pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
Hans Verkuilb9600742009-01-18 19:59:11 -0300530
Hans Verkuil66804272012-04-30 04:58:27 -0300531 mxb->cur_audinput = video_audio_connect[input];
Hans Verkuilb9600742009-01-18 19:59:11 -0300532 /* switch the audio-source only if necessary */
Hans Verkuil5325b422009-04-02 11:26:22 -0300533 if (0 == mxb->cur_mute)
Hans Verkuil66804272012-04-30 04:58:27 -0300534 tea6420_route(mxb, mxb->cur_audinput);
Hans Verkuil4894b702012-05-01 10:12:22 -0300535 if (mxb->cur_audinput == 0)
536 mxb_update_audmode(mxb);
Hans Verkuilb9600742009-01-18 19:59:11 -0300537
538 return 0;
539}
540
541static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
542{
543 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
544 struct mxb *mxb = (struct mxb *)dev->ext_priv;
545
546 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300547 DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
548 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300549 return -EINVAL;
550 }
551
Joe Perches44d0b802011-08-21 19:56:44 -0300552 DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300553
554 memset(t, 0, sizeof(*t));
Hans Verkuilb9600742009-01-18 19:59:11 -0300555 strlcpy(t->name, "TV Tuner", sizeof(t->name));
556 t->type = V4L2_TUNER_ANALOG_TV;
557 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
558 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
559 t->audmode = mxb->cur_mode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300560 return call_all(dev, tuner, g_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300561}
562
563static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
564{
565 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
566 struct mxb *mxb = (struct mxb *)dev->ext_priv;
567
568 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300569 DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
570 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300571 return -EINVAL;
572 }
573
574 mxb->cur_mode = t->audmode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300575 return call_all(dev, tuner, s_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300576}
577
Hans Verkuil313fce72012-05-01 13:13:49 -0300578static int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *norm)
579{
580 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
581
582 return call_all(dev, video, querystd, norm);
583}
584
Hans Verkuilb9600742009-01-18 19:59:11 -0300585static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
586{
587 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
588 struct mxb *mxb = (struct mxb *)dev->ext_priv;
589
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300590 if (f->tuner)
Hans Verkuilb9600742009-01-18 19:59:11 -0300591 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300592 *f = mxb->cur_freq;
593
Joe Perches44d0b802011-08-21 19:56:44 -0300594 DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300595 return 0;
596}
597
598static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
599{
600 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
601 struct mxb *mxb = (struct mxb *)dev->ext_priv;
602 struct saa7146_vv *vv = dev->vv_data;
603
604 if (f->tuner)
605 return -EINVAL;
606
607 if (V4L2_TUNER_ANALOG_TV != f->type)
608 return -EINVAL;
609
Joe Perches44d0b802011-08-21 19:56:44 -0300610 DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300611
612 /* tune in desired frequency */
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300613 tuner_call(mxb, tuner, s_frequency, f);
614 /* let the tuner subdev clamp the frequency to the tuner range */
615 tuner_call(mxb, tuner, g_frequency, f);
616 mxb->cur_freq = *f;
Hans Verkuil4894b702012-05-01 10:12:22 -0300617 if (mxb->cur_audinput == 0)
618 mxb_update_audmode(mxb);
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300619
620 if (mxb->cur_input)
621 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300622
623 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
624 spin_lock(&dev->slock);
625 vv->vbi_fieldcount = 0;
626 spin_unlock(&dev->slock);
627
628 return 0;
629}
630
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300631static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
632{
633 if (a->index >= MXB_AUDIOS)
634 return -EINVAL;
635 *a = mxb_audios[a->index];
636 return 0;
637}
638
Hans Verkuilb9600742009-01-18 19:59:11 -0300639static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
640{
641 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
642 struct mxb *mxb = (struct mxb *)dev->ext_priv;
643
Hans Verkuil4894b702012-05-01 10:12:22 -0300644 DEB_EE("VIDIOC_G_AUDIO\n");
645 *a = mxb_audios[mxb->cur_audinput];
Hans Verkuilb9600742009-01-18 19:59:11 -0300646 return 0;
647}
648
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300649static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
Hans Verkuilb9600742009-01-18 19:59:11 -0300650{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300651 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
652 struct mxb *mxb = (struct mxb *)dev->ext_priv;
653
Joe Perches44d0b802011-08-21 19:56:44 -0300654 DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
Hans Verkuil66804272012-04-30 04:58:27 -0300655 if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) {
656 if (mxb->cur_audinput != a->index) {
657 mxb->cur_audinput = a->index;
658 tea6420_route(mxb, a->index);
Hans Verkuil4894b702012-05-01 10:12:22 -0300659 if (mxb->cur_audinput == 0)
660 mxb_update_audmode(mxb);
Hans Verkuil66804272012-04-30 04:58:27 -0300661 }
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300662 return 0;
Hans Verkuil66804272012-04-30 04:58:27 -0300663 }
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300664 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300665}
666
667#ifdef CONFIG_VIDEO_ADV_DEBUG
668static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
669{
670 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300671
Hans Verkuilab49ae02012-05-01 12:57:57 -0300672 if (!capable(CAP_SYS_ADMIN))
673 return -EPERM;
674 if (v4l2_chip_match_host(&reg->match)) {
675 reg->val = saa7146_read(dev, reg->reg);
676 reg->size = 4;
677 return 0;
678 }
679 call_all(dev, core, g_register, reg);
680 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300681}
682
683static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
684{
685 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300686
Hans Verkuilab49ae02012-05-01 12:57:57 -0300687 if (!capable(CAP_SYS_ADMIN))
688 return -EPERM;
689 if (v4l2_chip_match_host(&reg->match)) {
690 saa7146_write(dev, reg->reg, reg->val);
691 reg->size = 4;
692 return 0;
693 }
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300694 return call_all(dev, core, s_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300695}
696#endif
697
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698static struct saa7146_ext_vv vv_data;
699
700/* this function only gets called when the probing was successful */
Hans Verkuil26338122008-09-06 17:24:30 -0300701static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702{
Hans Verkuil03b19302010-03-24 19:09:55 -0300703 struct mxb *mxb;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300704
Joe Perches44d0b802011-08-21 19:56:44 -0300705 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Hans Verkuila8327812008-07-25 10:31:23 -0300707 saa7146_vv_init(dev, &vv_data);
Hans Verkuil03b19302010-03-24 19:09:55 -0300708 if (mxb_probe(dev)) {
709 saa7146_vv_release(dev);
710 return -1;
711 }
712 mxb = (struct mxb *)dev->ext_priv;
713
Hans Verkuilab49ae02012-05-01 12:57:57 -0300714 vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
715 vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
716 vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
Hans Verkuil313fce72012-05-01 13:13:49 -0300717 vv_data.vid_ops.vidioc_querystd = vidioc_querystd;
Hans Verkuilab49ae02012-05-01 12:57:57 -0300718 vv_data.vid_ops.vidioc_g_tuner = vidioc_g_tuner;
719 vv_data.vid_ops.vidioc_s_tuner = vidioc_s_tuner;
720 vv_data.vid_ops.vidioc_g_frequency = vidioc_g_frequency;
721 vv_data.vid_ops.vidioc_s_frequency = vidioc_s_frequency;
722 vv_data.vid_ops.vidioc_enumaudio = vidioc_enumaudio;
723 vv_data.vid_ops.vidioc_g_audio = vidioc_g_audio;
724 vv_data.vid_ops.vidioc_s_audio = vidioc_s_audio;
Hans Verkuilb9600742009-01-18 19:59:11 -0300725#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilab49ae02012-05-01 12:57:57 -0300726 vv_data.vid_ops.vidioc_g_register = vidioc_g_register;
727 vv_data.vid_ops.vidioc_s_register = vidioc_s_register;
Hans Verkuilb9600742009-01-18 19:59:11 -0300728#endif
Hans Verkuila8327812008-07-25 10:31:23 -0300729 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300730 ERR("cannot register capture v4l2 device. skipping.\n");
Hans Verkuil03b19302010-03-24 19:09:55 -0300731 saa7146_vv_release(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 return -1;
733 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300734
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300736 if (MXB_BOARD_CAN_DO_VBI(dev)) {
737 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300738 ERR("cannot register vbi v4l2 device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 }
740 }
741
Joe Perches44d0b802011-08-21 19:56:44 -0300742 pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
744 mxb_num++;
745 mxb_init_done(dev);
746 return 0;
747}
748
Hans Verkuil26338122008-09-06 17:24:30 -0300749static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
Hans Verkuil26338122008-09-06 17:24:30 -0300751 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
Joe Perches44d0b802011-08-21 19:56:44 -0300753 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
Hans Verkuild69f4a52012-04-29 18:59:38 -0300755 /* mute audio on tea6420s */
Hans Verkuil66804272012-04-30 04:58:27 -0300756 tea6420_route(mxb, 6);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300757
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");
Hans Verkuil4894b702012-05-01 10:12:22 -0300779 /* These two gpio calls set the GPIO pins that control the tda9820 */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300780 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300781 saa7111a_call(mxb, core, s_gpio, 0);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300782 saa7111a_call(mxb, core, s_std, std);
783 if (mxb->cur_input == 0)
784 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 } else {
Michael Hunold6acaba82006-03-13 21:20:41 -0800786 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300787
Hans Verkuild69f4a52012-04-29 18:59:38 -0300788 if (mxb->cur_input)
789 std = standard->id;
Joe Perches44d0b802011-08-21 19:56:44 -0300790 DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
Hans Verkuil4894b702012-05-01 10:12:22 -0300791 /* These two gpio calls set the GPIO pins that control the tda9820 */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300792 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300793 saa7111a_call(mxb, core, s_gpio, 1);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300794 saa7111a_call(mxb, core, s_std, std);
795 if (mxb->cur_input == 0)
796 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 }
798 return 0;
799}
800
801static struct saa7146_standard standard[] = {
802 {
803 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
804 .v_offset = 0x17, .v_field = 288,
805 .h_offset = 0x14, .h_pixels = 680,
806 .v_max_out = 576, .h_max_out = 768,
807 }, {
808 .name = "PAL-I", .id = V4L2_STD_PAL_I,
809 .v_offset = 0x17, .v_field = 288,
810 .h_offset = 0x14, .h_pixels = 680,
811 .v_max_out = 576, .h_max_out = 768,
812 }, {
813 .name = "NTSC", .id = V4L2_STD_NTSC,
814 .v_offset = 0x16, .v_field = 240,
815 .h_offset = 0x06, .h_pixels = 708,
816 .v_max_out = 480, .h_max_out = 640,
817 }, {
818 .name = "SECAM", .id = V4L2_STD_SECAM,
819 .v_offset = 0x14, .v_field = 288,
820 .h_offset = 0x14, .h_pixels = 720,
821 .v_max_out = 576, .h_max_out = 768,
822 }
823};
824
825static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300826 .ext_priv = "Multimedia eXtension Board",
827 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828};
829
830static struct pci_device_id pci_tbl[] = {
831 {
832 .vendor = PCI_VENDOR_ID_PHILIPS,
833 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
834 .subvendor = 0x0000,
835 .subdevice = 0x0000,
836 .driver_data = (unsigned long)&mxb,
837 }, {
838 .vendor = 0,
839 }
840};
841
842MODULE_DEVICE_TABLE(pci, pci_tbl);
843
844static struct saa7146_ext_vv vv_data = {
845 .inputs = MXB_INPUTS,
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300846 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 .stds = &standard[0],
848 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300849 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850};
851
852static struct saa7146_extension extension = {
Hans Verkuil66804272012-04-30 04:58:27 -0300853 .name = "Multimedia eXtension Board",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300855
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 .pci_tbl = &pci_tbl[0],
857 .module = THIS_MODULE,
858
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 .attach = mxb_attach,
860 .detach = mxb_detach,
861
862 .irq_mask = 0,
863 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300864};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
866static int __init mxb_init_module(void)
867{
Hans Verkuil26338122008-09-06 17:24:30 -0300868 if (saa7146_register_extension(&extension)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300869 DEB_S("failed to register extension\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 return -ENODEV;
871 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300872
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 return 0;
874}
875
876static void __exit mxb_cleanup_module(void)
877{
878 saa7146_unregister_extension(&extension);
879}
880
881module_init(mxb_init_module);
882module_exit(mxb_cleanup_module);
883
884MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
885MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
886MODULE_LICENSE("GPL");