x86: remove vestigial fix_ioremap prototypes
[linux-2.6/mini2440.git] / drivers / staging / go7007 / s2250-board.c
blobfb6845e37884da7202a79271943baeb4608c578f
1 /*
2 * Copyright (C) 2008 Sensoray Company Inc.
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.
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.
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.
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"
27 extern int s2250loader_init(void);
28 extern void s2250loader_cleanup(void);
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
40 struct go7007_usb_board {
41 unsigned int flags;
42 struct go7007_board_info main_info;
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;
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,
72 static unsigned char vid_regs[] = {
73 0xF2, 0x0f,
74 0xAA, 0x00,
75 0xF8, 0xff,
76 0x00, 0x00,
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
104 /* PAL specific values */
105 static u16 vid_regs_fp_pal[] =
107 0x120, 0x017,
108 0x121, 0xd22,
109 0x122, 0x122,
110 0x12A, 0x017,
111 0x12B, 0x122,
112 0x12C, 0x122,
113 0x140, 0x060,
114 0x000, 0x000,
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;
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)
132 struct go7007_usb *usb = go->hpi_context;
133 int timeout = 5000;
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);
147 /* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
149 static int write_reg(struct i2c_client *client, u8 reg, u8 value)
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;
157 if (go == NULL)
158 return -ENODEV;
160 if (go->status == STATUS_SHUTDOWN)
161 return -EBUSY;
163 buf = kzalloc(16, GFP_KERNEL);
164 if (buf == NULL)
165 return -ENOMEM;
167 if (down_interruptible(&usb->i2c_lock) != 0) {
168 printk(KERN_INFO "i2c lock failed\n");
169 return -EINTR;
171 rc = go7007_usb_vendor_request(go, 0x55, dev_addr,
172 (reg<<8 | value),
173 buf,
174 16, 1);
176 up(&usb->i2c_lock);
177 kfree(buf);
178 return rc;
181 static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
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);
188 if (go == NULL)
189 return -ENODEV;
191 if (go->status == STATUS_SHUTDOWN)
192 return -EBUSY;
194 buf = kzalloc(16, GFP_KERNEL);
196 if (buf == NULL)
197 return -ENOMEM;
201 memset(buf, 0xcd, 6);
203 if (down_interruptible(&usb->i2c_lock) != 0) {
204 printk(KERN_INFO "i2c lock failed\n");
205 return -EINTR;
207 if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0)
208 return -EFAULT;
210 up(&usb->i2c_lock);
211 if (buf[0] == 0) {
212 unsigned int subaddr, val_read;
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;
221 if (subaddr != addr) {
222 printk(KERN_INFO "invalid fp write addr %x %x\n",
223 subaddr, addr);
224 return -EFAULT;
226 } else
227 return -EFAULT;
229 /* save last 12b value */
230 if (addr == 0x12b)
231 dec->reg12b_val = val;
233 return 0;
236 static int write_regs(struct i2c_client *client, u8 *regs)
238 int i;
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;
246 return 0;
249 static int write_regs_fp(struct i2c_client *client, u16 *regs)
251 int i;
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;
259 return 0;
263 static int s2250_command(struct i2c_client *client,
264 unsigned int cmd, void *arg)
266 struct s2250 *dec = i2c_get_clientdata(client);
268 switch (cmd) {
269 case VIDIOC_S_INPUT:
271 int vidsys;
272 int *input = arg;
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);
286 dec->input = *input;
287 break;
289 case VIDIOC_S_STD:
291 v4l2_std_id *std = arg;
292 u16 vidsource;
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;
309 break;
311 case VIDIOC_QUERYCTRL:
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,
321 static const u32 *ctrl_classes[] = {
322 user_ctrls,
323 NULL
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;
344 break;
346 case VIDIOC_S_CTRL:
348 struct v4l2_control *ctrl = arg;
349 int value1;
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;
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;
384 break;
386 case VIDIOC_G_CTRL:
388 struct v4l2_control *ctrl = arg;
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;
404 break;
406 case VIDIOC_S_FMT:
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);
416 return 0;
418 case VIDIOC_G_AUDIO:
420 struct v4l2_audio *audio = arg;
422 memset(audio, 0, sizeof(*audio));
423 audio->index = dec->audio_input;
424 /* fall through */
426 case VIDIOC_ENUMAUDIO:
428 struct v4l2_audio *audio = arg;
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;
444 audio->capability = V4L2_AUDCAP_STEREO;
445 audio->mode = 0;
446 return 0;
448 case VIDIOC_S_AUDIO:
450 struct v4l2_audio *audio = arg;
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;
466 dec->audio_input = audio->index;
467 return 0;
470 default:
471 printk(KERN_INFO "s2250: unknown command 0x%x\n", cmd);
472 break;
474 return 0;
477 static struct i2c_driver s2250_driver;
479 static struct i2c_client s2250_client_templ = {
480 .name = "Sensoray 2250",
481 .driver = &s2250_driver,
484 static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
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;
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;
499 dec = kmalloc(sizeof(struct s2250), GFP_KERNEL);
500 if (dec == NULL) {
501 kfree(client);
502 return -ENOMEM;
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);
513 printk(KERN_DEBUG
514 "s2250: initializing video decoder on %s\n",
515 adapter->name);
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;
526 client->addr = S2250_VIDDEC;
527 i2c_set_clientdata(client, dec);
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;
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;
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);
549 /* set default audio input */
550 dec->audio_input = 0;
551 write_reg(client, 0x08, 0x02); /* Line In */
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);
570 kfree(data);
572 up(&usb->i2c_lock);
575 i2c_attach_client(client);
576 printk("s2250: initialized successfully\n");
577 return 0;
580 static int s2250_detach(struct i2c_client *client)
582 struct s2250 *dec = i2c_get_clientdata(client);
583 int r;
585 r = i2c_detach_client(client);
586 if (r < 0)
587 return r;
589 kfree(client);
590 kfree(dec);
591 return 0;
594 static struct i2c_driver s2250_driver = {
595 .driver = {
596 .name = "Sensoray 2250 board driver",
598 .id = I2C_DRIVERID_S2250,
599 .detach_client = s2250_detach,
600 .command = s2250_command,
603 static int __init s2250_init(void)
605 int r;
607 r = s2250loader_init();
608 if (r < 0)
609 return r;
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);
617 static void __exit s2250_cleanup(void)
619 wis_i2c_del_driver(s2250_detect);
620 i2c_del_driver(&s2250_driver);
622 s2250loader_cleanup();
625 module_init(s2250_init);
626 module_exit(s2250_cleanup);
628 MODULE_AUTHOR("");
629 MODULE_DESCRIPTION("Board driver for Sensoryray 2250");
630 MODULE_LICENSE("GPL v2");