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