blob: 01be89fa5c7896e7595f3fde2047db16f160121a [file] [log] [blame]
Steven Toth265a6512008-04-18 21:34:00 -03001/*
2 * Driver for the Auvitek USB bridge
3 *
Steven Toth6d897612008-09-03 17:12:12 -03004 * Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
Steven Toth265a6512008-04-18 21:34:00 -03005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 *
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "au0828.h"
23#include "au0828-cards.h"
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030024#include "au8522.h"
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -030025#include "media/tuner.h"
26#include "media/v4l2-common.h"
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030027
28void hvr950q_cs5340_audio(void *priv, int enable)
29{
30 /* Because the HVR-950q shares an i2s bus between the cs5340 and the
31 au8522, we need to hold cs5340 in reset when using the au8522 */
32 struct au0828_dev *dev = priv;
33 if (enable == 1)
34 au0828_set(dev, REG_000, 0x10);
35 else
36 au0828_clear(dev, REG_000, 0x10);
37}
Steven Toth265a6512008-04-18 21:34:00 -030038
Steven Toth265a6512008-04-18 21:34:00 -030039struct au0828_board au0828_boards[] = {
40 [AU0828_BOARD_UNKNOWN] = {
41 .name = "Unknown board",
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -030042 .tuner_type = UNSET,
43 .tuner_addr = ADDR_UNSET,
Steven Toth265a6512008-04-18 21:34:00 -030044 },
45 [AU0828_BOARD_HAUPPAUGE_HVR850] = {
46 .name = "Hauppauge HVR850",
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -030047 .tuner_type = TUNER_XC5000,
48 .tuner_addr = 0x61,
Devin Heitmueller16af6f52009-04-01 00:11:31 -030049 .i2c_clk_divider = AU0828_I2C_CLK_30KHZ,
Devin Heitmueller7fdd7c72009-03-11 03:00:43 -030050 .input = {
51 {
52 .type = AU0828_VMUX_TELEVISION,
53 .vmux = AU8522_COMPOSITE_CH4_SIF,
54 .amux = AU8522_AUDIO_SIF,
55 },
56 {
57 .type = AU0828_VMUX_COMPOSITE,
58 .vmux = AU8522_COMPOSITE_CH1,
59 .amux = AU8522_AUDIO_NONE,
60 .audio_setup = hvr950q_cs5340_audio,
61 },
62 {
63 .type = AU0828_VMUX_SVIDEO,
64 .vmux = AU8522_SVIDEO_CH13,
65 .amux = AU8522_AUDIO_NONE,
66 .audio_setup = hvr950q_cs5340_audio,
67 },
68 },
Steven Toth265a6512008-04-18 21:34:00 -030069 },
70 [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
71 .name = "Hauppauge HVR950Q",
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -030072 .tuner_type = TUNER_XC5000,
73 .tuner_addr = 0x61,
Devin Heitmueller16af6f52009-04-01 00:11:31 -030074 /* The au0828 hardware i2c implementation does not properly
75 support the xc5000's i2c clock stretching. So we need to
76 lower the clock frequency enough where the 15us clock
77 stretch fits inside of a normal clock cycle, or else the
78 au0828 fails to set the STOP bit. A 30 KHz clock puts the
79 clock pulse width at 18us */
80 .i2c_clk_divider = AU0828_I2C_CLK_30KHZ,
Devin Heitmueller8b2f0792009-03-11 03:00:40 -030081 .input = {
82 {
83 .type = AU0828_VMUX_TELEVISION,
84 .vmux = AU8522_COMPOSITE_CH4_SIF,
85 .amux = AU8522_AUDIO_SIF,
86 },
87 {
88 .type = AU0828_VMUX_COMPOSITE,
89 .vmux = AU8522_COMPOSITE_CH1,
90 .amux = AU8522_AUDIO_NONE,
91 .audio_setup = hvr950q_cs5340_audio,
92 },
93 {
94 .type = AU0828_VMUX_SVIDEO,
95 .vmux = AU8522_SVIDEO_CH13,
96 .amux = AU8522_AUDIO_NONE,
97 .audio_setup = hvr950q_cs5340_audio,
98 },
99 },
Steven Toth265a6512008-04-18 21:34:00 -0300100 },
Michael Krufky59d27522008-07-09 00:23:08 -0300101 [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
102 .name = "Hauppauge HVR950Q rev xxF8",
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300103 .tuner_type = UNSET,
104 .tuner_addr = ADDR_UNSET,
Devin Heitmueller16af6f52009-04-01 00:11:31 -0300105 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
Michael Krufky59d27522008-07-09 00:23:08 -0300106 },
Steven Toth265a6512008-04-18 21:34:00 -0300107 [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
108 .name = "DViCO FusionHDTV USB",
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300109 .tuner_type = UNSET,
110 .tuner_addr = ADDR_UNSET,
Devin Heitmueller16af6f52009-04-01 00:11:31 -0300111 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
Steven Toth265a6512008-04-18 21:34:00 -0300112 },
Michael Krufky8e8bd222008-09-03 16:46:36 -0300113 [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
114 .name = "Hauppauge Woodbury",
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300115 .tuner_type = UNSET,
116 .tuner_addr = ADDR_UNSET,
Devin Heitmueller16af6f52009-04-01 00:11:31 -0300117 .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
Michael Krufky8e8bd222008-09-03 16:46:36 -0300118 },
Steven Toth265a6512008-04-18 21:34:00 -0300119};
Steven Toth265a6512008-04-18 21:34:00 -0300120
121/* Tuner callback function for au0828 boards. Currently only needed
122 * for HVR1500Q, which has an xc5000 tuner.
123 */
Michael Krufkyd7cba042008-09-12 13:31:45 -0300124int au0828_tuner_callback(void *priv, int component, int command, int arg)
Steven Toth265a6512008-04-18 21:34:00 -0300125{
126 struct au0828_dev *dev = priv;
127
Michael Krufkyf07e8e42008-04-18 21:42:30 -0300128 dprintk(1, "%s()\n", __func__);
Steven Tothbc3c6132008-04-18 21:39:11 -0300129
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300130 switch (dev->boardnr) {
Steven Toth265a6512008-04-18 21:34:00 -0300131 case AU0828_BOARD_HAUPPAUGE_HVR850:
132 case AU0828_BOARD_HAUPPAUGE_HVR950Q:
Michael Krufky59d27522008-07-09 00:23:08 -0300133 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
Steven Toth265a6512008-04-18 21:34:00 -0300134 case AU0828_BOARD_DVICO_FUSIONHDTV7:
Steven Totha9c36aa2008-04-17 21:41:28 -0300135 if (command == 0) {
Steven Toth265a6512008-04-18 21:34:00 -0300136 /* Tuner Reset Command from xc5000 */
137 /* Drive the tuner into reset and out */
138 au0828_clear(dev, REG_001, 2);
Devin Heitmuellerb25ed9c2009-04-02 22:14:51 -0300139 mdelay(10);
Steven Toth265a6512008-04-18 21:34:00 -0300140 au0828_set(dev, REG_001, 2);
Devin Heitmuellerb25ed9c2009-04-02 22:14:51 -0300141 mdelay(10);
Steven Toth265a6512008-04-18 21:34:00 -0300142 return 0;
Mauro Carvalho Chehab18d73c52008-04-18 22:12:52 -0300143 } else {
Steven Toth265a6512008-04-18 21:34:00 -0300144 printk(KERN_ERR
Michael Krufkyf07e8e42008-04-18 21:42:30 -0300145 "%s(): Unknown command.\n", __func__);
Steven Toth265a6512008-04-18 21:34:00 -0300146 return -EINVAL;
147 }
148 break;
149 }
150
151 return 0; /* Should never be here */
152}
153
Steven Toth28930fa2008-03-29 19:53:07 -0300154static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
155{
156 struct tveeprom tv;
157
158 tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300159 dev->board.tuner_type = tv.tuner_type;
Steven Toth28930fa2008-03-29 19:53:07 -0300160
161 /* Make sure we support the board model */
Steven Totha9c36aa2008-04-17 21:41:28 -0300162 switch (tv.model) {
Michael Krufky104fe9a2008-06-13 03:29:43 -0300163 case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */
Devin Heitmueller62899a22009-03-15 18:48:52 -0300164 case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
165 case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
166 case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
167 case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
168 case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
169 case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
170 case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */
Michael Krufky104fe9a2008-06-13 03:29:43 -0300171 case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
Steven Toth28930fa2008-03-29 19:53:07 -0300172 break;
173 default:
Michael Krufkyf07e8e42008-04-18 21:42:30 -0300174 printk(KERN_WARNING "%s: warning: "
175 "unknown hauppauge model #%d\n", __func__, tv.model);
Steven Toth28930fa2008-03-29 19:53:07 -0300176 break;
177 }
178
Michael Krufkyf07e8e42008-04-18 21:42:30 -0300179 printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
180 __func__, tv.model);
Steven Toth28930fa2008-03-29 19:53:07 -0300181}
182
Steven Toth28930fa2008-03-29 19:53:07 -0300183void au0828_card_setup(struct au0828_dev *dev)
184{
Steven Toth28930fa2008-03-29 19:53:07 -0300185 static u8 eeprom[256];
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300186 struct tuner_setup tun_setup;
Devin Heitmuellerb14667f2009-03-11 03:01:04 -0300187 struct v4l2_subdev *sd;
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300188 unsigned int mode_mask = T_ANALOG_TV |
189 T_DIGITAL_TV;
Steven Toth28930fa2008-03-29 19:53:07 -0300190
Michael Krufkyf07e8e42008-04-18 21:42:30 -0300191 dprintk(1, "%s()\n", __func__);
Steven Tothbc3c6132008-04-18 21:39:11 -0300192
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300193 memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board));
194
Steven Toth28930fa2008-03-29 19:53:07 -0300195 if (dev->i2c_rc == 0) {
196 dev->i2c_client.addr = 0xa0 >> 1;
197 tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
198 }
199
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300200 switch (dev->boardnr) {
Steven Toth28930fa2008-03-29 19:53:07 -0300201 case AU0828_BOARD_HAUPPAUGE_HVR850:
202 case AU0828_BOARD_HAUPPAUGE_HVR950Q:
Michael Krufky59d27522008-07-09 00:23:08 -0300203 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
Michael Krufky8e8bd222008-09-03 16:46:36 -0300204 case AU0828_BOARD_HAUPPAUGE_WOODBURY:
Steven Toth28930fa2008-03-29 19:53:07 -0300205 if (dev->i2c_rc == 0)
206 hauppauge_eeprom(dev, eeprom+0xa0);
207 break;
208 }
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300209
Devin Heitmueller220be772009-03-11 03:01:01 -0300210 if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) {
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300211 /* Load the analog demodulator driver (note this would need to
212 be abstracted out if we ever need to support a different
213 demod) */
Hans Verkuile6574f22009-04-01 03:57:53 -0300214 sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300215 "au8522", 0x8e >> 1, NULL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300216 if (sd == NULL)
217 printk(KERN_ERR "analog subdev registration failed\n");
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300218 }
219
220 /* Setup tuners */
221 if (dev->board.tuner_type != TUNER_ABSENT) {
222 /* Load the tuner module, which does the attach */
Hans Verkuile6574f22009-04-01 03:57:53 -0300223 sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
Laurent Pinchart9a1f8b32010-09-24 10:16:44 -0300224 "tuner", dev->board.tuner_addr, NULL);
Devin Heitmueller62899a22009-03-15 18:48:52 -0300225 if (sd == NULL)
226 printk(KERN_ERR "tuner subdev registration fail\n");
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300227
228 tun_setup.mode_mask = mode_mask;
229 tun_setup.type = dev->board.tuner_type;
230 tun_setup.addr = dev->board.tuner_addr;
231 tun_setup.tuner_callback = au0828_tuner_callback;
Devin Heitmueller2689d3d2009-03-15 20:01:53 -0300232 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr,
233 &tun_setup);
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300234 }
Steven Toth28930fa2008-03-29 19:53:07 -0300235}
236
Steven Toth265a6512008-04-18 21:34:00 -0300237/*
238 * The bridge has between 8 and 12 gpios.
239 * Regs 1 and 0 deal with output enables.
Steven Totha9c36aa2008-04-17 21:41:28 -0300240 * Regs 3 and 2 deal with direction.
Steven Toth265a6512008-04-18 21:34:00 -0300241 */
242void au0828_gpio_setup(struct au0828_dev *dev)
243{
Michael Krufkyf07e8e42008-04-18 21:42:30 -0300244 dprintk(1, "%s()\n", __func__);
Steven Tothbc3c6132008-04-18 21:39:11 -0300245
Devin Heitmuellerf1add5b2009-03-11 03:00:47 -0300246 switch (dev->boardnr) {
Steven Toth265a6512008-04-18 21:34:00 -0300247 case AU0828_BOARD_HAUPPAUGE_HVR850:
248 case AU0828_BOARD_HAUPPAUGE_HVR950Q:
Michael Krufky59d27522008-07-09 00:23:08 -0300249 case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
Michael Krufky8e8bd222008-09-03 16:46:36 -0300250 case AU0828_BOARD_HAUPPAUGE_WOODBURY:
Steven Toth265a6512008-04-18 21:34:00 -0300251 /* GPIO's
252 * 4 - CS5340
253 * 5 - AU8522 Demodulator
254 * 6 - eeprom W/P
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300255 * 7 - power supply
Steven Toth265a6512008-04-18 21:34:00 -0300256 * 9 - XC5000 Tuner
257 */
258
259 /* Into reset */
260 au0828_write(dev, REG_003, 0x02);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300261 au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10);
Steven Toth265a6512008-04-18 21:34:00 -0300262 au0828_write(dev, REG_001, 0x0);
263 au0828_write(dev, REG_000, 0x0);
264 msleep(100);
265
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300266 /* Out of reset (leave the cs5340 in reset until needed) */
Steven Toth265a6512008-04-18 21:34:00 -0300267 au0828_write(dev, REG_003, 0x02);
268 au0828_write(dev, REG_001, 0x02);
Devin Heitmueller8b2f0792009-03-11 03:00:40 -0300269 au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10);
270 au0828_write(dev, REG_000, 0x80 | 0x40 | 0x20);
271
Steven Toth265a6512008-04-18 21:34:00 -0300272 msleep(250);
273 break;
274 case AU0828_BOARD_DVICO_FUSIONHDTV7:
275 /* GPIO's
276 * 6 - ?
277 * 8 - AU8522 Demodulator
278 * 9 - XC5000 Tuner
279 */
280
281 /* Into reset */
282 au0828_write(dev, REG_003, 0x02);
283 au0828_write(dev, REG_002, 0xa0);
284 au0828_write(dev, REG_001, 0x0);
285 au0828_write(dev, REG_000, 0x0);
286 msleep(100);
287
288 /* Out of reset */
289 au0828_write(dev, REG_003, 0x02);
290 au0828_write(dev, REG_002, 0xa0);
291 au0828_write(dev, REG_001, 0x02);
292 au0828_write(dev, REG_000, 0xa0);
293 msleep(250);
294 break;
295 }
296}
297
298/* table of devices that work with this driver */
Steven Totha8eb9122008-10-16 20:19:41 -0300299struct usb_device_id au0828_usb_id_table[] = {
Steven Toth265a6512008-04-18 21:34:00 -0300300 { USB_DEVICE(0x2040, 0x7200),
301 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
302 { USB_DEVICE(0x2040, 0x7240),
303 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
304 { USB_DEVICE(0x0fe9, 0xd620),
305 .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
Michael Krufky104fe9a2008-06-13 03:29:43 -0300306 { USB_DEVICE(0x2040, 0x7210),
307 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
308 { USB_DEVICE(0x2040, 0x7217),
309 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
310 { USB_DEVICE(0x2040, 0x721b),
311 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
Michael Krufkya636da62008-10-15 17:00:31 -0300312 { USB_DEVICE(0x2040, 0x721e),
313 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
Michael Krufky104fe9a2008-06-13 03:29:43 -0300314 { USB_DEVICE(0x2040, 0x721f),
315 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
316 { USB_DEVICE(0x2040, 0x7280),
317 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
318 { USB_DEVICE(0x0fd9, 0x0008),
319 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
Michael Krufky59d27522008-07-09 00:23:08 -0300320 { USB_DEVICE(0x2040, 0x7201),
321 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
322 { USB_DEVICE(0x2040, 0x7211),
323 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
324 { USB_DEVICE(0x2040, 0x7281),
325 .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
Michael Krufky8e8bd222008-09-03 16:46:36 -0300326 { USB_DEVICE(0x2040, 0x8200),
327 .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
Steven Toth265a6512008-04-18 21:34:00 -0300328 { },
329};
330
331MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);