Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[deliverable/linux.git] / drivers / media / video / bt866.c
CommitLineData
fbe60daa
MS
1/*
2 bt866 - BT866 Digital Video Encoder (Rockwell Part)
3
4 Copyright (C) 1999 Mike Bernson <mike@mlb.org>
5 Copyright (C) 1998 Dave Perks <dperks@ibm.net>
6
7 Modifications for LML33/DC10plus unified driver
8 Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
9
10 This code was modify/ported from the saa7111 driver written
11 by Dave Perks.
12
13 This code was adapted for the bt866 by Christer Weinigel and ported
14 to 2.6 by Martin Samuelsson.
15
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 2 of the License, or
19 (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29*/
30
31#include <linux/module.h>
fbe60daa 32#include <linux/types.h>
c18fdcf6
HV
33#include <linux/ioctl.h>
34#include <asm/uaccess.h>
fbe60daa 35#include <linux/i2c.h>
c18fdcf6 36#include <linux/i2c-id.h>
fbe60daa 37#include <linux/videodev.h>
fbe60daa 38#include <linux/video_encoder.h>
c18fdcf6
HV
39#include <media/v4l2-common.h>
40#include <media/v4l2-i2c-drv-legacy.h>
fbe60daa 41
c18fdcf6
HV
42MODULE_DESCRIPTION("Brooktree-866 video encoder driver");
43MODULE_AUTHOR("Mike Bernson & Dave Perks");
fbe60daa
MS
44MODULE_LICENSE("GPL");
45
c18fdcf6
HV
46static int debug;
47module_param(debug, int, 0);
48MODULE_PARM_DESC(debug, "Debug level (0-1)");
fbe60daa
MS
49
50/* ----------------------------------------------------------------------- */
51
52struct bt866 {
c18fdcf6 53 u8 reg[256];
fbe60daa
MS
54
55 int norm;
56 int enable;
57 int bright;
58 int contrast;
59 int hue;
60 int sat;
61};
62
c18fdcf6
HV
63static int bt866_write(struct i2c_client *client, u8 subaddr, u8 data)
64{
65 struct bt866 *encoder = i2c_get_clientdata(client);
66 u8 buffer[2];
67 int err;
68
69 buffer[0] = subaddr;
70 buffer[1] = data;
71
72 encoder->reg[subaddr] = data;
73
74 v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data);
75
76 for (err = 0; err < 3;) {
77 if (i2c_master_send(client, buffer, 2) == 2)
78 break;
79 err++;
80 v4l_warn(client, "error #%d writing to 0x%02x\n",
81 err, subaddr);
82 schedule_timeout_interruptible(msecs_to_jiffies(100));
83 }
84 if (err == 3) {
85 v4l_warn(client, "giving up\n");
86 return -1;
87 }
88
89 return 0;
90}
fbe60daa 91
c18fdcf6 92static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
fbe60daa 93{
c18fdcf6
HV
94 struct bt866 *encoder = i2c_get_clientdata(client);
95
fbe60daa
MS
96 switch (cmd) {
97 case ENCODER_GET_CAPABILITIES:
98 {
99 struct video_encoder_capability *cap = arg;
100
c18fdcf6 101 v4l_dbg(1, debug, client, "get capabilities\n");
fbe60daa
MS
102
103 cap->flags
104 = VIDEO_ENCODER_PAL
105 | VIDEO_ENCODER_NTSC
106 | VIDEO_ENCODER_CCIR;
107 cap->inputs = 2;
108 cap->outputs = 1;
c18fdcf6 109 break;
fbe60daa 110 }
fbe60daa
MS
111
112 case ENCODER_SET_NORM:
113 {
114 int *iarg = arg;
115
c18fdcf6 116 v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
fbe60daa
MS
117
118 switch (*iarg) {
fbe60daa
MS
119 case VIDEO_MODE_NTSC:
120 break;
121
122 case VIDEO_MODE_PAL:
123 break;
124
125 default:
126 return -EINVAL;
fbe60daa
MS
127 }
128 encoder->norm = *iarg;
c18fdcf6 129 break;
fbe60daa 130 }
fbe60daa
MS
131
132 case ENCODER_SET_INPUT:
133 {
134 int *iarg = arg;
135 static const __u8 init[] = {
136 0xc8, 0xcc, /* CRSCALE */
137 0xca, 0x91, /* CBSCALE */
138 0xcc, 0x24, /* YC16 | OSDNUM */
139 0xda, 0x00, /* */
140 0xdc, 0x24, /* SETMODE | PAL */
141 0xde, 0x02, /* EACTIVE */
142
143 /* overlay colors */
144 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
145 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
146 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
147 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
148 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
149 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
150 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
151 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
152
153 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
154 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
155 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
156 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
157 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
158 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
159 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
160 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
161 };
162 int i;
163 u8 val;
164
165 for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
c18fdcf6 166 bt866_write(client, init[i], init[i+1]);
fbe60daa
MS
167
168 val = encoder->reg[0xdc];
169
170 if (*iarg == 0)
171 val |= 0x40; /* CBSWAP */
172 else
173 val &= ~0x40; /* !CBSWAP */
174
c18fdcf6 175 bt866_write(client, 0xdc, val);
fbe60daa
MS
176
177 val = encoder->reg[0xcc];
178 if (*iarg == 2)
179 val |= 0x01; /* OSDBAR */
180 else
181 val &= ~0x01; /* !OSDBAR */
c18fdcf6 182 bt866_write(client, 0xcc, val);
fbe60daa 183
c18fdcf6 184 v4l_dbg(1, debug, client, "set input %d\n", *iarg);
fbe60daa
MS
185
186 switch (*iarg) {
187 case 0:
188 break;
189 case 1:
190 break;
191 default:
192 return -EINVAL;
fbe60daa 193 }
c18fdcf6 194 break;
fbe60daa 195 }
fbe60daa
MS
196
197 case ENCODER_SET_OUTPUT:
198 {
199 int *iarg = arg;
200
c18fdcf6 201 v4l_dbg(1, debug, client, "set output %d\n", *iarg);
fbe60daa
MS
202
203 /* not much choice of outputs */
204 if (*iarg != 0)
205 return -EINVAL;
c18fdcf6 206 break;
fbe60daa 207 }
fbe60daa
MS
208
209 case ENCODER_ENABLE_OUTPUT:
210 {
211 int *iarg = arg;
212 encoder->enable = !!*iarg;
213
c18fdcf6
HV
214 v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
215 break;
fbe60daa 216 }
fbe60daa
MS
217
218 case 4711:
219 {
220 int *iarg = arg;
221 __u8 val;
222
c18fdcf6 223 v4l_dbg(1, debug, client, "square %d\n", *iarg);
fbe60daa
MS
224
225 val = encoder->reg[0xdc];
226 if (*iarg)
227 val |= 1; /* SQUARE */
228 else
229 val &= ~1; /* !SQUARE */
c18fdcf6 230 bt866_write(client, 0xdc, val);
fbe60daa
MS
231 break;
232 }
233
234 default:
235 return -EINVAL;
236 }
237
238 return 0;
239}
240
c18fdcf6 241static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
fbe60daa 242
c18fdcf6 243I2C_CLIENT_INSMOD;
fbe60daa 244
c18fdcf6
HV
245static int bt866_probe(struct i2c_client *client,
246 const struct i2c_device_id *id)
fbe60daa
MS
247{
248 struct bt866 *encoder;
fbe60daa 249
c18fdcf6
HV
250 v4l_info(client, "chip found @ 0x%x (%s)\n",
251 client->addr << 1, client->adapter->name);
fbe60daa
MS
252
253 encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
c18fdcf6 254 if (encoder == NULL)
fbe60daa 255 return -ENOMEM;
fbe60daa
MS
256
257 i2c_set_clientdata(client, encoder);
fbe60daa
MS
258 return 0;
259}
260
c18fdcf6 261static int bt866_remove(struct i2c_client *client)
fbe60daa 262{
c18fdcf6 263 kfree(i2c_get_clientdata(client));
fbe60daa
MS
264 return 0;
265}
266
c18fdcf6 267static int bt866_legacy_probe(struct i2c_adapter *adapter)
fbe60daa 268{
c18fdcf6 269 return adapter->id == I2C_HW_B_ZR36067;
fbe60daa
MS
270}
271
c18fdcf6
HV
272static const struct i2c_device_id bt866_id[] = {
273 { "bt866", 0 },
274 { }
275};
276MODULE_DEVICE_TABLE(i2c, bt866_id);
277
278static struct v4l2_i2c_driver_data v4l2_i2c_data = {
279 .name = "bt866",
280 .driverid = I2C_DRIVERID_BT866,
281 .command = bt866_command,
282 .probe = bt866_probe,
283 .remove = bt866_remove,
284 .legacy_probe = bt866_legacy_probe,
285 .id_table = bt866_id,
286};
This page took 0.525374 seconds and 5 git commands to generate.