xref: /linux/drivers/media/i2c/bt866.c (revision 6ed7ffddcf61f668114edb676417e5fb33773b59)
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>
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 module_i2c_driver(bt866_driver);
244