wis-tw2804.c revision 866b8695d67e83f47194731d3a7ba55826a7ec70
1866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman/* 2866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * Copyright (C) 2005-2006 Micronas USA Inc. 3866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * 4866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * This program is free software; you can redistribute it and/or modify 5866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * it under the terms of the GNU General Public License (Version 2) as 6866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * published by the Free Software Foundation. 7866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * 8866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * This program is distributed in the hope that it will be useful, 9866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * but WITHOUT ANY WARRANTY; without even the implied warranty of 10866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * GNU General Public License for more details. 12866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * 13866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * You should have received a copy of the GNU General Public License 14866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * along with this program; if not, write to the Free Software Foundation, 15866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 16866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman */ 17866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 18866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/module.h> 19866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/init.h> 20866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/version.h> 21866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/i2c.h> 22866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/videodev.h> 23866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/video_decoder.h> 24866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/ioctl.h> 25866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 26866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include "wis-i2c.h" 27866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 28866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstruct wis_tw2804 { 29866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int channel; 30866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int norm; 31866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int brightness; 32866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int contrast; 33866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int saturation; 34866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int hue; 35866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}; 36866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 37866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic u8 global_registers[] = 38866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 39866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x39, 0x00, 40866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3a, 0xff, 41866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3b, 0x84, 42866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3c, 0x80, 43866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3d, 0x80, 44866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3e, 0x82, 45866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3f, 0x82, 46866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ 47866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}; 48866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 49866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic u8 channel_registers[] = 50866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 51866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x01, 0xc4, 52866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x02, 0xa5, 53866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x03, 0x20, 54866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x04, 0xd0, 55866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x05, 0x20, 56866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x06, 0xd0, 57866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x07, 0x88, 58866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x08, 0x20, 59866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x09, 0x07, 60866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0a, 0xf0, 61866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0b, 0x07, 62866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0c, 0xf0, 63866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0d, 0x40, 64866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0e, 0xd2, 65866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0f, 0x80, 66866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x10, 0x80, 67866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x11, 0x80, 68866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x12, 0x80, 69866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x13, 0x1f, 70866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x14, 0x00, 71866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x15, 0x00, 72866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x16, 0x00, 73866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x17, 0x00, 74866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x18, 0xff, 75866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x19, 0xff, 76866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1a, 0xff, 77866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1b, 0xff, 78866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1c, 0xff, 79866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1d, 0xff, 80866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1e, 0xff, 81866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1f, 0xff, 82866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x20, 0x07, 83866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x21, 0x07, 84866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x22, 0x00, 85866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x23, 0x91, 86866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x24, 0x51, 87866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x25, 0x03, 88866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x26, 0x00, 89866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x27, 0x00, 90866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x28, 0x00, 91866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x29, 0x00, 92866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2a, 0x00, 93866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2b, 0x00, 94866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2c, 0x00, 95866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2d, 0x00, 96866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2e, 0x00, 97866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2f, 0x00, 98866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x30, 0x00, 99866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x31, 0x00, 100866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x32, 0x00, 101866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x33, 0x00, 102866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x34, 0x00, 103866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x35, 0x00, 104866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x36, 0x00, 105866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x37, 0x00, 106866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ 107866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}; 108866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 109866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int write_reg(struct i2c_client *client, u8 reg, u8 value, int channel) 110866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 111866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return i2c_smbus_write_byte_data(client, reg | (channel << 6), value); 112866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 113866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 114866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int write_regs(struct i2c_client *client, u8 *regs, int channel) 115866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 116866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int i; 117866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 118866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman for (i = 0; regs[i] != 0xff; i += 2) 119866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (i2c_smbus_write_byte_data(client, 120866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman regs[i] | (channel << 6), regs[i + 1]) < 0) 121866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return -1; 122866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 123866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 124866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 125866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int wis_tw2804_command(struct i2c_client *client, 126866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman unsigned int cmd, void *arg) 127866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 128866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct wis_tw2804 *dec = i2c_get_clientdata(client); 129866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 130866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (cmd == DECODER_SET_CHANNEL) { 131866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int *input = arg; 132866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 133866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (*input < 0 || *input > 3) { 134866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_ERR "wis-tw2804: channel %d is not " 135866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "between 0 and 3!\n", *input); 136866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 137866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 138866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->channel = *input; 139866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_DEBUG "wis-tw2804: initializing TW2804 " 140866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "channel %d\n", dec->channel); 141866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (dec->channel == 0 && 142866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_regs(client, global_registers, 0) < 0) { 143866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_ERR "wis-tw2804: error initializing " 144866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "TW2804 global registers\n"); 145866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 146866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 147866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (write_regs(client, channel_registers, dec->channel) < 0) { 148866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_ERR "wis-tw2804: error initializing " 149866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "TW2804 channel %d\n", dec->channel); 150866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 151866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 152866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 153866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 154866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 155866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (dec->channel < 0) { 156866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_DEBUG "wis-tw2804: ignoring command %08x until " 157866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "channel number is set\n", cmd); 158866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 159866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 160866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 161866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman switch (cmd) { 162866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case DECODER_SET_NORM: 163866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman { 164866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int *input = arg; 165866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman u8 regs[] = { 166866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x01, *input == VIDEO_MODE_NTSC ? 0xc4 : 0x84, 167866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x09, *input == VIDEO_MODE_NTSC ? 0x07 : 0x04, 168866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0a, *input == VIDEO_MODE_NTSC ? 0xf0 : 0x20, 169866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0b, *input == VIDEO_MODE_NTSC ? 0x07 : 0x04, 170866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0c, *input == VIDEO_MODE_NTSC ? 0xf0 : 0x20, 171866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0d, *input == VIDEO_MODE_NTSC ? 0x40 : 0x4a, 172866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x16, *input == VIDEO_MODE_NTSC ? 0x00 : 0x40, 173866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x17, *input == VIDEO_MODE_NTSC ? 0x00 : 0x40, 174866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x20, *input == VIDEO_MODE_NTSC ? 0x07 : 0x0f, 175866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x21, *input == VIDEO_MODE_NTSC ? 0x07 : 0x0f, 176866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0xff, 0xff, 177866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman }; 178866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_regs(client, regs, dec->channel); 179866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->norm = *input; 180866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 181866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 182866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case VIDIOC_QUERYCTRL: 183866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman { 184866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct v4l2_queryctrl *ctrl = arg; 185866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 186866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman switch (ctrl->id) { 187866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_BRIGHTNESS: 188866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->type = V4L2_CTRL_TYPE_INTEGER; 189866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)); 190866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->minimum = 0; 191866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->maximum = 255; 192866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->step = 1; 193866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->default_value = 128; 194866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->flags = 0; 195866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 196866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_CONTRAST: 197866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->type = V4L2_CTRL_TYPE_INTEGER; 198866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)); 199866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->minimum = 0; 200866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->maximum = 255; 201866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->step = 1; 202866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->default_value = 128; 203866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->flags = 0; 204866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 205866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_SATURATION: 206866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->type = V4L2_CTRL_TYPE_INTEGER; 207866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)); 208866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->minimum = 0; 209866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->maximum = 255; 210866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->step = 1; 211866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->default_value = 128; 212866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->flags = 0; 213866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 214866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_HUE: 215866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->type = V4L2_CTRL_TYPE_INTEGER; 216866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman strncpy(ctrl->name, "Hue", sizeof(ctrl->name)); 217866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->minimum = 0; 218866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->maximum = 255; 219866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->step = 1; 220866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->default_value = 128; 221866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->flags = 0; 222866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 223866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 224866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 225866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 226866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case VIDIOC_S_CTRL: 227866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman { 228866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct v4l2_control *ctrl = arg; 229866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 230866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman switch (ctrl->id) { 231866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_BRIGHTNESS: 232866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (ctrl->value > 255) 233866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->brightness = 255; 234866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else if (ctrl->value < 0) 235866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->brightness = 0; 236866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else 237866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->brightness = ctrl->value; 238866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_reg(client, 0x12, dec->brightness, dec->channel); 239866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 240866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_CONTRAST: 241866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (ctrl->value > 255) 242866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->contrast = 255; 243866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else if (ctrl->value < 0) 244866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->contrast = 0; 245866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else 246866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->contrast = ctrl->value; 247866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_reg(client, 0x11, dec->contrast, dec->channel); 248866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 249866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_SATURATION: 250866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (ctrl->value > 255) 251866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->saturation = 255; 252866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else if (ctrl->value < 0) 253866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->saturation = 0; 254866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else 255866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->saturation = ctrl->value; 256866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_reg(client, 0x10, dec->saturation, dec->channel); 257866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 258866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_HUE: 259866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (ctrl->value > 255) 260866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->hue = 255; 261866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else if (ctrl->value < 0) 262866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->hue = 0; 263866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else 264866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->hue = ctrl->value; 265866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_reg(client, 0x0f, dec->hue, dec->channel); 266866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 267866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 268866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 269866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 270866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case VIDIOC_G_CTRL: 271866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman { 272866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct v4l2_control *ctrl = arg; 273866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 274866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman switch (ctrl->id) { 275866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_BRIGHTNESS: 276866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->value = dec->brightness; 277866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 278866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_CONTRAST: 279866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->value = dec->contrast; 280866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 281866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_SATURATION: 282866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->value = dec->saturation; 283866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 284866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_HUE: 285866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->value = dec->hue; 286866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 287866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 288866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 289866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 290866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman default: 291866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 292866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 293866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 294866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 295866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 296866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic struct i2c_driver wis_tw2804_driver; 297866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 298866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic struct i2c_client wis_tw2804_client_templ = { 299866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .name = "TW2804 (WIS)", 300866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .driver = &wis_tw2804_driver, 301866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}; 302866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 303866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int wis_tw2804_detect(struct i2c_adapter *adapter, int addr, int kind) 304866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 305866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct i2c_client *client; 306866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct wis_tw2804 *dec; 307866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 308866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 309866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 310866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 311866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); 312866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (client == NULL) 313866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return -ENOMEM; 314866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman memcpy(client, &wis_tw2804_client_templ, 315866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman sizeof(wis_tw2804_client_templ)); 316866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman client->adapter = adapter; 317866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman client->addr = addr; 318866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 319866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec = kmalloc(sizeof(struct wis_tw2804), GFP_KERNEL); 320866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (dec == NULL) { 321866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman kfree(client); 322866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return -ENOMEM; 323866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 324866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->channel = -1; 325866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->norm = VIDEO_MODE_NTSC; 326866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->brightness = 128; 327866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->contrast = 128; 328866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->saturation = 128; 329866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->hue = 128; 330866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman i2c_set_clientdata(client, dec); 331866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 332866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n", 333866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman addr, adapter->name); 334866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 335866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman i2c_attach_client(client); 336866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 337866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 338866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 339866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int wis_tw2804_detach(struct i2c_client *client) 340866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 341866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct wis_tw2804 *dec = i2c_get_clientdata(client); 342866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int r; 343866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 344866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman r = i2c_detach_client(client); 345866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (r < 0) 346866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return r; 347866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 348866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman kfree(client); 349866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman kfree(dec); 350866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 351866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 352866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 353866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic struct i2c_driver wis_tw2804_driver = { 354866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .driver = { 355866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .name = "WIS TW2804 I2C driver", 356866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman }, 357866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .id = I2C_DRIVERID_WIS_TW2804, 358866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .detach_client = wis_tw2804_detach, 359866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .command = wis_tw2804_command, 360866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}; 361866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 362866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int __init wis_tw2804_init(void) 363866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 364866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int r; 365866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 366866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman r = i2c_add_driver(&wis_tw2804_driver); 367866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (r < 0) 368866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return r; 369866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return wis_i2c_add_driver(wis_tw2804_driver.id, wis_tw2804_detect); 370866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 371866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 372866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic void __exit wis_tw2804_cleanup(void) 373866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 374866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman wis_i2c_del_driver(wis_tw2804_detect); 375866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman i2c_del_driver(&wis_tw2804_driver); 376866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 377866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 378866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanmodule_init(wis_tw2804_init); 379866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanmodule_exit(wis_tw2804_cleanup); 380866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 381866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-HartmanMODULE_LICENSE("GPL v2"); 382