diff options
author | Pete Eberlein <pete@sensoray.com> | 2008-10-30 15:56:41 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-06 16:52:06 -0500 |
commit | b11869dbb6cc4b4de8da302f758866d0a167a277 (patch) | |
tree | fcd58485278741bd1d96f03e3dbf0c3540082898 /drivers/staging | |
parent | d73f822ce775e004836ffc01ce9feae27d0d65cf (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/Kconfig | 10 | ||||
-rw-r--r-- | drivers/staging/go7007/Makefile | 15 | ||||
-rw-r--r-- | drivers/staging/go7007/go7007-driver.c | 3 | ||||
-rw-r--r-- | drivers/staging/go7007/go7007-priv.h | 1 | ||||
-rw-r--r-- | drivers/staging/go7007/go7007-usb.c | 48 | ||||
-rw-r--r-- | drivers/staging/go7007/s2250-board.c | 630 | ||||
-rw-r--r-- | drivers/staging/go7007/s2250-loader.c | 188 | ||||
-rw-r--r-- | drivers/staging/go7007/wis-i2c.h | 1 |
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 | ||
28 | config 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 | ||
6 | obj-$(CONFIG_VIDEO_GO7007) += go7007.o | 6 | obj-$(CONFIG_VIDEO_GO7007) += go7007.o |
7 | obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o | 7 | obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o |
8 | obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o | ||
8 | 9 | ||
9 | go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o snd-go7007.o | 10 | go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ |
11 | snd-go7007.o wis-saa7113.o | ||
10 | 12 | ||
13 | s2250-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 | ||
21 | ifneq ($(CONFIG_VIDEO_GO7007_USB_S2250_BOARD),) | ||
22 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb | ||
23 | endif | ||
24 | |||
16 | EXTRA_CFLAGS += -Idrivers/staging/saa7134 | 25 | EXTRA_CFLAGS += -Idrivers/staging/saa7134 |
17 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 26 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
18 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 27 | EXTRA_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 | ||
401 | static 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 | |||
401 | static struct usb_device_id go7007_usb_id_table[] = { | 436 | static 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 | |||
27 | extern int s2250loader_init(void); | ||
28 | extern 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 | |||
40 | struct go7007_usb_board { | ||
41 | unsigned int flags; | ||
42 | struct go7007_board_info main_info; | ||
43 | }; | ||
44 | |||
45 | struct 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 | |||
54 | static 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 | |||
72 | static unsigned char vid_regs[] = { | ||
73 | 0xF2, 0x0f, | ||
74 | 0xAA, 0x00, | ||
75 | 0xF8, 0xff, | ||
76 | 0x00, 0x00, | ||
77 | }; | ||
78 | |||
79 | static 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 */ | ||
105 | static 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 | |||
117 | struct 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.*/ | ||
129 | static 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 | |||
149 | static 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 | |||
181 | static 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 | |||
236 | static 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 | |||
249 | static 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 | |||
263 | static 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 | |||
477 | static struct i2c_driver s2250_driver; | ||
478 | |||
479 | static struct i2c_client s2250_client_templ = { | ||
480 | .name = "Sensoray 2250", | ||
481 | .driver = &s2250_driver, | ||
482 | }; | ||
483 | |||
484 | static 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 | |||
580 | static 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 | |||
594 | static 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 | |||
603 | static 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 | |||
617 | static 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 | |||
625 | module_init(s2250_init); | ||
626 | module_exit(s2250_cleanup); | ||
627 | |||
628 | MODULE_AUTHOR(""); | ||
629 | MODULE_DESCRIPTION("Board driver for Sensoryray 2250"); | ||
630 | MODULE_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 | |||
26 | typedef 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 | |||
36 | static pdevice_extension_t s2250_dev_table[MAX_DEVICES]; | ||
37 | static DECLARE_MUTEX(s2250_dev_table_mutex); | ||
38 | |||
39 | #define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref) | ||
40 | static 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 | |||
47 | static 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 | |||
129 | failed: | ||
130 | up(&s2250_dev_table_mutex); | ||
131 | failed2: | ||
132 | if (s) | ||
133 | kref_put(&(s->kref), s2250loader_delete); | ||
134 | |||
135 | printk(KERN_ERR "probe failed\n"); | ||
136 | return -1; | ||
137 | } | ||
138 | |||
139 | static 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 | |||
150 | static struct usb_device_id s2250loader_ids[] = { | ||
151 | {USB_DEVICE(0x1943, 0xa250)}, | ||
152 | {} /* Terminating entry */ | ||
153 | }; | ||
154 | |||
155 | MODULE_DEVICE_TABLE(usb, s2250loader_ids); | ||
156 | |||
157 | static struct usb_driver s2250loader_driver = { | ||
158 | .name = "s2250-loader", | ||
159 | .probe = s2250loader_probe, | ||
160 | .disconnect = s2250loader_disconnect, | ||
161 | .id_table = s2250loader_ids, | ||
162 | }; | ||
163 | |||
164 | int 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 | } | ||
181 | EXPORT_SYMBOL(s2250loader_init); | ||
182 | |||
183 | void s2250loader_cleanup(void) | ||
184 | { | ||
185 | printk(KERN_INFO "s2250loader_cleanup\n"); | ||
186 | usb_deregister(&s2250loader_driver); | ||
187 | } | ||
188 | EXPORT_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 | ||