bonding: fix rx_handler locking
[linux/fpc-iii.git] / drivers / staging / go7007 / wis-saa7115.c
blob46cff59e28b7faddddd41c259c3d56815dc446cc
1 /*
2 * Copyright (C) 2005-2006 Micronas USA 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/i2c.h>
21 #include <linux/videodev2.h>
22 #include <linux/ioctl.h>
23 #include <linux/slab.h>
25 #include "wis-i2c.h"
27 struct wis_saa7115 {
28 int norm;
29 int brightness;
30 int contrast;
31 int saturation;
32 int hue;
35 static u8 initial_registers[] =
37 0x01, 0x08,
38 0x02, 0xc0,
39 0x03, 0x20,
40 0x04, 0x80,
41 0x05, 0x80,
42 0x06, 0xeb,
43 0x07, 0xe0,
44 0x08, 0xf0, /* always toggle FID */
45 0x09, 0x40,
46 0x0a, 0x80,
47 0x0b, 0x40,
48 0x0c, 0x40,
49 0x0d, 0x00,
50 0x0e, 0x03,
51 0x0f, 0x2a,
52 0x10, 0x0e,
53 0x11, 0x00,
54 0x12, 0x8d,
55 0x13, 0x00,
56 0x14, 0x00,
57 0x15, 0x11,
58 0x16, 0x01,
59 0x17, 0xda,
60 0x18, 0x40,
61 0x19, 0x80,
62 0x1a, 0x00,
63 0x1b, 0x42,
64 0x1c, 0xa9,
65 0x30, 0x66,
66 0x31, 0x90,
67 0x32, 0x01,
68 0x34, 0x00,
69 0x35, 0x00,
70 0x36, 0x20,
71 0x38, 0x03,
72 0x39, 0x20,
73 0x3a, 0x88,
74 0x40, 0x00,
75 0x41, 0xff,
76 0x42, 0xff,
77 0x43, 0xff,
78 0x44, 0xff,
79 0x45, 0xff,
80 0x46, 0xff,
81 0x47, 0xff,
82 0x48, 0xff,
83 0x49, 0xff,
84 0x4a, 0xff,
85 0x4b, 0xff,
86 0x4c, 0xff,
87 0x4d, 0xff,
88 0x4e, 0xff,
89 0x4f, 0xff,
90 0x50, 0xff,
91 0x51, 0xff,
92 0x52, 0xff,
93 0x53, 0xff,
94 0x54, 0xf4 /*0xff*/,
95 0x55, 0xff,
96 0x56, 0xff,
97 0x57, 0xff,
98 0x58, 0x40,
99 0x59, 0x47,
100 0x5a, 0x06 /*0x03*/,
101 0x5b, 0x83,
102 0x5d, 0x06,
103 0x5e, 0x00,
104 0x80, 0x30, /* window defined scaler operation, task A and B enabled */
105 0x81, 0x03, /* use scaler datapath generated V */
106 0x83, 0x00,
107 0x84, 0x00,
108 0x85, 0x00,
109 0x86, 0x45,
110 0x87, 0x31,
111 0x88, 0xc0,
112 0x90, 0x02, /* task A process top field */
113 0x91, 0x08,
114 0x92, 0x09,
115 0x93, 0x80,
116 0x94, 0x06,
117 0x95, 0x00,
118 0x96, 0xc0,
119 0x97, 0x02,
120 0x98, 0x12,
121 0x99, 0x00,
122 0x9a, 0xf2,
123 0x9b, 0x00,
124 0x9c, 0xd0,
125 0x9d, 0x02,
126 0x9e, 0xf2,
127 0x9f, 0x00,
128 0xa0, 0x01,
129 0xa1, 0x01,
130 0xa2, 0x01,
131 0xa4, 0x80,
132 0xa5, 0x40,
133 0xa6, 0x40,
134 0xa8, 0x00,
135 0xa9, 0x04,
136 0xaa, 0x00,
137 0xac, 0x00,
138 0xad, 0x02,
139 0xae, 0x00,
140 0xb0, 0x00,
141 0xb1, 0x04,
142 0xb2, 0x00,
143 0xb3, 0x04,
144 0xb4, 0x00,
145 0xb8, 0x00,
146 0xbc, 0x00,
147 0xc0, 0x03, /* task B process bottom field */
148 0xc1, 0x08,
149 0xc2, 0x09,
150 0xc3, 0x80,
151 0xc4, 0x06,
152 0xc5, 0x00,
153 0xc6, 0xc0,
154 0xc7, 0x02,
155 0xc8, 0x12,
156 0xc9, 0x00,
157 0xca, 0xf2,
158 0xcb, 0x00,
159 0xcc, 0xd0,
160 0xcd, 0x02,
161 0xce, 0xf2,
162 0xcf, 0x00,
163 0xd0, 0x01,
164 0xd1, 0x01,
165 0xd2, 0x01,
166 0xd4, 0x80,
167 0xd5, 0x40,
168 0xd6, 0x40,
169 0xd8, 0x00,
170 0xd9, 0x04,
171 0xda, 0x00,
172 0xdc, 0x00,
173 0xdd, 0x02,
174 0xde, 0x00,
175 0xe0, 0x00,
176 0xe1, 0x04,
177 0xe2, 0x00,
178 0xe3, 0x04,
179 0xe4, 0x00,
180 0xe8, 0x00,
181 0x88, 0xf0, /* End of original static list */
182 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
185 static int write_reg(struct i2c_client *client, u8 reg, u8 value)
187 return i2c_smbus_write_byte_data(client, reg, value);
190 static int write_regs(struct i2c_client *client, u8 *regs)
192 int i;
194 for (i = 0; regs[i] != 0x00; i += 2)
195 if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
196 return -1;
197 return 0;
200 static int wis_saa7115_command(struct i2c_client *client,
201 unsigned int cmd, void *arg)
203 struct wis_saa7115 *dec = i2c_get_clientdata(client);
205 switch (cmd) {
206 case VIDIOC_S_INPUT:
208 int *input = arg;
210 i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
211 i2c_smbus_write_byte_data(client, 0x09,
212 *input < 6 ? 0x40 : 0xC0);
213 break;
215 case DECODER_SET_RESOLUTION:
217 struct video_decoder_resolution *res = arg;
218 /* Course-grained scaler */
219 int h_integer_scaler = res->width < 704 ? 704 / res->width : 1;
220 /* Fine-grained scaler to take care of remainder */
221 int h_scaling_increment = (704 / h_integer_scaler) *
222 1024 / res->width;
223 /* Fine-grained scaler only */
224 int v_scaling_increment = (dec->norm & V4L2_STD_NTSC ?
225 240 : 288) * 1024 / res->height;
226 u8 regs[] = {
227 0x88, 0xc0,
228 0x9c, res->width & 0xff,
229 0x9d, res->width >> 8,
230 0x9e, res->height & 0xff,
231 0x9f, res->height >> 8,
232 0xa0, h_integer_scaler,
233 0xa1, 1,
234 0xa2, 1,
235 0xa8, h_scaling_increment & 0xff,
236 0xa9, h_scaling_increment >> 8,
237 0xac, (h_scaling_increment / 2) & 0xff,
238 0xad, (h_scaling_increment / 2) >> 8,
239 0xb0, v_scaling_increment & 0xff,
240 0xb1, v_scaling_increment >> 8,
241 0xb2, v_scaling_increment & 0xff,
242 0xb3, v_scaling_increment >> 8,
243 0xcc, res->width & 0xff,
244 0xcd, res->width >> 8,
245 0xce, res->height & 0xff,
246 0xcf, res->height >> 8,
247 0xd0, h_integer_scaler,
248 0xd1, 1,
249 0xd2, 1,
250 0xd8, h_scaling_increment & 0xff,
251 0xd9, h_scaling_increment >> 8,
252 0xdc, (h_scaling_increment / 2) & 0xff,
253 0xdd, (h_scaling_increment / 2) >> 8,
254 0xe0, v_scaling_increment & 0xff,
255 0xe1, v_scaling_increment >> 8,
256 0xe2, v_scaling_increment & 0xff,
257 0xe3, v_scaling_increment >> 8,
258 0x88, 0xf0,
259 0, 0,
261 write_regs(client, regs);
262 break;
264 case VIDIOC_S_STD:
266 v4l2_std_id *input = arg;
267 u8 regs[] = {
268 0x88, 0xc0,
269 0x98, *input & V4L2_STD_NTSC ? 0x12 : 0x16,
270 0x9a, *input & V4L2_STD_NTSC ? 0xf2 : 0x20,
271 0x9b, *input & V4L2_STD_NTSC ? 0x00 : 0x01,
272 0xc8, *input & V4L2_STD_NTSC ? 0x12 : 0x16,
273 0xca, *input & V4L2_STD_NTSC ? 0xf2 : 0x20,
274 0xcb, *input & V4L2_STD_NTSC ? 0x00 : 0x01,
275 0x88, 0xf0,
276 0x30, *input & V4L2_STD_NTSC ? 0x66 : 0x00,
277 0x31, *input & V4L2_STD_NTSC ? 0x90 : 0xe0,
278 0, 0,
280 write_regs(client, regs);
281 dec->norm = *input;
282 break;
284 case VIDIOC_QUERYCTRL:
286 struct v4l2_queryctrl *ctrl = arg;
288 switch (ctrl->id) {
289 case V4L2_CID_BRIGHTNESS:
290 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
291 strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
292 ctrl->minimum = 0;
293 ctrl->maximum = 255;
294 ctrl->step = 1;
295 ctrl->default_value = 128;
296 ctrl->flags = 0;
297 break;
298 case V4L2_CID_CONTRAST:
299 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
300 strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
301 ctrl->minimum = 0;
302 ctrl->maximum = 127;
303 ctrl->step = 1;
304 ctrl->default_value = 64;
305 ctrl->flags = 0;
306 break;
307 case V4L2_CID_SATURATION:
308 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
309 strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
310 ctrl->minimum = 0;
311 ctrl->maximum = 127;
312 ctrl->step = 1;
313 ctrl->default_value = 64;
314 ctrl->flags = 0;
315 break;
316 case V4L2_CID_HUE:
317 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
318 strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
319 ctrl->minimum = -128;
320 ctrl->maximum = 127;
321 ctrl->step = 1;
322 ctrl->default_value = 0;
323 ctrl->flags = 0;
324 break;
326 break;
328 case VIDIOC_S_CTRL:
330 struct v4l2_control *ctrl = arg;
332 switch (ctrl->id) {
333 case V4L2_CID_BRIGHTNESS:
334 if (ctrl->value > 255)
335 dec->brightness = 255;
336 else if (ctrl->value < 0)
337 dec->brightness = 0;
338 else
339 dec->brightness = ctrl->value;
340 write_reg(client, 0x0a, dec->brightness);
341 break;
342 case V4L2_CID_CONTRAST:
343 if (ctrl->value > 127)
344 dec->contrast = 127;
345 else if (ctrl->value < 0)
346 dec->contrast = 0;
347 else
348 dec->contrast = ctrl->value;
349 write_reg(client, 0x0b, dec->contrast);
350 break;
351 case V4L2_CID_SATURATION:
352 if (ctrl->value > 127)
353 dec->saturation = 127;
354 else if (ctrl->value < 0)
355 dec->saturation = 0;
356 else
357 dec->saturation = ctrl->value;
358 write_reg(client, 0x0c, dec->saturation);
359 break;
360 case V4L2_CID_HUE:
361 if (ctrl->value > 127)
362 dec->hue = 127;
363 else if (ctrl->value < -128)
364 dec->hue = -128;
365 else
366 dec->hue = ctrl->value;
367 write_reg(client, 0x0d, dec->hue);
368 break;
370 break;
372 case VIDIOC_G_CTRL:
374 struct v4l2_control *ctrl = arg;
376 switch (ctrl->id) {
377 case V4L2_CID_BRIGHTNESS:
378 ctrl->value = dec->brightness;
379 break;
380 case V4L2_CID_CONTRAST:
381 ctrl->value = dec->contrast;
382 break;
383 case V4L2_CID_SATURATION:
384 ctrl->value = dec->saturation;
385 break;
386 case V4L2_CID_HUE:
387 ctrl->value = dec->hue;
388 break;
390 break;
392 default:
393 break;
395 return 0;
398 static int wis_saa7115_probe(struct i2c_client *client,
399 const struct i2c_device_id *id)
401 struct i2c_adapter *adapter = client->adapter;
402 struct wis_saa7115 *dec;
404 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
405 return -ENODEV;
407 dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL);
408 if (dec == NULL)
409 return -ENOMEM;
411 dec->norm = V4L2_STD_NTSC;
412 dec->brightness = 128;
413 dec->contrast = 64;
414 dec->saturation = 64;
415 dec->hue = 0;
416 i2c_set_clientdata(client, dec);
418 printk(KERN_DEBUG
419 "wis-saa7115: initializing SAA7115 at address %d on %s\n",
420 client->addr, adapter->name);
422 if (write_regs(client, initial_registers) < 0) {
423 printk(KERN_ERR
424 "wis-saa7115: error initializing SAA7115\n");
425 kfree(dec);
426 return -ENODEV;
429 return 0;
432 static int wis_saa7115_remove(struct i2c_client *client)
434 struct wis_saa7115 *dec = i2c_get_clientdata(client);
436 kfree(dec);
437 return 0;
440 static const struct i2c_device_id wis_saa7115_id[] = {
441 { "wis_saa7115", 0 },
444 MODULE_DEVICE_TABLE(i2c, wis_saa7115_id);
446 static struct i2c_driver wis_saa7115_driver = {
447 .driver = {
448 .name = "WIS SAA7115 I2C driver",
450 .probe = wis_saa7115_probe,
451 .remove = wis_saa7115_remove,
452 .command = wis_saa7115_command,
453 .id_table = wis_saa7115_id,
456 static int __init wis_saa7115_init(void)
458 return i2c_add_driver(&wis_saa7115_driver);
461 static void __exit wis_saa7115_cleanup(void)
463 i2c_del_driver(&wis_saa7115_driver);
466 module_init(wis_saa7115_init);
467 module_exit(wis_saa7115_cleanup);
469 MODULE_LICENSE("GPL v2");