wis-tw2804.c revision 5a0e3ad6af8660be21ca98a971cd00f331318c05
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/i2c.h> 21df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen#include <linux/videodev2.h> 22866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include <linux/ioctl.h> 235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 24866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 25866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman#include "wis-i2c.h" 26866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 27866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstruct wis_tw2804 { 28866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int channel; 29866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int norm; 30866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int brightness; 31866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int contrast; 32866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int saturation; 33866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int hue; 34866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}; 35866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 36866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic u8 global_registers[] = 37866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 38866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x39, 0x00, 39866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3a, 0xff, 40866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3b, 0x84, 41866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3c, 0x80, 42866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3d, 0x80, 43866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3e, 0x82, 44866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x3f, 0x82, 45866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ 46866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}; 47866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 48866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic u8 channel_registers[] = 49866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 50866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x01, 0xc4, 51866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x02, 0xa5, 52866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x03, 0x20, 53866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x04, 0xd0, 54866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x05, 0x20, 55866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x06, 0xd0, 56866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x07, 0x88, 57866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x08, 0x20, 58866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x09, 0x07, 59866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0a, 0xf0, 60866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0b, 0x07, 61866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0c, 0xf0, 62866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0d, 0x40, 63866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0e, 0xd2, 64866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x0f, 0x80, 65866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x10, 0x80, 66866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x11, 0x80, 67866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x12, 0x80, 68866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x13, 0x1f, 69866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x14, 0x00, 70866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x15, 0x00, 71866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x16, 0x00, 72866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x17, 0x00, 73866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x18, 0xff, 74866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x19, 0xff, 75866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1a, 0xff, 76866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1b, 0xff, 77866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1c, 0xff, 78866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1d, 0xff, 79866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1e, 0xff, 80866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x1f, 0xff, 81866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x20, 0x07, 82866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x21, 0x07, 83866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x22, 0x00, 84866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x23, 0x91, 85866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x24, 0x51, 86866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x25, 0x03, 87866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x26, 0x00, 88866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x27, 0x00, 89866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x28, 0x00, 90866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x29, 0x00, 91866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2a, 0x00, 92866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2b, 0x00, 93866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2c, 0x00, 94866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2d, 0x00, 95866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2e, 0x00, 96866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x2f, 0x00, 97866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x30, 0x00, 98866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x31, 0x00, 99866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x32, 0x00, 100866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x33, 0x00, 101866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x34, 0x00, 102866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x35, 0x00, 103866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x36, 0x00, 104866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0x37, 0x00, 105866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0xff, 0xff, /* Terminator (reg 0xff does not exist) */ 106866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}; 107866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 108866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int write_reg(struct i2c_client *client, u8 reg, u8 value, int channel) 109866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 110866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return i2c_smbus_write_byte_data(client, reg | (channel << 6), value); 111866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 112866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 113866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int write_regs(struct i2c_client *client, u8 *regs, int channel) 114866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 115866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int i; 116866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 117866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman for (i = 0; regs[i] != 0xff; i += 2) 118866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (i2c_smbus_write_byte_data(client, 119866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman regs[i] | (channel << 6), regs[i + 1]) < 0) 120866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return -1; 121866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 122866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 123866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 124866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int wis_tw2804_command(struct i2c_client *client, 125866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman unsigned int cmd, void *arg) 126866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 127866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct wis_tw2804 *dec = i2c_get_clientdata(client); 128866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 129866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (cmd == DECODER_SET_CHANNEL) { 130866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman int *input = arg; 131866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 132866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (*input < 0 || *input > 3) { 133866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_ERR "wis-tw2804: channel %d is not " 134866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "between 0 and 3!\n", *input); 135866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 136866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 137866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->channel = *input; 138866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_DEBUG "wis-tw2804: initializing TW2804 " 139866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "channel %d\n", dec->channel); 140866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (dec->channel == 0 && 141866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_regs(client, global_registers, 0) < 0) { 142866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_ERR "wis-tw2804: error initializing " 143866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "TW2804 global registers\n"); 144866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 145866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 146866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (write_regs(client, channel_registers, dec->channel) < 0) { 147866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_ERR "wis-tw2804: error initializing " 148866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "TW2804 channel %d\n", dec->channel); 149866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 150866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 151866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 152866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 153866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 154866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (dec->channel < 0) { 155866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_DEBUG "wis-tw2804: ignoring command %08x until " 156866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman "channel number is set\n", cmd); 157866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 158866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 159866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 160866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman switch (cmd) { 161df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen case VIDIOC_S_STD: 162866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman { 163df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen v4l2_std_id *input = arg; 164866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman u8 regs[] = { 165df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x01, *input & V4L2_STD_NTSC ? 0xc4 : 0x84, 166df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x09, *input & V4L2_STD_NTSC ? 0x07 : 0x04, 167df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x0a, *input & V4L2_STD_NTSC ? 0xf0 : 0x20, 168df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x0b, *input & V4L2_STD_NTSC ? 0x07 : 0x04, 169df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x0c, *input & V4L2_STD_NTSC ? 0xf0 : 0x20, 170df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x0d, *input & V4L2_STD_NTSC ? 0x40 : 0x4a, 171df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x16, *input & V4L2_STD_NTSC ? 0x00 : 0x40, 172df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x17, *input & V4L2_STD_NTSC ? 0x00 : 0x40, 173df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x20, *input & V4L2_STD_NTSC ? 0x07 : 0x0f, 174df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen 0x21, *input & V4L2_STD_NTSC ? 0x07 : 0x0f, 175866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 0xff, 0xff, 176866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman }; 177866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_regs(client, regs, dec->channel); 178866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->norm = *input; 179866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 180866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 181866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case VIDIOC_QUERYCTRL: 182866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman { 183866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct v4l2_queryctrl *ctrl = arg; 184866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 185866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman switch (ctrl->id) { 186866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_BRIGHTNESS: 187866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->type = V4L2_CTRL_TYPE_INTEGER; 188866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)); 189866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->minimum = 0; 190866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->maximum = 255; 191866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->step = 1; 192866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->default_value = 128; 193866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->flags = 0; 194866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 195866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_CONTRAST: 196866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->type = V4L2_CTRL_TYPE_INTEGER; 197866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)); 198866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->minimum = 0; 199866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->maximum = 255; 200866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->step = 1; 201866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->default_value = 128; 202866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->flags = 0; 203866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 204866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_SATURATION: 205866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->type = V4L2_CTRL_TYPE_INTEGER; 206866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)); 207866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->minimum = 0; 208866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->maximum = 255; 209866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->step = 1; 210866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->default_value = 128; 211866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->flags = 0; 212866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 213866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_HUE: 214866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->type = V4L2_CTRL_TYPE_INTEGER; 215866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman strncpy(ctrl->name, "Hue", sizeof(ctrl->name)); 216866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->minimum = 0; 217866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->maximum = 255; 218866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->step = 1; 219866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->default_value = 128; 220866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->flags = 0; 221866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 222866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 223866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 224866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 225866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case VIDIOC_S_CTRL: 226866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman { 227866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct v4l2_control *ctrl = arg; 228866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 229866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman switch (ctrl->id) { 230866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_BRIGHTNESS: 231866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (ctrl->value > 255) 232866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->brightness = 255; 233866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else if (ctrl->value < 0) 234866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->brightness = 0; 235866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else 236866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->brightness = ctrl->value; 237866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_reg(client, 0x12, dec->brightness, dec->channel); 238866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 239866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_CONTRAST: 240866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (ctrl->value > 255) 241866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->contrast = 255; 242866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else if (ctrl->value < 0) 243866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->contrast = 0; 244866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else 245866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->contrast = ctrl->value; 246866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_reg(client, 0x11, dec->contrast, dec->channel); 247866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 248866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_SATURATION: 249866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (ctrl->value > 255) 250866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->saturation = 255; 251866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else if (ctrl->value < 0) 252866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->saturation = 0; 253866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else 254866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->saturation = ctrl->value; 255866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_reg(client, 0x10, dec->saturation, dec->channel); 256866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 257866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_HUE: 258866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (ctrl->value > 255) 259866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->hue = 255; 260866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else if (ctrl->value < 0) 261866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->hue = 0; 262866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman else 263866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->hue = ctrl->value; 264866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman write_reg(client, 0x0f, dec->hue, dec->channel); 265866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 266866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 267866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 268866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 269866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case VIDIOC_G_CTRL: 270866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman { 271866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct v4l2_control *ctrl = arg; 272866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 273866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman switch (ctrl->id) { 274866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_BRIGHTNESS: 275866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->value = dec->brightness; 276866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 277866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_CONTRAST: 278866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->value = dec->contrast; 279866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 280866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_SATURATION: 281866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->value = dec->saturation; 282866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 283866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman case V4L2_CID_HUE: 284866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman ctrl->value = dec->hue; 285866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 286866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 287866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 288866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 289866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman default: 290866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman break; 291866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman } 292866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 293866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 294866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 2957400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvarestatic int wis_tw2804_probe(struct i2c_client *client, 2967400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare const struct i2c_device_id *id) 297866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 2987400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare struct i2c_adapter *adapter = client->adapter; 299866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct wis_tw2804 *dec; 300866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 301866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 3027400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare return -ENODEV; 303866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 304866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec = kmalloc(sizeof(struct wis_tw2804), GFP_KERNEL); 3057400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare if (dec == NULL) 306866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return -ENOMEM; 3077400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare 308866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->channel = -1; 309df20d69ec968b33526461457c219ad4ba8ba8ac8Ross Cohen dec->norm = V4L2_STD_NTSC; 310866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->brightness = 128; 311866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->contrast = 128; 312866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->saturation = 128; 313866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman dec->hue = 128; 314866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman i2c_set_clientdata(client, dec); 315866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 316866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman printk(KERN_DEBUG "wis-tw2804: creating TW2804 at address %d on %s\n", 3177400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare client->addr, adapter->name); 318866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 319866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 320866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 321866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 3227400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvarestatic int wis_tw2804_remove(struct i2c_client *client) 323866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 324866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman struct wis_tw2804 *dec = i2c_get_clientdata(client); 325866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 3267400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare i2c_set_clientdata(client, NULL); 327866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman kfree(dec); 328866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman return 0; 329866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 330866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 331b76a32638d9d7d6b421fccce02e667007509bd7bNémeth Mártonstatic const struct i2c_device_id wis_tw2804_id[] = { 3327400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare { "wis_tw2804", 0 }, 3337400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare { } 3347400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare}; 3357400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare 336866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic struct i2c_driver wis_tw2804_driver = { 337866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .driver = { 338866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .name = "WIS TW2804 I2C driver", 339866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman }, 3407400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare .probe = wis_tw2804_probe, 3417400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare .remove = wis_tw2804_remove, 342866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman .command = wis_tw2804_command, 3437400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare .id_table = wis_tw2804_id, 344866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman}; 345866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 346866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic int __init wis_tw2804_init(void) 347866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 3487400516ab40d8fe55031dc8d614e2b365bd95f1cJean Delvare return i2c_add_driver(&wis_tw2804_driver); 349866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 350866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 351866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanstatic void __exit wis_tw2804_cleanup(void) 352866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman{ 353866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman i2c_del_driver(&wis_tw2804_driver); 354866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman} 355866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 356866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanmodule_init(wis_tw2804_init); 357866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartmanmodule_exit(wis_tw2804_cleanup); 358866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-Hartman 359866b8695d67e83f47194731d3a7ba55826a7ec70Greg Kroah-HartmanMODULE_LICENSE("GPL v2"); 360