]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/go7007/wis-saa7115.c
Staging: go7007: fix dangling i2c pointers
[net-next-2.6.git] / drivers / staging / go7007 / wis-saa7115.c
CommitLineData
866b8695
GKH
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>
866b8695 20#include <linux/i2c.h>
df20d69e 21#include <linux/videodev2.h>
866b8695 22#include <linux/ioctl.h>
5a0e3ad6 23#include <linux/slab.h>
866b8695
GKH
24
25#include "wis-i2c.h"
26
27struct wis_saa7115 {
28 int norm;
29 int brightness;
30 int contrast;
31 int saturation;
32 int hue;
33};
34
35static u8 initial_registers[] =
36{
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) */
183};
184
185static int write_reg(struct i2c_client *client, u8 reg, u8 value)
186{
187 return i2c_smbus_write_byte_data(client, reg, value);
188}
189
190static int write_regs(struct i2c_client *client, u8 *regs)
191{
192 int i;
193
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;
198}
199
200static int wis_saa7115_command(struct i2c_client *client,
201 unsigned int cmd, void *arg)
202{
203 struct wis_saa7115 *dec = i2c_get_clientdata(client);
204
205 switch (cmd) {
df20d69e 206 case VIDIOC_S_INPUT:
866b8695
GKH
207 {
208 int *input = arg;
209
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;
214 }
215 case DECODER_SET_RESOLUTION:
216 {
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 */
df20d69e 224 int v_scaling_increment = (dec->norm & V4L2_STD_NTSC ?
866b8695
GKH
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,
260 };
261 write_regs(client, regs);
262 break;
263 }
df20d69e 264 case VIDIOC_S_STD:
866b8695 265 {
df20d69e 266 v4l2_std_id *input = arg;
866b8695
GKH
267 u8 regs[] = {
268 0x88, 0xc0,
df20d69e
RC
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,
866b8695 275 0x88, 0xf0,
df20d69e
RC
276 0x30, *input & V4L2_STD_NTSC ? 0x66 : 0x00,
277 0x31, *input & V4L2_STD_NTSC ? 0x90 : 0xe0,
866b8695
GKH
278 0, 0,
279 };
280 write_regs(client, regs);
281 dec->norm = *input;
282 break;
283 }
284 case VIDIOC_QUERYCTRL:
285 {
286 struct v4l2_queryctrl *ctrl = arg;
287
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;
325 }
326 break;
327 }
328 case VIDIOC_S_CTRL:
329 {
330 struct v4l2_control *ctrl = arg;
331
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;
369 }
370 break;
371 }
372 case VIDIOC_G_CTRL:
373 {
374 struct v4l2_control *ctrl = arg;
375
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;
389 }
390 break;
391 }
392 default:
393 break;
394 }
395 return 0;
396}
397
7400516a
JD
398static int wis_saa7115_probe(struct i2c_client *client,
399 const struct i2c_device_id *id)
866b8695 400{
7400516a 401 struct i2c_adapter *adapter = client->adapter;
866b8695
GKH
402 struct wis_saa7115 *dec;
403
404 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
7400516a 405 return -ENODEV;
866b8695
GKH
406
407 dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL);
7400516a 408 if (dec == NULL)
866b8695 409 return -ENOMEM;
7400516a 410
df20d69e 411 dec->norm = V4L2_STD_NTSC;
866b8695
GKH
412 dec->brightness = 128;
413 dec->contrast = 64;
414 dec->saturation = 64;
415 dec->hue = 0;
416 i2c_set_clientdata(client, dec);
417
418 printk(KERN_DEBUG
419 "wis-saa7115: initializing SAA7115 at address %d on %s\n",
7400516a 420 client->addr, adapter->name);
866b8695
GKH
421
422 if (write_regs(client, initial_registers) < 0) {
423 printk(KERN_ERR
424 "wis-saa7115: error initializing SAA7115\n");
665752e5 425 i2c_set_clientdata(client, NULL);
866b8695 426 kfree(dec);
7400516a 427 return -ENODEV;
866b8695
GKH
428 }
429
866b8695
GKH
430 return 0;
431}
432
7400516a 433static int wis_saa7115_remove(struct i2c_client *client)
866b8695
GKH
434{
435 struct wis_saa7115 *dec = i2c_get_clientdata(client);
866b8695 436
7400516a 437 i2c_set_clientdata(client, NULL);
866b8695
GKH
438 kfree(dec);
439 return 0;
440}
441
b76a3263 442static const struct i2c_device_id wis_saa7115_id[] = {
7400516a
JD
443 { "wis_saa7115", 0 },
444 { }
445};
446
866b8695
GKH
447static struct i2c_driver wis_saa7115_driver = {
448 .driver = {
449 .name = "WIS SAA7115 I2C driver",
450 },
7400516a
JD
451 .probe = wis_saa7115_probe,
452 .remove = wis_saa7115_remove,
866b8695 453 .command = wis_saa7115_command,
7400516a 454 .id_table = wis_saa7115_id,
866b8695
GKH
455};
456
457static int __init wis_saa7115_init(void)
458{
7400516a 459 return i2c_add_driver(&wis_saa7115_driver);
866b8695
GKH
460}
461
462static void __exit wis_saa7115_cleanup(void)
463{
866b8695
GKH
464 i2c_del_driver(&wis_saa7115_driver);
465}
466
467module_init(wis_saa7115_init);
468module_exit(wis_saa7115_cleanup);
469
470MODULE_LICENSE("GPL v2");