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/videodev.h>
23 #include <linux/video_decoder.h>
24 #include <linux/ioctl.h>
36 static u8 initial_registers[] =
45 0x08, 0xf0, /* always toggle FID */
105 0x80, 0x30, /* window defined scaler operation, task A and B enabled */
106 0x81, 0x03, /* use scaler datapath generated V */
113 0x90, 0x02, /* task A process top field */
148 0xc0, 0x03, /* task B process bottom field */
182 0x88, 0xf0, /* End of original static list */
183 0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
186 static int write_reg(struct i2c_client *client, u8 reg, u8 value)
188 return i2c_smbus_write_byte_data(client, reg, value);
191 static int write_regs(struct i2c_client *client, u8 *regs)
195 for (i = 0; regs[i] != 0x00; i += 2)
196 if (i2c_smbus_write_byte_data(client, regs[i], regs[i + 1]) < 0)
201 static int wis_saa7115_command(struct i2c_client *client,
202 unsigned int cmd, void *arg)
204 struct wis_saa7115 *dec = i2c_get_clientdata(client);
207 case DECODER_SET_INPUT:
211 i2c_smbus_write_byte_data(client, 0x02, 0xC0 | *input);
212 i2c_smbus_write_byte_data(client, 0x09,
213 *input < 6 ? 0x40 : 0xC0);
216 case DECODER_SET_RESOLUTION:
218 struct video_decoder_resolution *res = arg;
219 /* Course-grained scaler */
220 int h_integer_scaler = res->width < 704 ? 704 / res->width : 1;
221 /* Fine-grained scaler to take care of remainder */
222 int h_scaling_increment = (704 / h_integer_scaler) *
224 /* Fine-grained scaler only */
225 int v_scaling_increment = (dec->norm == VIDEO_MODE_NTSC ?
226 240 : 288) * 1024 / res->height;
229 0x9c, res->width & 0xff,
230 0x9d, res->width >> 8,
231 0x9e, res->height & 0xff,
232 0x9f, res->height >> 8,
233 0xa0, h_integer_scaler,
236 0xa8, h_scaling_increment & 0xff,
237 0xa9, h_scaling_increment >> 8,
238 0xac, (h_scaling_increment / 2) & 0xff,
239 0xad, (h_scaling_increment / 2) >> 8,
240 0xb0, v_scaling_increment & 0xff,
241 0xb1, v_scaling_increment >> 8,
242 0xb2, v_scaling_increment & 0xff,
243 0xb3, v_scaling_increment >> 8,
244 0xcc, res->width & 0xff,
245 0xcd, res->width >> 8,
246 0xce, res->height & 0xff,
247 0xcf, res->height >> 8,
248 0xd0, h_integer_scaler,
251 0xd8, h_scaling_increment & 0xff,
252 0xd9, h_scaling_increment >> 8,
253 0xdc, (h_scaling_increment / 2) & 0xff,
254 0xdd, (h_scaling_increment / 2) >> 8,
255 0xe0, v_scaling_increment & 0xff,
256 0xe1, v_scaling_increment >> 8,
257 0xe2, v_scaling_increment & 0xff,
258 0xe3, v_scaling_increment >> 8,
262 write_regs(client, regs);
265 case DECODER_SET_NORM:
270 0x98, *input == VIDEO_MODE_NTSC ? 0x12 : 0x16,
271 0x9a, *input == VIDEO_MODE_NTSC ? 0xf2 : 0x20,
272 0x9b, *input == VIDEO_MODE_NTSC ? 0x00 : 0x01,
273 0xc8, *input == VIDEO_MODE_NTSC ? 0x12 : 0x16,
274 0xca, *input == VIDEO_MODE_NTSC ? 0xf2 : 0x20,
275 0xcb, *input == VIDEO_MODE_NTSC ? 0x00 : 0x01,
277 0x30, *input == VIDEO_MODE_NTSC ? 0x66 : 0x00,
278 0x31, *input == VIDEO_MODE_NTSC ? 0x90 : 0xe0,
281 write_regs(client, regs);
285 case VIDIOC_QUERYCTRL:
287 struct v4l2_queryctrl *ctrl = arg;
290 case V4L2_CID_BRIGHTNESS:
291 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
292 strncpy(ctrl->name, "Brightness", sizeof(ctrl->name));
296 ctrl->default_value = 128;
299 case V4L2_CID_CONTRAST:
300 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
301 strncpy(ctrl->name, "Contrast", sizeof(ctrl->name));
305 ctrl->default_value = 64;
308 case V4L2_CID_SATURATION:
309 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
310 strncpy(ctrl->name, "Saturation", sizeof(ctrl->name));
314 ctrl->default_value = 64;
318 ctrl->type = V4L2_CTRL_TYPE_INTEGER;
319 strncpy(ctrl->name, "Hue", sizeof(ctrl->name));
320 ctrl->minimum = -128;
323 ctrl->default_value = 0;
331 struct v4l2_control *ctrl = arg;
334 case V4L2_CID_BRIGHTNESS:
335 if (ctrl->value > 255)
336 dec->brightness = 255;
337 else if (ctrl->value < 0)
340 dec->brightness = ctrl->value;
341 write_reg(client, 0x0a, dec->brightness);
343 case V4L2_CID_CONTRAST:
344 if (ctrl->value > 127)
346 else if (ctrl->value < 0)
349 dec->contrast = ctrl->value;
350 write_reg(client, 0x0b, dec->contrast);
352 case V4L2_CID_SATURATION:
353 if (ctrl->value > 127)
354 dec->saturation = 127;
355 else if (ctrl->value < 0)
358 dec->saturation = ctrl->value;
359 write_reg(client, 0x0c, dec->saturation);
362 if (ctrl->value > 127)
364 else if (ctrl->value < -128)
367 dec->hue = ctrl->value;
368 write_reg(client, 0x0d, dec->hue);
375 struct v4l2_control *ctrl = arg;
378 case V4L2_CID_BRIGHTNESS:
379 ctrl->value = dec->brightness;
381 case V4L2_CID_CONTRAST:
382 ctrl->value = dec->contrast;
384 case V4L2_CID_SATURATION:
385 ctrl->value = dec->saturation;
388 ctrl->value = dec->hue;
399 static struct i2c_driver wis_saa7115_driver;
401 static struct i2c_client wis_saa7115_client_templ = {
402 .name = "SAA7115 (WIS)",
403 .driver = &wis_saa7115_driver,
406 static int wis_saa7115_detect(struct i2c_adapter *adapter, int addr, int kind)
408 struct i2c_client *client;
409 struct wis_saa7115 *dec;
411 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
414 client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
417 memcpy(client, &wis_saa7115_client_templ,
418 sizeof(wis_saa7115_client_templ));
419 client->adapter = adapter;
422 dec = kmalloc(sizeof(struct wis_saa7115), GFP_KERNEL);
427 dec->norm = VIDEO_MODE_NTSC;
428 dec->brightness = 128;
430 dec->saturation = 64;
432 i2c_set_clientdata(client, dec);
435 "wis-saa7115: initializing SAA7115 at address %d on %s\n",
436 addr, adapter->name);
438 if (write_regs(client, initial_registers) < 0) {
440 "wis-saa7115: error initializing SAA7115\n");
446 i2c_attach_client(client);
450 static int wis_saa7115_detach(struct i2c_client *client)
452 struct wis_saa7115 *dec = i2c_get_clientdata(client);
455 r = i2c_detach_client(client);
464 static struct i2c_driver wis_saa7115_driver = {
466 .name = "WIS SAA7115 I2C driver",
468 .id = I2C_DRIVERID_WIS_SAA7115,
469 .detach_client = wis_saa7115_detach,
470 .command = wis_saa7115_command,
473 static int __init wis_saa7115_init(void)
477 r = i2c_add_driver(&wis_saa7115_driver);
480 return wis_i2c_add_driver(wis_saa7115_driver.id, wis_saa7115_detect);
483 static void __exit wis_saa7115_cleanup(void)
485 wis_i2c_del_driver(wis_saa7115_detect);
486 i2c_del_driver(&wis_saa7115_driver);
489 module_init(wis_saa7115_init);
490 module_exit(wis_saa7115_cleanup);
492 MODULE_LICENSE("GPL v2");