blob: e6a71c17566d2b7bf6c92104433bc7bafee51f68 [file] [log] [blame]
Thomas Gleixner74ba9202019-05-20 09:19:02 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 mxb - v4l2 driver for the Multimedia eXtension Board
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -03004
Michael Hunold6acaba82006-03-13 21:20:41 -08005 Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
Linus Torvalds1da177e2005-04-16 15:20:36 -07006
Mauro Carvalho Chehab4a3fad72018-01-04 06:47:28 -05007 Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 for further details about this card.
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -03009
Linus Torvalds1da177e2005-04-16 15:20:36 -070010*/
11
Joe Perches44d0b802011-08-21 19:56:44 -030012#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#define DEBUG_VARIABLE debug
15
Mauro Carvalho Chehabd647f0b2015-11-13 19:40:07 -020016#include <media/drv-intf/saa7146_vv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <media/tuner.h>
Michael Krufky5e453dc2006-01-09 15:32:31 -020018#include <media/v4l2-common.h>
Mauro Carvalho Chehabb5dcee22015-11-10 12:01:44 -020019#include <media/i2c/saa7115.h>
Paul Gortmaker7a707b82011-07-03 14:03:12 -040020#include <linux/module.h>
Jérémy Lefauree40d14a2017-10-01 15:30:41 -040021#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include "tea6415c.h"
24#include "tea6420.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070025
Hans Verkuil66804272012-04-30 04:58:27 -030026#define MXB_AUDIOS 6
27
Hans Verkuil1b8dac12009-02-07 11:18:05 -030028#define I2C_SAA7111A 0x24
29#define I2C_TDA9840 0x42
30#define I2C_TEA6415C 0x43
31#define I2C_TEA6420_1 0x4c
32#define I2C_TEA6420_2 0x4d
33#define I2C_TUNER 0x60
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030035#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
37/* global variable */
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030038static int mxb_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030040/* initial frequence the tuner will be tuned to.
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 in verden (lower saxony, germany) 4148 is a
42 channel called "phoenix" */
43static int freq = 4148;
44module_param(freq, int, 0644);
45MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
46
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030047static int debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -070048module_param(debug, int, 0644);
49MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
50
51#define MXB_INPUTS 4
52enum { TUNER, AUX1, AUX3, AUX3_YC };
53
54static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
Hans Verkuil4894b702012-05-01 10:12:22 -030055 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030056 V4L2_STD_PAL_BG | V4L2_STD_PAL_I, 0, V4L2_IN_CAP_STD },
Hans Verkuil4894b702012-05-01 10:12:22 -030057 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030058 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
Hans Verkuil4894b702012-05-01 10:12:22 -030059 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030060 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
Hans Verkuil4894b702012-05-01 10:12:22 -030061 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 0x3f, 0,
Hans Verkuil66804272012-04-30 04:58:27 -030062 V4L2_STD_ALL, 0, V4L2_IN_CAP_STD },
Linus Torvalds1da177e2005-04-16 15:20:36 -070063};
64
65/* this array holds the information, which port of the saa7146 each
66 input actually uses. the mxb uses port 0 for every input */
67static struct {
68 int hps_source;
69 int hps_sync;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -030070} input_port_selection[MXB_INPUTS] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
72 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
73 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
74 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
75};
76
77/* this array holds the information of the audio source (mxb_audios),
78 which has to be switched corresponding to the video source (mxb_channels) */
79static int video_audio_connect[MXB_INPUTS] =
80 { 0, 1, 3, 3 };
81
Hans Verkuil5325b422009-04-02 11:26:22 -030082struct mxb_routing {
83 u32 input;
84 u32 output;
85};
86
Hans Verkuil6e65ca92012-04-29 16:47:47 -030087/* these are the available audio sources, which can switched
88 to the line- and cd-output individually */
89static struct v4l2_audio mxb_audios[MXB_AUDIOS] = {
90 {
91 .index = 0,
92 .name = "Tuner",
93 .capability = V4L2_AUDCAP_STEREO,
94 } , {
95 .index = 1,
96 .name = "AUX1",
97 .capability = V4L2_AUDCAP_STEREO,
98 } , {
99 .index = 2,
100 .name = "AUX2",
101 .capability = V4L2_AUDCAP_STEREO,
102 } , {
103 .index = 3,
104 .name = "AUX3",
105 .capability = V4L2_AUDCAP_STEREO,
106 } , {
107 .index = 4,
108 .name = "Radio (X9)",
109 .capability = V4L2_AUDCAP_STEREO,
110 } , {
111 .index = 5,
112 .name = "CD-ROM (X10)",
113 .capability = V4L2_AUDCAP_STEREO,
114 }
115};
116
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300117/* These are the necessary input-output-pins for bringing one audio source
118 (see above) to the CD-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -0300119static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300120 { { 1, 1 }, { 1, 1 } }, /* Tuner */
121 { { 5, 1 }, { 6, 1 } }, /* AUX 1 */
122 { { 4, 1 }, { 6, 1 } }, /* AUX 2 */
123 { { 3, 1 }, { 6, 1 } }, /* AUX 3 */
124 { { 1, 1 }, { 3, 1 } }, /* Radio */
125 { { 1, 1 }, { 2, 1 } }, /* CD-Rom */
126 { { 6, 1 }, { 6, 1 } } /* Mute */
127};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
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 line-output. Note that gain is set to 0 in this table. */
Hans Verkuil5325b422009-04-02 11:26:22 -0300131static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300132 { { 2, 3 }, { 1, 2 } },
133 { { 5, 3 }, { 6, 2 } },
134 { { 4, 3 }, { 6, 2 } },
135 { { 3, 3 }, { 6, 2 } },
136 { { 2, 3 }, { 3, 2 } },
137 { { 2, 3 }, { 2, 2 } },
138 { { 6, 3 }, { 6, 2 } } /* Mute */
139};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141struct mxb
142{
Hans Verkuil3ae863e2015-03-09 13:33:57 -0300143 struct video_device video_dev;
144 struct video_device vbi_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300146 struct i2c_adapter i2c_adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300148 struct v4l2_subdev *saa7111a;
149 struct v4l2_subdev *tda9840;
150 struct v4l2_subdev *tea6415c;
151 struct v4l2_subdev *tuner;
152 struct v4l2_subdev *tea6420_1;
153 struct v4l2_subdev *tea6420_2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
155 int cur_mode; /* current audio mode (mono, stereo, ...) */
156 int cur_input; /* current input */
Hans Verkuil66804272012-04-30 04:58:27 -0300157 int cur_audinput; /* current audio input */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 int cur_mute; /* current mute status */
Michael Hunold9d2599d2005-07-27 11:46:00 -0700159 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160};
161
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300162#define saa7111a_call(mxb, o, f, args...) \
163 v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300164#define tda9840_call(mxb, o, f, args...) \
165 v4l2_subdev_call(mxb->tda9840, o, f, ##args)
166#define tea6415c_call(mxb, o, f, args...) \
167 v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
168#define tuner_call(mxb, o, f, args...) \
169 v4l2_subdev_call(mxb->tuner, o, f, ##args)
170#define call_all(dev, o, f, args...) \
171 v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
172
Hans Verkuil4894b702012-05-01 10:12:22 -0300173static void mxb_update_audmode(struct mxb *mxb)
174{
175 struct v4l2_tuner t = {
176 .audmode = mxb->cur_mode,
177 };
178
179 tda9840_call(mxb, tuner, s_tuner, &t);
180}
181
Hans Verkuil66804272012-04-30 04:58:27 -0300182static inline void tea6420_route(struct mxb *mxb, int idx)
Hans Verkuil5325b422009-04-02 11:26:22 -0300183{
184 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
185 TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
186 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
187 TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
Hans Verkuil5325b422009-04-02 11:26:22 -0300188 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 */
Hans Verkuil66804272012-04-30 04:58:27 -0300206 tea6420_route(mxb, ctrl->val ? 6 :
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300207 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,
Hans Verkuil4894b702012-05-01 10:12:22 -0300225 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300226 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
Hans Verkuild69f4a52012-04-29 18:59:38 -0300271 v4l2_ctrl_handler_setup(hdl);
272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 return 0;
274}
275
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300276/* some init data for the saa7740, the so-called 'sound arena module'.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 there are no specs available, so we simply use some init values */
278static struct {
279 int length;
280 char data[9];
281} mxb_saa7740_init[] = {
282 { 3, { 0x80, 0x00, 0x00 } },{ 3, { 0x80, 0x89, 0x00 } },
283 { 3, { 0x80, 0xb0, 0x0a } },{ 3, { 0x00, 0x00, 0x00 } },
284 { 3, { 0x49, 0x00, 0x00 } },{ 3, { 0x4a, 0x00, 0x00 } },
285 { 3, { 0x4b, 0x00, 0x00 } },{ 3, { 0x4c, 0x00, 0x00 } },
286 { 3, { 0x4d, 0x00, 0x00 } },{ 3, { 0x4e, 0x00, 0x00 } },
287 { 3, { 0x4f, 0x00, 0x00 } },{ 3, { 0x50, 0x00, 0x00 } },
288 { 3, { 0x51, 0x00, 0x00 } },{ 3, { 0x52, 0x00, 0x00 } },
289 { 3, { 0x53, 0x00, 0x00 } },{ 3, { 0x54, 0x00, 0x00 } },
290 { 3, { 0x55, 0x00, 0x00 } },{ 3, { 0x56, 0x00, 0x00 } },
291 { 3, { 0x57, 0x00, 0x00 } },{ 3, { 0x58, 0x00, 0x00 } },
292 { 3, { 0x59, 0x00, 0x00 } },{ 3, { 0x5a, 0x00, 0x00 } },
293 { 3, { 0x5b, 0x00, 0x00 } },{ 3, { 0x5c, 0x00, 0x00 } },
294 { 3, { 0x5d, 0x00, 0x00 } },{ 3, { 0x5e, 0x00, 0x00 } },
295 { 3, { 0x5f, 0x00, 0x00 } },{ 3, { 0x60, 0x00, 0x00 } },
296 { 3, { 0x61, 0x00, 0x00 } },{ 3, { 0x62, 0x00, 0x00 } },
297 { 3, { 0x63, 0x00, 0x00 } },{ 3, { 0x64, 0x00, 0x00 } },
298 { 3, { 0x65, 0x00, 0x00 } },{ 3, { 0x66, 0x00, 0x00 } },
299 { 3, { 0x67, 0x00, 0x00 } },{ 3, { 0x68, 0x00, 0x00 } },
300 { 3, { 0x69, 0x00, 0x00 } },{ 3, { 0x6a, 0x00, 0x00 } },
301 { 3, { 0x6b, 0x00, 0x00 } },{ 3, { 0x6c, 0x00, 0x00 } },
302 { 3, { 0x6d, 0x00, 0x00 } },{ 3, { 0x6e, 0x00, 0x00 } },
303 { 3, { 0x6f, 0x00, 0x00 } },{ 3, { 0x70, 0x00, 0x00 } },
304 { 3, { 0x71, 0x00, 0x00 } },{ 3, { 0x72, 0x00, 0x00 } },
305 { 3, { 0x73, 0x00, 0x00 } },{ 3, { 0x74, 0x00, 0x00 } },
306 { 3, { 0x75, 0x00, 0x00 } },{ 3, { 0x76, 0x00, 0x00 } },
307 { 3, { 0x77, 0x00, 0x00 } },{ 3, { 0x41, 0x00, 0x42 } },
308 { 3, { 0x42, 0x10, 0x42 } },{ 3, { 0x43, 0x20, 0x42 } },
309 { 3, { 0x44, 0x30, 0x42 } },{ 3, { 0x45, 0x00, 0x01 } },
310 { 3, { 0x46, 0x00, 0x01 } },{ 3, { 0x47, 0x00, 0x01 } },
311 { 3, { 0x48, 0x00, 0x01 } },
312 { 9, { 0x01, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
313 { 9, { 0x21, 0x03, 0xc5, 0x5c, 0x7a, 0x85, 0x01, 0x00, 0x54 } },
314 { 9, { 0x09, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
315 { 9, { 0x29, 0x0b, 0xb4, 0x6b, 0x74, 0x85, 0x95, 0x00, 0x34 } },
316 { 9, { 0x11, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
317 { 9, { 0x31, 0x17, 0x43, 0x62, 0x68, 0x89, 0xd1, 0xff, 0xb0 } },
318 { 9, { 0x19, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
319 { 9, { 0x39, 0x20, 0x62, 0x51, 0x5a, 0x95, 0x19, 0x01, 0x50 } },
320 { 9, { 0x05, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
321 { 9, { 0x25, 0x3e, 0xd2, 0x69, 0x4e, 0x9a, 0x51, 0x00, 0xf0 } },
322 { 9, { 0x0d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
323 { 9, { 0x2d, 0x3d, 0xa1, 0x40, 0x7d, 0x9f, 0x29, 0xfe, 0x14 } },
324 { 9, { 0x15, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
325 { 9, { 0x35, 0x73, 0xa1, 0x50, 0x5d, 0xa6, 0xf5, 0xfe, 0x38 } },
326 { 9, { 0x1d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
327 { 9, { 0x3d, 0xed, 0xd0, 0x68, 0x29, 0xb4, 0xe1, 0x00, 0xb8 } },
328 { 3, { 0x80, 0xb3, 0x0a } },
Hans Verkuil26338122008-09-06 17:24:30 -0300329 {-1, { 0 } }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330};
331
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332/* bring hardware to a sane state. this has to be done, just in case someone
333 wants to capture from this device before it has been properly initialized.
334 the capture engine would badly fail, because no valid signal arrives on the
335 saa7146, thus leading to timeouts and stuff. */
336static int mxb_init_done(struct saa7146_dev* dev)
337{
338 struct mxb* mxb = (struct mxb*)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 struct i2c_msg msg;
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700340 struct tuner_setup tun_setup;
Michael Hunold6acaba82006-03-13 21:20:41 -0800341 v4l2_std_id std = V4L2_STD_PAL_BG;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
343 int i = 0, err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
Hans Verkuil4894b702012-05-01 10:12:22 -0300345 /* mute audio on tea6420s */
346 tea6420_route(mxb, 6);
347
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 /* select video mode in saa7111a */
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300349 saa7111a_call(mxb, video, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
351 /* select tuner-output on saa7111a */
352 i = 0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300353 saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
Hans Verkuil340dde82010-02-20 08:07:51 -0300354 SAA7111_FMT_CCIR, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
356 /* select a tuner type */
Mauro Carvalho Chehab85369df2005-07-12 13:58:59 -0700357 tun_setup.mode_mask = T_ANALOG_TV;
358 tun_setup.addr = ADDR_UNSET;
Michael Hunold9d2599d2005-07-27 11:46:00 -0700359 tun_setup.type = TUNER_PHILIPS_PAL;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300360 tuner_call(mxb, tuner, s_type_addr, &tun_setup);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700361 /* tune in some frequency on tuner */
362 mxb->cur_freq.tuner = 0;
363 mxb->cur_freq.type = V4L2_TUNER_ANALOG_TV;
364 mxb->cur_freq.frequency = freq;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300365 tuner_call(mxb, tuner, s_frequency, &mxb->cur_freq);
Michael Hunold9d2599d2005-07-27 11:46:00 -0700366
Michael Hunold6acaba82006-03-13 21:20:41 -0800367 /* set a default video standard */
Hans Verkuil4894b702012-05-01 10:12:22 -0300368 /* These two gpio calls set the GPIO pins that control the tda9820 */
369 saa7146_write(dev, GPIO_CTRL, 0x00404050);
370 saa7111a_call(mxb, core, s_gpio, 1);
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300371 saa7111a_call(mxb, video, s_std, std);
372 tuner_call(mxb, video, s_std, std);
Michael Hunold6acaba82006-03-13 21:20:41 -0800373
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300374 /* switch to tuner-channel on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300375 tea6415c_call(mxb, video, s_routing, 3, 17, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300377 /* select tuner-output on multicable on tea6415c */
Hans Verkuil5325b422009-04-02 11:26:22 -0300378 tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 /* the rest for mxb */
381 mxb->cur_input = 0;
Hans Verkuil66804272012-04-30 04:58:27 -0300382 mxb->cur_audinput = video_audio_connect[mxb->cur_input];
Hans Verkuil4894b702012-05-01 10:12:22 -0300383 mxb->cur_mute = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
385 mxb->cur_mode = V4L2_TUNER_MODE_STEREO;
Hans Verkuil4894b702012-05-01 10:12:22 -0300386 mxb_update_audmode(mxb);
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300387
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 /* check if the saa7740 (aka 'sound arena module') is present
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300389 on the mxb. if so, we must initialize it. due to lack of
Mauro Carvalho Chehab16790552019-02-18 14:28:59 -0500390 information about the saa7740, the values were reverse
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 engineered. */
392 msg.addr = 0x1b;
393 msg.flags = 0;
394 msg.len = mxb_saa7740_init[0].length;
395 msg.buf = &mxb_saa7740_init[0].data[0];
396
Hans Verkuil26338122008-09-06 17:24:30 -0300397 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
398 if (err == 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 /* the sound arena module is a pos, that's probably the reason
400 philips refuses to hand out a datasheet for the saa7740...
401 it seems to screw up the i2c bus, so we disable fast irq
402 based i2c transactions here and rely on the slow and safe
403 polling method ... */
404 extension.flags &= ~SAA7146_USE_I2C_IRQ;
Hans Verkuil26338122008-09-06 17:24:30 -0300405 for (i = 1; ; i++) {
406 if (-1 == mxb_saa7740_init[i].length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300409 msg.len = mxb_saa7740_init[i].length;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 msg.buf = &mxb_saa7740_init[i].data[0];
Hans Verkuil26338122008-09-06 17:24:30 -0300411 err = i2c_transfer(&mxb->i2c_adapter, &msg, 1);
412 if (err != 1) {
Joe Perches44d0b802011-08-21 19:56:44 -0300413 DEB_D("failed to initialize 'sound arena module'\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 goto err;
415 }
416 }
Joe Perches44d0b802011-08-21 19:56:44 -0300417 pr_info("'sound arena module' detected\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300419err:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 /* the rest for saa7146: you should definitely set some basic values
421 for the input-port handling of the saa7146. */
422
423 /* ext->saa has been filled by the core driver */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300424
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 /* some stuff is done via variables */
Hans Verkuil26338122008-09-06 17:24:30 -0300426 saa7146_set_hps_source_and_sync(dev, input_port_selection[mxb->cur_input].hps_source,
427 input_port_selection[mxb->cur_input].hps_sync);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 /* some stuff is done via direct write to the registers */
430
431 /* this is ugly, but because of the fact that this is completely
432 hardware dependend, it should be done directly... */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300433 saa7146_write(dev, DD1_STREAM_B, 0x00000000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 saa7146_write(dev, DD1_INIT, 0x02000200);
435 saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
436
437 return 0;
438}
439
440/* interrupt-handler. this gets called when irq_mask is != 0.
441 it must clear the interrupt-bits in irq_mask it has handled */
442/*
443void mxb_irq_bh(struct saa7146_dev* dev, u32* irq_mask)
444{
445 struct mxb* mxb = (struct mxb*)dev->ext_priv;
446}
447*/
448
Hans Verkuilb9600742009-01-18 19:59:11 -0300449static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
450{
Joe Perches44d0b802011-08-21 19:56:44 -0300451 DEB_EE("VIDIOC_ENUMINPUT %d\n", i->index);
Roel Kluin223ffe52009-05-02 16:38:47 -0300452 if (i->index >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300453 return -EINVAL;
454 memcpy(i, &mxb_inputs[i->index], sizeof(struct v4l2_input));
455 return 0;
456}
457
458static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
459{
460 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
461 struct mxb *mxb = (struct mxb *)dev->ext_priv;
462 *i = mxb->cur_input;
463
Joe Perches44d0b802011-08-21 19:56:44 -0300464 DEB_EE("VIDIOC_G_INPUT %d\n", *i);
Hans Verkuilb9600742009-01-18 19:59:11 -0300465 return 0;
466}
467
468static int vidioc_s_input(struct file *file, void *fh, unsigned int input)
469{
470 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
471 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Hans Verkuil5325b422009-04-02 11:26:22 -0300472 int err = 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300473 int i = 0;
474
Joe Perches44d0b802011-08-21 19:56:44 -0300475 DEB_EE("VIDIOC_S_INPUT %d\n", input);
Hans Verkuilb9600742009-01-18 19:59:11 -0300476
Roel Kluinf14a2972009-10-23 07:59:42 -0300477 if (input >= MXB_INPUTS)
Hans Verkuilb9600742009-01-18 19:59:11 -0300478 return -EINVAL;
479
480 mxb->cur_input = input;
481
482 saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source,
483 input_port_selection[input].hps_sync);
484
485 /* prepare switching of tea6415c and saa7111a;
Mauro Carvalho Chehab16790552019-02-18 14:28:59 -0500486 have a look at the 'background'-file for further information */
Hans Verkuilb9600742009-01-18 19:59:11 -0300487 switch (input) {
488 case TUNER:
489 i = SAA7115_COMPOSITE0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300490
Hans Verkuil5325b422009-04-02 11:26:22 -0300491 err = tea6415c_call(mxb, video, s_routing, 3, 17, 0);
492
Hans Verkuilb9600742009-01-18 19:59:11 -0300493 /* connect tuner-output always to multicable */
Hans Verkuil5325b422009-04-02 11:26:22 -0300494 if (!err)
495 err = tea6415c_call(mxb, video, s_routing, 3, 13, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300496 break;
497 case AUX3_YC:
498 /* nothing to be done here. aux3_yc is
499 directly connected to the saa711a */
500 i = SAA7115_SVIDEO1;
501 break;
502 case AUX3:
503 /* nothing to be done here. aux3 is
504 directly connected to the saa711a */
505 i = SAA7115_COMPOSITE1;
506 break;
507 case AUX1:
508 i = SAA7115_COMPOSITE0;
Hans Verkuil5325b422009-04-02 11:26:22 -0300509 err = tea6415c_call(mxb, video, s_routing, 1, 17, 0);
Hans Verkuilb9600742009-01-18 19:59:11 -0300510 break;
511 }
512
Hans Verkuil5325b422009-04-02 11:26:22 -0300513 if (err)
514 return err;
Hans Verkuilb9600742009-01-18 19:59:11 -0300515
516 /* switch video in saa7111a */
Hans Verkuil340dde82010-02-20 08:07:51 -0300517 if (saa7111a_call(mxb, video, s_routing, i, SAA7111_FMT_CCIR, 0))
Joe Perches44d0b802011-08-21 19:56:44 -0300518 pr_err("VIDIOC_S_INPUT: could not address saa7111a\n");
Hans Verkuilb9600742009-01-18 19:59:11 -0300519
Hans Verkuil66804272012-04-30 04:58:27 -0300520 mxb->cur_audinput = video_audio_connect[input];
Hans Verkuilb9600742009-01-18 19:59:11 -0300521 /* switch the audio-source only if necessary */
Hans Verkuil5325b422009-04-02 11:26:22 -0300522 if (0 == mxb->cur_mute)
Hans Verkuil66804272012-04-30 04:58:27 -0300523 tea6420_route(mxb, mxb->cur_audinput);
Hans Verkuil4894b702012-05-01 10:12:22 -0300524 if (mxb->cur_audinput == 0)
525 mxb_update_audmode(mxb);
Hans Verkuilb9600742009-01-18 19:59:11 -0300526
527 return 0;
528}
529
530static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t)
531{
532 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
533 struct mxb *mxb = (struct mxb *)dev->ext_priv;
534
535 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300536 DEB_D("VIDIOC_G_TUNER: channel %d does not have a tuner attached\n",
537 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300538 return -EINVAL;
539 }
540
Joe Perches44d0b802011-08-21 19:56:44 -0300541 DEB_EE("VIDIOC_G_TUNER: %d\n", t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300542
543 memset(t, 0, sizeof(*t));
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -0400544 strscpy(t->name, "TV Tuner", sizeof(t->name));
Hans Verkuilb9600742009-01-18 19:59:11 -0300545 t->type = V4L2_TUNER_ANALOG_TV;
546 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
547 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
548 t->audmode = mxb->cur_mode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300549 return call_all(dev, tuner, g_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300550}
551
Hans Verkuil2f73c7c2013-03-15 06:10:06 -0300552static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *t)
Hans Verkuilb9600742009-01-18 19:59:11 -0300553{
554 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
555 struct mxb *mxb = (struct mxb *)dev->ext_priv;
556
557 if (t->index) {
Joe Perches44d0b802011-08-21 19:56:44 -0300558 DEB_D("VIDIOC_S_TUNER: channel %d does not have a tuner attached\n",
559 t->index);
Hans Verkuilb9600742009-01-18 19:59:11 -0300560 return -EINVAL;
561 }
562
563 mxb->cur_mode = t->audmode;
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300564 return call_all(dev, tuner, s_tuner, t);
Hans Verkuilb9600742009-01-18 19:59:11 -0300565}
566
Hans Verkuil313fce72012-05-01 13:13:49 -0300567static int vidioc_querystd(struct file *file, void *fh, v4l2_std_id *norm)
568{
569 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
570
571 return call_all(dev, video, querystd, norm);
572}
573
Hans Verkuilb9600742009-01-18 19:59:11 -0300574static int vidioc_g_frequency(struct file *file, void *fh, struct v4l2_frequency *f)
575{
576 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
577 struct mxb *mxb = (struct mxb *)dev->ext_priv;
578
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300579 if (f->tuner)
Hans Verkuilb9600742009-01-18 19:59:11 -0300580 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300581 *f = mxb->cur_freq;
582
Joe Perches44d0b802011-08-21 19:56:44 -0300583 DEB_EE("VIDIOC_G_FREQ: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300584 return 0;
585}
586
Hans Verkuilb530a442013-03-19 04:09:26 -0300587static int vidioc_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *f)
Hans Verkuilb9600742009-01-18 19:59:11 -0300588{
589 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
590 struct mxb *mxb = (struct mxb *)dev->ext_priv;
591 struct saa7146_vv *vv = dev->vv_data;
592
593 if (f->tuner)
594 return -EINVAL;
595
596 if (V4L2_TUNER_ANALOG_TV != f->type)
597 return -EINVAL;
598
Joe Perches44d0b802011-08-21 19:56:44 -0300599 DEB_EE("VIDIOC_S_FREQUENCY: freq:0x%08x\n", mxb->cur_freq.frequency);
Hans Verkuilb9600742009-01-18 19:59:11 -0300600
601 /* tune in desired frequency */
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300602 tuner_call(mxb, tuner, s_frequency, f);
603 /* let the tuner subdev clamp the frequency to the tuner range */
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300604 mxb->cur_freq = *f;
Hans Verkuilb530a442013-03-19 04:09:26 -0300605 tuner_call(mxb, tuner, g_frequency, &mxb->cur_freq);
Hans Verkuil4894b702012-05-01 10:12:22 -0300606 if (mxb->cur_audinput == 0)
607 mxb_update_audmode(mxb);
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300608
609 if (mxb->cur_input)
610 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300611
612 /* hack: changing the frequency should invalidate the vbi-counter (=> alevt) */
613 spin_lock(&dev->slock);
614 vv->vbi_fieldcount = 0;
615 spin_unlock(&dev->slock);
616
617 return 0;
618}
619
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300620static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
621{
622 if (a->index >= MXB_AUDIOS)
623 return -EINVAL;
624 *a = mxb_audios[a->index];
625 return 0;
626}
627
Hans Verkuilb9600742009-01-18 19:59:11 -0300628static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
629{
630 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
631 struct mxb *mxb = (struct mxb *)dev->ext_priv;
632
Hans Verkuil4894b702012-05-01 10:12:22 -0300633 DEB_EE("VIDIOC_G_AUDIO\n");
634 *a = mxb_audios[mxb->cur_audinput];
Hans Verkuilb9600742009-01-18 19:59:11 -0300635 return 0;
636}
637
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300638static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
Hans Verkuilb9600742009-01-18 19:59:11 -0300639{
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300640 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
641 struct mxb *mxb = (struct mxb *)dev->ext_priv;
642
Joe Perches44d0b802011-08-21 19:56:44 -0300643 DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
Hans Verkuil66804272012-04-30 04:58:27 -0300644 if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) {
645 if (mxb->cur_audinput != a->index) {
646 mxb->cur_audinput = a->index;
647 tea6420_route(mxb, a->index);
Hans Verkuil4894b702012-05-01 10:12:22 -0300648 if (mxb->cur_audinput == 0)
649 mxb_update_audmode(mxb);
Hans Verkuil66804272012-04-30 04:58:27 -0300650 }
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300651 return 0;
Hans Verkuil66804272012-04-30 04:58:27 -0300652 }
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300653 return -EINVAL;
Hans Verkuilb9600742009-01-18 19:59:11 -0300654}
655
656#ifdef CONFIG_VIDEO_ADV_DEBUG
657static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
658{
659 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300660
Hans Verkuild2cac162013-05-29 07:00:00 -0300661 if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
662 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -0300663 reg->val = saa7146_read(dev, reg->reg);
664 reg->size = 4;
Hans Verkuilab49ae02012-05-01 12:57:57 -0300665 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300666}
667
Hans Verkuil977ba3b12013-03-24 08:28:46 -0300668static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg)
Hans Verkuilb9600742009-01-18 19:59:11 -0300669{
670 struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
Hans Verkuilb9600742009-01-18 19:59:11 -0300671
Hans Verkuild2cac162013-05-29 07:00:00 -0300672 if (reg->reg > pci_resource_len(dev->pci, 0) - 4)
673 return -EINVAL;
Hans Verkuilabca2052013-05-29 06:59:35 -0300674 saa7146_write(dev, reg->reg, reg->val);
675 return 0;
Hans Verkuilb9600742009-01-18 19:59:11 -0300676}
677#endif
678
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679static struct saa7146_ext_vv vv_data;
680
681/* this function only gets called when the probing was successful */
Hans Verkuil26338122008-09-06 17:24:30 -0300682static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683{
Hans Verkuil03b19302010-03-24 19:09:55 -0300684 struct mxb *mxb;
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300685
Joe Perches44d0b802011-08-21 19:56:44 -0300686 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
Hans Verkuila8327812008-07-25 10:31:23 -0300688 saa7146_vv_init(dev, &vv_data);
Hans Verkuil03b19302010-03-24 19:09:55 -0300689 if (mxb_probe(dev)) {
690 saa7146_vv_release(dev);
691 return -1;
692 }
693 mxb = (struct mxb *)dev->ext_priv;
694
Hans Verkuilab49ae02012-05-01 12:57:57 -0300695 vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
696 vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
697 vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
Hans Verkuil313fce72012-05-01 13:13:49 -0300698 vv_data.vid_ops.vidioc_querystd = vidioc_querystd;
Hans Verkuilab49ae02012-05-01 12:57:57 -0300699 vv_data.vid_ops.vidioc_g_tuner = vidioc_g_tuner;
700 vv_data.vid_ops.vidioc_s_tuner = vidioc_s_tuner;
701 vv_data.vid_ops.vidioc_g_frequency = vidioc_g_frequency;
702 vv_data.vid_ops.vidioc_s_frequency = vidioc_s_frequency;
703 vv_data.vid_ops.vidioc_enumaudio = vidioc_enumaudio;
704 vv_data.vid_ops.vidioc_g_audio = vidioc_g_audio;
705 vv_data.vid_ops.vidioc_s_audio = vidioc_s_audio;
Hans Verkuilb9600742009-01-18 19:59:11 -0300706#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilab49ae02012-05-01 12:57:57 -0300707 vv_data.vid_ops.vidioc_g_register = vidioc_g_register;
708 vv_data.vid_ops.vidioc_s_register = vidioc_s_register;
Hans Verkuilb9600742009-01-18 19:59:11 -0300709#endif
Hans Verkuila8327812008-07-25 10:31:23 -0300710 if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300711 ERR("cannot register capture v4l2 device. skipping.\n");
Hans Verkuil03b19302010-03-24 19:09:55 -0300712 saa7146_vv_release(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 return -1;
714 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300715
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/
Hans Verkuila8327812008-07-25 10:31:23 -0300717 if (MXB_BOARD_CAN_DO_VBI(dev)) {
718 if (saa7146_register_device(&mxb->vbi_dev, dev, "mxb", VFL_TYPE_VBI)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300719 ERR("cannot register vbi v4l2 device. skipping.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 }
721 }
722
Joe Perches44d0b802011-08-21 19:56:44 -0300723 pr_info("found Multimedia eXtension Board #%d\n", mxb_num);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725 mxb_num++;
726 mxb_init_done(dev);
727 return 0;
728}
729
Hans Verkuil26338122008-09-06 17:24:30 -0300730static int mxb_detach(struct saa7146_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731{
Hans Verkuil26338122008-09-06 17:24:30 -0300732 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
Joe Perches44d0b802011-08-21 19:56:44 -0300734 DEB_EE("dev:%p\n", dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
Hans Verkuild69f4a52012-04-29 18:59:38 -0300736 /* mute audio on tea6420s */
Hans Verkuil66804272012-04-30 04:58:27 -0300737 tea6420_route(mxb, 6);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300738
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 saa7146_unregister_device(&mxb->video_dev,dev);
Hans Verkuil26338122008-09-06 17:24:30 -0300740 if (MXB_BOARD_CAN_DO_VBI(dev))
741 saa7146_unregister_device(&mxb->vbi_dev, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 saa7146_vv_release(dev);
743
744 mxb_num--;
745
746 i2c_del_adapter(&mxb->i2c_adapter);
747 kfree(mxb);
748
749 return 0;
750}
751
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300752static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *standard)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753{
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300754 struct mxb *mxb = (struct mxb *)dev->ext_priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300756 if (V4L2_STD_PAL_I == standard->id) {
Michael Hunold6acaba82006-03-13 21:20:41 -0800757 v4l2_std_id std = V4L2_STD_PAL_I;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300758
Joe Perches44d0b802011-08-21 19:56:44 -0300759 DEB_D("VIDIOC_S_STD: setting mxb for PAL_I\n");
Hans Verkuil4894b702012-05-01 10:12:22 -0300760 /* These two gpio calls set the GPIO pins that control the tda9820 */
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300761 saa7146_write(dev, GPIO_CTRL, 0x00404050);
Hans Verkuil1b8dac12009-02-07 11:18:05 -0300762 saa7111a_call(mxb, core, s_gpio, 0);
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300763 saa7111a_call(mxb, video, s_std, std);
Hans Verkuild69f4a52012-04-29 18:59:38 -0300764 if (mxb->cur_input == 0)
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300765 tuner_call(mxb, video, s_std, std);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 } else {
Michael Hunold6acaba82006-03-13 21:20:41 -0800767 v4l2_std_id std = V4L2_STD_PAL_BG;
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -0300768
Hans Verkuild69f4a52012-04-29 18:59:38 -0300769 if (mxb->cur_input)
770 std = standard->id;
Joe Perches44d0b802011-08-21 19:56:44 -0300771 DEB_D("VIDIOC_S_STD: setting mxb for PAL/NTSC/SECAM\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, 1);
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 }
779 return 0;
780}
781
782static struct saa7146_standard standard[] = {
783 {
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500784 .name = "PAL-BG", .id = V4L2_STD_PAL_BG,
785 .v_offset = 0x17, .v_field = 288,
786 .h_offset = 0x14, .h_pixels = 680,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 .v_max_out = 576, .h_max_out = 768,
788 }, {
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500789 .name = "PAL-I", .id = V4L2_STD_PAL_I,
790 .v_offset = 0x17, .v_field = 288,
791 .h_offset = 0x14, .h_pixels = 680,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 .v_max_out = 576, .h_max_out = 768,
793 }, {
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500794 .name = "NTSC", .id = V4L2_STD_NTSC,
795 .v_offset = 0x16, .v_field = 240,
796 .h_offset = 0x06, .h_pixels = 708,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 .v_max_out = 480, .h_max_out = 640,
798 }, {
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500799 .name = "SECAM", .id = V4L2_STD_SECAM,
800 .v_offset = 0x14, .v_field = 288,
801 .h_offset = 0x14, .h_pixels = 720,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 .v_max_out = 576, .h_max_out = 768,
803 }
804};
805
806static struct saa7146_pci_extension_data mxb = {
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300807 .ext_priv = "Multimedia eXtension Board",
808 .ext = &extension,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809};
810
Arvind Yadav34e7b452017-08-02 13:14:55 -0400811static const struct pci_device_id pci_tbl[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 {
813 .vendor = PCI_VENDOR_ID_PHILIPS,
814 .device = PCI_DEVICE_ID_PHILIPS_SAA7146,
815 .subvendor = 0x0000,
816 .subdevice = 0x0000,
817 .driver_data = (unsigned long)&mxb,
818 }, {
819 .vendor = 0,
820 }
821};
822
823MODULE_DEVICE_TABLE(pci, pci_tbl);
824
825static struct saa7146_ext_vv vv_data = {
826 .inputs = MXB_INPUTS,
Hans Verkuil6e65ca92012-04-29 16:47:47 -0300827 .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_AUDIO,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 .stds = &standard[0],
Jérémy Lefauree40d14a2017-10-01 15:30:41 -0400829 .num_stds = ARRAY_SIZE(standard),
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300830 .std_callback = &std_callback,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831};
832
833static struct saa7146_extension extension = {
Hans Verkuil66804272012-04-30 04:58:27 -0300834 .name = "Multimedia eXtension Board",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 .flags = SAA7146_USE_I2C_IRQ,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300836
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 .pci_tbl = &pci_tbl[0],
838 .module = THIS_MODULE,
839
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 .attach = mxb_attach,
841 .detach = mxb_detach,
842
843 .irq_mask = 0,
844 .irq_func = NULL,
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300845};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
847static int __init mxb_init_module(void)
848{
Hans Verkuil26338122008-09-06 17:24:30 -0300849 if (saa7146_register_extension(&extension)) {
Joe Perches44d0b802011-08-21 19:56:44 -0300850 DEB_S("failed to register extension\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 return -ENODEV;
852 }
Mauro Carvalho Chehaba8733ca2006-03-17 10:37:02 -0300853
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 return 0;
855}
856
857static void __exit mxb_cleanup_module(void)
858{
859 saa7146_unregister_extension(&extension);
860}
861
862module_init(mxb_init_module);
863module_exit(mxb_cleanup_module);
864
865MODULE_DESCRIPTION("video4linux-2 driver for the Siemens-Nixdorf 'Multimedia eXtension board'");
866MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
867MODULE_LICENSE("GPL");