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 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/i2c.h> 17 #include <linux/videodev2.h> 18 #include <linux/ioctl.h> 19 #include <linux/slab.h> 20 #include <media/v4l2-subdev.h> 21 #include <media/v4l2-device.h> 22 #include <media/v4l2-ctrls.h> 23 24 #define TW2804_REG_AUTOGAIN 0x02 25 #define TW2804_REG_HUE 0x0f 26 #define TW2804_REG_SATURATION 0x10 27 #define TW2804_REG_CONTRAST 0x11 28 #define TW2804_REG_BRIGHTNESS 0x12 29 #define TW2804_REG_COLOR_KILLER 0x14 30 #define TW2804_REG_GAIN 0x3c 31 #define TW2804_REG_CHROMA_GAIN 0x3d 32 #define TW2804_REG_BLUE_BALANCE 0x3e 33 #define TW2804_REG_RED_BALANCE 0x3f 34 35 struct tw2804 { 36 struct v4l2_subdev sd; 37 struct v4l2_ctrl_handler hdl; 38 u8 channel:2; 39 u8 input:1; 40 int norm; 41 }; 42 43 static const u8 global_registers[] = { 44 0x39, 0x00, 45 0x3a, 0xff, 46 0x3b, 0x84, 47 0x3c, 0x80, 48 0x3d, 0x80, 49 0x3e, 0x82, 50 0x3f, 0x82, 51 0x78, 0x00, 52 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ 53 }; 54 55 static const u8 channel_registers[] = { 56 0x01, 0xc4, 57 0x02, 0xa5, 58 0x03, 0x20, 59 0x04, 0xd0, 60 0x05, 0x20, 61 0x06, 0xd0, 62 0x07, 0x88, 63 0x08, 0x20, 64 0x09, 0x07, 65 0x0a, 0xf0, 66 0x0b, 0x07, 67 0x0c, 0xf0, 68 0x0d, 0x40, 69 0x0e, 0xd2, 70 0x0f, 0x80, 71 0x10, 0x80, 72 0x11, 0x80, 73 0x12, 0x80, 74 0x13, 0x1f, 75 0x14, 0x00, 76 0x15, 0x00, 77 0x16, 0x00, 78 0x17, 0x00, 79 0x18, 0xff, 80 0x19, 0xff, 81 0x1a, 0xff, 82 0x1b, 0xff, 83 0x1c, 0xff, 84 0x1d, 0xff, 85 0x1e, 0xff, 86 0x1f, 0xff, 87 0x20, 0x07, 88 0x21, 0x07, 89 0x22, 0x00, 90 0x23, 0x91, 91 0x24, 0x51, 92 0x25, 0x03, 93 0x26, 0x00, 94 0x27, 0x00, 95 0x28, 0x00, 96 0x29, 0x00, 97 0x2a, 0x00, 98 0x2b, 0x00, 99 0x2c, 0x00, 100 0x2d, 0x00, 101 0x2e, 0x00, 102 0x2f, 0x00, 103 0x30, 0x00, 104 0x31, 0x00, 105 0x32, 0x00, 106 0x33, 0x00, 107 0x34, 0x00, 108 0x35, 0x00, 109 0x36, 0x00, 110 0x37, 0x00, 111 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ 112 }; 113 114 static int write_reg(struct i2c_client *client, u8 reg, u8 value, u8 channel) 115 { 116 return i2c_smbus_write_byte_data(client, reg | (channel << 6), value); 117 } 118 119 static int write_regs(struct i2c_client *client, const u8 *regs, u8 channel) 120 { 121 int ret; 122 int i; 123 124 for (i = 0; regs[i] != 0xff; i += 2) { 125 ret = i2c_smbus_write_byte_data(client, 126 regs[i] | (channel << 6), regs[i + 1]); 127 if (ret < 0) 128 return ret; 129 } 130 return 0; 131 } 132 133 static int read_reg(struct i2c_client *client, u8 reg, u8 channel) 134 { 135 return i2c_smbus_read_byte_data(client, (reg) | (channel << 6)); 136 } 137 138 static inline struct tw2804 *to_state(struct v4l2_subdev *sd) 139 { 140 return container_of(sd, struct tw2804, sd); 141 } 142 143 static inline struct tw2804 *to_state_from_ctrl(struct v4l2_ctrl *ctrl) 144 { 145 return container_of(ctrl->handler, struct tw2804, hdl); 146 } 147 148 static int tw2804_log_status(struct v4l2_subdev *sd) 149 { 150 struct tw2804 *state = to_state(sd); 151 152 v4l2_info(sd, "Standard: %s\n", 153 state->norm & V4L2_STD_525_60 ? "60 Hz" : "50 Hz"); 154 v4l2_info(sd, "Channel: %d\n", state->channel); 155 v4l2_info(sd, "Input: %d\n", state->input); 156 return v4l2_ctrl_subdev_log_status(sd); 157 } 158 159 /* 160 * These volatile controls are needed because all four channels share 161 * these controls. So a change made to them through one channel would 162 * require another channel to be updated. 163 * 164 * Normally this would have been done in a different way, but since the one 165 * board that uses this driver sees this single chip as if it was on four 166 * different i2c adapters (each adapter belonging to a separate instance of 167 * the same USB driver) there is no reliable method that I have found to let 168 * the instances know about each other. 169 * 170 * So implementing these global registers as volatile is the best we can do. 171 */ 172 static int tw2804_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 173 { 174 struct tw2804 *state = to_state_from_ctrl(ctrl); 175 struct i2c_client *client = v4l2_get_subdevdata(&state->sd); 176 177 switch (ctrl->id) { 178 case V4L2_CID_GAIN: 179 ctrl->val = read_reg(client, TW2804_REG_GAIN, 0); 180 return 0; 181 182 case V4L2_CID_CHROMA_GAIN: 183 ctrl->val = read_reg(client, TW2804_REG_CHROMA_GAIN, 0); 184 return 0; 185 186 case V4L2_CID_BLUE_BALANCE: 187 ctrl->val = read_reg(client, TW2804_REG_BLUE_BALANCE, 0); 188 return 0; 189 190 case V4L2_CID_RED_BALANCE: 191 ctrl->val = read_reg(client, TW2804_REG_RED_BALANCE, 0); 192 return 0; 193 } 194 return 0; 195 } 196 197 static int tw2804_s_ctrl(struct v4l2_ctrl *ctrl) 198 { 199 struct tw2804 *state = to_state_from_ctrl(ctrl); 200 struct i2c_client *client = v4l2_get_subdevdata(&state->sd); 201 int addr; 202 int reg; 203 204 switch (ctrl->id) { 205 case V4L2_CID_AUTOGAIN: 206 addr = TW2804_REG_AUTOGAIN; 207 reg = read_reg(client, addr, state->channel); 208 if (reg < 0) 209 return reg; 210 if (ctrl->val == 0) 211 reg &= ~(1 << 7); 212 else 213 reg |= 1 << 7; 214 return write_reg(client, addr, reg, state->channel); 215 216 case V4L2_CID_COLOR_KILLER: 217 addr = TW2804_REG_COLOR_KILLER; 218 reg = read_reg(client, addr, state->channel); 219 if (reg < 0) 220 return reg; 221 reg = (reg & ~(0x03)) | (ctrl->val == 0 ? 0x02 : 0x03); 222 return write_reg(client, addr, reg, state->channel); 223 224 case V4L2_CID_GAIN: 225 return write_reg(client, TW2804_REG_GAIN, ctrl->val, 0); 226 227 case V4L2_CID_CHROMA_GAIN: 228 return write_reg(client, TW2804_REG_CHROMA_GAIN, ctrl->val, 0); 229 230 case V4L2_CID_BLUE_BALANCE: 231 return write_reg(client, TW2804_REG_BLUE_BALANCE, ctrl->val, 0); 232 233 case V4L2_CID_RED_BALANCE: 234 return write_reg(client, TW2804_REG_RED_BALANCE, ctrl->val, 0); 235 236 case V4L2_CID_BRIGHTNESS: 237 return write_reg(client, TW2804_REG_BRIGHTNESS, 238 ctrl->val, state->channel); 239 240 case V4L2_CID_CONTRAST: 241 return write_reg(client, TW2804_REG_CONTRAST, 242 ctrl->val, state->channel); 243 244 case V4L2_CID_SATURATION: 245 return write_reg(client, TW2804_REG_SATURATION, 246 ctrl->val, state->channel); 247 248 case V4L2_CID_HUE: 249 return write_reg(client, TW2804_REG_HUE, 250 ctrl->val, state->channel); 251 252 default: 253 break; 254 } 255 return -EINVAL; 256 } 257 258 static int tw2804_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) 259 { 260 struct tw2804 *dec = to_state(sd); 261 struct i2c_client *client = v4l2_get_subdevdata(sd); 262 bool is_60hz = norm & V4L2_STD_525_60; 263 u8 regs[] = { 264 0x01, is_60hz ? 0xc4 : 0x84, 265 0x09, is_60hz ? 0x07 : 0x04, 266 0x0a, is_60hz ? 0xf0 : 0x20, 267 0x0b, is_60hz ? 0x07 : 0x04, 268 0x0c, is_60hz ? 0xf0 : 0x20, 269 0x0d, is_60hz ? 0x40 : 0x4a, 270 0x16, is_60hz ? 0x00 : 0x40, 271 0x17, is_60hz ? 0x00 : 0x40, 272 0x20, is_60hz ? 0x07 : 0x0f, 273 0x21, is_60hz ? 0x07 : 0x0f, 274 0xff, 0xff, 275 }; 276 277 write_regs(client, regs, dec->channel); 278 dec->norm = norm; 279 return 0; 280 } 281 282 static int tw2804_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output, 283 u32 config) 284 { 285 struct tw2804 *dec = to_state(sd); 286 struct i2c_client *client = v4l2_get_subdevdata(sd); 287 int reg; 288 289 if (config && config - 1 != dec->channel) { 290 if (config > 4) { 291 dev_err(&client->dev, 292 "channel %d is not between 1 and 4!\n", config); 293 return -EINVAL; 294 } 295 dec->channel = config - 1; 296 dev_dbg(&client->dev, "initializing TW2804 channel %d\n", 297 dec->channel); 298 if (dec->channel == 0 && 299 write_regs(client, global_registers, 0) < 0) { 300 dev_err(&client->dev, 301 "error initializing TW2804 global registers\n"); 302 return -EIO; 303 } 304 if (write_regs(client, channel_registers, dec->channel) < 0) { 305 dev_err(&client->dev, 306 "error initializing TW2804 channel %d\n", 307 dec->channel); 308 return -EIO; 309 } 310 } 311 312 if (input > 1) 313 return -EINVAL; 314 315 if (input == dec->input) 316 return 0; 317 318 reg = read_reg(client, 0x22, dec->channel); 319 320 if (reg >= 0) { 321 if (input == 0) 322 reg &= ~(1 << 2); 323 else 324 reg |= 1 << 2; 325 reg = write_reg(client, 0x22, reg, dec->channel); 326 } 327 328 if (reg >= 0) 329 dec->input = input; 330 else 331 return reg; 332 return 0; 333 } 334 335 static const struct v4l2_ctrl_ops tw2804_ctrl_ops = { 336 .g_volatile_ctrl = tw2804_g_volatile_ctrl, 337 .s_ctrl = tw2804_s_ctrl, 338 }; 339 340 static const struct v4l2_subdev_video_ops tw2804_video_ops = { 341 .s_std = tw2804_s_std, 342 .s_routing = tw2804_s_video_routing, 343 }; 344 345 static const struct v4l2_subdev_core_ops tw2804_core_ops = { 346 .log_status = tw2804_log_status, 347 }; 348 349 static const struct v4l2_subdev_ops tw2804_ops = { 350 .core = &tw2804_core_ops, 351 .video = &tw2804_video_ops, 352 }; 353 354 static int tw2804_probe(struct i2c_client *client, 355 const struct i2c_device_id *id) 356 { 357 struct i2c_adapter *adapter = client->adapter; 358 struct tw2804 *state; 359 struct v4l2_subdev *sd; 360 struct v4l2_ctrl *ctrl; 361 int err; 362 363 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 364 return -ENODEV; 365 366 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); 367 if (state == NULL) 368 return -ENOMEM; 369 sd = &state->sd; 370 v4l2_i2c_subdev_init(sd, client, &tw2804_ops); 371 state->channel = -1; 372 state->norm = V4L2_STD_NTSC; 373 374 v4l2_ctrl_handler_init(&state->hdl, 10); 375 v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 376 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); 377 v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 378 V4L2_CID_CONTRAST, 0, 255, 1, 128); 379 v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 380 V4L2_CID_SATURATION, 0, 255, 1, 128); 381 v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 382 V4L2_CID_HUE, 0, 255, 1, 128); 383 v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 384 V4L2_CID_COLOR_KILLER, 0, 1, 1, 0); 385 v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 386 V4L2_CID_AUTOGAIN, 0, 1, 1, 0); 387 ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 388 V4L2_CID_GAIN, 0, 255, 1, 128); 389 if (ctrl) 390 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 391 ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 392 V4L2_CID_CHROMA_GAIN, 0, 255, 1, 128); 393 if (ctrl) 394 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 395 ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 396 V4L2_CID_BLUE_BALANCE, 0, 255, 1, 122); 397 if (ctrl) 398 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 399 ctrl = v4l2_ctrl_new_std(&state->hdl, &tw2804_ctrl_ops, 400 V4L2_CID_RED_BALANCE, 0, 255, 1, 122); 401 if (ctrl) 402 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; 403 sd->ctrl_handler = &state->hdl; 404 err = state->hdl.error; 405 if (err) { 406 v4l2_ctrl_handler_free(&state->hdl); 407 return err; 408 } 409 410 v4l_info(client, "chip found @ 0x%02x (%s)\n", 411 client->addr << 1, client->adapter->name); 412 413 return 0; 414 } 415 416 static int tw2804_remove(struct i2c_client *client) 417 { 418 struct v4l2_subdev *sd = i2c_get_clientdata(client); 419 struct tw2804 *state = to_state(sd); 420 421 v4l2_device_unregister_subdev(sd); 422 v4l2_ctrl_handler_free(&state->hdl); 423 return 0; 424 } 425 426 static const struct i2c_device_id tw2804_id[] = { 427 { "tw2804", 0 }, 428 { } 429 }; 430 MODULE_DEVICE_TABLE(i2c, tw2804_id); 431 432 static struct i2c_driver tw2804_driver = { 433 .driver = { 434 .name = "tw2804", 435 }, 436 .probe = tw2804_probe, 437 .remove = tw2804_remove, 438 .id_table = tw2804_id, 439 }; 440 441 module_i2c_driver(tw2804_driver); 442 443 MODULE_LICENSE("GPL v2"); 444 MODULE_DESCRIPTION("TW2804/TW2802 V4L2 i2c driver"); 445 MODULE_AUTHOR("Micronas USA Inc"); 446