]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/staging/go7007/wis-saa7113.c
Staging: add the go7007 video driver
[linux-2.6-omap-h63xx.git] / drivers / staging / go7007 / wis-saa7113.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_saa7113 {
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, 0x33,
41         0x04, 0x00,
42         0x05, 0x00,
43         0x06, 0xe9,
44         0x07, 0x0d,
45         0x08, 0xd8,
46         0x09, 0x40,
47         0x0a, 0x80,
48         0x0b, 0x47,
49         0x0c, 0x40,
50         0x0d, 0x00,
51         0x0e, 0x01,
52         0x0f, 0x2a,
53         0x10, 0x40,
54         0x11, 0x0c,
55         0x12, 0xfe,
56         0x13, 0x00,
57         0x14, 0x00,
58         0x15, 0x04,
59         0x16, 0x00,
60         0x17, 0x00,
61         0x18, 0x00,
62         0x19, 0x00,
63         0x1a, 0x00,
64         0x1b, 0x00,
65         0x1c, 0x00,
66         0x1d, 0x00,
67         0x1e, 0x00,
68         0x1f, 0xc8,
69         0x40, 0x00,
70         0x41, 0xff,
71         0x42, 0xff,
72         0x43, 0xff,
73         0x44, 0xff,
74         0x45, 0xff,
75         0x46, 0xff,
76         0x47, 0xff,
77         0x48, 0xff,
78         0x49, 0xff,
79         0x4a, 0xff,
80         0x4b, 0xff,
81         0x4c, 0xff,
82         0x4d, 0xff,
83         0x4e, 0xff,
84         0x4f, 0xff,
85         0x50, 0xff,
86         0x51, 0xff,
87         0x52, 0xff,
88         0x53, 0xff,
89         0x54, 0xff,
90         0x55, 0xff,
91         0x56, 0xff,
92         0x57, 0xff,
93         0x58, 0x00,
94         0x59, 0x54,
95         0x5a, 0x07,
96         0x5b, 0x83,
97         0x5c, 0x00,
98         0x5d, 0x00,
99         0x5e, 0x00,
100         0x5f, 0x00,
101         0x60, 0x00,
102         0x61, 0x00,
103         0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
104 };
105
106 static int write_reg(struct i2c_client *client, u8 reg, u8 value)
107 {
108         return i2c_smbus_write_byte_data(client, reg, value);
109 }
110
111 static int write_regs(struct i2c_client *client, u8 *regs)
112 {
113         int i;
114
115         for (i = 0; regs[i] != 0x00; i += 2)
116                 if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
117                         return -1;
118         return 0;
119 }
120
121 static int wis_saa7113_command(struct i2c_client *client,
122                                 unsigned int cmd, void *arg)
123 {
124         struct wis_saa7113 *dec = i2c_get_clientdata(client);
125
126         switch (cmd) {
127         case DECODER_SET_INPUT:
128         {
129                 int *input = arg;
130
131                 i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
132                 i2c_smbus_write_byte_data(client, 0x09,
133                                 *input < 6 ? 0x40 : 0x80);
134                 break;
135         }
136         case DECODER_SET_NORM:
137         {
138                 int *input = arg;
139                 dec->norm = *input;
140                 switch (dec->norm) {
141                 case VIDEO_MODE_PAL:
142                         write_reg(client, 0x0e, 0x01);
143                         write_reg(client, 0x10, 0x48);
144                         break;
145                 case VIDEO_MODE_NTSC:
146                         write_reg(client, 0x0e, 0x01);
147                         write_reg(client, 0x10, 0x40);
148                         break;
149                 case VIDEO_MODE_SECAM:
150                         write_reg(client, 0x0e, 0x50);
151                         write_reg(client, 0x10, 0x48);
152                         break;
153                 }
154                 break;
155         }
156         case VIDIOC_QUERYCTRL:
157         {
158                 struct v4l2_queryctrl *ctrl = arg;
159
160                 switch (ctrl->id) {
161                 case V4L2_CID_BRIGHTNESS:
162                         ctrl->type = V4L2_CTRL_TYPE_INTEGER;
163                         strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
164                         ctrl->minimum = 0;
165                         ctrl->maximum = 255;
166                         ctrl->step = 1;
167                         ctrl->default_value = 128;
168                         ctrl->flags = 0;
169                         break;
170                 case V4L2_CID_CONTRAST:
171                         ctrl->type = V4L2_CTRL_TYPE_INTEGER;
172                         strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
173                         ctrl->minimum = 0;
174                         ctrl->maximum = 127;
175                         ctrl->step = 1;
176                         ctrl->default_value = 71;
177                         ctrl->flags = 0;
178                         break;
179                 case V4L2_CID_SATURATION:
180                         ctrl->type = V4L2_CTRL_TYPE_INTEGER;
181                         strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
182                         ctrl->minimum = 0;
183                         ctrl->maximum = 127;
184                         ctrl->step = 1;
185                         ctrl->default_value = 64;
186                         ctrl->flags = 0;
187                         break;
188                 case V4L2_CID_HUE:
189                         ctrl->type = V4L2_CTRL_TYPE_INTEGER;
190                         strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
191                         ctrl->minimum = -128;
192                         ctrl->maximum = 127;
193                         ctrl->step = 1;
194                         ctrl->default_value = 0;
195                         ctrl->flags = 0;
196                         break;
197                 }
198                 break;
199         }
200         case VIDIOC_S_CTRL:
201         {
202                 struct v4l2_control *ctrl = arg;
203
204                 switch (ctrl->id) {
205                 case V4L2_CID_BRIGHTNESS:
206                         if (ctrl->value > 255)
207                                 dec->brightness = 255;
208                         else if (ctrl->value < 0)
209                                 dec->brightness = 0;
210                         else
211                                 dec->brightness = ctrl->value;
212                         write_reg(client, 0x0a, dec->brightness);
213                         break;
214                 case V4L2_CID_CONTRAST:
215                         if (ctrl->value > 127)
216                                 dec->contrast = 127;
217                         else if (ctrl->value < 0)
218                                 dec->contrast = 0;
219                         else
220                                 dec->contrast = ctrl->value;
221                         write_reg(client, 0x0b, dec->contrast);
222                         break;
223                 case V4L2_CID_SATURATION:
224                         if (ctrl->value > 127)
225                                 dec->saturation = 127;
226                         else if (ctrl->value < 0)
227                                 dec->saturation = 0;
228                         else
229                                 dec->saturation = ctrl->value;
230                         write_reg(client, 0x0c, dec->saturation);
231                         break;
232                 case V4L2_CID_HUE:
233                         if (ctrl->value > 127)
234                                 dec->hue = 127;
235                         else if (ctrl->value < -128)
236                                 dec->hue = -128;
237                         else
238                                 dec->hue = ctrl->value;
239                         write_reg(client, 0x0d, dec->hue);
240                         break;
241                 }
242                 break;
243         }
244         case VIDIOC_G_CTRL:
245         {
246                 struct v4l2_control *ctrl = arg;
247
248                 switch (ctrl->id) {
249                 case V4L2_CID_BRIGHTNESS:
250                         ctrl->value = dec->brightness;
251                         break;
252                 case V4L2_CID_CONTRAST:
253                         ctrl->value = dec->contrast;
254                         break;
255                 case V4L2_CID_SATURATION:
256                         ctrl->value = dec->saturation;
257                         break;
258                 case V4L2_CID_HUE:
259                         ctrl->value = dec->hue;
260                         break;
261                 }
262                 break;
263         }
264         default:
265                 break;
266         }
267         return 0;
268 }
269
270 static struct i2c_driver wis_saa7113_driver;
271
272 static struct i2c_client wis_saa7113_client_templ = {
273         .name           = "SAA7113 (WIS)",
274         .driver         = &wis_saa7113_driver,
275 };
276
277 static int wis_saa7113_detect(struct i2c_adapter *adapter, int addr, int kind)
278 {
279         struct i2c_client *client;
280         struct wis_saa7113 *dec;
281
282         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
283                 return 0;
284
285         client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
286         if (client == NULL)
287                 return -ENOMEM;
288         memcpy(client, &wis_saa7113_client_templ,
289                         sizeof(wis_saa7113_client_templ));
290         client->adapter = adapter;
291         client->addr = addr;
292
293         dec = kmalloc(sizeof(struct wis_saa7113), GFP_KERNEL);
294         if (dec == NULL) {
295                 kfree(client);
296                 return -ENOMEM;
297         }
298         dec->norm = VIDEO_MODE_NTSC;
299         dec->brightness = 128;
300         dec->contrast = 71;
301         dec->saturation = 64;
302         dec->hue = 0;
303         i2c_set_clientdata(client, dec);
304
305         printk(KERN_DEBUG
306                 "wis-saa7113: initializing SAA7113 at address %d on %s\n",
307                 addr, adapter->name);
308
309         if (write_regs(client, initial_registers) < 0) {
310                 printk(KERN_ERR
311                         "wis-saa7113: error initializing SAA7113\n");
312                 kfree(client);
313                 kfree(dec);
314                 return 0;
315         }
316
317         i2c_attach_client(client);
318         return 0;
319 }
320
321 static int wis_saa7113_detach(struct i2c_client *client)
322 {
323         struct wis_saa7113 *dec = i2c_get_clientdata(client);
324         int r;
325
326         r = i2c_detach_client(client);
327         if (r < 0)
328                 return r;
329
330         kfree(client);
331         kfree(dec);
332         return 0;
333 }
334
335 static struct i2c_driver wis_saa7113_driver = {
336         .driver = {
337                 .name   = "WIS SAA7113 I2C driver",
338         },
339         .id             = I2C_DRIVERID_WIS_SAA7113,
340         .detach_client  = wis_saa7113_detach,
341         .command        = wis_saa7113_command,
342 };
343
344 static int __init wis_saa7113_init(void)
345 {
346         int r;
347
348         r = i2c_add_driver(&wis_saa7113_driver);
349         if (r < 0)
350                 return r;
351         return wis_i2c_add_driver(wis_saa7113_driver.id, wis_saa7113_detect);
352 }
353
354 static void __exit wis_saa7113_cleanup(void)
355 {
356         wis_i2c_del_driver(wis_saa7113_detect);
357         i2c_del_driver(&wis_saa7113_driver);
358 }
359
360 module_init(wis_saa7113_init);
361 module_exit(wis_saa7113_cleanup);
362
363 MODULE_LICENSE("GPL v2");