Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
wis-saa7113.c
Go to the documentation of this file.
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/i2c.h>
21 #include <linux/videodev2.h>
22 #include <linux/ioctl.h>
23 #include <linux/slab.h>
24 
25 #include "wis-i2c.h"
26 
27 struct wis_saa7113 {
28  int norm;
30  int contrast;
32  int hue;
33 };
34 
35 static u8 initial_registers[] =
36 {
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) */
103 };
104 
105 static int write_reg(struct i2c_client *client, u8 reg, u8 value)
106 {
107  return i2c_smbus_write_byte_data(client, reg, value);
108 }
109 
110 static int write_regs(struct i2c_client *client, u8 *regs)
111 {
112  int i;
113 
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;
118 }
119 
120 static int wis_saa7113_command(struct i2c_client *client,
121  unsigned int cmd, void *arg)
122 {
123  struct wis_saa7113 *dec = i2c_get_clientdata(client);
124 
125  switch (cmd) {
126  case VIDIOC_S_INPUT:
127  {
128  int *input = arg;
129 
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;
134  }
135  case VIDIOC_S_STD:
136  {
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);
148  }
149  break;
150  }
151  case VIDIOC_QUERYCTRL:
152  {
153  struct v4l2_queryctrl *ctrl = arg;
154 
155  switch (ctrl->id) {
156  case V4L2_CID_BRIGHTNESS:
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:
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:
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:
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;
192  }
193  break;
194  }
195  case VIDIOC_S_CTRL:
196  {
197  struct v4l2_control *ctrl = arg;
198 
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;
236  }
237  break;
238  }
239  case VIDIOC_G_CTRL:
240  {
241  struct v4l2_control *ctrl = arg;
242 
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;
256  }
257  break;
258  }
259  default:
260  break;
261  }
262  return 0;
263 }
264 
265 static int wis_saa7113_probe(struct i2c_client *client,
266  const struct i2c_device_id *id)
267 {
268  struct i2c_adapter *adapter = client->adapter;
269  struct wis_saa7113 *dec;
270 
271  if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
272  return -ENODEV;
273 
274  dec = kmalloc(sizeof(struct wis_saa7113), GFP_KERNEL);
275  if (dec == NULL)
276  return -ENOMEM;
277 
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);
284 
286  "wis-saa7113: initializing SAA7113 at address %d on %s\n",
287  client->addr, adapter->name);
288 
289  if (write_regs(client, initial_registers) < 0) {
291  "wis-saa7113: error initializing SAA7113\n");
292  kfree(dec);
293  return -ENODEV;
294  }
295 
296  return 0;
297 }
298 
299 static int wis_saa7113_remove(struct i2c_client *client)
300 {
301  struct wis_saa7113 *dec = i2c_get_clientdata(client);
302 
303  kfree(dec);
304  return 0;
305 }
306 
307 static const struct i2c_device_id wis_saa7113_id[] = {
308  { "wis_saa7113", 0 },
309  { }
310 };
311 MODULE_DEVICE_TABLE(i2c, wis_saa7113_id);
312 
313 static struct i2c_driver wis_saa7113_driver = {
314  .driver = {
315  .name = "WIS SAA7113 I2C driver",
316  },
317  .probe = wis_saa7113_probe,
318  .remove = wis_saa7113_remove,
319  .command = wis_saa7113_command,
320  .id_table = wis_saa7113_id,
321 };
322 
323 static int __init wis_saa7113_init(void)
324 {
325  return i2c_add_driver(&wis_saa7113_driver);
326 }
327 
328 static void __exit wis_saa7113_cleanup(void)
329 {
330  i2c_del_driver(&wis_saa7113_driver);
331 }
332 
333 module_init(wis_saa7113_init);
334 module_exit(wis_saa7113_cleanup);
335 
336 MODULE_LICENSE("GPL v2");