aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorPete Eberlein <pete@sensoray.com>2008-10-30 15:56:41 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-06 16:52:06 -0500
commitb11869dbb6cc4b4de8da302f758866d0a167a277 (patch)
treefcd58485278741bd1d96f03e3dbf0c3540082898 /drivers/staging
parentd73f822ce775e004836ffc01ce9feae27d0d65cf (diff)
Staging: go7007: add sensoray 2250/2251 support
This is the driver for the Sensoray 2250/2251 USB devices added to go7007 driver. Signed-off-by: Pete Eberlein <pete@sensoray.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/go7007/Kconfig10
-rw-r--r--drivers/staging/go7007/Makefile15
-rw-r--r--drivers/staging/go7007/go7007-driver.c3
-rw-r--r--drivers/staging/go7007/go7007-priv.h1
-rw-r--r--drivers/staging/go7007/go7007-usb.c48
-rw-r--r--drivers/staging/go7007/s2250-board.c630
-rw-r--r--drivers/staging/go7007/s2250-loader.c188
-rw-r--r--drivers/staging/go7007/wis-i2c.h1
8 files changed, 893 insertions, 3 deletions
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig
index 593fdb767aa..f2cf7f66ae0 100644
--- a/drivers/staging/go7007/Kconfig
+++ b/drivers/staging/go7007/Kconfig
@@ -25,3 +25,13 @@ config VIDEO_GO7007_USB
25 To compile this driver as a module, choose M here: the 25 To compile this driver as a module, choose M here: the
26 module will be called go7007-usb 26 module will be called go7007-usb
27 27
28config VIDEO_GO7007_USB_S2250_BOARD
29 tristate "Sensoray 2250/2251 support"
30 depends on VIDEO_GO7007_USB && DVB_USB
31 default N
32 ---help---
33 This is a video4linux driver for the Sensoray 2250/2251 device
34
35 To compile this driver as a module, choose M here: the
36 module will be called s2250-board
37
diff --git a/drivers/staging/go7007/Makefile b/drivers/staging/go7007/Makefile
index 9b9310cae1c..e514b4af6d0 100644
--- a/drivers/staging/go7007/Makefile
+++ b/drivers/staging/go7007/Makefile
@@ -5,14 +5,23 @@
5 5
6obj-$(CONFIG_VIDEO_GO7007) += go7007.o 6obj-$(CONFIG_VIDEO_GO7007) += go7007.o
7obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o 7obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o
8obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o
8 9
9go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o snd-go7007.o 10go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \
11 snd-go7007.o wis-saa7113.o
10 12
13s2250-objs += s2250-board.o s2250-loader.o
11 14
12#ifneq ($(SAA7134_BUILD),) 15# Uncompile when the saa7134 patches get into upstream
13#obj-m += saa7134-go7007.o 16#ifneq ($(CONFIG_VIDEO_SAA7134),)
17#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
18#EXTRA_CFLAGS += -Idrivers/media/video/saa7134
14#endif 19#endif
15 20
21ifneq ($(CONFIG_VIDEO_GO7007_USB_S2250_BOARD),)
22EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
23endif
24
16EXTRA_CFLAGS += -Idrivers/staging/saa7134 25EXTRA_CFLAGS += -Idrivers/staging/saa7134
17EXTRA_CFLAGS += -Idrivers/media/dvb/frontends 26EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
18EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core 27EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c
index 510c23b4684..58bfc8d81b3 100644
--- a/drivers/staging/go7007/go7007-driver.c
+++ b/drivers/staging/go7007/go7007-driver.c
@@ -217,6 +217,9 @@ static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr)
217 case I2C_DRIVERID_WIS_OV7640: 217 case I2C_DRIVERID_WIS_OV7640:
218 modname = "wis-ov7640"; 218 modname = "wis-ov7640";
219 break; 219 break;
220 case I2C_DRIVERID_S2250:
221 modname = "s2250-board";
222 break;
220 default: 223 default:
221 modname = NULL; 224 modname = NULL;
222 break; 225 break;
diff --git a/drivers/staging/go7007/go7007-priv.h b/drivers/staging/go7007/go7007-priv.h
index f61d983efa3..372f1f1c09b 100644
--- a/drivers/staging/go7007/go7007-priv.h
+++ b/drivers/staging/go7007/go7007-priv.h
@@ -40,6 +40,7 @@ struct go7007;
40#define GO7007_BOARDID_LIFEVIEW_LR192 21 /* TV Walker Ultra */ 40#define GO7007_BOARDID_LIFEVIEW_LR192 21 /* TV Walker Ultra */
41#define GO7007_BOARDID_ENDURA 22 41#define GO7007_BOARDID_ENDURA 22
42#define GO7007_BOARDID_ADLINK_MPG24 23 42#define GO7007_BOARDID_ADLINK_MPG24 23
43#define GO7007_BOARDID_SENSORAY_2250 24 /* Sensoray 2250/2251 */
43 44
44/* Various characteristics of each board */ 45/* Various characteristics of each board */
45#define GO7007_BOARD_HAS_AUDIO (1<<0) 46#define GO7007_BOARD_HAS_AUDIO (1<<0)
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
index 04cc144e0c1..f18eaa4bffb 100644
--- a/drivers/staging/go7007/go7007-usb.c
+++ b/drivers/staging/go7007/go7007-usb.c
@@ -398,6 +398,41 @@ static struct go7007_usb_board board_adlink_mpg24 = {
398 }, 398 },
399}; 399};
400 400
401static struct go7007_usb_board board_sensoray_2250 = {
402 .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
403 .main_info = {
404 .firmware = "go7007tv.bin",
405 .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
406 GO7007_AUDIO_I2S_MASTER |
407 GO7007_AUDIO_WORD_16,
408 .flags = GO7007_BOARD_HAS_AUDIO,
409 .audio_rate = 48000,
410 .audio_bclk_div = 8,
411 .audio_main_div = 2,
412 .hpi_buffer_cap = 7,
413 .sensor_flags = GO7007_SENSOR_656 |
414 GO7007_SENSOR_TV,
415 .num_i2c_devs = 1,
416 .i2c_devs = {
417 {
418 .id = I2C_DRIVERID_S2250,
419 .addr = 0x34,
420 },
421 },
422 .num_inputs = 2,
423 .inputs = {
424 {
425 .video_input = 0,
426 .name = "Composite",
427 },
428 {
429 .video_input = 1,
430 .name = "S-Video",
431 },
432 },
433 },
434};
435
401static struct usb_device_id go7007_usb_id_table[] = { 436static struct usb_device_id go7007_usb_id_table[] = {
402 { 437 {
403 .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 438 .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
@@ -491,6 +526,14 @@ static struct usb_device_id go7007_usb_id_table[] = {
491 .bcdDevice_hi = 0x1, 526 .bcdDevice_hi = 0x1,
492 .driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192, 527 .driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192,
493 }, 528 },
529 {
530 .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
531 .idVendor = 0x1943, /* Vendor ID Sensoray */
532 .idProduct = 0x2250, /* Product ID of 2250/2251 */
533 .bcdDevice_lo = 0x1,
534 .bcdDevice_hi = 0x1,
535 .driver_info = (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250,
536 },
494 { } /* Terminating entry */ 537 { } /* Terminating entry */
495}; 538};
496 539
@@ -965,6 +1008,11 @@ static int go7007_usb_probe(struct usb_interface *intf,
965 name = "Lifeview TV Walker Ultra"; 1008 name = "Lifeview TV Walker Ultra";
966 board = &board_lifeview_lr192; 1009 board = &board_lifeview_lr192;
967 break; 1010 break;
1011 case GO7007_BOARDID_SENSORAY_2250:
1012 printk(KERN_INFO "Sensoray 2250 found\n");
1013 name = "Sensoray 2250/2251\n";
1014 board = &board_sensoray_2250;
1015 break;
968 default: 1016 default:
969 printk(KERN_ERR "go7007-usb: unknown board ID %d!\n", 1017 printk(KERN_ERR "go7007-usb: unknown board ID %d!\n",
970 (unsigned int)id->driver_info); 1018 (unsigned int)id->driver_info);
diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c
new file mode 100644
index 00000000000..fb6845e3788
--- /dev/null
+++ b/drivers/staging/go7007/s2250-board.c
@@ -0,0 +1,630 @@
1/*
2 * Copyright (C) 2008 Sensoray Company Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License (Version 2) as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/usb.h>
21#include <linux/i2c.h>
22#include <linux/videodev2.h>
23#include <media/v4l2-common.h>
24#include "go7007-priv.h"
25#include "wis-i2c.h"
26
27extern int s2250loader_init(void);
28extern void s2250loader_cleanup(void);
29
30#define TLV320_ADDRESS 0x34
31#define S2250_VIDDEC 0x86
32#define VPX322_ADDR_ANALOGCONTROL1 0x02
33#define VPX322_ADDR_BRIGHTNESS0 0x0127
34#define VPX322_ADDR_BRIGHTNESS1 0x0131
35#define VPX322_ADDR_CONTRAST0 0x0128
36#define VPX322_ADDR_CONTRAST1 0x0132
37#define VPX322_ADDR_HUE 0x00dc
38#define VPX322_ADDR_SAT 0x0030
39
40struct go7007_usb_board {
41 unsigned int flags;
42 struct go7007_board_info main_info;
43};
44
45struct go7007_usb {
46 struct go7007_usb_board *board;
47 struct semaphore i2c_lock;
48 struct usb_device *usbdev;
49 struct urb *video_urbs[8];
50 struct urb *audio_urbs[8];
51 struct urb *intr_urb;
52};
53
54static unsigned char aud_regs[] = {
55 0x1e, 0x00,
56 0x00, 0x17,
57 0x02, 0x17,
58 0x04, 0xf9,
59 0x06, 0xf9,
60 0x08, 0x02,
61 0x0a, 0x00,
62 0x0c, 0x00,
63 0x0a, 0x00,
64 0x0c, 0x00,
65 0x0e, 0x02,
66 0x10, 0x00,
67 0x12, 0x01,
68 0x00, 0x00,
69};
70
71
72static unsigned char vid_regs[] = {
73 0xF2, 0x0f,
74 0xAA, 0x00,
75 0xF8, 0xff,
76 0x00, 0x00,
77};
78
79static u16 vid_regs_fp[] = {
80 0x028, 0x067,
81 0x120, 0x016,
82 0x121, 0xcF2,
83 0x122, 0x0F2,
84 0x123, 0x00c,
85 0x124, 0x2d0,
86 0x125, 0x2e0,
87 0x126, 0x004,
88 0x128, 0x1E0,
89 0x12A, 0x016,
90 0x12B, 0x0F2,
91 0x12C, 0x0F2,
92 0x12D, 0x00c,
93 0x12E, 0x2d0,
94 0x12F, 0x2e0,
95 0x130, 0x004,
96 0x132, 0x1E0,
97 0x140, 0x060,
98 0x153, 0x00C,
99 0x154, 0x200,
100 0x150, 0x801,
101 0x000, 0x000
102};
103
104/* PAL specific values */
105static u16 vid_regs_fp_pal[] =
106{
107 0x120, 0x017,
108 0x121, 0xd22,
109 0x122, 0x122,
110 0x12A, 0x017,
111 0x12B, 0x122,
112 0x12C, 0x122,
113 0x140, 0x060,
114 0x000, 0x000,
115};
116
117struct s2250 {
118 int std;
119 int input;
120 int brightness;
121 int contrast;
122 int saturation;
123 int hue;
124 int reg12b_val;
125 int audio_input;
126};
127
128/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
129static int go7007_usb_vendor_request(struct go7007 *go, u16 request,
130 u16 value, u16 index, void *transfer_buffer, int length, int in)
131{
132 struct go7007_usb *usb = go->hpi_context;
133 int timeout = 5000;
134
135 if (in) {
136 return usb_control_msg(usb->usbdev,
137 usb_rcvctrlpipe(usb->usbdev, 0), request,
138 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
139 value, index, transfer_buffer, length, timeout);
140 } else {
141 return usb_control_msg(usb->usbdev,
142 usb_sndctrlpipe(usb->usbdev, 0), request,
143 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
144 value, index, transfer_buffer, length, timeout);
145 }
146}
147/* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
148
149static int write_reg(struct i2c_client *client, u8 reg, u8 value)
150{
151 struct go7007 *go = i2c_get_adapdata(client->adapter);
152 struct go7007_usb *usb = go->hpi_context;
153 int rc;
154 int dev_addr = client->addr;
155 u8 *buf;
156
157 if (go == NULL)
158 return -ENODEV;
159
160 if (go->status == STATUS_SHUTDOWN)
161 return -EBUSY;
162
163 buf = kzalloc(16, GFP_KERNEL);
164 if (buf == NULL)
165 return -ENOMEM;
166
167 if (down_interruptible(&usb->i2c_lock) != 0) {
168 printk(KERN_INFO "i2c lock failed\n");
169 return -EINTR;
170 }
171 rc = go7007_usb_vendor_request(go, 0x55, dev_addr,
172 (reg<<8 | value),
173 buf,
174 16, 1);
175
176 up(&usb->i2c_lock);
177 kfree(buf);
178 return rc;
179}
180
181static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
182{
183 struct go7007 *go = i2c_get_adapdata(client->adapter);
184 struct go7007_usb *usb = go->hpi_context;
185 u8 *buf;
186 struct s2250 *dec = i2c_get_clientdata(client);
187
188 if (go == NULL)
189 return -ENODEV;
190
191 if (go->status == STATUS_SHUTDOWN)
192 return -EBUSY;
193
194 buf = kzalloc(16, GFP_KERNEL);
195
196 if (buf == NULL)
197 return -ENOMEM;
198
199
200
201 memset(buf, 0xcd, 6);
202
203 if (down_interruptible(&usb->i2c_lock) != 0) {
204 printk(KERN_INFO "i2c lock failed\n");
205 return -EINTR;
206 }
207 if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0)
208 return -EFAULT;
209
210 up(&usb->i2c_lock);
211 if (buf[0] == 0) {
212 unsigned int subaddr, val_read;
213
214 subaddr = (buf[4] << 8) + buf[5];
215 val_read = (buf[2] << 8) + buf[3];
216 if (val_read != val) {
217 printk(KERN_INFO "invalid fp write %x %x\n",
218 val_read, val);
219 return -EFAULT;
220 }
221 if (subaddr != addr) {
222 printk(KERN_INFO "invalid fp write addr %x %x\n",
223 subaddr, addr);
224 return -EFAULT;
225 }
226 } else
227 return -EFAULT;
228
229 /* save last 12b value */
230 if (addr == 0x12b)
231 dec->reg12b_val = val;
232
233 return 0;
234}
235
236static int write_regs(struct i2c_client *client, u8 *regs)
237{
238 int i;
239
240 for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
241 if (write_reg(client, regs[i], regs[i+1]) < 0) {
242 printk(KERN_INFO "s2250: failed\n");
243 return -1;
244 }
245 }
246 return 0;
247}
248
249static int write_regs_fp(struct i2c_client *client, u16 *regs)
250{
251 int i;
252
253 for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
254 if (write_reg_fp(client, regs[i], regs[i+1]) < 0) {
255 printk(KERN_INFO "s2250: failed fp\n");
256 return -1;
257 }
258 }
259 return 0;
260}
261
262
263static int s2250_command(struct i2c_client *client,
264 unsigned int cmd, void *arg)
265{
266 struct s2250 *dec = i2c_get_clientdata(client);
267
268 switch (cmd) {
269 case VIDIOC_S_INPUT:
270 {
271 int vidsys;
272 int *input = arg;
273
274 vidsys = (dec->std == V4L2_STD_NTSC) ? 0x01 : 0x00;
275 if (*input == 0) {
276 /* composite */
277 write_reg_fp(client, 0x20, 0x020 | vidsys);
278 write_reg_fp(client, 0x21, 0x662);
279 write_reg_fp(client, 0x140, 0x060);
280 } else {
281 /* S-Video */
282 write_reg_fp(client, 0x20, 0x040 | vidsys);
283 write_reg_fp(client, 0x21, 0x666);
284 write_reg_fp(client, 0x140, 0x060);
285 }
286 dec->input = *input;
287 break;
288 }
289 case VIDIOC_S_STD:
290 {
291 v4l2_std_id *std = arg;
292 u16 vidsource;
293
294 vidsource = (dec->input == 1) ? 0x040 : 0x020;
295 dec->std = *std;
296 switch (dec->std) {
297 case V4L2_STD_NTSC:
298 write_regs_fp(client, vid_regs_fp);
299 write_reg_fp(client, 0x20, vidsource | 1);
300 break;
301 case V4L2_STD_PAL:
302 write_regs_fp(client, vid_regs_fp);
303 write_regs_fp(client, vid_regs_fp_pal);
304 write_reg_fp(client, 0x20, vidsource);
305 break;
306 default:
307 return -EINVAL;
308 }
309 break;
310 }
311 case VIDIOC_QUERYCTRL:
312 {
313 struct v4l2_queryctrl *ctrl = arg;
314 static const u32 user_ctrls[] = {
315 V4L2_CID_BRIGHTNESS,
316 V4L2_CID_CONTRAST,
317 V4L2_CID_SATURATION,
318 V4L2_CID_HUE,
319 0
320 };
321 static const u32 *ctrl_classes[] = {
322 user_ctrls,
323 NULL
324 };
325
326 ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id);
327 switch (ctrl->id) {
328 case V4L2_CID_BRIGHTNESS:
329 v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
330 break;
331 case V4L2_CID_CONTRAST:
332 v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
333 break;
334 case V4L2_CID_SATURATION:
335 v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
336 break;
337 case V4L2_CID_HUE:
338 v4l2_ctrl_query_fill(ctrl, -50, 50, 1, 0);
339 break;
340 default:
341 ctrl->name[0] = '\0';
342 return -EINVAL;
343 }
344 break;
345 }
346 case VIDIOC_S_CTRL:
347 {
348 struct v4l2_control *ctrl = arg;
349 int value1;
350
351 switch (ctrl->id) {
352 case V4L2_CID_BRIGHTNESS:
353 printk(KERN_INFO "s2250: future setting\n");
354 return -EINVAL;
355 case V4L2_CID_CONTRAST:
356 printk(KERN_INFO "s2250: future setting\n");
357 return -EINVAL;
358 break;
359 case V4L2_CID_SATURATION:
360 if (ctrl->value > 127)
361 dec->saturation = 127;
362 else if (ctrl->value < 0)
363 dec->saturation = 0;
364 else
365 dec->saturation = ctrl->value;
366
367 value1 = dec->saturation * 4140 / 100;
368 if (value1 > 4094)
369 value1 = 4094;
370 write_reg_fp(client, VPX322_ADDR_SAT, value1);
371 break;
372 case V4L2_CID_HUE:
373 if (ctrl->value > 50)
374 dec->hue = 50;
375 else if (ctrl->value < -50)
376 dec->hue = -50;
377 else
378 dec->hue = ctrl->value;
379 /* clamp the hue range */
380 value1 = dec->hue * 280 / 50;
381 write_reg_fp(client, VPX322_ADDR_HUE, value1);
382 break;
383 }
384 break;
385 }
386 case VIDIOC_G_CTRL:
387 {
388 struct v4l2_control *ctrl = arg;
389
390 switch (ctrl->id) {
391 case V4L2_CID_BRIGHTNESS:
392 ctrl->value = dec->brightness;
393 break;
394 case V4L2_CID_CONTRAST:
395 ctrl->value = dec->contrast;
396 break;
397 case V4L2_CID_SATURATION:
398 ctrl->value = dec->saturation;
399 break;
400 case V4L2_CID_HUE:
401 ctrl->value = dec->hue;
402 break;
403 }
404 break;
405 }
406 case VIDIOC_S_FMT:
407 {
408 struct v4l2_format *fmt = arg;
409 if (fmt->fmt.pix.height < 640) {
410 write_reg_fp(client, 0x12b, dec->reg12b_val | 0x400);
411 write_reg_fp(client, 0x140, 0x060);
412 } else {
413 write_reg_fp(client, 0x12b, dec->reg12b_val & ~0x400);
414 write_reg_fp(client, 0x140, 0x060);
415 }
416 return 0;
417 }
418 case VIDIOC_G_AUDIO:
419 {
420 struct v4l2_audio *audio = arg;
421
422 memset(audio, 0, sizeof(*audio));
423 audio->index = dec->audio_input;
424 /* fall through */
425 }
426 case VIDIOC_ENUMAUDIO:
427 {
428 struct v4l2_audio *audio = arg;
429
430 switch (audio->index) {
431 case 0:
432 strcpy(audio->name, "Line In");
433 break;
434 case 1:
435 strcpy(audio->name, "Mic");
436 break;
437 case 2:
438 strcpy(audio->name, "Mic Boost");
439 break;
440 default:
441 audio->name[0] = '\0';
442 return 0;
443 }
444 audio->capability = V4L2_AUDCAP_STEREO;
445 audio->mode = 0;
446 return 0;
447 }
448 case VIDIOC_S_AUDIO:
449 {
450 struct v4l2_audio *audio = arg;
451
452 client->addr = TLV320_ADDRESS;
453 switch (audio->index) {
454 case 0:
455 write_reg(client, 0x08, 0x02); /* Line In */
456 break;
457 case 1:
458 write_reg(client, 0x08, 0x04); /* Mic */
459 break;
460 case 2:
461 write_reg(client, 0x08, 0x05); /* Mic Boost */
462 break;
463 default:
464 return -EINVAL;
465 }
466 dec->audio_input = audio->index;
467 return 0;
468 }
469
470 default:
471 printk(KERN_INFO "s2250: unknown command 0x%x\n", cmd);
472 break;
473 }
474 return 0;
475}
476
477static struct i2c_driver s2250_driver;
478
479static struct i2c_client s2250_client_templ = {
480 .name = "Sensoray 2250",
481 .driver = &s2250_driver,
482};
483
484static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
485{
486 struct i2c_client *client;
487 struct s2250 *dec;
488 u8 *data;
489 struct go7007 *go = i2c_get_adapdata(adapter);
490 struct go7007_usb *usb = go->hpi_context;
491
492 client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
493 if (client == NULL)
494 return -ENOMEM;
495 memcpy(client, &s2250_client_templ,
496 sizeof(s2250_client_templ));
497 client->adapter = adapter;
498
499 dec = kmalloc(sizeof(struct s2250), GFP_KERNEL);
500 if (dec == NULL) {
501 kfree(client);
502 return -ENOMEM;
503 }
504
505 dec->std = V4L2_STD_NTSC;
506 dec->brightness = 50;
507 dec->contrast = 50;
508 dec->saturation = 50;
509 dec->hue = 0;
510 client->addr = TLV320_ADDRESS;
511 i2c_set_clientdata(client, dec);
512
513 printk(KERN_DEBUG
514 "s2250: initializing video decoder on %s\n",
515 adapter->name);
516
517 /* initialize the audio */
518 client->addr = TLV320_ADDRESS;
519 if (write_regs(client, aud_regs) < 0) {
520 printk(KERN_ERR
521 "s2250: error initializing audio\n");
522 kfree(client);
523 kfree(dec);
524 return 0;
525 }
526 client->addr = S2250_VIDDEC;
527 i2c_set_clientdata(client, dec);
528
529 if (write_regs(client, vid_regs) < 0) {
530 printk(KERN_ERR
531 "s2250: error initializing decoder\n");
532 kfree(client);
533 kfree(dec);
534 return 0;
535 }
536 if (write_regs_fp(client, vid_regs_fp) < 0) {
537 printk(KERN_ERR
538 "s2250: error initializing decoder\n");
539 kfree(client);
540 kfree(dec);
541 return 0;
542 }
543 /* set default channel */
544 /* composite */
545 write_reg_fp(client, 0x20, 0x020 | 1);
546 write_reg_fp(client, 0x21, 0x662);
547 write_reg_fp(client, 0x140, 0x060);
548
549 /* set default audio input */
550 dec->audio_input = 0;
551 write_reg(client, 0x08, 0x02); /* Line In */
552
553 if (down_interruptible(&usb->i2c_lock) == 0) {
554 data = kzalloc(16, GFP_KERNEL);
555 if (data != NULL) {
556 int rc;
557 rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
558 data, 16, 1);
559 if (rc > 0) {
560 u8 mask;
561 data[0] = 0;
562 mask = 1<<5;
563 data[0] &= ~mask;
564 data[1] |= mask;
565 go7007_usb_vendor_request(go, 0x40, 0,
566 (data[1]<<8)
567 + data[1],
568 data, 16, 0);
569 }
570 kfree(data);
571 }
572 up(&usb->i2c_lock);
573 }
574
575 i2c_attach_client(client);
576 printk("s2250: initialized successfully\n");
577 return 0;
578}
579
580static int s2250_detach(struct i2c_client *client)
581{
582 struct s2250 *dec = i2c_get_clientdata(client);
583 int r;
584
585 r = i2c_detach_client(client);
586 if (r < 0)
587 return r;
588
589 kfree(client);
590 kfree(dec);
591 return 0;
592}
593
594static struct i2c_driver s2250_driver = {
595 .driver = {
596 .name = "Sensoray 2250 board driver",
597 },
598 .id = I2C_DRIVERID_S2250,
599 .detach_client = s2250_detach,
600 .command = s2250_command,
601};
602
603static int __init s2250_init(void)
604{
605 int r;
606
607 r = s2250loader_init();
608 if (r < 0)
609 return r;
610
611 r = i2c_add_driver(&s2250_driver);
612 if (r < 0)
613 return r;
614 return wis_i2c_add_driver(s2250_driver.id, s2250_detect);
615}
616
617static void __exit s2250_cleanup(void)
618{
619 wis_i2c_del_driver(s2250_detect);
620 i2c_del_driver(&s2250_driver);
621
622 s2250loader_cleanup();
623}
624
625module_init(s2250_init);
626module_exit(s2250_cleanup);
627
628MODULE_AUTHOR("");
629MODULE_DESCRIPTION("Board driver for Sensoryray 2250");
630MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c
new file mode 100644
index 00000000000..a5e4acab089
--- /dev/null
+++ b/drivers/staging/go7007/s2250-loader.c
@@ -0,0 +1,188 @@
1/*
2 * Copyright (C) 2008 Sensoray Company Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License (Version 2) as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
16 */
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/usb.h>
21#include <dvb-usb.h>
22
23#define S2250_LOADER_FIRMWARE "s2250_loader.fw"
24#define S2250_FIRMWARE "s2250.fw"
25
26typedef struct device_extension_s {
27 struct kref kref;
28 int minor;
29 struct usb_device *usbdev;
30} device_extension_t, *pdevice_extension_t;
31
32#define USB_s2250loader_MAJOR 240
33#define USB_s2250loader_MINOR_BASE 0
34#define MAX_DEVICES 256
35
36static pdevice_extension_t s2250_dev_table[MAX_DEVICES];
37static DECLARE_MUTEX(s2250_dev_table_mutex);
38
39#define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref)
40static void s2250loader_delete(struct kref *kref)
41{
42 pdevice_extension_t s = to_s2250loader_dev_common(kref);
43 s2250_dev_table[s->minor] = NULL;
44 kfree(s);
45}
46
47static int s2250loader_probe(struct usb_interface *interface,
48 const struct usb_device_id *id)
49{
50 struct usb_device *usbdev;
51 int minor, ret;
52 pdevice_extension_t s = NULL;
53 const struct firmware *fw;
54
55 usbdev = usb_get_dev(interface_to_usbdev(interface));
56 if (!usbdev) {
57 printk(KERN_ERR "Enter s2250loader_probe failed\n");
58 return -1;
59 }
60 printk(KERN_INFO "Enter s2250loader_probe 2.6 kernel\n");
61 printk(KERN_INFO "vendor id 0x%x, device id 0x%x devnum:%d\n",
62 usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
63 usbdev->devnum);
64
65 if (usbdev->descriptor.bNumConfigurations != 1) {
66 printk(KERN_ERR "can't handle multiple config\n");
67 return -1;
68 }
69 down(&s2250_dev_table_mutex);
70
71 for (minor = 0; minor < MAX_DEVICES; minor++) {
72 if (s2250_dev_table[minor] == NULL)
73 break;
74 }
75
76 if (minor < 0 || minor >= MAX_DEVICES) {
77 printk(KERN_ERR "Invalid minor: %d\n", minor);
78 goto failed;
79 }
80
81 /* Allocate dev data structure */
82 s = kmalloc(sizeof(device_extension_t), GFP_KERNEL);
83 if (s == NULL) {
84 printk(KERN_ERR "Out of memory\n");
85 goto failed;
86 }
87 s2250_dev_table[minor] = s;
88
89 printk(KERN_INFO "s2250loader_probe: Device %d on Bus %d Minor %d\n",
90 usbdev->devnum, usbdev->bus->busnum, minor);
91
92 memset(s, 0, sizeof(device_extension_t));
93 s->usbdev = usbdev;
94 printk(KERN_INFO "loading 2250 loader\n");
95
96 kref_init(&(s->kref));
97
98 up(&s2250_dev_table_mutex);
99
100 if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) {
101 printk(KERN_ERR
102 "s2250: unable to load firmware from file \"%s\"\n",
103 S2250_LOADER_FIRMWARE);
104 goto failed2;
105 }
106 ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
107 release_firmware(fw);
108 if (0 != ret) {
109 printk(KERN_ERR "loader download failed\n");
110 goto failed2;
111 }
112
113 if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) {
114 printk(KERN_ERR
115 "s2250: unable to load firmware from file \"%s\"\n",
116 S2250_FIRMWARE);
117 goto failed2;
118 }
119 ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
120 release_firmware(fw);
121 if (0 != ret) {
122 printk(KERN_ERR "firmware_s2250 download failed\n");
123 goto failed2;
124 }
125
126 usb_set_intfdata(interface, s);
127 return 0;
128
129failed:
130 up(&s2250_dev_table_mutex);
131failed2:
132 if (s)
133 kref_put(&(s->kref), s2250loader_delete);
134
135 printk(KERN_ERR "probe failed\n");
136 return -1;
137}
138
139static void s2250loader_disconnect(struct usb_interface *interface)
140{
141 pdevice_extension_t s = usb_get_intfdata(interface);
142 printk(KERN_INFO "s2250: disconnect\n");
143 lock_kernel();
144 s = usb_get_intfdata(interface);
145 usb_set_intfdata(interface, NULL);
146 kref_put(&(s->kref), s2250loader_delete);
147 unlock_kernel();
148}
149
150static struct usb_device_id s2250loader_ids[] = {
151 {USB_DEVICE(0x1943, 0xa250)},
152 {} /* Terminating entry */
153};
154
155MODULE_DEVICE_TABLE(usb, s2250loader_ids);
156
157static struct usb_driver s2250loader_driver = {
158 .name = "s2250-loader",
159 .probe = s2250loader_probe,
160 .disconnect = s2250loader_disconnect,
161 .id_table = s2250loader_ids,
162};
163
164int s2250loader_init(void)
165{
166 int r;
167 unsigned i = 0;
168
169 for (i = 0; i < MAX_DEVICES; i++)
170 s2250_dev_table[i] = NULL;
171
172 r = usb_register(&s2250loader_driver);
173 if (r) {
174 printk(KERN_ERR "usb_register failed. Error number %d\n", r);
175 return -1;
176 }
177
178 printk(KERN_INFO "s2250loader_init: driver registered\n");
179 return 0;
180}
181EXPORT_SYMBOL(s2250loader_init);
182
183void s2250loader_cleanup(void)
184{
185 printk(KERN_INFO "s2250loader_cleanup\n");
186 usb_deregister(&s2250loader_driver);
187}
188EXPORT_SYMBOL(s2250loader_cleanup);
diff --git a/drivers/staging/go7007/wis-i2c.h b/drivers/staging/go7007/wis-i2c.h
index 993f658ad73..431f41dd396 100644
--- a/drivers/staging/go7007/wis-i2c.h
+++ b/drivers/staging/go7007/wis-i2c.h
@@ -23,6 +23,7 @@
23#define I2C_DRIVERID_WIS_SAA7113 0xf0f4 23#define I2C_DRIVERID_WIS_SAA7113 0xf0f4
24#define I2C_DRIVERID_WIS_OV7640 0xf0f5 24#define I2C_DRIVERID_WIS_OV7640 0xf0f5
25#define I2C_DRIVERID_WIS_TW2804 0xf0f6 25#define I2C_DRIVERID_WIS_TW2804 0xf0f6
26#define I2C_DRIVERID_S2250 0xf0f7
26#define I2C_ALGO_GO7007 0xf00000 27#define I2C_ALGO_GO7007 0xf00000
27#define I2C_ALGO_GO7007_USB 0xf10000 28#define I2C_ALGO_GO7007_USB 0xf10000
28 29