blob: 44440c6208df3fa66c2fbe5c26430ca72658604b [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
Mauro Carvalho Chehab4a3fad72018-01-04 06:47:28 -05006 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
Mauro Carvalho Chehabd647f0b2015-11-13 19:40:07 -020028#include <media/drv-intf/saa7146_vv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <media/tuner.h>
Michael Krufky5e453dc2006-01-09 15:32:31 -020030#include <media/v4l2-common.h>
Mauro Carvalho Chehabb5dcee22015-11-10 12:01:44 -020031#include <media/i2c/saa7115.h>
Paul Gortmaker7a707b82011-07-03 14:03:12 -040032#include <linux/module.h>
Jérémy Lefauree40d14a2017-10-01 15:30:41 -040033#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include "tea6415c.h"
36#include "tea6420.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
Hans Verkuil66804272012-04-30 04:58:27 -030038#define MXB_AUDIOS 6
39
Hans Verkuil1b8dac12009-02-07 11:18:05 -030040#define I2C_SAA7111A 0x24
41#define I2C_TDA9840 0x42
42#define I2C_TEA6415C 0x43
43#define I2C_TEA6420_1 0x4c
44#define I2C_TEA6420_2 0x4d
45#define I2C_TUNER 0x60
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030047#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49/* global variable */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030050static int mxb_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030052/* initial frequence the tuner will be tuned to.
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 in verden (lower saxony, germany) 4148 is a
54 channel called "phoenix" */
55static int freq = 4148;
56module_param(freq, int, 0644);
57MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
58
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030059static int debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070060module_param(debug, int, 0644);
61MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
62
63#define MXB_INPUTS 4
64enum { TUNER, AUX1, AUX3, AUX3_YC };
65
66static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
Hans Verkuil4894b702012-05-01 10:12:22 -030067 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030068 V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },
Hans Verkuil4894b702012-05-01 10:12:22 -030069 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030070 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
Hans Verkuil4894b702012-05-01 10:12:22 -030071 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030072 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
Hans Verkuil4894b702012-05-01 10:12:22 -030073 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030074 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
Linus Torvalds1da177e2005-04-16 15:20:36 -070075};
76
77/* this array holds the information, which port of the saa7146 each
78 input actually uses. the mxb uses port 0 for every input */
79static struct {
80 int hps_source;
81 int hps_sync;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030082} input_port_selection[MXB_INPUTS] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 { 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 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
87};
88
89/* this array holds the information of the audio source (mxb_audios),
90 which has to be switched corresponding to the video source (mxb_channels) */
91static int video_audio_connect[MXB_INPUTS] =
92 { 0, 1, 3, 3 };
93
Hans Verkuil5325b422009-04-02 11:26:22 -030094struct mxb_routing {
95 u32 input;
96 u32 output;
97};
98
Hans Verkuil6e65ca92012-04-29 16:47:47 -030099/* these are the available audio sources, which can switched
100 to the line- and cd-output individually */
101static struct v4l2_audio mxb_audios[MXB_AUDIOS] = {
102 {
103 .index = 0,
104 .name = "Tuner",
105 .capability = V4L2_AUDCAP_STEREO,
106 } , {
107 .index = 1,
108 .name = "AUX1",
109 .capability = V4L2_AUDCAP_STEREO,
110 } , {
111 .index = 2,
112 .name = "AUX2",
113 .capability = V4L2_AUDCAP_STEREO,
114 } , {
115 .index = 3,
116 .name = "AUX3",
117 .capability = V4L2_AUDCAP_STEREO,
118 } , {
119 .index = 4,
120 .name = "Radio (X9)",
121 .capability = V4L2_AUDCAP_STEREO,
122 } , {
123 .index = 5,
124 .name = "CD-ROM (X10)",
125 .capability = V4L2_AUDCAP_STEREO,
126 }
127};
128
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300129/* These are the necessary input-output-pins for bringing one audio source
130 (see above) to the CD-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -0300131static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300132 { { 1, 1 }, { 1, 1 } }, /* Tuner */
133 { { 5, 1 }, { 6, 1 } }, /* AUX 1 */
134 { { 4, 1 }, { 6, 1 } }, /* AUX 2 */
135 { { 3, 1 }, { 6, 1 } }, /* AUX 3 */
136 { { 1, 1 }, { 3, 1 } }, /* Radio */
137 { { 1, 1 }, { 2, 1 } }, /* CD-Rom */
138 { { 6, 1 }, { 6, 1 } } /* Mute */
139};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300141/* These are the necessary input-output-pins for bringing one audio source
142 (see above) to the line-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -0300143static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300144 { { 2, 3 }, { 1, 2 } },
145 { { 5, 3 }, { 6, 2 } },
146 { { 4, 3 }, { 6, 2 } },
147 { { 3, 3 }, { 6, 2 } },
148 { { 2, 3 }, { 3, 2 } },
149 { { 2, 3 }, { 2, 2 } },
150 { { 6, 3 }, { 6, 2 } } /* Mute */
151};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153struct mxb
154{
Hans Verkuil3ae863e2015-03-09 13:33:57 -0300155 struct video_device video_dev;
156 struct video_device vbi_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300158 struct i2c_adapter i2c_adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300160 struct v4l2_subdev *saa7111a;
161 struct v4l2_subdev *tda9840;
162 struct v4l2_subdev *tea6415c;
163 struct v4l2_subdev *tuner;
164 struct v4l2_subdev *tea6420_1;
165 struct v4l2_subdev *tea6420_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167 int cur_mode; /* current audio mode (mono, stereo, ...) */
168 int cur_input; /* current input */
Hans Verkuil66804272012-04-30 04:58:27 -0300169 int cur_audinput; /* current audio input */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 int cur_mute; /* current mute status */
Michael Hunold9d2599d2005-07-27 11:46:00 -0700171 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172};
173
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300174#define saa7111a_call(mxb, o, f, args...) \
175 v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300176#define tda9840_call(mxb, o, f, args...) \
177 v4l2_subdev_call(mxb->tda9840, o, f, ##args)
178#define tea6415c_call(mxb, o, f, args...) \
179 v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
180#define tuner_call(mxb, o, f, args...) \
181 v4l2_subdev_call(mxb->tuner, o, f, ##args)
182#define call_all(dev, o, f, args...) \
183 v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
184
Hans Verkuil4894b702012-05-01 10:12:22 -0300185static void mxb_update_audmode(struct mxb *mxb)
186{
187 struct v4l2_tuner t = {
188 .audmode = mxb->cur_mode,
189 };
190
191 tda9840_call(mxb, tuner, s_tuner, &t);
192}
193
Hans Verkuil66804272012-04-30 04:58:27 -0300194static inline void tea6420_route(struct mxb *mxb, int idx)
Hans Verkuil5325b422009-04-02 11:26:22 -0300195{
196 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
197 TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
198 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
199 TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
Hans Verkuil5325b422009-04-02 11:26:22 -0300200 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
201 TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
202 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
203 TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
204}
205
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206static struct saa7146_extension extension;
207
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300208static int mxb_s_ctrl(struct v4l2_ctrl *ctrl)
209{
210 struct saa7146_dev *dev = container_of(ctrl->handler,
211 struct saa7146_dev, ctrl_handler);
212 struct mxb *mxb = dev->ext_priv;
213
214 switch (ctrl->id) {
215 case V4L2_CID_AUDIO_MUTE:
216 mxb->cur_mute = ctrl->val;
217 /* switch the audio-source */
Hans Verkuil66804272012-04-30 04:58:27 -0300218 tea6420_route(mxb, ctrl->val ? 6 :
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300219 video_audio_connect[mxb->cur_input]);
220 break;
221 default:
222 return -EINVAL;
223 }
224 return 0;
225}
226
227static const struct v4l2_ctrl_ops mxb_ctrl_ops = {
228 .s_ctrl = mxb_s_ctrl,
229};
230
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300231static int mxb_probe(struct saa7146_dev *dev)
Jean Delvare961f80f2008-01-27 18:14:51 +0100232{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300233 struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300234 struct mxb *mxb = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300236 v4l2_ctrl_new_std(hdl, &mxb_ctrl_ops,
Hans Verkuil4894b702012-05-01 10:12:22 -0300237 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300238 if (hdl->error)
239 return hdl->error;
Panagiotis Issaris74081872006-01-11 19:40:56 -0200240 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300241 if (mxb == NULL) {
Joe Perches44d0b802011-08-21 19:56:44 -0300242 DEB_D("not enough kernel memory\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 return -ENOMEM;
244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300246
Hans Verkuil9ebeae52008-09-07 08:32:44 -0300247 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
248
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300250 if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
Joe Perches44d0b802011-08-21 19:56:44 -0300251 DEB_S("cannot register i2c-device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 kfree(mxb);
253 return -EFAULT;
254 }
255
Hans Verkuile6574f22009-04-01 03:57:53 -0300256 mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300257 "saa7111", I2C_SAA7111A, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300258 mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300259 "tea6420", I2C_TEA6420_1, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300260 mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300261 "tea6420", I2C_TEA6420_2, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300262 mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300263 "tea6415c", I2C_TEA6415C, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300264 mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300265 "tda9840", I2C_TDA9840, NULL);
Hans Verkuile6574f22009-04-01 03:57:53 -0300266 mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300267 "tuner", I2C_TUNER, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
269 /* check if all devices are present */
Al Viro5fa12472008-03-29 03:07:38 +0000270 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
271 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
Joe Perches44d0b802011-08-21 19:56:44 -0300272 pr_err("did not find all i2c devices. aborting\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 i2c_del_adapter(&mxb->i2c_adapter);
274 kfree(mxb);
275 return -ENODEV;
276 }
277
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300278 /* all devices are present, probe was successful */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
280 /* we store the pointer in our private data field */
281 dev->ext_priv = mxb;
282
Hans Verkuild69f4a52012-04-29 18:59:38 -0300283 v4l2_ctrl_handler_setup(hdl);
284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 return 0;
286}
287
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300288/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 there are no specs available, so we simply use some init values */
290static struct {
291 int length;
292 char data[9];
293} mxb_saa7740_init[] = {
294 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
295 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
296 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
297 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
298 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
299 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
300 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
301 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
302 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
303 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
304 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
305 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
306 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
307 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
308 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
309 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
310 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
311 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
312 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
313 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
314 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
315 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
316 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
317 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
318 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
319 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
320 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
321 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
322 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
323 { 3, { 0x48, 0x00, 0x01 } },
324 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
325 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
326 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
327 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
328 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
329 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
330 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
331 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
332 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
333 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
334 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
335 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
336 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
337 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
338 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
339 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
340 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300341 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342};
343
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344/* bring hardware to a sane state. this has to be done, just in case someone
345 wants to capture from this device before it has been properly initialized.
346 the capture engine would badly fail, because no valid signal arrives on the
347 saa7146, thus leading to timeouts and stuff. */
348static int mxb_init_done(struct saa7146_dev* dev)
349{
350 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700352 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800353 v4l2_std_id std = V4L2_STD_PAL_BG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
355 int i = 0, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
Hans Verkuil4894b702012-05-01 10:12:22 -0300357 /* mute audio on tea6420s */
358 tea6420_route(mxb, 6);
359
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 /* select video mode in saa7111a */
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300361 saa7111a_call(mxb, video, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362
363 /* select tuner-output on saa7111a */
364 i = 0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300365 saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
Hans Verkuil340dde82010-02-20 08:07:51 -0300366 SAA7111_FMT_CCIR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
368 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700369 tun_setup.mode_mask = T_ANALOG_TV;
370 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700371 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300372 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700373 /* tune in some frequency on tuner */
374 mxb->cur_freq.tuner = 0;
375 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
376 mxb->cur_freq.frequency = freq;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300377 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700378
Michael Hunold6acaba82006-03-13 21:20:41 -0800379 /* set a default video standard */
Hans Verkuil4894b702012-05-01 10:12:22 -0300380 /* These two gpio calls set the GPIO pins that control the tda9820 */
381 saa7146_write(dev, GPIO_CTRL, 0x00404050);
382 saa7111a_call(mxb, core, s_gpio, 1);
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300383 saa7111a_call(mxb, video, s_std, std);
384 tuner_call(mxb, video, s_std, std);
Michael Hunold6acaba82006-03-13 21:20:41 -0800385
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300386 /* switch to tuner-channel on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300387 tea6415c_call(mxb, video, s_routing, 3, 17, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300389 /* select tuner-output on multicable on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300390 tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300391
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 /* the rest for mxb */
393 mxb->cur_input = 0;
Hans Verkuil66804272012-04-30 04:58:27 -0300394 mxb->cur_audinput = video_audio_connect[mxb->cur_input];
Hans Verkuil4894b702012-05-01 10:12:22 -0300395 mxb->cur_mute = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Hans Verkuil4894b702012-05-01 10:12:22 -0300398 mxb_update_audmode(mxb);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300401 on the mxb. if so, we must initialize it. due to lack of
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 informations about the saa7740, the values were reverse
403 engineered. */
404 msg.addr = 0x1b;
405 msg.flags = 0;
406 msg.len = mxb_saa7740_init[0].length;
407 msg.buf = &mxb_saa7740_init[0].data[0];
408
Hans Verkuil26338122008-09-06 17:24:30 -0300409 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
410 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 /* the sound arena module is a pos, that's probably the reason
412 philips refuses to hand out a datasheet for the saa7740...
413 it seems to screw up the i2c bus, so we disable fast irq
414 based i2c transactions here and rely on the slow and safe
415 polling method ... */
416 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300417 for (i = 1; ; i++) {
418 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300421 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300423 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
424 if (err != 1) {
Joe Perches44d0b802011-08-21 19:56:44 -0300425 DEB_D("failed to initialize 'sound arena module'\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 goto err;
427 }
428 }
Joe Perches44d0b802011-08-21 19:56:44 -0300429 pr_info("'sound arena module' detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300431err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 /* the rest for saa7146: you should definitely set some basic values
433 for the input-port handling of the saa7146. */
434
435 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300438 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
439 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
441 /* some stuff is done via direct write to the registers */
442
443 /* this is ugly, but because of the fact that this is completely
444 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300445 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 saa7146_write(dev, DD1_INIT, 0x02000200);
447 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
448
449 return 0;
450}
451
452/* interrupt-handler. this gets called when irq_mask is != 0.
453 it must clear the interrupt-bits in irq_mask it has handled */
454/*
455void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
456{
457 struct mxb* mxb = (struct mxb*)dev->ext_priv;
458}
459*/
460
Hans Verkuilb9600742009-01-18 19:59:11 -0300461static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
462{
Joe Perches44d0b802011-08-21 19:56:44 -0300463 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
Roel Kluin223ffe52009-05-02 16:38:47 -0300464 if (i->index >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300465 return -EINVAL;
466 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
467 return 0;
468}
469
470static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
471{
472 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
473 struct mxb *mxb = (struct mxb *)dev->ext_priv;
474 *i = mxb->cur_input;
475
Joe Perches44d0b802011-08-21 19:56:44 -0300476 DEB_EE("VIDIOC_G_INPUT %d\n", *i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300477 return 0;
478}
479
480static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
481{
482 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
483 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Hans Verkuil5325b422009-04-02 11:26:22 -0300484 int err = 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300485 int i = 0;
486
Joe Perches44d0b802011-08-21 19:56:44 -0300487 DEB_EE("VIDIOC_S_INPUT %d\n", input);
Hans Verkuilb9600742009-01-18 19:59:11 -0300488
Roel Kluinf14a2972009-10-23 07:59:42 -0300489 if (input >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300490 return -EINVAL;
491
492 mxb->cur_input = input;
493
494 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
495 input_port_selection[input].hps_sync);
496
497 /* prepare switching of tea6415c and saa7111a;
498 have a look at the 'background'-file for further informations */
499 switch (input) {
500 case TUNER:
501 i = SAA7115_COMPOSITE0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300502
Hans Verkuil5325b422009-04-02 11:26:22 -0300503 err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
504
Hans Verkuilb9600742009-01-18 19:59:11 -0300505 /* connect tuner-output always to multicable */
Hans Verkuil5325b422009-04-02 11:26:22 -0300506 if (!err)
507 err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300508 break;
509 case AUX3_YC:
510 /* nothing to be done here. aux3_yc is
511 directly connected to the saa711a */
512 i = SAA7115_SVIDEO1;
513 break;
514 case AUX3:
515 /* nothing to be done here. aux3 is
516 directly connected to the saa711a */
517 i = SAA7115_COMPOSITE1;
518 break;
519 case AUX1:
520 i = SAA7115_COMPOSITE0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300521 err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300522 break;
523 }
524
Hans Verkuil5325b422009-04-02 11:26:22 -0300525 if (err)
526 return err;
Hans Verkuilb9600742009-01-18 19:59:11 -0300527
528 /* switch video in saa7111a */
Hans Verkuil340dde82010-02-20 08:07:51 -0300529 if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
Joe Perches44d0b802011-08-21 19:56:44 -0300530 pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
Hans Verkuilb9600742009-01-18 19:59:11 -0300531
Hans Verkuil66804272012-04-30 04:58:27 -0300532 mxb->cur_audinput = video_audio_connect[input];
Hans Verkuilb9600742009-01-18 19:59:11 -0300533 /* switch the audio-source only if necessary */
Hans Verkuil5325b422009-04-02 11:26:22 -0300534 if (0 == mxb->cur_mute)
Hans Verkuil66804272012-04-30 04:58:27 -0300535 tea6420_route(mxb, mxb->cur_audinput);
Hans Verkuil4894b702012-05-01 10:12:22 -0300536 if (mxb->cur_audinput == 0)
537 mxb_update_audmode(mxb);
Hans Verkuilb9600742009-01-18 19:59:11 -0300538
539 return 0;
540}
541
542static int vidioc_g_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_G_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
Joe Perches44d0b802011-08-21 19:56:44 -0300553 DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300554
555 memset(t, 0, sizeof(*t));
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -0400556 strscpy(t->name, "TV Tuner", sizeof(t->name));
Hans Verkuilb9600742009-01-18 19:59:11 -0300557 t->type = V4L2_TUNER_ANALOG_TV;
558 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
559 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
560 t->audmode = mxb->cur_mode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300561 return call_all(dev, tuner, g_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300562}
563
Hans Verkuil2f73c7c2013-03-15 06:10:06 -0300564static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
Hans Verkuilb9600742009-01-18 19:59:11 -0300565{
566 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
567 struct mxb *mxb = (struct mxb *)dev->ext_priv;
568
569 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300570 DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
571 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300572 return -EINVAL;
573 }
574
575 mxb->cur_mode = t->audmode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300576 return call_all(dev, tuner, s_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300577}
578
Hans Verkuil313fce72012-05-01 13:13:49 -0300579static int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *norm)
580{
581 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
582
583 return call_all(dev, video, querystd, norm);
584}
585
Hans Verkuilb9600742009-01-18 19:59:11 -0300586static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
587{
588 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
589 struct mxb *mxb = (struct mxb *)dev->ext_priv;
590
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300591 if (f->tuner)
Hans Verkuilb9600742009-01-18 19:59:11 -0300592 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300593 *f = mxb->cur_freq;
594
Joe Perches44d0b802011-08-21 19:56:44 -0300595 DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300596 return 0;
597}
598
Hans Verkuilb530a442013-03-19 04:09:26 -0300599static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
Hans Verkuilb9600742009-01-18 19:59:11 -0300600{
601 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
602 struct mxb *mxb = (struct mxb *)dev->ext_priv;
603 struct saa7146_vv *vv = dev->vv_data;
604
605 if (f->tuner)
606 return -EINVAL;
607
608 if (V4L2_TUNER_ANALOG_TV != f->type)
609 return -EINVAL;
610
Joe Perches44d0b802011-08-21 19:56:44 -0300611 DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300612
613 /* tune in desired frequency */
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300614 tuner_call(mxb, tuner, s_frequency, f);
615 /* let the tuner subdev clamp the frequency to the tuner range */
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300616 mxb->cur_freq = *f;
Hans Verkuilb530a442013-03-19 04:09:26 -0300617 tuner_call(mxb, tuner, g_frequency, &mxb->cur_freq);
Hans Verkuil4894b702012-05-01 10:12:22 -0300618 if (mxb->cur_audinput == 0)
619 mxb_update_audmode(mxb);
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300620
621 if (mxb->cur_input)
622 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300623
624 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
625 spin_lock(&dev->slock);
626 vv->vbi_fieldcount = 0;
627 spin_unlock(&dev->slock);
628
629 return 0;
630}
631
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300632static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
633{
634 if (a->index >= MXB_AUDIOS)
635 return -EINVAL;
636 *a = mxb_audios[a->index];
637 return 0;
638}
639
Hans Verkuilb9600742009-01-18 19:59:11 -0300640static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
641{
642 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
643 struct mxb *mxb = (struct mxb *)dev->ext_priv;
644
Hans Verkuil4894b702012-05-01 10:12:22 -0300645 DEB_EE("VIDIOC_G_AUDIO\n");
646 *a = mxb_audios[mxb->cur_audinput];
Hans Verkuilb9600742009-01-18 19:59:11 -0300647 return 0;
648}
649
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300650static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
Hans Verkuilb9600742009-01-18 19:59:11 -0300651{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300652 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
653 struct mxb *mxb = (struct mxb *)dev->ext_priv;
654
Joe Perches44d0b802011-08-21 19:56:44 -0300655 DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
Hans Verkuil66804272012-04-30 04:58:27 -0300656 if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) {
657 if (mxb->cur_audinput != a->index) {
658 mxb->cur_audinput = a->index;
659 tea6420_route(mxb, a->index);
Hans Verkuil4894b702012-05-01 10:12:22 -0300660 if (mxb->cur_audinput == 0)
661 mxb_update_audmode(mxb);
Hans Verkuil66804272012-04-30 04:58:27 -0300662 }
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300663 return 0;
Hans Verkuil66804272012-04-30 04:58:27 -0300664 }
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300665 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300666}
667
668#ifdef CONFIG_VIDEO_ADV_DEBUG
669static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
670{
671 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300672
Hans Verkuild2cac162013-05-29 07:00:00 -0300673 if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
674 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -0300675 reg->val = saa7146_read(dev, reg->reg);
676 reg->size = 4;
Hans Verkuilab49ae02012-05-01 12:57:57 -0300677 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300678}
679
Hans Verkuil977ba3b12013-03-24 08:28:46 -0300680static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg)
Hans Verkuilb9600742009-01-18 19:59:11 -0300681{
682 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300683
Hans Verkuild2cac162013-05-29 07:00:00 -0300684 if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
685 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -0300686 saa7146_write(dev, reg->reg, reg->val);
687 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300688}
689#endif
690
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691static struct saa7146_ext_vv vv_data;
692
693/* this function only gets called when the probing was successful */
Hans Verkuil26338122008-09-06 17:24:30 -0300694static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695{
Hans Verkuil03b19302010-03-24 19:09:55 -0300696 struct mxb *mxb;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300697
Joe Perches44d0b802011-08-21 19:56:44 -0300698 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Hans Verkuila8327812008-07-25 10:31:23 -0300700 saa7146_vv_init(dev, &vv_data);
Hans Verkuil03b19302010-03-24 19:09:55 -0300701 if (mxb_probe(dev)) {
702 saa7146_vv_release(dev);
703 return -1;
704 }
705 mxb = (struct mxb *)dev->ext_priv;
706
Hans Verkuilab49ae02012-05-01 12:57:57 -0300707 vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
708 vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
709 vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
Hans Verkuil313fce72012-05-01 13:13:49 -0300710 vv_data.vid_ops.vidioc_querystd = vidioc_querystd;
Hans Verkuilab49ae02012-05-01 12:57:57 -0300711 vv_data.vid_ops.vidioc_g_tuner = vidioc_g_tuner;
712 vv_data.vid_ops.vidioc_s_tuner = vidioc_s_tuner;
713 vv_data.vid_ops.vidioc_g_frequency = vidioc_g_frequency;
714 vv_data.vid_ops.vidioc_s_frequency = vidioc_s_frequency;
715 vv_data.vid_ops.vidioc_enumaudio = vidioc_enumaudio;
716 vv_data.vid_ops.vidioc_g_audio = vidioc_g_audio;
717 vv_data.vid_ops.vidioc_s_audio = vidioc_s_audio;
Hans Verkuilb9600742009-01-18 19:59:11 -0300718#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilab49ae02012-05-01 12:57:57 -0300719 vv_data.vid_ops.vidioc_g_register = vidioc_g_register;
720 vv_data.vid_ops.vidioc_s_register = vidioc_s_register;
Hans Verkuilb9600742009-01-18 19:59:11 -0300721#endif
Hans Verkuila8327812008-07-25 10:31:23 -0300722 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300723 ERR("cannot register capture v4l2 device. skipping.\n");
Hans Verkuil03b19302010-03-24 19:09:55 -0300724 saa7146_vv_release(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 return -1;
726 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300727
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300729 if (MXB_BOARD_CAN_DO_VBI(dev)) {
730 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300731 ERR("cannot register vbi v4l2 device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 }
733 }
734
Joe Perches44d0b802011-08-21 19:56:44 -0300735 pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
737 mxb_num++;
738 mxb_init_done(dev);
739 return 0;
740}
741
Hans Verkuil26338122008-09-06 17:24:30 -0300742static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743{
Hans Verkuil26338122008-09-06 17:24:30 -0300744 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
Joe Perches44d0b802011-08-21 19:56:44 -0300746 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
Hans Verkuild69f4a52012-04-29 18:59:38 -0300748 /* mute audio on tea6420s */
Hans Verkuil66804272012-04-30 04:58:27 -0300749 tea6420_route(mxb, 6);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300750
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 saa7146_unregister_device(&mxb->video_dev,dev);
Hans Verkuil26338122008-09-06 17:24:30 -0300752 if (MXB_BOARD_CAN_DO_VBI(dev))
753 saa7146_unregister_device(&mxb->vbi_dev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 saa7146_vv_release(dev);
755
756 mxb_num--;
757
758 i2c_del_adapter(&mxb->i2c_adapter);
759 kfree(mxb);
760
761 return 0;
762}
763
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300764static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765{
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300766 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300768 if (V4L2_STD_PAL_I == standard->id) {
Michael Hunold6acaba82006-03-13 21:20:41 -0800769 v4l2_std_id std = V4L2_STD_PAL_I;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300770
Joe Perches44d0b802011-08-21 19:56:44 -0300771 DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
Hans Verkuil4894b702012-05-01 10:12:22 -0300772 /* These two gpio calls set the GPIO pins that control the tda9820 */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300773 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300774 saa7111a_call(mxb, core, s_gpio, 0);
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300775 saa7111a_call(mxb, video, s_std, std);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300776 if (mxb->cur_input == 0)
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300777 tuner_call(mxb, video, 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
Hans Verkuild69f4a52012-04-29 18:59:38 -0300781 if (mxb->cur_input)
782 std = standard->id;
Joe Perches44d0b802011-08-21 19:56:44 -0300783 DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\n");
Hans Verkuil4894b702012-05-01 10:12:22 -0300784 /* These two gpio calls set the GPIO pins that control the tda9820 */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300785 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300786 saa7111a_call(mxb, core, s_gpio, 1);
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300787 saa7111a_call(mxb, video, s_std, std);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300788 if (mxb->cur_input == 0)
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300789 tuner_call(mxb, video, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 }
791 return 0;
792}
793
794static struct saa7146_standard standard[] = {
795 {
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500796 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
797 .v_offset = 0x17, .v_field = 288,
798 .h_offset = 0x14, .h_pixels = 680,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 .v_max_out = 576, .h_max_out = 768,
800 }, {
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500801 .name = "PAL-I", .id = V4L2_STD_PAL_I,
802 .v_offset = 0x17, .v_field = 288,
803 .h_offset = 0x14, .h_pixels = 680,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 .v_max_out = 576, .h_max_out = 768,
805 }, {
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500806 .name = "NTSC", .id = V4L2_STD_NTSC,
807 .v_offset = 0x16, .v_field = 240,
808 .h_offset = 0x06, .h_pixels = 708,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 .v_max_out = 480, .h_max_out = 640,
810 }, {
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500811 .name = "SECAM", .id = V4L2_STD_SECAM,
812 .v_offset = 0x14, .v_field = 288,
813 .h_offset = 0x14, .h_pixels = 720,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 .v_max_out = 576, .h_max_out = 768,
815 }
816};
817
818static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300819 .ext_priv = "Multimedia eXtension Board",
820 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821};
822
Arvind Yadav34e7b452017-08-02 13:14:55 -0400823static const struct pci_device_id pci_tbl[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 {
825 .vendor = PCI_VENDOR_ID_PHILIPS,
826 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
827 .subvendor = 0x0000,
828 .subdevice = 0x0000,
829 .driver_data = (unsigned long)&mxb,
830 }, {
831 .vendor = 0,
832 }
833};
834
835MODULE_DEVICE_TABLE(pci, pci_tbl);
836
837static struct saa7146_ext_vv vv_data = {
838 .inputs = MXB_INPUTS,
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300839 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 .stds = &standard[0],
Jérémy Lefauree40d14a2017-10-01 15:30:41 -0400841 .num_stds = ARRAY_SIZE(standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300842 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843};
844
845static struct saa7146_extension extension = {
Hans Verkuil66804272012-04-30 04:58:27 -0300846 .name = "Multimedia eXtension Board",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300848
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 .pci_tbl = &pci_tbl[0],
850 .module = THIS_MODULE,
851
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 .attach = mxb_attach,
853 .detach = mxb_detach,
854
855 .irq_mask = 0,
856 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300857};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858
859static int __init mxb_init_module(void)
860{
Hans Verkuil26338122008-09-06 17:24:30 -0300861 if (saa7146_register_extension(&extension)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300862 DEB_S("failed to register extension\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 return -ENODEV;
864 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300865
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 return 0;
867}
868
869static void __exit mxb_cleanup_module(void)
870{
871 saa7146_unregister_extension(&extension);
872}
873
874module_init(mxb_init_module);
875module_exit(mxb_cleanup_module);
876
877MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
878MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
879MODULE_LICENSE("GPL");