]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/media/video/bt856.c
V4L/DVB (10714): zoran et al: convert zoran i2c modules to V4L2.
[karo-tx-linux.git] / drivers / media / video / bt856.c
1 /*
2  * bt856 - BT856A 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  * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
14  *   - moved over to linux>=2.4.x i2c protocol (9/9/2002)
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/ioctl.h>
34 #include <asm/uaccess.h>
35 #include <linux/i2c.h>
36 #include <linux/i2c-id.h>
37 #include <linux/videodev.h>
38 #include <linux/video_encoder.h>
39 #include <media/v4l2-common.h>
40 #include <media/v4l2-i2c-drv-legacy.h>
41
42 MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
43 MODULE_AUTHOR("Mike Bernson & Dave Perks");
44 MODULE_LICENSE("GPL");
45
46 static int debug;
47 module_param(debug, int, 0);
48 MODULE_PARM_DESC(debug, "Debug level (0-1)");
49
50 /* ----------------------------------------------------------------------- */
51
52 #define BT856_REG_OFFSET        0xDA
53 #define BT856_NR_REG            6
54
55 struct bt856 {
56         unsigned char reg[BT856_NR_REG];
57
58         v4l2_std_id norm;
59 };
60
61 /* ----------------------------------------------------------------------- */
62
63 static inline int bt856_write(struct i2c_client *client, u8 reg, u8 value)
64 {
65         struct bt856 *encoder = i2c_get_clientdata(client);
66
67         encoder->reg[reg - BT856_REG_OFFSET] = value;
68         return i2c_smbus_write_byte_data(client, reg, value);
69 }
70
71 static inline int bt856_setbit(struct i2c_client *client, u8 reg, u8 bit, u8 value)
72 {
73         struct bt856 *encoder = i2c_get_clientdata(client);
74
75         return bt856_write(client, reg,
76                 (encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
77                                 (value ? (1 << bit) : 0));
78 }
79
80 static void bt856_dump(struct i2c_client *client)
81 {
82         int i;
83         struct bt856 *encoder = i2c_get_clientdata(client);
84
85         v4l_info(client, "register dump:\n");
86         for (i = 0; i < BT856_NR_REG; i += 2)
87                 printk(KERN_CONT " %02x", encoder->reg[i]);
88         printk(KERN_CONT "\n");
89 }
90
91 /* ----------------------------------------------------------------------- */
92
93 static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
94 {
95         struct bt856 *encoder = i2c_get_clientdata(client);
96
97         switch (cmd) {
98         case VIDIOC_INT_INIT:
99                 /* This is just for testing!!! */
100                 v4l_dbg(1, debug, client, "init\n");
101                 bt856_write(client, 0xdc, 0x18);
102                 bt856_write(client, 0xda, 0);
103                 bt856_write(client, 0xde, 0);
104
105                 bt856_setbit(client, 0xdc, 3, 1);
106                 //bt856_setbit(client, 0xdc, 6, 0);
107                 bt856_setbit(client, 0xdc, 4, 1);
108
109                 if (encoder->norm & V4L2_STD_NTSC)
110                         bt856_setbit(client, 0xdc, 2, 0);
111                 else
112                         bt856_setbit(client, 0xdc, 2, 1);
113
114                 bt856_setbit(client, 0xdc, 1, 1);
115                 bt856_setbit(client, 0xde, 4, 0);
116                 bt856_setbit(client, 0xde, 3, 1);
117                 if (debug != 0)
118                         bt856_dump(client);
119                 break;
120
121         case VIDIOC_INT_S_STD_OUTPUT:
122         {
123                 v4l2_std_id *iarg = arg;
124
125                 v4l_dbg(1, debug, client, "set norm %llx\n", *iarg);
126
127                 if (*iarg & V4L2_STD_NTSC) {
128                         bt856_setbit(client, 0xdc, 2, 0);
129                 } else if (*iarg & V4L2_STD_PAL) {
130                         bt856_setbit(client, 0xdc, 2, 1);
131                         bt856_setbit(client, 0xda, 0, 0);
132                         //bt856_setbit(client, 0xda, 0, 1);
133                 } else {
134                         return -EINVAL;
135                 }
136                 encoder->norm = *iarg;
137                 if (debug != 0)
138                         bt856_dump(client);
139                 break;
140         }
141
142         case VIDIOC_INT_S_VIDEO_ROUTING:
143         {
144                 struct v4l2_routing *route = arg;
145
146                 v4l_dbg(1, debug, client, "set input %d\n", route->input);
147
148                 /* We only have video bus.
149                  * route->input= 0: input is from bt819
150                  * route->input= 1: input is from ZR36060 */
151                 switch (route->input) {
152                 case 0:
153                         bt856_setbit(client, 0xde, 4, 0);
154                         bt856_setbit(client, 0xde, 3, 1);
155                         bt856_setbit(client, 0xdc, 3, 1);
156                         bt856_setbit(client, 0xdc, 6, 0);
157                         break;
158                 case 1:
159                         bt856_setbit(client, 0xde, 4, 0);
160                         bt856_setbit(client, 0xde, 3, 1);
161                         bt856_setbit(client, 0xdc, 3, 1);
162                         bt856_setbit(client, 0xdc, 6, 1);
163                         break;
164                 case 2: // Color bar
165                         bt856_setbit(client, 0xdc, 3, 0);
166                         bt856_setbit(client, 0xde, 4, 1);
167                         break;
168                 default:
169                         return -EINVAL;
170                 }
171
172                 if (debug != 0)
173                         bt856_dump(client);
174                 break;
175         }
176
177         default:
178                 return -EINVAL;
179         }
180
181         return 0;
182 }
183
184 /* ----------------------------------------------------------------------- */
185
186 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
187
188 I2C_CLIENT_INSMOD;
189
190 static int bt856_probe(struct i2c_client *client,
191                         const struct i2c_device_id *id)
192 {
193         struct bt856 *encoder;
194
195         /* Check if the adapter supports the needed features */
196         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
197                 return -ENODEV;
198
199         v4l_info(client, "chip found @ 0x%x (%s)\n",
200                         client->addr << 1, client->adapter->name);
201
202         encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
203         if (encoder == NULL)
204                 return -ENOMEM;
205         encoder->norm = V4L2_STD_NTSC;
206         i2c_set_clientdata(client, encoder);
207
208         bt856_write(client, 0xdc, 0x18);
209         bt856_write(client, 0xda, 0);
210         bt856_write(client, 0xde, 0);
211
212         bt856_setbit(client, 0xdc, 3, 1);
213         //bt856_setbit(client, 0xdc, 6, 0);
214         bt856_setbit(client, 0xdc, 4, 1);
215
216         if (encoder->norm & V4L2_STD_NTSC)
217                 bt856_setbit(client, 0xdc, 2, 0);
218         else
219                 bt856_setbit(client, 0xdc, 2, 1);
220
221         bt856_setbit(client, 0xdc, 1, 1);
222         bt856_setbit(client, 0xde, 4, 0);
223         bt856_setbit(client, 0xde, 3, 1);
224
225         if (debug != 0)
226                 bt856_dump(client);
227         return 0;
228 }
229
230 static int bt856_remove(struct i2c_client *client)
231 {
232         kfree(i2c_get_clientdata(client));
233         return 0;
234 }
235
236 static const struct i2c_device_id bt856_id[] = {
237         { "bt856", 0 },
238         { }
239 };
240 MODULE_DEVICE_TABLE(i2c, bt856_id);
241
242 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
243         .name = "bt856",
244         .driverid = I2C_DRIVERID_BT856,
245         .command = bt856_command,
246         .probe = bt856_probe,
247         .remove = bt856_remove,
248         .id_table = bt856_id,
249 };