blob: f0c3968ac7ebf68098f510d5604a82cfd7c01745 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
33#include "mxb.h"
34#include "tea6415c.h"
35#include "tea6420.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
Hans Verkuil1b8dac12009-02-07 11:18:05 -030037#define I2C_SAA7111A 0x24
38#define I2C_TDA9840 0x42
39#define I2C_TEA6415C 0x43
40#define I2C_TEA6420_1 0x4c
41#define I2C_TEA6420_2 0x4d
42#define I2C_TUNER 0x60
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030044#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46/* global variable */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030047static int mxb_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030049/* initial frequence the tuner will be tuned to.
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 in verden (lower saxony, germany) 4148 is a
51 channel called "phoenix" */
52static int freq = 4148;
53module_param(freq, int, 0644);
54MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
55
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030056static int debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070057module_param(debug, int, 0644);
58MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
59
60#define MXB_INPUTS 4
61enum { TUNER, AUX1, AUX3, AUX3_YC };
62
63static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
Hans Verkuil657f2272010-12-29 14:29:55 -030064 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
65 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
66 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
67 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
Linus Torvalds1da177e2005-04-16 15:20:36 -070068};
69
70/* this array holds the information, which port of the saa7146 each
71 input actually uses. the mxb uses port 0 for every input */
72static struct {
73 int hps_source;
74 int hps_sync;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030075} input_port_selection[MXB_INPUTS] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
77 { 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};
81
82/* this array holds the information of the audio source (mxb_audios),
83 which has to be switched corresponding to the video source (mxb_channels) */
84static int video_audio_connect[MXB_INPUTS] =
85 { 0, 1, 3, 3 };
86
Hans Verkuil5325b422009-04-02 11:26:22 -030087struct mxb_routing {
88 u32 input;
89 u32 output;
90};
91
Hans Verkuil1b8dac12009-02-07 11:18:05 -030092/* These are the necessary input-output-pins for bringing one audio source
93 (see above) to the CD-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -030094static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -030095 { { 1, 1 }, { 1, 1 } }, /* Tuner */
96 { { 5, 1 }, { 6, 1 } }, /* AUX 1 */
97 { { 4, 1 }, { 6, 1 } }, /* AUX 2 */
98 { { 3, 1 }, { 6, 1 } }, /* AUX 3 */
99 { { 1, 1 }, { 3, 1 } }, /* Radio */
100 { { 1, 1 }, { 2, 1 } }, /* CD-Rom */
101 { { 6, 1 }, { 6, 1 } } /* Mute */
102};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300104/* These are the necessary input-output-pins for bringing one audio source
105 (see above) to the line-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -0300106static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300107 { { 2, 3 }, { 1, 2 } },
108 { { 5, 3 }, { 6, 2 } },
109 { { 4, 3 }, { 6, 2 } },
110 { { 3, 3 }, { 6, 2 } },
111 { { 2, 3 }, { 3, 2 } },
112 { { 2, 3 }, { 2, 2 } },
113 { { 6, 3 }, { 6, 2 } } /* Mute */
114};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
116#define MAXCONTROLS 1
117static struct v4l2_queryctrl mxb_controls[] = {
118 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
119};
120
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121struct mxb
122{
123 struct video_device *video_dev;
124 struct video_device *vbi_dev;
125
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300126 struct i2c_adapter i2c_adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300128 struct v4l2_subdev *saa7111a;
129 struct v4l2_subdev *tda9840;
130 struct v4l2_subdev *tea6415c;
131 struct v4l2_subdev *tuner;
132 struct v4l2_subdev *tea6420_1;
133 struct v4l2_subdev *tea6420_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
135 int cur_mode; /* current audio mode (mono, stereo, ...) */
136 int cur_input; /* current input */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 int cur_mute; /* current mute status */
Michael Hunold9d2599d2005-07-27 11:46:00 -0700138 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139};
140
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300141#define saa7111a_call(mxb, o, f, args...) \
142 v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300143#define tda9840_call(mxb, o, f, args...) \
144 v4l2_subdev_call(mxb->tda9840, o, f, ##args)
145#define tea6415c_call(mxb, o, f, args...) \
146 v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
147#define tuner_call(mxb, o, f, args...) \
148 v4l2_subdev_call(mxb->tuner, o, f, ##args)
149#define call_all(dev, o, f, args...) \
150 v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
151
Hans Verkuil5325b422009-04-02 11:26:22 -0300152static inline void tea6420_route_cd(struct mxb *mxb, int idx)
153{
154 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
155 TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
156 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
157 TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
158}
159
160static inline void tea6420_route_line(struct mxb *mxb, int idx)
161{
162 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
163 TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
164 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
165 TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
166}
167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168static struct saa7146_extension extension;
169
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300170static int mxb_probe(struct saa7146_dev *dev)
Jean Delvare961f80f2008-01-27 18:14:51 +0100171{
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300172 struct mxb *mxb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
Panagiotis Issaris74081872006-01-11 19:40:56 -0200174 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300175 if (mxb == NULL) {
Joe Perches44d0b802011-08-21 19:56:44 -0300176 DEB_D("not enough kernel memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 return -ENOMEM;
178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Hans Verkuil9ebeae52008-09-07 08:32:44 -0300180 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
181
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300183 if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
Joe Perches44d0b802011-08-21 19:56:44 -0300184 DEB_S("cannot register i2c-device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 kfree(mxb);
186 return -EFAULT;
187 }
188
Hans Verkuile6574f22009-04-01 03:57:53 -0300189 mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300190 "saa7111", I2C_SAA7111A, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300191 mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300192 "tea6420", I2C_TEA6420_1, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300193 mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300194 "tea6420", I2C_TEA6420_2, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300195 mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300196 "tea6415c", I2C_TEA6415C, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300197 mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300198 "tda9840", I2C_TDA9840, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300199 mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300200 "tuner", I2C_TUNER, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202 /* check if all devices are present */
Al Viro5fa12472008-03-29 03:07:38 +0000203 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
204 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
Joe Perches44d0b802011-08-21 19:56:44 -0300205 pr_err("did not find all i2c devices. aborting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 i2c_del_adapter(&mxb->i2c_adapter);
207 kfree(mxb);
208 return -ENODEV;
209 }
210
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300211 /* all devices are present, probe was successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
213 /* we store the pointer in our private data field */
214 dev->ext_priv = mxb;
215
216 return 0;
217}
218
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300219/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 there are no specs available, so we simply use some init values */
221static struct {
222 int length;
223 char data[9];
224} mxb_saa7740_init[] = {
225 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
226 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
227 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
228 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
229 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
230 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
231 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
232 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
233 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
234 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
235 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
236 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
237 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
238 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
239 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
240 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
241 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
242 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
243 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
244 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
245 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
246 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
247 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
248 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
249 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
250 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
251 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
252 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
253 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
254 { 3, { 0x48, 0x00, 0x01 } },
255 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
256 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
257 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
258 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
259 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
260 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
261 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
262 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
263 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
264 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
265 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
266 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
267 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
268 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
269 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
270 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
271 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300272 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273};
274
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275/* bring hardware to a sane state. this has to be done, just in case someone
276 wants to capture from this device before it has been properly initialized.
277 the capture engine would badly fail, because no valid signal arrives on the
278 saa7146, thus leading to timeouts and stuff. */
279static int mxb_init_done(struct saa7146_dev* dev)
280{
281 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700283 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800284 v4l2_std_id std = V4L2_STD_PAL_BG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
286 int i = 0, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
288 /* select video mode in saa7111a */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300289 saa7111a_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
291 /* select tuner-output on saa7111a */
292 i = 0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300293 saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
Hans Verkuil340dde82010-02-20 08:07:51 -0300294 SAA7111_FMT_CCIR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
296 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700297 tun_setup.mode_mask = T_ANALOG_TV;
298 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700299 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300300 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700301 /* tune in some frequency on tuner */
302 mxb->cur_freq.tuner = 0;
303 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
304 mxb->cur_freq.frequency = freq;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300305 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700306
Michael Hunold6acaba82006-03-13 21:20:41 -0800307 /* set a default video standard */
Hans Verkuilf41737e2009-04-01 03:52:39 -0300308 tuner_call(mxb, core, s_std, std);
Michael Hunold6acaba82006-03-13 21:20:41 -0800309
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 /* mute audio on tea6420s */
Hans Verkuil5325b422009-04-02 11:26:22 -0300311 tea6420_route_line(mxb, 6);
312 tea6420_route_cd(mxb, 6);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300314 /* switch to tuner-channel on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300315 tea6415c_call(mxb, video, s_routing, 3, 17, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300317 /* select tuner-output on multicable on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300318 tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300319
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 /* the rest for mxb */
321 mxb->cur_input = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 mxb->cur_mute = 1;
323
324 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300325
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300327 on the mxb. if so, we must initialize it. due to lack of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 informations about the saa7740, the values were reverse
329 engineered. */
330 msg.addr = 0x1b;
331 msg.flags = 0;
332 msg.len = mxb_saa7740_init[0].length;
333 msg.buf = &mxb_saa7740_init[0].data[0];
334
Hans Verkuil26338122008-09-06 17:24:30 -0300335 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
336 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 /* the sound arena module is a pos, that's probably the reason
338 philips refuses to hand out a datasheet for the saa7740...
339 it seems to screw up the i2c bus, so we disable fast irq
340 based i2c transactions here and rely on the slow and safe
341 polling method ... */
342 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300343 for (i = 1; ; i++) {
344 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300347 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300349 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
350 if (err != 1) {
Joe Perches44d0b802011-08-21 19:56:44 -0300351 DEB_D("failed to initialize 'sound arena module'\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 goto err;
353 }
354 }
Joe Perches44d0b802011-08-21 19:56:44 -0300355 pr_info("'sound arena module' detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300357err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 /* the rest for saa7146: you should definitely set some basic values
359 for the input-port handling of the saa7146. */
360
361 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300362
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300364 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
365 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 /* some stuff is done via direct write to the registers */
368
369 /* this is ugly, but because of the fact that this is completely
370 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300371 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 saa7146_write(dev, DD1_INIT, 0x02000200);
373 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
374
375 return 0;
376}
377
378/* interrupt-handler. this gets called when irq_mask is != 0.
379 it must clear the interrupt-bits in irq_mask it has handled */
380/*
381void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
382{
383 struct mxb* mxb = (struct mxb*)dev->ext_priv;
384}
385*/
386
Hans Verkuilb9600742009-01-18 19:59:11 -0300387static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
388{
389 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
390 int i;
391
392 for (i = MAXCONTROLS - 1; i >= 0; i--) {
393 if (mxb_controls[i].id == qc->id) {
394 *qc = mxb_controls[i];
Joe Perches44d0b802011-08-21 19:56:44 -0300395 DEB_D("VIDIOC_QUERYCTRL %d\n", qc->id);
Hans Verkuilb9600742009-01-18 19:59:11 -0300396 return 0;
397 }
398 }
399 return dev->ext_vv_data->core_ops->vidioc_queryctrl(file, fh, qc);
400}
401
402static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
403{
404 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
405 struct mxb *mxb = (struct mxb *)dev->ext_priv;
406 int i;
407
408 for (i = MAXCONTROLS - 1; i >= 0; i--) {
409 if (mxb_controls[i].id == vc->id)
410 break;
411 }
412
413 if (i < 0)
414 return dev->ext_vv_data->core_ops->vidioc_g_ctrl(file, fh, vc);
415
416 if (vc->id == V4L2_CID_AUDIO_MUTE) {
417 vc->value = mxb->cur_mute;
Joe Perches44d0b802011-08-21 19:56:44 -0300418 DEB_D("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value);
Hans Verkuilb9600742009-01-18 19:59:11 -0300419 return 0;
420 }
421
Joe Perches44d0b802011-08-21 19:56:44 -0300422 DEB_EE("VIDIOC_G_CTRL V4L2_CID_AUDIO_MUTE:%d\n", vc->value);
Hans Verkuilb9600742009-01-18 19:59:11 -0300423 return 0;
424}
425
426static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *vc)
427{
428 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
429 struct mxb *mxb = (struct mxb *)dev->ext_priv;
430 int i = 0;
431
432 for (i = MAXCONTROLS - 1; i >= 0; i--) {
433 if (mxb_controls[i].id == vc->id)
434 break;
435 }
436
437 if (i < 0)
438 return dev->ext_vv_data->core_ops->vidioc_s_ctrl(file, fh, vc);
439
440 if (vc->id == V4L2_CID_AUDIO_MUTE) {
441 mxb->cur_mute = vc->value;
Hans Verkuil5325b422009-04-02 11:26:22 -0300442 /* switch the audio-source */
443 tea6420_route_line(mxb, vc->value ? 6 :
444 video_audio_connect[mxb->cur_input]);
Joe Perches44d0b802011-08-21 19:56:44 -0300445 DEB_EE("VIDIOC_S_CTRL, V4L2_CID_AUDIO_MUTE: %d\n", vc->value);
Hans Verkuilb9600742009-01-18 19:59:11 -0300446 }
447 return 0;
448}
449
450static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
451{
Joe Perches44d0b802011-08-21 19:56:44 -0300452 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
Roel Kluin223ffe52009-05-02 16:38:47 -0300453 if (i->index >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300454 return -EINVAL;
455 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
456 return 0;
457}
458
459static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
460{
461 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
462 struct mxb *mxb = (struct mxb *)dev->ext_priv;
463 *i = mxb->cur_input;
464
Joe Perches44d0b802011-08-21 19:56:44 -0300465 DEB_EE("VIDIOC_G_INPUT %d\n", *i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300466 return 0;
467}
468
469static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
470{
471 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
472 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Hans Verkuil5325b422009-04-02 11:26:22 -0300473 int err = 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300474 int i = 0;
475
Joe Perches44d0b802011-08-21 19:56:44 -0300476 DEB_EE("VIDIOC_S_INPUT %d\n", input);
Hans Verkuilb9600742009-01-18 19:59:11 -0300477
Roel Kluinf14a2972009-10-23 07:59:42 -0300478 if (input >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300479 return -EINVAL;
480
481 mxb->cur_input = input;
482
483 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
484 input_port_selection[input].hps_sync);
485
486 /* prepare switching of tea6415c and saa7111a;
487 have a look at the 'background'-file for further informations */
488 switch (input) {
489 case TUNER:
490 i = SAA7115_COMPOSITE0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300491
Hans Verkuil5325b422009-04-02 11:26:22 -0300492 err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
493
Hans Verkuilb9600742009-01-18 19:59:11 -0300494 /* connect tuner-output always to multicable */
Hans Verkuil5325b422009-04-02 11:26:22 -0300495 if (!err)
496 err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300497 break;
498 case AUX3_YC:
499 /* nothing to be done here. aux3_yc is
500 directly connected to the saa711a */
501 i = SAA7115_SVIDEO1;
502 break;
503 case AUX3:
504 /* nothing to be done here. aux3 is
505 directly connected to the saa711a */
506 i = SAA7115_COMPOSITE1;
507 break;
508 case AUX1:
509 i = SAA7115_COMPOSITE0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300510 err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300511 break;
512 }
513
Hans Verkuil5325b422009-04-02 11:26:22 -0300514 if (err)
515 return err;
Hans Verkuilb9600742009-01-18 19:59:11 -0300516
517 /* switch video in saa7111a */
Hans Verkuil340dde82010-02-20 08:07:51 -0300518 if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
Joe Perches44d0b802011-08-21 19:56:44 -0300519 pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
Hans Verkuilb9600742009-01-18 19:59:11 -0300520
521 /* switch the audio-source only if necessary */
Hans Verkuil5325b422009-04-02 11:26:22 -0300522 if (0 == mxb->cur_mute)
523 tea6420_route_line(mxb, video_audio_connect[input]);
Hans Verkuilb9600742009-01-18 19:59:11 -0300524
525 return 0;
526}
527
528static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
529{
530 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
531 struct mxb *mxb = (struct mxb *)dev->ext_priv;
532
533 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300534 DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
535 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300536 return -EINVAL;
537 }
538
Joe Perches44d0b802011-08-21 19:56:44 -0300539 DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300540
541 memset(t, 0, sizeof(*t));
Hans Verkuilb9600742009-01-18 19:59:11 -0300542 strlcpy(t->name, "TV Tuner", sizeof(t->name));
543 t->type = V4L2_TUNER_ANALOG_TV;
544 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
545 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
546 t->audmode = mxb->cur_mode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300547 return call_all(dev, tuner, g_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300548}
549
550static int vidioc_s_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
551{
552 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
553 struct mxb *mxb = (struct mxb *)dev->ext_priv;
554
555 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300556 DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
557 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300558 return -EINVAL;
559 }
560
561 mxb->cur_mode = t->audmode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300562 return call_all(dev, tuner, s_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300563}
564
565static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
566{
567 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
568 struct mxb *mxb = (struct mxb *)dev->ext_priv;
569
570 if (mxb->cur_input) {
Joe Perches44d0b802011-08-21 19:56:44 -0300571 DEB_D("VIDIOC_G_FREQ: channel %d does not have a tuner!\n",
572 mxb->cur_input);
Hans Verkuilb9600742009-01-18 19:59:11 -0300573 return -EINVAL;
574 }
575
576 *f = mxb->cur_freq;
577
Joe Perches44d0b802011-08-21 19:56:44 -0300578 DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300579 return 0;
580}
581
582static int vidioc_s_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
583{
584 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
585 struct mxb *mxb = (struct mxb *)dev->ext_priv;
586 struct saa7146_vv *vv = dev->vv_data;
587
588 if (f->tuner)
589 return -EINVAL;
590
591 if (V4L2_TUNER_ANALOG_TV != f->type)
592 return -EINVAL;
593
594 if (mxb->cur_input) {
Joe Perches44d0b802011-08-21 19:56:44 -0300595 DEB_D("VIDIOC_S_FREQ: channel %d does not have a tuner!\n",
596 mxb->cur_input);
Hans Verkuilb9600742009-01-18 19:59:11 -0300597 return -EINVAL;
598 }
599
600 mxb->cur_freq = *f;
Joe Perches44d0b802011-08-21 19:56:44 -0300601 DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300602
603 /* tune in desired frequency */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300604 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Hans Verkuilb9600742009-01-18 19:59:11 -0300605
606 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
607 spin_lock(&dev->slock);
608 vv->vbi_fieldcount = 0;
609 spin_unlock(&dev->slock);
610
611 return 0;
612}
613
614static 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 Verkuilb9600742009-01-18 19:59:11 -0300625 memcpy(a, &mxb_audios[video_audio_connect[mxb->cur_input]], sizeof(struct v4l2_audio));
626 return 0;
627}
628
629static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
630{
Joe Perches44d0b802011-08-21 19:56:44 -0300631 DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300632 return 0;
633}
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*/
690 return -ENOIOCTLCMD;
691 }
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_queryctrl = vidioc_queryctrl;
712 vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
713 vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
714 vv_data.ops.vidioc_enum_input = vidioc_enum_input;
715 vv_data.ops.vidioc_g_input = vidioc_g_input;
716 vv_data.ops.vidioc_s_input = vidioc_s_input;
717 vv_data.ops.vidioc_g_tuner = vidioc_g_tuner;
718 vv_data.ops.vidioc_s_tuner = vidioc_s_tuner;
719 vv_data.ops.vidioc_g_frequency = vidioc_g_frequency;
720 vv_data.ops.vidioc_s_frequency = vidioc_s_frequency;
721 vv_data.ops.vidioc_g_audio = vidioc_g_audio;
722 vv_data.ops.vidioc_s_audio = vidioc_s_audio;
723#ifdef CONFIG_VIDEO_ADV_DEBUG
724 vv_data.ops.vidioc_g_register = vidioc_g_register;
725 vv_data.ops.vidioc_s_register = vidioc_s_register;
726#endif
727 vv_data.ops.vidioc_default = vidioc_default;
Hans Verkuila8327812008-07-25 10:31:23 -0300728 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300729 ERR("cannot register capture v4l2 device. skipping.\n");
Hans Verkuil03b19302010-03-24 19:09:55 -0300730 saa7146_vv_release(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 return -1;
732 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300733
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300735 if (MXB_BOARD_CAN_DO_VBI(dev)) {
736 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300737 ERR("cannot register vbi v4l2 device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 }
739 }
740
Joe Perches44d0b802011-08-21 19:56:44 -0300741 pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
743 mxb_num++;
744 mxb_init_done(dev);
745 return 0;
746}
747
Hans Verkuil26338122008-09-06 17:24:30 -0300748static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749{
Hans Verkuil26338122008-09-06 17:24:30 -0300750 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
Joe Perches44d0b802011-08-21 19:56:44 -0300752 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 saa7146_unregister_device(&mxb->video_dev,dev);
Hans Verkuil26338122008-09-06 17:24:30 -0300755 if (MXB_BOARD_CAN_DO_VBI(dev))
756 saa7146_unregister_device(&mxb->vbi_dev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 saa7146_vv_release(dev);
758
759 mxb_num--;
760
761 i2c_del_adapter(&mxb->i2c_adapter);
762 kfree(mxb);
763
764 return 0;
765}
766
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300767static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768{
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300769 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300771 if (V4L2_STD_PAL_I == standard->id) {
Michael Hunold6acaba82006-03-13 21:20:41 -0800772 v4l2_std_id std = V4L2_STD_PAL_I;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300773
Joe Perches44d0b802011-08-21 19:56:44 -0300774 DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300776 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 /* unset the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300778 saa7111a_call(mxb, core, s_gpio, 0);
Hans Verkuilf41737e2009-04-01 03:52:39 -0300779 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 } else {
Michael Hunold6acaba82006-03-13 21:20:41 -0800781 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300782
Joe Perches44d0b802011-08-21 19:56:44 -0300783 DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 /* set the 7146 gpio register -- I don't know what this does exactly */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300785 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 /* set the 7111 gpio register -- I don't know what this does exactly */
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300787 saa7111a_call(mxb, core, s_gpio, 1);
Hans Verkuilf41737e2009-04-01 03:52:39 -0300788 tuner_call(mxb, core, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 }
790 return 0;
791}
792
793static struct saa7146_standard standard[] = {
794 {
795 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
796 .v_offset = 0x17, .v_field = 288,
797 .h_offset = 0x14, .h_pixels = 680,
798 .v_max_out = 576, .h_max_out = 768,
799 }, {
800 .name = "PAL-I", .id = V4L2_STD_PAL_I,
801 .v_offset = 0x17, .v_field = 288,
802 .h_offset = 0x14, .h_pixels = 680,
803 .v_max_out = 576, .h_max_out = 768,
804 }, {
805 .name = "NTSC", .id = V4L2_STD_NTSC,
806 .v_offset = 0x16, .v_field = 240,
807 .h_offset = 0x06, .h_pixels = 708,
808 .v_max_out = 480, .h_max_out = 640,
809 }, {
810 .name = "SECAM", .id = V4L2_STD_SECAM,
811 .v_offset = 0x14, .v_field = 288,
812 .h_offset = 0x14, .h_pixels = 720,
813 .v_max_out = 576, .h_max_out = 768,
814 }
815};
816
817static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300818 .ext_priv = "Multimedia eXtension Board",
819 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820};
821
822static struct pci_device_id pci_tbl[] = {
823 {
824 .vendor = PCI_VENDOR_ID_PHILIPS,
825 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
826 .subvendor = 0x0000,
827 .subdevice = 0x0000,
828 .driver_data = (unsigned long)&mxb,
829 }, {
830 .vendor = 0,
831 }
832};
833
834MODULE_DEVICE_TABLE(pci, pci_tbl);
835
836static struct saa7146_ext_vv vv_data = {
837 .inputs = MXB_INPUTS,
838 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
839 .stds = &standard[0],
840 .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300841 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842};
843
844static struct saa7146_extension extension = {
845 .name = MXB_IDENTIFIER,
846 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300847
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 .pci_tbl = &pci_tbl[0],
849 .module = THIS_MODULE,
850
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 .attach = mxb_attach,
852 .detach = mxb_detach,
853
854 .irq_mask = 0,
855 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300856};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
858static int __init mxb_init_module(void)
859{
Hans Verkuil26338122008-09-06 17:24:30 -0300860 if (saa7146_register_extension(&extension)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300861 DEB_S("failed to register extension\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 return -ENODEV;
863 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300864
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 return 0;
866}
867
868static void __exit mxb_cleanup_module(void)
869{
870 saa7146_unregister_extension(&extension);
871}
872
873module_init(mxb_init_module);
874module_exit(mxb_cleanup_module);
875
876MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
877MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
878MODULE_LICENSE("GPL");