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>
34 static u8 initial_registers[] =
43 0x08, 0xf0, /* always toggle FID */
103 0x80, 0x30, /* window defined scaler operation, task A and B enabled */
104 0x81, 0x03, /* use scaler datapath generated V */
111 0x90, 0x02, /* task A process top field */
146 0xc0, 0x03, /* task B process bottom field */
180 0x88, 0xf0, /* End of original static list */
181 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
184 static int write_reg(struct i2c_client *client, u8 reg, u8 value)
186 return i2c_smbus_write_byte_data(client, reg, value);
189 static int write_regs(struct i2c_client *client, u8 *regs)
193 for (i = 0; regs[i] != 0x00; i += 2)
194 if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
199 static int wis_saa7115_command(struct i2c_client *client,
200 unsigned int cmd, void *arg)
202 struct wis_saa7115 *dec = i2c_get_clientdata(client);
209 i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
210 i2c_smbus_write_byte_data(client, 0x09,
211 *input < 6 ? 0x40 : 0xC0);
214 case DECODER_SET_RESOLUTION:
216 struct video_decoder_resolution *res = arg;
217 /* Course-grained scaler */
218 int h_integer_scaler = res->width < 704 ? 704 / res->width : 1;
219 /* Fine-grained scaler to take care of remainder */
220 int h_scaling_increment = (704 / h_integer_scaler) *
222 /* Fine-grained scaler only */
223 int v_scaling_increment = (dec->norm & V4L2_STD_NTSC ?
224 240 : 288) * 1024 / res->height;
227 0x9c, res->width & 0xff,
228 0x9d, res->width >> 8,
229 0x9e, res->height & 0xff,
230 0x9f, res->height >> 8,
231 0xa0, h_integer_scaler,
234 0xa8, h_scaling_increment & 0xff,
235 0xa9, h_scaling_increment >> 8,
236 0xac, (h_scaling_increment / 2) & 0xff,
237 0xad, (h_scaling_increment / 2) >> 8,
238 0xb0, v_scaling_increment & 0xff,
239 0xb1, v_scaling_increment >> 8,
240 0xb2, v_scaling_increment & 0xff,
241 0xb3, v_scaling_increment >> 8,
242 0xcc, res->width & 0xff,
243 0xcd, res->width >> 8,
244 0xce, res->height & 0xff,
245 0xcf, res->height >> 8,
246 0xd0, h_integer_scaler,
249 0xd8, h_scaling_increment & 0xff,
250 0xd9, h_scaling_increment >> 8,
251 0xdc, (h_scaling_increment / 2) & 0xff,
252 0xdd, (h_scaling_increment / 2) >> 8,
253 0xe0, v_scaling_increment & 0xff,
254 0xe1, v_scaling_increment >> 8,
255 0xe2, v_scaling_increment & 0xff,
256 0xe3, v_scaling_increment >> 8,
260 write_regs(client, regs);
265 v4l2_std_id *input = arg;
268 0x98, *input & V4L2_STD_NTSC ? 0x12 : 0x16,
269 0x9a, *input & V4L2_STD_NTSC ? 0xf2 : 0x20,
270 0x9b, *input & V4L2_STD_NTSC ? 0x00 : 0x01,
271 0xc8, *input & V4L2_STD_NTSC ? 0x12 : 0x16,
272 0xca, *input & V4L2_STD_NTSC ? 0xf2 : 0x20,
273 0xcb, *input & V4L2_STD_NTSC ? 0x00 : 0x01,
275 0x30, *input & V4L2_STD_NTSC ? 0x66 : 0x00,
276 0x31, *input & V4L2_STD_NTSC ? 0x90 : 0xe0,
279 write_regs(client, regs);
283 case VIDIOC_QUERYCTRL:
285 struct v4l2_queryctrl *ctrl = arg;
288 case V4L2_CID_BRIGHTNESS:
289 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
290 strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
294 ctrl->default_value = 128;
297 case V4L2_CID_CONTRAST:
298 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
299 strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
303 ctrl->default_value = 64;
306 case V4L2_CID_SATURATION:
307 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
308 strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
312 ctrl->default_value = 64;
316 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
317 strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
318 ctrl->minimum = -128;
321 ctrl->default_value = 0;
329 struct v4l2_control *ctrl = arg;
332 case V4L2_CID_BRIGHTNESS:
333 if (ctrl->value > 255)
334 dec->brightness = 255;
335 else if (ctrl->value < 0)
338 dec->brightness = ctrl->value;
339 write_reg(client, 0x0a, dec->brightness);
341 case V4L2_CID_CONTRAST:
342 if (ctrl->value > 127)
344 else if (ctrl->value < 0)
347 dec->contrast = ctrl->value;
348 write_reg(client, 0x0b, dec->contrast);
350 case V4L2_CID_SATURATION:
351 if (ctrl->value > 127)
352 dec->saturation = 127;
353 else if (ctrl->value < 0)
356 dec->saturation = ctrl->value;
357 write_reg(client, 0x0c, dec->saturation);
360 if (ctrl->value > 127)
362 else if (ctrl->value < -128)
365 dec->hue = ctrl->value;
366 write_reg(client, 0x0d, dec->hue);
373 struct v4l2_control *ctrl = arg;
376 case V4L2_CID_BRIGHTNESS:
377 ctrl->value = dec->brightness;
379 case V4L2_CID_CONTRAST:
380 ctrl->value = dec->contrast;
382 case V4L2_CID_SATURATION:
383 ctrl->value = dec->saturation;
386 ctrl->value = dec->hue;
397 static struct i2c_driver wis_saa7115_driver;
399 static struct i2c_client wis_saa7115_client_templ = {
400 .name = "SAA7115 (WIS)",
401 .driver = &wis_saa7115_driver,
404 static int wis_saa7115_detect(struct i2c_adapter *adapter, int addr, int kind)
406 struct i2c_client *client;
407 struct wis_saa7115 *dec;
409 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
412 client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
415 memcpy(client, &wis_saa7115_client_templ,
416 sizeof(wis_saa7115_client_templ));
417 client->adapter = adapter;
420 dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL);
425 dec->norm = V4L2_STD_NTSC;
426 dec->brightness = 128;
428 dec->saturation = 64;
430 i2c_set_clientdata(client, dec);
433 "wis-saa7115: initializing SAA7115 at address %d on %s\n",
434 addr, adapter->name);
436 if (write_regs(client, initial_registers) < 0) {
438 "wis-saa7115: error initializing SAA7115\n");
444 i2c_attach_client(client);
448 static int wis_saa7115_detach(struct i2c_client *client)
450 struct wis_saa7115 *dec = i2c_get_clientdata(client);
453 r = i2c_detach_client(client);
462 static struct i2c_driver wis_saa7115_driver = {
464 .name = "WIS SAA7115 I2C driver",
466 .id = I2C_DRIVERID_WIS_SAA7115,
467 .detach_client = wis_saa7115_detach,
468 .command = wis_saa7115_command,
471 static int __init wis_saa7115_init(void)
475 r = i2c_add_driver(&wis_saa7115_driver);
478 return wis_i2c_add_driver(wis_saa7115_driver.id, wis_saa7115_detect);
481 static void __exit wis_saa7115_cleanup(void)
483 wis_i2c_del_driver(wis_saa7115_detect);
484 i2c_del_driver(&wis_saa7115_driver);
487 module_init(wis_saa7115_init);
488 module_exit(wis_saa7115_cleanup);
490 MODULE_LICENSE("GPL v2");