Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/bt866.c
17531 views
1
/*
2
bt866 - BT866 Digital Video Encoder (Rockwell Part)
3
4
Copyright (C) 1999 Mike Bernson <[email protected]>
5
Copyright (C) 1998 Dave Perks <[email protected]>
6
7
Modifications for LML33/DC10plus unified driver
8
Copyright (C) 2000 Serguei Miridonov <[email protected]>
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>
32
#include <linux/types.h>
33
#include <linux/slab.h>
34
#include <linux/ioctl.h>
35
#include <asm/uaccess.h>
36
#include <linux/i2c.h>
37
#include <linux/videodev2.h>
38
#include <media/v4l2-device.h>
39
#include <media/v4l2-chip-ident.h>
40
41
MODULE_DESCRIPTION("Brooktree-866 video encoder driver");
42
MODULE_AUTHOR("Mike Bernson & Dave Perks");
43
MODULE_LICENSE("GPL");
44
45
static int debug;
46
module_param(debug, int, 0);
47
MODULE_PARM_DESC(debug, "Debug level (0-1)");
48
49
50
/* ----------------------------------------------------------------------- */
51
52
struct bt866 {
53
struct v4l2_subdev sd;
54
u8 reg[256];
55
};
56
57
static inline struct bt866 *to_bt866(struct v4l2_subdev *sd)
58
{
59
return container_of(sd, struct bt866, sd);
60
}
61
62
static int bt866_write(struct bt866 *encoder, u8 subaddr, u8 data)
63
{
64
struct i2c_client *client = v4l2_get_subdevdata(&encoder->sd);
65
u8 buffer[2];
66
int err;
67
68
buffer[0] = subaddr;
69
buffer[1] = data;
70
71
encoder->reg[subaddr] = data;
72
73
v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data);
74
75
for (err = 0; err < 3;) {
76
if (i2c_master_send(client, buffer, 2) == 2)
77
break;
78
err++;
79
v4l_warn(client, "error #%d writing to 0x%02x\n",
80
err, subaddr);
81
schedule_timeout_interruptible(msecs_to_jiffies(100));
82
}
83
if (err == 3) {
84
v4l_warn(client, "giving up\n");
85
return -1;
86
}
87
88
return 0;
89
}
90
91
static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
92
{
93
v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
94
95
/* Only PAL supported by this driver at the moment! */
96
if (!(std & V4L2_STD_NTSC))
97
return -EINVAL;
98
return 0;
99
}
100
101
static int bt866_s_routing(struct v4l2_subdev *sd,
102
u32 input, u32 output, u32 config)
103
{
104
static const __u8 init[] = {
105
0xc8, 0xcc, /* CRSCALE */
106
0xca, 0x91, /* CBSCALE */
107
0xcc, 0x24, /* YC16 | OSDNUM */
108
0xda, 0x00, /* */
109
0xdc, 0x24, /* SETMODE | PAL */
110
0xde, 0x02, /* EACTIVE */
111
112
/* overlay colors */
113
0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
114
0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
115
0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
116
0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
117
0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
118
0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
119
0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
120
0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
121
122
0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
123
0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
124
0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
125
0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
126
0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
127
0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
128
0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
129
0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
130
};
131
struct bt866 *encoder = to_bt866(sd);
132
u8 val;
133
int i;
134
135
for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
136
bt866_write(encoder, init[i], init[i+1]);
137
138
val = encoder->reg[0xdc];
139
140
if (input == 0)
141
val |= 0x40; /* CBSWAP */
142
else
143
val &= ~0x40; /* !CBSWAP */
144
145
bt866_write(encoder, 0xdc, val);
146
147
val = encoder->reg[0xcc];
148
if (input == 2)
149
val |= 0x01; /* OSDBAR */
150
else
151
val &= ~0x01; /* !OSDBAR */
152
bt866_write(encoder, 0xcc, val);
153
154
v4l2_dbg(1, debug, sd, "set input %d\n", input);
155
156
switch (input) {
157
case 0:
158
case 1:
159
case 2:
160
break;
161
default:
162
return -EINVAL;
163
}
164
return 0;
165
}
166
167
#if 0
168
/* Code to setup square pixels, might be of some use in the future,
169
but is currently unused. */
170
val = encoder->reg[0xdc];
171
if (*iarg)
172
val |= 1; /* SQUARE */
173
else
174
val &= ~1; /* !SQUARE */
175
bt866_write(client, 0xdc, val);
176
#endif
177
178
static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
179
{
180
struct i2c_client *client = v4l2_get_subdevdata(sd);
181
182
return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0);
183
}
184
185
/* ----------------------------------------------------------------------- */
186
187
static const struct v4l2_subdev_core_ops bt866_core_ops = {
188
.g_chip_ident = bt866_g_chip_ident,
189
};
190
191
static const struct v4l2_subdev_video_ops bt866_video_ops = {
192
.s_std_output = bt866_s_std_output,
193
.s_routing = bt866_s_routing,
194
};
195
196
static const struct v4l2_subdev_ops bt866_ops = {
197
.core = &bt866_core_ops,
198
.video = &bt866_video_ops,
199
};
200
201
static int bt866_probe(struct i2c_client *client,
202
const struct i2c_device_id *id)
203
{
204
struct bt866 *encoder;
205
struct v4l2_subdev *sd;
206
207
v4l_info(client, "chip found @ 0x%x (%s)\n",
208
client->addr << 1, client->adapter->name);
209
210
encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
211
if (encoder == NULL)
212
return -ENOMEM;
213
sd = &encoder->sd;
214
v4l2_i2c_subdev_init(sd, client, &bt866_ops);
215
return 0;
216
}
217
218
static int bt866_remove(struct i2c_client *client)
219
{
220
struct v4l2_subdev *sd = i2c_get_clientdata(client);
221
222
v4l2_device_unregister_subdev(sd);
223
kfree(to_bt866(sd));
224
return 0;
225
}
226
227
static const struct i2c_device_id bt866_id[] = {
228
{ "bt866", 0 },
229
{ }
230
};
231
MODULE_DEVICE_TABLE(i2c, bt866_id);
232
233
static struct i2c_driver bt866_driver = {
234
.driver = {
235
.owner = THIS_MODULE,
236
.name = "bt866",
237
},
238
.probe = bt866_probe,
239
.remove = bt866_remove,
240
.id_table = bt866_id,
241
};
242
243
static __init int init_bt866(void)
244
{
245
return i2c_add_driver(&bt866_driver);
246
}
247
248
static __exit void exit_bt866(void)
249
{
250
i2c_del_driver(&bt866_driver);
251
}
252
253
module_init(init_bt866);
254
module_exit(exit_bt866);
255
256