thinkpad-acpi: handle HKEY 0x4010, 0x4011 events
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / go7007 / wis-saa7113.c
blob05e0e108386427b4ee22677707f373fd699bda65
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_saa7113 {
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, 0x33,
40 0x04, 0x00,
41 0x05, 0x00,
42 0x06, 0xe9,
43 0x07, 0x0d,
44 0x08, 0xd8,
45 0x09, 0x40,
46 0x0a, 0x80,
47 0x0b, 0x47,
48 0x0c, 0x40,
49 0x0d, 0x00,
50 0x0e, 0x01,
51 0x0f, 0x2a,
52 0x10, 0x40,
53 0x11, 0x0c,
54 0x12, 0xfe,
55 0x13, 0x00,
56 0x14, 0x00,
57 0x15, 0x04,
58 0x16, 0x00,
59 0x17, 0x00,
60 0x18, 0x00,
61 0x19, 0x00,
62 0x1a, 0x00,
63 0x1b, 0x00,
64 0x1c, 0x00,
65 0x1d, 0x00,
66 0x1e, 0x00,
67 0x1f, 0xc8,
68 0x40, 0x00,
69 0x41, 0xff,
70 0x42, 0xff,
71 0x43, 0xff,
72 0x44, 0xff,
73 0x45, 0xff,
74 0x46, 0xff,
75 0x47, 0xff,
76 0x48, 0xff,
77 0x49, 0xff,
78 0x4a, 0xff,
79 0x4b, 0xff,
80 0x4c, 0xff,
81 0x4d, 0xff,
82 0x4e, 0xff,
83 0x4f, 0xff,
84 0x50, 0xff,
85 0x51, 0xff,
86 0x52, 0xff,
87 0x53, 0xff,
88 0x54, 0xff,
89 0x55, 0xff,
90 0x56, 0xff,
91 0x57, 0xff,
92 0x58, 0x00,
93 0x59, 0x54,
94 0x5a, 0x07,
95 0x5b, 0x83,
96 0x5c, 0x00,
97 0x5d, 0x00,
98 0x5e, 0x00,
99 0x5f, 0x00,
100 0x60, 0x00,
101 0x61, 0x00,
102 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
105 static int write_reg(struct i2c_client *client, u8 reg, u8 value)
107 return i2c_smbus_write_byte_data(client, reg, value);
110 static int write_regs(struct i2c_client *client, u8 *regs)
112 int i;
114 for (i = 0; regs[i] != 0x00; i += 2)
115 if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
116 return -1;
117 return 0;
120 static int wis_saa7113_command(struct i2c_client *client,
121 unsigned int cmd, void *arg)
123 struct wis_saa7113 *dec = i2c_get_clientdata(client);
125 switch (cmd) {
126 case VIDIOC_S_INPUT:
128 int *input = arg;
130 i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
131 i2c_smbus_write_byte_data(client, 0x09,
132 *input < 6 ? 0x40 : 0x80);
133 break;
135 case VIDIOC_S_STD:
137 v4l2_std_id *input = arg;
138 dec->norm = *input;
139 if (dec->norm & V4L2_STD_NTSC) {
140 write_reg(client, 0x0e, 0x01);
141 write_reg(client, 0x10, 0x40);
142 } else if (dec->norm & V4L2_STD_PAL) {
143 write_reg(client, 0x0e, 0x01);
144 write_reg(client, 0x10, 0x48);
145 } else if (dec->norm * V4L2_STD_SECAM) {
146 write_reg(client, 0x0e, 0x50);
147 write_reg(client, 0x10, 0x48);
149 break;
151 case VIDIOC_QUERYCTRL:
153 struct v4l2_queryctrl *ctrl = arg;
155 switch (ctrl->id) {
156 case V4L2_CID_BRIGHTNESS:
157 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
158 strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
159 ctrl->minimum = 0;
160 ctrl->maximum = 255;
161 ctrl->step = 1;
162 ctrl->default_value = 128;
163 ctrl->flags = 0;
164 break;
165 case V4L2_CID_CONTRAST:
166 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
167 strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
168 ctrl->minimum = 0;
169 ctrl->maximum = 127;
170 ctrl->step = 1;
171 ctrl->default_value = 71;
172 ctrl->flags = 0;
173 break;
174 case V4L2_CID_SATURATION:
175 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
176 strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
177 ctrl->minimum = 0;
178 ctrl->maximum = 127;
179 ctrl->step = 1;
180 ctrl->default_value = 64;
181 ctrl->flags = 0;
182 break;
183 case V4L2_CID_HUE:
184 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
185 strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
186 ctrl->minimum = -128;
187 ctrl->maximum = 127;
188 ctrl->step = 1;
189 ctrl->default_value = 0;
190 ctrl->flags = 0;
191 break;
193 break;
195 case VIDIOC_S_CTRL:
197 struct v4l2_control *ctrl = arg;
199 switch (ctrl->id) {
200 case V4L2_CID_BRIGHTNESS:
201 if (ctrl->value > 255)
202 dec->brightness = 255;
203 else if (ctrl->value < 0)
204 dec->brightness = 0;
205 else
206 dec->brightness = ctrl->value;
207 write_reg(client, 0x0a, dec->brightness);
208 break;
209 case V4L2_CID_CONTRAST:
210 if (ctrl->value > 127)
211 dec->contrast = 127;
212 else if (ctrl->value < 0)
213 dec->contrast = 0;
214 else
215 dec->contrast = ctrl->value;
216 write_reg(client, 0x0b, dec->contrast);
217 break;
218 case V4L2_CID_SATURATION:
219 if (ctrl->value > 127)
220 dec->saturation = 127;
221 else if (ctrl->value < 0)
222 dec->saturation = 0;
223 else
224 dec->saturation = ctrl->value;
225 write_reg(client, 0x0c, dec->saturation);
226 break;
227 case V4L2_CID_HUE:
228 if (ctrl->value > 127)
229 dec->hue = 127;
230 else if (ctrl->value < -128)
231 dec->hue = -128;
232 else
233 dec->hue = ctrl->value;
234 write_reg(client, 0x0d, dec->hue);
235 break;
237 break;
239 case VIDIOC_G_CTRL:
241 struct v4l2_control *ctrl = arg;
243 switch (ctrl->id) {
244 case V4L2_CID_BRIGHTNESS:
245 ctrl->value = dec->brightness;
246 break;
247 case V4L2_CID_CONTRAST:
248 ctrl->value = dec->contrast;
249 break;
250 case V4L2_CID_SATURATION:
251 ctrl->value = dec->saturation;
252 break;
253 case V4L2_CID_HUE:
254 ctrl->value = dec->hue;
255 break;
257 break;
259 default:
260 break;
262 return 0;
265 static int wis_saa7113_probe(struct i2c_client *client,
266 const struct i2c_device_id *id)
268 struct i2c_adapter *adapter = client->adapter;
269 struct wis_saa7113 *dec;
271 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
272 return -ENODEV;
274 dec = kmalloc(sizeof(struct wis_saa7113), GFP_KERNEL);
275 if (dec == NULL)
276 return -ENOMEM;
278 dec->norm = V4L2_STD_NTSC;
279 dec->brightness = 128;
280 dec->contrast = 71;
281 dec->saturation = 64;
282 dec->hue = 0;
283 i2c_set_clientdata(client, dec);
285 printk(KERN_DEBUG
286 "wis-saa7113: initializing SAA7113 at address %d on %s\n",
287 client->addr, adapter->name);
289 if (write_regs(client, initial_registers) < 0) {
290 printk(KERN_ERR
291 "wis-saa7113: error initializing SAA7113\n");
292 kfree(dec);
293 return -ENODEV;
296 return 0;
299 static int wis_saa7113_remove(struct i2c_client *client)
301 struct wis_saa7113 *dec = i2c_get_clientdata(client);
303 kfree(dec);
304 return 0;
307 static const struct i2c_device_id wis_saa7113_id[] = {
308 { "wis_saa7113", 0 },
311 MODULE_DEVICE_TABLE(i2c, wis_saa7113_id);
313 static struct i2c_driver wis_saa7113_driver = {
314 .driver = {
315 .name = "WIS SAA7113 I2C driver",
317 .probe = wis_saa7113_probe,
318 .remove = wis_saa7113_remove,
319 .command = wis_saa7113_command,
320 .id_table = wis_saa7113_id,
323 static int __init wis_saa7113_init(void)
325 return i2c_add_driver(&wis_saa7113_driver);
328 static void __exit wis_saa7113_cleanup(void)
330 i2c_del_driver(&wis_saa7113_driver);
333 module_init(wis_saa7113_init);
334 module_exit(wis_saa7113_cleanup);
336 MODULE_LICENSE("GPL v2");