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/version.h>
21 #include <linux/i2c.h>
22 #include <linux/videodev2.h>
23 #include <linux/ioctl.h>
35 static u8 initial_registers[] =
44 0x08, 0xf0, /* always toggle FID */
104 0x80, 0x30, /* window defined scaler operation, task A and B enabled */
105 0x81, 0x03, /* use scaler datapath generated V */
112 0x90, 0x02, /* task A process top field */
147 0xc0, 0x03, /* task B process bottom field */
181 0x88, 0xf0, /* End of original static list */
182 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
185 static int write_reg(struct i2c_client *client, u8 reg, u8 value)
187 return i2c_smbus_write_byte_data(client, reg, value);
190 static int write_regs(struct i2c_client *client, u8 *regs)
194 for (i = 0; regs[i] != 0x00; i += 2)
195 if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
200 static int wis_saa7115_command(struct i2c_client *client,
201 unsigned int cmd, void *arg)
203 struct wis_saa7115 *dec = i2c_get_clientdata(client);
210 i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
211 i2c_smbus_write_byte_data(client, 0x09,
212 *input < 6 ? 0x40 : 0xC0);
215 case DECODER_SET_RESOLUTION:
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) *
223 /* Fine-grained scaler only */
224 int v_scaling_increment = (dec->norm & V4L2_STD_NTSC ?
225 240 : 288) * 1024 / res->height;
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,
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,
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,
261 write_regs(client, regs);
266 v4l2_std_id *input = arg;
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,
276 0x30, *input & V4L2_STD_NTSC ? 0x66 : 0x00,
277 0x31, *input & V4L2_STD_NTSC ? 0x90 : 0xe0,
280 write_regs(client, regs);
284 case VIDIOC_QUERYCTRL:
286 struct v4l2_queryctrl *ctrl = arg;
289 case V4L2_CID_BRIGHTNESS:
290 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
291 strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
295 ctrl->default_value = 128;
298 case V4L2_CID_CONTRAST:
299 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
300 strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
304 ctrl->default_value = 64;
307 case V4L2_CID_SATURATION:
308 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
309 strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
313 ctrl->default_value = 64;
317 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
318 strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
319 ctrl->minimum = -128;
322 ctrl->default_value = 0;
330 struct v4l2_control *ctrl = arg;
333 case V4L2_CID_BRIGHTNESS:
334 if (ctrl->value > 255)
335 dec->brightness = 255;
336 else if (ctrl->value < 0)
339 dec->brightness = ctrl->value;
340 write_reg(client, 0x0a, dec->brightness);
342 case V4L2_CID_CONTRAST:
343 if (ctrl->value > 127)
345 else if (ctrl->value < 0)
348 dec->contrast = ctrl->value;
349 write_reg(client, 0x0b, dec->contrast);
351 case V4L2_CID_SATURATION:
352 if (ctrl->value > 127)
353 dec->saturation = 127;
354 else if (ctrl->value < 0)
357 dec->saturation = ctrl->value;
358 write_reg(client, 0x0c, dec->saturation);
361 if (ctrl->value > 127)
363 else if (ctrl->value < -128)
366 dec->hue = ctrl->value;
367 write_reg(client, 0x0d, dec->hue);
374 struct v4l2_control *ctrl = arg;
377 case V4L2_CID_BRIGHTNESS:
378 ctrl->value = dec->brightness;
380 case V4L2_CID_CONTRAST:
381 ctrl->value = dec->contrast;
383 case V4L2_CID_SATURATION:
384 ctrl->value = dec->saturation;
387 ctrl->value = dec->hue;
398 static struct i2c_driver wis_saa7115_driver;
400 static struct i2c_client wis_saa7115_client_templ = {
401 .name = "SAA7115 (WIS)",
402 .driver = &wis_saa7115_driver,
405 static int wis_saa7115_detect(struct i2c_adapter *adapter, int addr, int kind)
407 struct i2c_client *client;
408 struct wis_saa7115 *dec;
410 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
413 client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
416 memcpy(client, &wis_saa7115_client_templ,
417 sizeof(wis_saa7115_client_templ));
418 client->adapter = adapter;
421 dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL);
426 dec->norm = V4L2_STD_NTSC;
427 dec->brightness = 128;
429 dec->saturation = 64;
431 i2c_set_clientdata(client, dec);
434 "wis-saa7115: initializing SAA7115 at address %d on %s\n",
435 addr, adapter->name);
437 if (write_regs(client, initial_registers) < 0) {
439 "wis-saa7115: error initializing SAA7115\n");
445 i2c_attach_client(client);
449 static int wis_saa7115_detach(struct i2c_client *client)
451 struct wis_saa7115 *dec = i2c_get_clientdata(client);
454 r = i2c_detach_client(client);
463 static struct i2c_driver wis_saa7115_driver = {
465 .name = "WIS SAA7115 I2C driver",
467 .id = I2C_DRIVERID_WIS_SAA7115,
468 .detach_client = wis_saa7115_detach,
469 .command = wis_saa7115_command,
472 static int __init wis_saa7115_init(void)
476 r = i2c_add_driver(&wis_saa7115_driver);
479 return wis_i2c_add_driver(wis_saa7115_driver.id, wis_saa7115_detect);
482 static void __exit wis_saa7115_cleanup(void)
484 wis_i2c_del_driver(wis_saa7115_detect);
485 i2c_del_driver(&wis_saa7115_driver);
488 module_init(wis_saa7115_init);
489 module_exit(wis_saa7115_cleanup);
491 MODULE_LICENSE("GPL v2");