blob: 2bed92ff9476bb868859634705001e420787d97a [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
271 return 0;
272}
273
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300274/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 there are no specs available, so we simply use some init values */
276static struct {
277 int length;
278 char data[9];
279} mxb_saa7740_init[] = {
280 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
281 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
282 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
283 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
284 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
285 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
286 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
287 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
288 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
289 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
290 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
291 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
292 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
293 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
294 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
295 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
296 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
297 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
298 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
299 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
300 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
301 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
302 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
303 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
304 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
305 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
306 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
307 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
308 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
309 { 3, { 0x48, 0x00, 0x01 } },
310 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
311 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
312 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
313 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
314 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
315 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
316 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
317 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
318 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
319 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
320 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
321 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
322 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
323 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
324 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
325 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
326 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300327 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328};
329
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330/* bring hardware to a sane state. this has to be done, just in case someone
331 wants to capture from this device before it has been properly initialized.
332 the capture engine would badly fail, because no valid signal arrives on the
333 saa7146, thus leading to timeouts and stuff. */
334static int mxb_init_done(struct saa7146_dev* dev)
335{
336 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700338 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800339 v4l2_std_id std = V4L2_STD_PAL_BG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
341 int i = 0, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
343 /* select video mode in saa7111a */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300344 saa7111a_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
346 /* select tuner-output on saa7111a */
347 i = 0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300348 saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
Hans Verkuil340dde82010-02-20 08:07:51 -0300349 SAA7111_FMT_CCIR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
351 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700352 tun_setup.mode_mask = T_ANALOG_TV;
353 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700354 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300355 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700356 /* tune in some frequency on tuner */
357 mxb->cur_freq.tuner = 0;
358 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
359 mxb->cur_freq.frequency = freq;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300360 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700361
Michael Hunold6acaba82006-03-13 21:20:41 -0800362 /* set a default video standard */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300363 tuner_call(mxb, core, s_std, std);
Michael Hunold6acaba82006-03-13 21:20:41 -0800364
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 /* mute audio on tea6420s */
Hans Verkuil5325b422009-04-02 11:26:22 -0300366 tea6420_route_line(mxb, 6);
367 tea6420_route_cd(mxb, 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300369 /* switch to tuner-channel on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300370 tea6415c_call(mxb, video, s_routing, 3, 17, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300372 /* select tuner-output on multicable on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300373 tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300374
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 /* the rest for mxb */
376 mxb->cur_input = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 mxb->cur_mute = 1;
378
379 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300382 on the mxb. if so, we must initialize it. due to lack of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 informations about the saa7740, the values were reverse
384 engineered. */
385 msg.addr = 0x1b;
386 msg.flags = 0;
387 msg.len = mxb_saa7740_init[0].length;
388 msg.buf = &mxb_saa7740_init[0].data[0];
389
Hans Verkuil26338122008-09-06 17:24:30 -0300390 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
391 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 /* the sound arena module is a pos, that's probably the reason
393 philips refuses to hand out a datasheet for the saa7740...
394 it seems to screw up the i2c bus, so we disable fast irq
395 based i2c transactions here and rely on the slow and safe
396 polling method ... */
397 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300398 for (i = 1; ; i++) {
399 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300402 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300404 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
405 if (err != 1) {
Joe Perches44d0b802011-08-21 19:56:44 -0300406 DEB_D("failed to initialize 'sound arena module'\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 goto err;
408 }
409 }
Joe Perches44d0b802011-08-21 19:56:44 -0300410 pr_info("'sound arena module' detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300412err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 /* the rest for saa7146: you should definitely set some basic values
414 for the input-port handling of the saa7146. */
415
416 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300417
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300419 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
420 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
422 /* some stuff is done via direct write to the registers */
423
424 /* this is ugly, but because of the fact that this is completely
425 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300426 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 saa7146_write(dev, DD1_INIT, 0x02000200);
428 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
429
430 return 0;
431}
432
433/* interrupt-handler. this gets called when irq_mask is != 0.
434 it must clear the interrupt-bits in irq_mask it has handled */
435/*
436void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
437{
438 struct mxb* mxb = (struct mxb*)dev->ext_priv;
439}
440*/
441
Hans Verkuilb9600742009-01-18 19:59:11 -0300442static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
443{
Joe Perches44d0b802011-08-21 19:56:44 -0300444 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
Roel Kluin223ffe52009-05-02 16:38:47 -0300445 if (i->index >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300446 return -EINVAL;
447 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
448 return 0;
449}
450
451static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
452{
453 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
454 struct mxb *mxb = (struct mxb *)dev->ext_priv;
455 *i = mxb->cur_input;
456
Joe Perches44d0b802011-08-21 19:56:44 -0300457 DEB_EE("VIDIOC_G_INPUT %d\n", *i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300458 return 0;
459}
460
461static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
462{
463 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
464 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Hans Verkuil5325b422009-04-02 11:26:22 -0300465 int err = 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300466 int i = 0;
467
Joe Perches44d0b802011-08-21 19:56:44 -0300468 DEB_EE("VIDIOC_S_INPUT %d\n", input);
Hans Verkuilb9600742009-01-18 19:59:11 -0300469
Roel Kluinf14a2972009-10-23 07:59:42 -0300470 if (input >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300471 return -EINVAL;
472
473 mxb->cur_input = input;
474
475 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
476 input_port_selection[input].hps_sync);
477
478 /* prepare switching of tea6415c and saa7111a;
479 have a look at the 'background'-file for further informations */
480 switch (input) {
481 case TUNER:
482 i = SAA7115_COMPOSITE0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300483
Hans Verkuil5325b422009-04-02 11:26:22 -0300484 err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
485
Hans Verkuilb9600742009-01-18 19:59:11 -0300486 /* connect tuner-output always to multicable */
Hans Verkuil5325b422009-04-02 11:26:22 -0300487 if (!err)
488 err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300489 break;
490 case AUX3_YC:
491 /* nothing to be done here. aux3_yc is
492 directly connected to the saa711a */
493 i = SAA7115_SVIDEO1;
494 break;
495 case AUX3:
496 /* nothing to be done here. aux3 is
497 directly connected to the saa711a */
498 i = SAA7115_COMPOSITE1;
499 break;
500 case AUX1:
501 i = SAA7115_COMPOSITE0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300502 err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300503 break;
504 }
505
Hans Verkuil5325b422009-04-02 11:26:22 -0300506 if (err)
507 return err;
Hans Verkuilb9600742009-01-18 19:59:11 -0300508
509 /* switch video in saa7111a */
Hans Verkuil340dde82010-02-20 08:07:51 -0300510 if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
Joe Perches44d0b802011-08-21 19:56:44 -0300511 pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
Hans Verkuilb9600742009-01-18 19:59:11 -0300512
513 /* switch the audio-source only if necessary */
Hans Verkuil5325b422009-04-02 11:26:22 -0300514 if (0 == mxb->cur_mute)
515 tea6420_route_line(mxb, video_audio_connect[input]);
Hans Verkuilb9600742009-01-18 19:59:11 -0300516
517 return 0;
518}
519
520static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
521{
522 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
523 struct mxb *mxb = (struct mxb *)dev->ext_priv;
524
525 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300526 DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
527 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300528 return -EINVAL;
529 }
530
Joe Perches44d0b802011-08-21 19:56:44 -0300531 DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300532
533 memset(t, 0, sizeof(*t));
Hans Verkuilb9600742009-01-18 19:59:11 -0300534 strlcpy(t->name, "TV Tuner", sizeof(t->name));
535 t->type = V4L2_TUNER_ANALOG_TV;
536 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
537 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
538 t->audmode = mxb->cur_mode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300539 return call_all(dev, tuner, g_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300540}
541
542static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
543{
544 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
545 struct mxb *mxb = (struct mxb *)dev->ext_priv;
546
547 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300548 DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
549 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300550 return -EINVAL;
551 }
552
553 mxb->cur_mode = t->audmode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300554 return call_all(dev, tuner, s_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300555}
556
557static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
558{
559 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
560 struct mxb *mxb = (struct mxb *)dev->ext_priv;
561
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300562 if (f->tuner)
Hans Verkuilb9600742009-01-18 19:59:11 -0300563 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300564 *f = mxb->cur_freq;
565
Joe Perches44d0b802011-08-21 19:56:44 -0300566 DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300567 return 0;
568}
569
570static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
571{
572 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
573 struct mxb *mxb = (struct mxb *)dev->ext_priv;
574 struct saa7146_vv *vv = dev->vv_data;
575
576 if (f->tuner)
577 return -EINVAL;
578
579 if (V4L2_TUNER_ANALOG_TV != f->type)
580 return -EINVAL;
581
Joe Perches44d0b802011-08-21 19:56:44 -0300582 DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300583
584 /* tune in desired frequency */
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300585 tuner_call(mxb, tuner, s_frequency, f);
586 /* let the tuner subdev clamp the frequency to the tuner range */
587 tuner_call(mxb, tuner, g_frequency, f);
588 mxb->cur_freq = *f;
589
590 if (mxb->cur_input)
591 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300592
593 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
594 spin_lock(&dev->slock);
595 vv->vbi_fieldcount = 0;
596 spin_unlock(&dev->slock);
597
598 return 0;
599}
600
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300601static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
602{
603 if (a->index >= MXB_AUDIOS)
604 return -EINVAL;
605 *a = mxb_audios[a->index];
606 return 0;
607}
608
Hans Verkuilb9600742009-01-18 19:59:11 -0300609static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
610{
611 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
612 struct mxb *mxb = (struct mxb *)dev->ext_priv;
613
Roel Kluin223ffe52009-05-02 16:38:47 -0300614 if (a->index > MXB_INPUTS) {
Joe Perches44d0b802011-08-21 19:56:44 -0300615 DEB_D("VIDIOC_G_AUDIO %d out of range\n", a->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300616 return -EINVAL;
617 }
618
Joe Perches44d0b802011-08-21 19:56:44 -0300619 DEB_EE("VIDIOC_G_AUDIO %d\n", a->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300620 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
621 return 0;
622}
623
624static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
625{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300626 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
627 struct mxb *mxb = (struct mxb *)dev->ext_priv;
628
Joe Perches44d0b802011-08-21 19:56:44 -0300629 DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300630 if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index))
631 return 0;
632 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300633}
634
635#ifdef CONFIG_VIDEO_ADV_DEBUG
636static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
637{
638 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300639
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300640 return call_all(dev, core, g_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300641}
642
643static int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
644{
645 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300646
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300647 return call_all(dev, core, s_register, reg);
Hans Verkuilb9600742009-01-18 19:59:11 -0300648}
649#endif
650
Hans Verkuil99cd47bc2011-03-11 19:00:56 -0300651static long vidioc_default(struct file *file, void *fh, bool valid_prio,
652 int cmd, void *arg)
Hans Verkuilb9600742009-01-18 19:59:11 -0300653{
654 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
655 struct mxb *mxb = (struct mxb *)dev->ext_priv;
656
657 switch (cmd) {
658 case MXB_S_AUDIO_CD:
659 {
660 int i = *(int *)arg;
661
662 if (i < 0 || i >= MXB_AUDIOS) {
Joe Perches44d0b802011-08-21 19:56:44 -0300663 DEB_D("invalid argument to MXB_S_AUDIO_CD: i:%d\n", i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300664 return -EINVAL;
665 }
666
Joe Perches44d0b802011-08-21 19:56:44 -0300667 DEB_EE("MXB_S_AUDIO_CD: i:%d\n", i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300668
Hans Verkuil5325b422009-04-02 11:26:22 -0300669 tea6420_route_cd(mxb, i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300670 return 0;
671 }
672 case MXB_S_AUDIO_LINE:
673 {
674 int i = *(int *)arg;
675
676 if (i < 0 || i >= MXB_AUDIOS) {
Joe Perches44d0b802011-08-21 19:56:44 -0300677 DEB_D("invalid argument to MXB_S_AUDIO_LINE: i:%d\n",
678 i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300679 return -EINVAL;
680 }
681
Joe Perches44d0b802011-08-21 19:56:44 -0300682 DEB_EE("MXB_S_AUDIO_LINE: i:%d\n", i);
Hans Verkuil5325b422009-04-02 11:26:22 -0300683 tea6420_route_line(mxb, i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300684 return 0;
685 }
686 default:
687/*
Joe Perches44d0b802011-08-21 19:56:44 -0300688 DEB2(pr_err("does not handle this ioctl\n"));
Hans Verkuilb9600742009-01-18 19:59:11 -0300689*/
Hans Verkuild1c754a2012-04-19 12:36:03 -0300690 return -ENOTTY;
Hans Verkuilb9600742009-01-18 19:59:11 -0300691 }
692 return 0;
693}
694
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695static struct saa7146_ext_vv vv_data;
696
697/* this function only gets called when the probing was successful */
Hans Verkuil26338122008-09-06 17:24:30 -0300698static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
Hans Verkuil03b19302010-03-24 19:09:55 -0300700 struct mxb *mxb;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300701
Joe Perches44d0b802011-08-21 19:56:44 -0300702 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
Hans Verkuila8327812008-07-25 10:31:23 -0300704 saa7146_vv_init(dev, &vv_data);
Hans Verkuil03b19302010-03-24 19:09:55 -0300705 if (mxb_probe(dev)) {
706 saa7146_vv_release(dev);
707 return -1;
708 }
709 mxb = (struct mxb *)dev->ext_priv;
710
Hans Verkuilb9600742009-01-18 19:59:11 -0300711 vv_data.ops.vidioc_enum_input = vidioc_enum_input;
712 vv_data.ops.vidioc_g_input = vidioc_g_input;
713 vv_data.ops.vidioc_s_input = vidioc_s_input;
714 vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
715 vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
716 vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
717 vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300718 vv_data.ops.vidioc_enumaudio = vidioc_enumaudio;
Hans Verkuilb9600742009-01-18 19:59:11 -0300719 vv_data.ops.vidioc_g_audio = vidioc_g_audio;
720 vv_data.ops.vidioc_s_audio = vidioc_s_audio;
721#ifdef CONFIG_VIDEO_ADV_DEBUG
722 vv_data.ops.vidioc_g_register = vidioc_g_register;
723 vv_data.ops.vidioc_s_register = vidioc_s_register;
724#endif
725 vv_data.ops.vidioc_default = vidioc_default;
Hans Verkuila8327812008-07-25 10:31:23 -0300726 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300727 ERR("cannot register capture v4l2 device. skipping.\n");
Hans Verkuil03b19302010-03-24 19:09:55 -0300728 saa7146_vv_release(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 return -1;
730 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300731
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300733 if (MXB_BOARD_CAN_DO_VBI(dev)) {
734 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300735 ERR("cannot register vbi v4l2 device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 }
737 }
738
Joe Perches44d0b802011-08-21 19:56:44 -0300739 pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
741 mxb_num++;
742 mxb_init_done(dev);
743 return 0;
744}
745
Hans Verkuil26338122008-09-06 17:24:30 -0300746static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747{
Hans Verkuil26338122008-09-06 17:24:30 -0300748 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
Joe Perches44d0b802011-08-21 19:56:44 -0300750 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 saa7146_unregister_device(&mxb->video_dev,dev);
Hans Verkuil26338122008-09-06 17:24:30 -0300753 if (MXB_BOARD_CAN_DO_VBI(dev))
754 saa7146_unregister_device(&mxb->vbi_dev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 saa7146_vv_release(dev);
756
757 mxb_num--;
758
759 i2c_del_adapter(&mxb->i2c_adapter);
760 kfree(mxb);
761
762 return 0;
763}
764
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300765static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766{
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300767 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300769 if (V4L2_STD_PAL_I == standard->id) {
Michael Hunold6acaba82006-03-13 21:20:41 -0800770 v4l2_std_id std = V4L2_STD_PAL_I;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300771
Joe Perches44d0b802011-08-21 19:56:44 -0300772 DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300774 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 /* unset the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300776 saa7111a_call(mxb, core, s_gpio, 0);
Hans Verkuilf41737e2009-04-01 03:52:39 -0300777 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 } else {
Michael Hunold6acaba82006-03-13 21:20:41 -0800779 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300780
Joe Perches44d0b802011-08-21 19:56:44 -0300781 DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300783 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 /* set the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300785 saa7111a_call(mxb, core, s_gpio, 1);
Hans Verkuilf41737e2009-04-01 03:52:39 -0300786 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 }
788 return 0;
789}
790
791static struct saa7146_standard standard[] = {
792 {
793 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
794 .v_offset = 0x17, .v_field = 288,
795 .h_offset = 0x14, .h_pixels = 680,
796 .v_max_out = 576, .h_max_out = 768,
797 }, {
798 .name = "PAL-I", .id = V4L2_STD_PAL_I,
799 .v_offset = 0x17, .v_field = 288,
800 .h_offset = 0x14, .h_pixels = 680,
801 .v_max_out = 576, .h_max_out = 768,
802 }, {
803 .name = "NTSC", .id = V4L2_STD_NTSC,
804 .v_offset = 0x16, .v_field = 240,
805 .h_offset = 0x06, .h_pixels = 708,
806 .v_max_out = 480, .h_max_out = 640,
807 }, {
808 .name = "SECAM", .id = V4L2_STD_SECAM,
809 .v_offset = 0x14, .v_field = 288,
810 .h_offset = 0x14, .h_pixels = 720,
811 .v_max_out = 576, .h_max_out = 768,
812 }
813};
814
815static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300816 .ext_priv = "Multimedia eXtension Board",
817 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818};
819
820static struct pci_device_id pci_tbl[] = {
821 {
822 .vendor = PCI_VENDOR_ID_PHILIPS,
823 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
824 .subvendor = 0x0000,
825 .subdevice = 0x0000,
826 .driver_data = (unsigned long)&mxb,
827 }, {
828 .vendor = 0,
829 }
830};
831
832MODULE_DEVICE_TABLE(pci, pci_tbl);
833
834static struct saa7146_ext_vv vv_data = {
835 .inputs = MXB_INPUTS,
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300836 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 .stds = &standard[0],
838 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300839 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840};
841
842static struct saa7146_extension extension = {
843 .name = MXB_IDENTIFIER,
844 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300845
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 .pci_tbl = &pci_tbl[0],
847 .module = THIS_MODULE,
848
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 .attach = mxb_attach,
850 .detach = mxb_detach,
851
852 .irq_mask = 0,
853 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300854};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855
856static int __init mxb_init_module(void)
857{
Hans Verkuil26338122008-09-06 17:24:30 -0300858 if (saa7146_register_extension(&extension)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300859 DEB_S("failed to register extension\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 return -ENODEV;
861 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300862
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 return 0;
864}
865
866static void __exit mxb_cleanup_module(void)
867{
868 saa7146_unregister_extension(&extension);
869}
870
871module_init(mxb_init_module);
872module_exit(mxb_cleanup_module);
873
874MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
875MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
876MODULE_LICENSE("GPL");