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