• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/go7007/
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 <linux/slab.h>
24#include <media/v4l2-device.h>
25#include <media/v4l2-common.h>
26#include <media/v4l2-i2c-drv.h>
27#include <media/v4l2-subdev.h>
28#include "go7007-priv.h"
29
30MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver");
31MODULE_LICENSE("GPL v2");
32
33#define TLV320_ADDRESS      0x34
34#define VPX322_ADDR_ANALOGCONTROL1	0x02
35#define VPX322_ADDR_BRIGHTNESS0		0x0127
36#define VPX322_ADDR_BRIGHTNESS1		0x0131
37#define VPX322_ADDR_CONTRAST0		0x0128
38#define VPX322_ADDR_CONTRAST1		0x0132
39#define VPX322_ADDR_HUE			0x00dc
40#define VPX322_ADDR_SAT			0x0030
41
42struct go7007_usb_board {
43	unsigned int flags;
44	struct go7007_board_info main_info;
45};
46
47struct go7007_usb {
48	struct go7007_usb_board *board;
49	struct mutex i2c_lock;
50	struct usb_device *usbdev;
51	struct urb *video_urbs[8];
52	struct urb *audio_urbs[8];
53	struct urb *intr_urb;
54};
55
56static unsigned char aud_regs[] = {
57	0x1e, 0x00,
58	0x00, 0x17,
59	0x02, 0x17,
60	0x04, 0xf9,
61	0x06, 0xf9,
62	0x08, 0x02,
63	0x0a, 0x00,
64	0x0c, 0x00,
65	0x0a, 0x00,
66	0x0c, 0x00,
67	0x0e, 0x02,
68	0x10, 0x00,
69	0x12, 0x01,
70	0x00, 0x00,
71};
72
73
74static unsigned char vid_regs[] = {
75	0xF2, 0x0f,
76	0xAA, 0x00,
77	0xF8, 0xff,
78	0x00, 0x00,
79};
80
81static u16 vid_regs_fp[] = {
82	0x028, 0x067,
83	0x120, 0x016,
84	0x121, 0xcF2,
85	0x122, 0x0F2,
86	0x123, 0x00c,
87	0x124, 0x2d0,
88	0x125, 0x2e0,
89	0x126, 0x004,
90	0x128, 0x1E0,
91	0x12A, 0x016,
92	0x12B, 0x0F2,
93	0x12C, 0x0F2,
94	0x12D, 0x00c,
95	0x12E, 0x2d0,
96	0x12F, 0x2e0,
97	0x130, 0x004,
98	0x132, 0x1E0,
99	0x140, 0x060,
100	0x153, 0x00C,
101	0x154, 0x200,
102	0x150, 0x801,
103	0x000, 0x000
104};
105
106/* PAL specific values */
107static u16 vid_regs_fp_pal[] =
108{
109	0x120, 0x017,
110	0x121, 0xd22,
111	0x122, 0x122,
112	0x12A, 0x017,
113	0x12B, 0x122,
114	0x12C, 0x122,
115	0x140, 0x060,
116	0x000, 0x000,
117};
118
119struct s2250 {
120	struct v4l2_subdev sd;
121	v4l2_std_id std;
122	int input;
123	int brightness;
124	int contrast;
125	int saturation;
126	int hue;
127	int reg12b_val;
128	int audio_input;
129	struct i2c_client *audio;
130};
131
132static inline struct s2250 *to_state(struct v4l2_subdev *sd)
133{
134	return container_of(sd, struct s2250, sd);
135}
136
137/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
138static int go7007_usb_vendor_request(struct go7007 *go, u16 request,
139	u16 value, u16 index, void *transfer_buffer, int length, int in)
140{
141	struct go7007_usb *usb = go->hpi_context;
142	int timeout = 5000;
143
144	if (in) {
145		return usb_control_msg(usb->usbdev,
146				usb_rcvctrlpipe(usb->usbdev, 0), request,
147				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
148				value, index, transfer_buffer, length, timeout);
149	} else {
150		return usb_control_msg(usb->usbdev,
151				usb_sndctrlpipe(usb->usbdev, 0), request,
152				USB_TYPE_VENDOR | USB_RECIP_DEVICE,
153				value, index, transfer_buffer, length, timeout);
154	}
155}
156/* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
157
158static int write_reg(struct i2c_client *client, u8 reg, u8 value)
159{
160	struct go7007 *go = i2c_get_adapdata(client->adapter);
161	struct go7007_usb *usb;
162	int rc;
163	int dev_addr = client->addr << 1;  /* firmware wants 8-bit address */
164	u8 *buf;
165
166	if (go == NULL)
167		return -ENODEV;
168
169	if (go->status == STATUS_SHUTDOWN)
170		return -EBUSY;
171
172	buf = kzalloc(16, GFP_KERNEL);
173	if (buf == NULL)
174		return -ENOMEM;
175
176	usb = go->hpi_context;
177	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
178		printk(KERN_INFO "i2c lock failed\n");
179		kfree(buf);
180		return -EINTR;
181	}
182	rc = go7007_usb_vendor_request(go, 0x55, dev_addr,
183				       (reg<<8 | value),
184				       buf,
185				       16, 1);
186
187	mutex_unlock(&usb->i2c_lock);
188	kfree(buf);
189	return rc;
190}
191
192static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
193{
194	struct go7007 *go = i2c_get_adapdata(client->adapter);
195	struct go7007_usb *usb;
196	u8 *buf;
197	struct s2250 *dec = i2c_get_clientdata(client);
198
199	if (go == NULL)
200		return -ENODEV;
201
202	if (go->status == STATUS_SHUTDOWN)
203		return -EBUSY;
204
205	buf = kzalloc(16, GFP_KERNEL);
206
207	if (buf == NULL)
208		return -ENOMEM;
209
210
211
212	memset(buf, 0xcd, 6);
213
214	usb = go->hpi_context;
215	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
216		printk(KERN_INFO "i2c lock failed\n");
217		kfree(buf);
218		return -EINTR;
219	}
220	if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0) {
221		kfree(buf);
222		return -EFAULT;
223	}
224
225	mutex_unlock(&usb->i2c_lock);
226	if (buf[0] == 0) {
227		unsigned int subaddr, val_read;
228
229		subaddr = (buf[4] << 8) + buf[5];
230		val_read = (buf[2] << 8) + buf[3];
231		kfree(buf);
232		if (val_read != val) {
233			printk(KERN_INFO "invalid fp write %x %x\n",
234			       val_read, val);
235			return -EFAULT;
236		}
237		if (subaddr != addr) {
238			printk(KERN_INFO "invalid fp write addr %x %x\n",
239			       subaddr, addr);
240			return -EFAULT;
241		}
242	} else {
243		kfree(buf);
244		return -EFAULT;
245	}
246
247	/* save last 12b value */
248	if (addr == 0x12b)
249		dec->reg12b_val = val;
250
251	return 0;
252}
253
254static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val)
255{
256	struct go7007 *go = i2c_get_adapdata(client->adapter);
257	struct go7007_usb *usb;
258	u8 *buf;
259
260	if (go == NULL)
261		return -ENODEV;
262
263	if (go->status == STATUS_SHUTDOWN)
264		return -EBUSY;
265
266	buf = kzalloc(16, GFP_KERNEL);
267
268	if (buf == NULL)
269		return -ENOMEM;
270
271
272
273	memset(buf, 0xcd, 6);
274	usb = go->hpi_context;
275	if (mutex_lock_interruptible(&usb->i2c_lock) != 0) {
276		printk(KERN_INFO "i2c lock failed\n");
277		kfree(buf);
278		return -EINTR;
279	}
280	if (go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1) < 0) {
281		kfree(buf);
282		return -EFAULT;
283	}
284	mutex_unlock(&usb->i2c_lock);
285
286	*val = (buf[0] << 8) | buf[1];
287	kfree(buf);
288
289	return 0;
290}
291
292
293static int write_regs(struct i2c_client *client, u8 *regs)
294{
295	int i;
296
297	for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
298		if (write_reg(client, regs[i], regs[i+1]) < 0) {
299			printk(KERN_INFO "s2250: failed\n");
300			return -1;
301		}
302	}
303	return 0;
304}
305
306static int write_regs_fp(struct i2c_client *client, u16 *regs)
307{
308	int i;
309
310	for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
311		if (write_reg_fp(client, regs[i], regs[i+1]) < 0) {
312			printk(KERN_INFO "s2250: failed fp\n");
313			return -1;
314		}
315	}
316	return 0;
317}
318
319
320/* ------------------------------------------------------------------------- */
321
322static int s2250_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output,
323				 u32 config)
324{
325	struct s2250 *state = to_state(sd);
326	struct i2c_client *client = v4l2_get_subdevdata(sd);
327	int vidsys;
328
329	vidsys = (state->std == V4L2_STD_NTSC) ? 0x01 : 0x00;
330	if (input == 0) {
331		/* composite */
332		write_reg_fp(client, 0x20, 0x020 | vidsys);
333		write_reg_fp(client, 0x21, 0x662);
334		write_reg_fp(client, 0x140, 0x060);
335	} else if (input == 1) {
336		/* S-Video */
337		write_reg_fp(client, 0x20, 0x040 | vidsys);
338		write_reg_fp(client, 0x21, 0x666);
339		write_reg_fp(client, 0x140, 0x060);
340	} else {
341		return -EINVAL;
342	}
343	state->input = input;
344	return 0;
345}
346
347static int s2250_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
348{
349	struct s2250 *state = to_state(sd);
350	struct i2c_client *client = v4l2_get_subdevdata(sd);
351	u16 vidsource;
352
353	vidsource = (state->input == 1) ? 0x040 : 0x020;
354	switch (norm) {
355	case V4L2_STD_NTSC:
356		write_regs_fp(client, vid_regs_fp);
357		write_reg_fp(client, 0x20, vidsource | 1);
358		break;
359	case V4L2_STD_PAL:
360		write_regs_fp(client, vid_regs_fp);
361		write_regs_fp(client, vid_regs_fp_pal);
362		write_reg_fp(client, 0x20, vidsource);
363		break;
364	default:
365		return -EINVAL;
366	}
367	state->std = norm;
368	return 0;
369}
370
371static int s2250_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *query)
372{
373	switch (query->id) {
374	case V4L2_CID_BRIGHTNESS:
375		return v4l2_ctrl_query_fill(query, 0, 100, 1, 50);
376	case V4L2_CID_CONTRAST:
377		return v4l2_ctrl_query_fill(query, 0, 100, 1, 50);
378	case V4L2_CID_SATURATION:
379		return v4l2_ctrl_query_fill(query, 0, 100, 1, 50);
380	case V4L2_CID_HUE:
381		return v4l2_ctrl_query_fill(query, -50, 50, 1, 0);
382	default:
383		return -EINVAL;
384	}
385	return 0;
386}
387
388static int s2250_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
389{
390	struct s2250 *state = to_state(sd);
391	struct i2c_client *client = v4l2_get_subdevdata(sd);
392	int value1;
393	u16 oldvalue;
394
395	switch (ctrl->id) {
396	case V4L2_CID_BRIGHTNESS:
397		if (ctrl->value > 100)
398			state->brightness = 100;
399		else if (ctrl->value < 0)
400			state->brightness = 0;
401		else
402			state->brightness = ctrl->value;
403		value1 = (state->brightness - 50) * 255 / 100;
404		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue);
405		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0,
406			     value1 | (oldvalue & ~0xff));
407		read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue);
408		write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1,
409			     value1 | (oldvalue & ~0xff));
410		write_reg_fp(client, 0x140, 0x60);
411		break;
412	case V4L2_CID_CONTRAST:
413		if (ctrl->value > 100)
414			state->contrast = 100;
415		else if (ctrl->value < 0)
416			state->contrast = 0;
417		else
418			state->contrast = ctrl->value;
419		value1 = state->contrast * 0x40 / 100;
420		if (value1 > 0x3f)
421			value1 = 0x3f; /* max */
422		read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue);
423		write_reg_fp(client, VPX322_ADDR_CONTRAST0,
424			     value1 | (oldvalue & ~0x3f));
425		read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue);
426		write_reg_fp(client, VPX322_ADDR_CONTRAST1,
427			     value1 | (oldvalue & ~0x3f));
428		write_reg_fp(client, 0x140, 0x60);
429		break;
430	case V4L2_CID_SATURATION:
431		if (ctrl->value > 100)
432			state->saturation = 100;
433		else if (ctrl->value < 0)
434			state->saturation = 0;
435		else
436			state->saturation = ctrl->value;
437		value1 = state->saturation * 4140 / 100;
438		if (value1 > 4094)
439			value1 = 4094;
440		write_reg_fp(client, VPX322_ADDR_SAT, value1);
441		break;
442	case V4L2_CID_HUE:
443		if (ctrl->value > 50)
444			state->hue = 50;
445		else if (ctrl->value < -50)
446			state->hue = -50;
447		else
448			state->hue = ctrl->value;
449		/* clamp the hue range */
450		value1 = state->hue * 280 / 50;
451		write_reg_fp(client, VPX322_ADDR_HUE, value1);
452		break;
453	default:
454		return -EINVAL;
455	}
456	return 0;
457}
458
459static int s2250_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
460{
461	struct s2250 *state = to_state(sd);
462
463	switch (ctrl->id) {
464	case V4L2_CID_BRIGHTNESS:
465		ctrl->value = state->brightness;
466		break;
467	case V4L2_CID_CONTRAST:
468		ctrl->value = state->contrast;
469		break;
470	case V4L2_CID_SATURATION:
471		ctrl->value = state->saturation;
472		break;
473	case V4L2_CID_HUE:
474		ctrl->value = state->hue;
475		break;
476	default:
477		return -EINVAL;
478	}
479	return 0;
480}
481
482static int s2250_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
483{
484	struct s2250 *state = to_state(sd);
485	struct i2c_client *client = v4l2_get_subdevdata(sd);
486
487	if (fmt->fmt.pix.height < 640) {
488		write_reg_fp(client, 0x12b, state->reg12b_val | 0x400);
489		write_reg_fp(client, 0x140, 0x060);
490	} else {
491		write_reg_fp(client, 0x12b, state->reg12b_val & ~0x400);
492		write_reg_fp(client, 0x140, 0x060);
493	}
494	return 0;
495}
496
497static int s2250_s_audio_routing(struct v4l2_subdev *sd, u32 input, u32 output,
498				 u32 config)
499{
500	struct s2250 *state = to_state(sd);
501
502	switch (input) {
503	case 0:
504		write_reg(state->audio, 0x08, 0x02); /* Line In */
505		break;
506	case 1:
507		write_reg(state->audio, 0x08, 0x04); /* Mic */
508		break;
509	case 2:
510		write_reg(state->audio, 0x08, 0x05); /* Mic Boost */
511		break;
512	default:
513		return -EINVAL;
514	}
515	state->audio_input = input;
516	return 0;
517}
518
519
520static int s2250_log_status(struct v4l2_subdev *sd)
521{
522	struct s2250 *state = to_state(sd);
523
524	v4l2_info(sd, "Standard: %s\n", state->std == V4L2_STD_NTSC ? "NTSC" :
525					state->std == V4L2_STD_PAL ? "PAL" :
526					state->std == V4L2_STD_SECAM ? "SECAM" :
527					"unknown");
528	v4l2_info(sd, "Input: %s\n", state->input == 0 ? "Composite" :
529					state->input == 1 ? "S-video" :
530					"error");
531	v4l2_info(sd, "Brightness: %d\n", state->brightness);
532	v4l2_info(sd, "Contrast: %d\n", state->contrast);
533	v4l2_info(sd, "Saturation: %d\n", state->saturation);
534	v4l2_info(sd, "Hue: %d\n", state->hue);	return 0;
535	v4l2_info(sd, "Audio input: %s\n", state->audio_input == 0 ? "Line In" :
536					state->audio_input == 1 ? "Mic" :
537					state->audio_input == 2 ? "Mic Boost" :
538					"error");
539	return 0;
540}
541
542/* --------------------------------------------------------------------------*/
543
544static const struct v4l2_subdev_core_ops s2250_core_ops = {
545	.log_status = s2250_log_status,
546	.g_ctrl = s2250_g_ctrl,
547	.s_ctrl = s2250_s_ctrl,
548	.queryctrl = s2250_queryctrl,
549	.s_std = s2250_s_std,
550};
551
552static const struct v4l2_subdev_audio_ops s2250_audio_ops = {
553	.s_routing = s2250_s_audio_routing,
554};
555
556static const struct v4l2_subdev_video_ops s2250_video_ops = {
557	.s_routing = s2250_s_video_routing,
558	.s_fmt = s2250_s_fmt,
559};
560
561static const struct v4l2_subdev_ops s2250_ops = {
562	.core = &s2250_core_ops,
563	.audio = &s2250_audio_ops,
564	.video = &s2250_video_ops,
565};
566
567/* --------------------------------------------------------------------------*/
568
569static int s2250_probe(struct i2c_client *client,
570		       const struct i2c_device_id *id)
571{
572	struct i2c_client *audio;
573	struct i2c_adapter *adapter = client->adapter;
574	struct s2250 *state;
575	struct v4l2_subdev *sd;
576	u8 *data;
577	struct go7007 *go = i2c_get_adapdata(adapter);
578	struct go7007_usb *usb = go->hpi_context;
579
580	audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1);
581	if (audio == NULL)
582		return -ENOMEM;
583
584	state = kmalloc(sizeof(struct s2250), GFP_KERNEL);
585	if (state == NULL) {
586		i2c_unregister_device(audio);
587		return -ENOMEM;
588	}
589
590	sd = &state->sd;
591	v4l2_i2c_subdev_init(sd, client, &s2250_ops);
592
593	v4l2_info(sd, "initializing %s at address 0x%x on %s\n",
594	       "Sensoray 2250/2251", client->addr, client->adapter->name);
595
596	state->std = V4L2_STD_NTSC;
597	state->brightness = 50;
598	state->contrast = 50;
599	state->saturation = 50;
600	state->hue = 0;
601	state->audio = audio;
602
603	/* initialize the audio */
604	if (write_regs(audio, aud_regs) < 0) {
605		printk(KERN_ERR
606		       "s2250: error initializing audio\n");
607		i2c_unregister_device(audio);
608		kfree(state);
609		return 0;
610	}
611
612	if (write_regs(client, vid_regs) < 0) {
613		printk(KERN_ERR
614		       "s2250: error initializing decoder\n");
615		i2c_unregister_device(audio);
616		kfree(state);
617		return 0;
618	}
619	if (write_regs_fp(client, vid_regs_fp) < 0) {
620		printk(KERN_ERR
621		       "s2250: error initializing decoder\n");
622		i2c_unregister_device(audio);
623		kfree(state);
624		return 0;
625	}
626	/* set default channel */
627	/* composite */
628	write_reg_fp(client, 0x20, 0x020 | 1);
629	write_reg_fp(client, 0x21, 0x662);
630	write_reg_fp(client, 0x140, 0x060);
631
632	/* set default audio input */
633	state->audio_input = 0;
634	write_reg(client, 0x08, 0x02); /* Line In */
635
636	if (mutex_lock_interruptible(&usb->i2c_lock) == 0) {
637		data = kzalloc(16, GFP_KERNEL);
638		if (data != NULL) {
639			int rc;
640			rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
641						       data, 16, 1);
642			if (rc > 0) {
643				u8 mask;
644				data[0] = 0;
645				mask = 1<<5;
646				data[0] &= ~mask;
647				data[1] |= mask;
648				go7007_usb_vendor_request(go, 0x40, 0,
649							  (data[1]<<8)
650							  + data[1],
651							  data, 16, 0);
652			}
653			kfree(data);
654		}
655		mutex_unlock(&usb->i2c_lock);
656	}
657
658	v4l2_info(sd, "initialized successfully\n");
659	return 0;
660}
661
662static int s2250_remove(struct i2c_client *client)
663{
664	struct v4l2_subdev *sd = i2c_get_clientdata(client);
665
666	v4l2_device_unregister_subdev(sd);
667	kfree(to_state(sd));
668	return 0;
669}
670
671static const struct i2c_device_id s2250_id[] = {
672	{ "s2250", 0 },
673	{ }
674};
675MODULE_DEVICE_TABLE(i2c, s2250_id);
676
677static struct v4l2_i2c_driver_data v4l2_i2c_data = {
678	.name = "s2250",
679	.probe = s2250_probe,
680	.remove = s2250_remove,
681	.id_table = s2250_id,
682};
683