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 27struct wis_saa7113 { 28 int norm; 29 int brightness; 30 int contrast; 31 int saturation; 32 int hue; 33}; 34 35static 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 105static int write_reg(struct i2c_client *client, u8 reg, u8 value) 106{ 107 return i2c_smbus_write_byte_data(client, reg, value); 108} 109 110static 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 120static 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: 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; 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 265static 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 285 printk(KERN_DEBUG 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) { 290 printk(KERN_ERR 291 "wis-saa7113: error initializing SAA7113\n"); 292 kfree(dec); 293 return -ENODEV; 294 } 295 296 return 0; 297} 298 299static 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 307static const struct i2c_device_id wis_saa7113_id[] = { 308 { "wis_saa7113", 0 }, 309 { } 310}; 311MODULE_DEVICE_TABLE(i2c, wis_saa7113_id); 312 313static 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 323static int __init wis_saa7113_init(void) 324{ 325 return i2c_add_driver(&wis_saa7113_driver); 326} 327 328static void __exit wis_saa7113_cleanup(void) 329{ 330 i2c_del_driver(&wis_saa7113_driver); 331} 332 333module_init(wis_saa7113_init); 334module_exit(wis_saa7113_cleanup); 335 336MODULE_LICENSE("GPL v2"); 337