aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mxb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mxb.c')
-rw-r--r--drivers/media/video/mxb.c872
1 files changed, 872 insertions, 0 deletions
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
new file mode 100644
index 00000000000..0b385002350
--- /dev/null
+++ b/drivers/media/video/mxb.c
@@ -0,0 +1,872 @@
1/*
2 mxb - v4l2 driver for the Multimedia eXtension Board
3
4 Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
5
6 Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html
7 for further details about this card.
8
9 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
24#define DEBUG_VARIABLE debug
25
26#include <media/saa7146_vv.h>
27#include <media/tuner.h>
28#include <media/v4l2-common.h>
29#include <media/saa7115.h>
30
31#include "mxb.h"
32#include "tea6415c.h"
33#include "tea6420.h"
34
35#define I2C_SAA7111A 0x24
36#define I2C_TDA9840 0x42
37#define I2C_TEA6415C 0x43
38#define I2C_TEA6420_1 0x4c
39#define I2C_TEA6420_2 0x4d
40#define I2C_TUNER 0x60
41
42#define MXB_BOARD_CAN_DO_VBI(dev) (dev->revision != 0)
43
44/* global variable */
45static int mxb_num;
46
47/* initial frequence the tuner will be tuned to.
48 in verden (lower saxony, germany) 4148 is a
49 channel called "phoenix" */
50static int freq = 4148;
51module_param(freq, int, 0644);
52MODULE_PARM_DESC(freq, "initial frequency the tuner will be tuned to while setup");
53
54static int debug;
55module_param(debug, int, 0644);
56MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
57
58#define MXB_INPUTS 4
59enum { TUNER, AUX1, AUX3, AUX3_YC };
60
61static struct v4l2_input mxb_inputs[MXB_INPUTS] = {
62 { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
63 { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
64 { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
65 { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
66};
67
68/* this array holds the information, which port of the saa7146 each
69 input actually uses. the mxb uses port 0 for every input */
70static struct {
71 int hps_source;
72 int hps_sync;
73} input_port_selection[MXB_INPUTS] = {
74 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
75 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
76 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
77 { SAA7146_HPS_SOURCE_PORT_A, SAA7146_HPS_SYNC_PORT_A },
78};
79
80/* this array holds the information of the audio source (mxb_audios),
81 which has to be switched corresponding to the video source (mxb_channels) */
82static int video_audio_connect[MXB_INPUTS] =
83 { 0, 1, 3, 3 };
84
85struct mxb_routing {
86 u32 input;
87 u32 output;
88};
89
90/* These are the necessary input-output-pins for bringing one audio source
91 (see above) to the CD-output. Note that gain is set to 0 in this table. */
92static struct mxb_routing TEA6420_cd[MXB_AUDIOS + 1][2] = {
93 { { 1, 1 }, { 1, 1 } }, /* Tuner */
94 { { 5, 1 }, { 6, 1 } }, /* AUX 1 */
95 { { 4, 1 }, { 6, 1 } }, /* AUX 2 */
96 { { 3, 1 }, { 6, 1 } }, /* AUX 3 */
97 { { 1, 1 }, { 3, 1 } }, /* Radio */
98 { { 1, 1 }, { 2, 1 } }, /* CD-Rom */
99 { { 6, 1 }, { 6, 1 } } /* Mute */
100};
101
102/* These are the necessary input-output-pins for bringing one audio source
103 (see above) to the line-output. Note that gain is set to 0 in this table. */
104static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
105 { { 2, 3 }, { 1, 2 } },
106 { { 5, 3 }, { 6, 2 } },
107 { { 4, 3 }, { 6, 2 } },
108 { { 3, 3 }, { 6, 2 } },
109 { { 2, 3 }, { 3, 2 } },
110 { { 2, 3 }, { 2, 2 } },
111 { { 6, 3 }, { 6, 2 } } /* Mute */
112};
113
114#define MAXCONTROLS 1
115static struct v4l2_queryctrl mxb_controls[] = {
116 { V4L2_CID_AUDIO_MUTE, V4L2_CTRL_TYPE_BOOLEAN, "Mute", 0, 1, 1, 0, 0 },
117};
118
119struct mxb
120{
121 struct video_device *video_dev;
122 struct video_device *vbi_dev;
123
124 struct i2c_adapter i2c_adapter;
125
126 struct v4l2_subdev *saa7111a;
127 struct v4l2_subdev *tda9840;
128 struct v4l2_subdev *tea6415c;
129 struct v4l2_subdev *tuner;
130 struct v4l2_subdev *tea6420_1;
131 struct v4l2_subdev *tea6420_2;
132
133 int cur_mode; /* current audio mode (mono, stereo, ...) */
134 int cur_input; /* current input */
135 int cur_mute; /* current mute status */
136 struct v4l2_frequency cur_freq; /* current frequency the tuner is tuned to */
137};
138
139#define saa7111a_call(mxb, o, f, args...) \
140 v4l2_subdev_call(mxb->saa7111a, o, f, ##args)
141#define tda9840_call(mxb, o, f, args...) \
142 v4l2_subdev_call(mxb->tda9840, o, f, ##args)
143#define tea6415c_call(mxb, o, f, args...) \
144 v4l2_subdev_call(mxb->tea6415c, o, f, ##args)
145#define tuner_call(mxb, o, f, args...) \
146 v4l2_subdev_call(mxb->tuner, o, f, ##args)
147#define call_all(dev, o, f, args...) \
148 v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
149
150static inline void tea6420_route_cd(struct mxb *mxb, int idx)
151{
152 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
153 TEA6420_cd[idx][0].input, TEA6420_cd[idx][0].output, 0);
154 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
155 TEA6420_cd[idx][1].input, TEA6420_cd[idx][1].output, 0);
156}
157
158static inline void tea6420_route_line(struct mxb *mxb, int idx)
159{
160 v4l2_subdev_call(mxb->tea6420_1, audio, s_routing,
161 TEA6420_line[idx][0].input, TEA6420_line[idx][0].output, 0);
162 v4l2_subdev_call(mxb->tea6420_2, audio, s_routing,
163 TEA6420_line[idx][1].input, TEA6420_line[idx][1].output, 0);
164}
165
166static struct saa7146_extension extension;
167
168static int mxb_probe(struct saa7146_dev *dev)
169{
170 struct mxb *mxb = NULL;
171
172 mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
173 if (mxb == NULL) {
174 DEB_D(("not enough kernel memory.\n"));
175 return -ENOMEM;
176 }
177
178 snprintf(mxb->i2c_adapter.name, sizeof(mxb->i2c_adapter.name), "mxb%d", mxb_num);
179
180 saa7146_i2c_adapter_prepare(dev, &mxb->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480);
181 if (i2c_add_adapter(&mxb->i2c_adapter) < 0) {
182 DEB_S(("cannot register i2c-device. skipping.\n"));
183 kfree(mxb);
184 return -EFAULT;
185 }
186
187 mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
188 "saa7111", I2C_SAA7111A, NULL);
189 mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
190 "tea6420", I2C_TEA6420_1, NULL);
191 mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
192 "tea6420", I2C_TEA6420_2, NULL);
193 mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
194 "tea6415c", I2C_TEA6415C, NULL);
195 mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
196 "tda9840", I2C_TDA9840, NULL);
197 mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
198 "tuner", I2C_TUNER, NULL);
199
200 /* check if all devices are present */
201 if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
202 !mxb->tda9840 || !mxb->saa7111a || !mxb->tuner) {
203 printk("mxb: did not find all i2c devices. aborting\n");
204 i2c_del_adapter(&mxb->i2c_adapter);
205 kfree(mxb);
206 return -ENODEV;
207 }
208
209 /* all devices are present, probe was successful */
210
211 /* we store the pointer in our private data field */
212 dev->ext_priv = mxb;
213
214 return 0;
215}
216
217/* some init data for the saa7740, the so-called 'sound arena module'.