1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/module.h>
24#include <linux/types.h>
25#include <linux/slab.h>
26#include <linux/ioctl.h>
27#include <linux/uaccess.h>
28#include <linux/i2c.h>
29#include <linux/videodev2.h>
30#include <media/v4l2-device.h>
31
32MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
33MODULE_AUTHOR("Dave Perks");
34MODULE_LICENSE("GPL");
35
36static int debug;
37module_param(debug, int, 0);
38MODULE_PARM_DESC(debug, "Debug level (0-1)");
39
40
41
42
43struct saa7185 {
44 struct v4l2_subdev sd;
45 unsigned char reg[128];
46
47 v4l2_std_id norm;
48};
49
50static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd)
51{
52 return container_of(sd, struct saa7185, sd);
53}
54
55
56
57static inline int saa7185_read(struct v4l2_subdev *sd)
58{
59 struct i2c_client *client = v4l2_get_subdevdata(sd);
60
61 return i2c_smbus_read_byte(client);
62}
63
64static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value)
65{
66 struct i2c_client *client = v4l2_get_subdevdata(sd);
67 struct saa7185 *encoder = to_saa7185(sd);
68
69 v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value);
70 encoder->reg[reg] = value;
71 return i2c_smbus_write_byte_data(client, reg, value);
72}
73
74static int saa7185_write_block(struct v4l2_subdev *sd,
75 const u8 *data, unsigned int len)
76{
77 struct i2c_client *client = v4l2_get_subdevdata(sd);
78 struct saa7185 *encoder = to_saa7185(sd);
79 int ret = -1;
80 u8 reg;
81
82
83
84 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
85
86 u8 block_data[32];
87 int block_len;
88
89 while (len >= 2) {
90 block_len = 0;
91 block_data[block_len++] = reg = data[0];
92 do {
93 block_data[block_len++] =
94 encoder->reg[reg++] = data[1];
95 len -= 2;
96 data += 2;
97 } while (len >= 2 && data[0] == reg && block_len < 32);
98 ret = i2c_master_send(client, block_data, block_len);
99 if (ret < 0)
100 break;
101 }
102 } else {
103
104 while (len >= 2) {
105 reg = *data++;
106 ret = saa7185_write(sd, reg, *data++);
107 if (ret < 0)
108 break;
109 len -= 2;
110 }
111 }
112
113 return ret;
114}
115
116
117
118static const unsigned char init_common[] = {
119 0x3a, 0x0f,
120
121
122 0x42, 0x6b,
123 0x43, 0x00,
124 0x44, 0x00,
125 0x45, 0x22,
126 0x46, 0xac,
127 0x47, 0x0e,
128 0x48, 0x03,
129 0x49, 0x1d,
130 0x4a, 0xac,
131 0x4b, 0xf0,
132 0x4c, 0xc8,
133 0x4d, 0xb9,
134 0x4e, 0xd4,
135 0x4f, 0x38,
136 0x50, 0x47,
137 0x51, 0xc1,
138 0x52, 0xe3,
139 0x53, 0x54,
140 0x54, 0xa3,
141 0x55, 0x54,
142 0x56, 0xf2,
143 0x57, 0x90,
144 0x58, 0x00,
145 0x59, 0x00,
146
147 0x5a, 0x00,
148 0x5b, 0x76,
149 0x5c, 0xa5,
150 0x5d, 0x3c,
151 0x5e, 0x3a,
152 0x5f, 0x3a,
153 0x60, 0x00,
154
155
156
157 0x67, 0x00,
158 0x68, 0x00,
159 0x69, 0x00,
160 0x6a, 0x00,
161
162 0x6b, 0x91,
163 0x6c, 0x20,
164
165 0x6d, 0x00,
166
167 0x6e, 0x0e,
168
169 0x6f, 0x00,
170 0x70, 0x20,
171
172
173
174 0x71, 0x15,
175 0x72, 0x90,
176 0x73, 0x61,
177 0x74, 0x00,
178 0x75, 0x00,
179 0x76, 0x00,
180 0x77, 0x15,
181 0x78, 0x90,
182 0x79, 0x61,
183
184
185
186 0x7a, 0x70,
187
188
189
190 0x7b, 0x16,
191 0x7c, 0x35,
192 0x7d, 0x20,
193};
194
195static const unsigned char init_pal[] = {
196 0x61, 0x1e,
197
198 0x62, 0xc8,
199 0x63, 0xcb,
200 0x64, 0x8a,
201 0x65, 0x09,
202 0x66, 0x2a,
203};
204
205static const unsigned char init_ntsc[] = {
206 0x61, 0x1d,
207
208 0x62, 0xe6,
209 0x63, 0x1f,
210 0x64, 0x7c,
211 0x65, 0xf0,
212 0x66, 0x21,
213};
214
215
216static int saa7185_init(struct v4l2_subdev *sd, u32 val)
217{
218 struct saa7185 *encoder = to_saa7185(sd);
219
220 saa7185_write_block(sd, init_common, sizeof(init_common));
221 if (encoder->norm & V4L2_STD_NTSC)
222 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
223 else
224 saa7185_write_block(sd, init_pal, sizeof(init_pal));
225 return 0;
226}
227
228static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
229{
230 struct saa7185 *encoder = to_saa7185(sd);
231
232 if (std & V4L2_STD_NTSC)
233 saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
234 else if (std & V4L2_STD_PAL)
235 saa7185_write_block(sd, init_pal, sizeof(init_pal));
236 else
237 return -EINVAL;
238 encoder->norm = std;
239 return 0;
240}
241
242static int saa7185_s_routing(struct v4l2_subdev *sd,
243 u32 input, u32 output, u32 config)
244{
245 struct saa7185 *encoder = to_saa7185(sd);
246
247
248
249
250 switch (input) {
251 case 0:
252
253 saa7185_write(sd, 0x3a, 0x0f);
254
255 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
256 saa7185_write(sd, 0x6e, 0x01);
257 break;
258
259 case 1:
260
261 saa7185_write(sd, 0x3a, 0x0f);
262
263 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00);
264
265 saa7185_write(sd, 0x6e, 0x00);
266 break;
267
268 case 2:
269
270 saa7185_write(sd, 0x3a, 0x8f);
271
272 saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08);
273
274 saa7185_write(sd, 0x6e, 0x01);
275 break;
276
277 default:
278 return -EINVAL;
279 }
280 return 0;
281}
282
283
284
285static const struct v4l2_subdev_core_ops saa7185_core_ops = {
286 .init = saa7185_init,
287};
288
289static const struct v4l2_subdev_video_ops saa7185_video_ops = {
290 .s_std_output = saa7185_s_std_output,
291 .s_routing = saa7185_s_routing,
292};
293
294static const struct v4l2_subdev_ops saa7185_ops = {
295 .core = &saa7185_core_ops,
296 .video = &saa7185_video_ops,
297};
298
299
300
301
302static int saa7185_probe(struct i2c_client *client,
303 const struct i2c_device_id *id)
304{
305 int i;
306 struct saa7185 *encoder;
307 struct v4l2_subdev *sd;
308
309
310 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
311 return -ENODEV;
312
313 v4l_info(client, "chip found @ 0x%x (%s)\n",
314 client->addr << 1, client->adapter->name);
315
316 encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL);
317 if (encoder == NULL)
318 return -ENOMEM;
319 encoder->norm = V4L2_STD_NTSC;
320 sd = &encoder->sd;
321 v4l2_i2c_subdev_init(sd, client, &saa7185_ops);
322
323 i = saa7185_write_block(sd, init_common, sizeof(init_common));
324 if (i >= 0)
325 i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
326 if (i < 0)
327 v4l2_dbg(1, debug, sd, "init error %d\n", i);
328 else
329 v4l2_dbg(1, debug, sd, "revision 0x%x\n",
330 saa7185_read(sd) >> 5);
331 return 0;
332}
333
334static int saa7185_remove(struct i2c_client *client)
335{
336 struct v4l2_subdev *sd = i2c_get_clientdata(client);
337 struct saa7185 *encoder = to_saa7185(sd);
338
339 v4l2_device_unregister_subdev(sd);
340
341 saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40);
342 return 0;
343}
344
345
346
347static const struct i2c_device_id saa7185_id[] = {
348 { "saa7185", 0 },
349 { }
350};
351MODULE_DEVICE_TABLE(i2c, saa7185_id);
352
353static struct i2c_driver saa7185_driver = {
354 .driver = {
355 .name = "saa7185",
356 },
357 .probe = saa7185_probe,
358 .remove = saa7185_remove,
359 .id_table = saa7185_id,
360};
361
362module_i2c_driver(saa7185_driver);
363