This source file includes following definitions.
- to_vpx3220
- to_sd
- vpx3220_write
- vpx3220_read
- vpx3220_fp_status
- vpx3220_fp_write
- vpx3220_fp_read
- vpx3220_write_block
- vpx3220_write_fp_block
- vpx3220_init
- vpx3220_status
- vpx3220_querystd
- vpx3220_g_input_status
- vpx3220_s_std
- vpx3220_s_routing
- vpx3220_s_stream
- vpx3220_s_ctrl
- vpx3220_probe
- vpx3220_remove
1
2
3
4
5
6
7
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/delay.h>
11 #include <linux/types.h>
12 #include <linux/slab.h>
13 #include <linux/uaccess.h>
14 #include <linux/i2c.h>
15 #include <linux/videodev2.h>
16 #include <media/v4l2-device.h>
17 #include <media/v4l2-ctrls.h>
18
19 MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
20 MODULE_AUTHOR("Laurent Pinchart");
21 MODULE_LICENSE("GPL");
22
23 static int debug;
24 module_param(debug, int, 0);
25 MODULE_PARM_DESC(debug, "Debug level (0-1)");
26
27
28 #define VPX_TIMEOUT_COUNT 10
29
30
31
32 struct vpx3220 {
33 struct v4l2_subdev sd;
34 struct v4l2_ctrl_handler hdl;
35 unsigned char reg[255];
36
37 v4l2_std_id norm;
38 int input;
39 int enable;
40 };
41
42 static inline struct vpx3220 *to_vpx3220(struct v4l2_subdev *sd)
43 {
44 return container_of(sd, struct vpx3220, sd);
45 }
46
47 static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
48 {
49 return &container_of(ctrl->handler, struct vpx3220, hdl)->sd;
50 }
51
52 static char *inputs[] = { "internal", "composite", "svideo" };
53
54
55
56 static inline int vpx3220_write(struct v4l2_subdev *sd, u8 reg, u8 value)
57 {
58 struct i2c_client *client = v4l2_get_subdevdata(sd);
59 struct vpx3220 *decoder = i2c_get_clientdata(client);
60
61 decoder->reg[reg] = value;
62 return i2c_smbus_write_byte_data(client, reg, value);
63 }
64
65 static inline int vpx3220_read(struct v4l2_subdev *sd, u8 reg)
66 {
67 struct i2c_client *client = v4l2_get_subdevdata(sd);
68
69 return i2c_smbus_read_byte_data(client, reg);
70 }
71
72 static int vpx3220_fp_status(struct v4l2_subdev *sd)
73 {
74 unsigned char status;
75 unsigned int i;
76
77 for (i = 0; i < VPX_TIMEOUT_COUNT; i++) {
78 status = vpx3220_read(sd, 0x29);
79
80 if (!(status & 4))
81 return 0;
82
83 udelay(10);
84
85 if (need_resched())
86 cond_resched();
87 }
88
89 return -1;
90 }
91
92 static int vpx3220_fp_write(struct v4l2_subdev *sd, u8 fpaddr, u16 data)
93 {
94 struct i2c_client *client = v4l2_get_subdevdata(sd);
95
96
97 if (i2c_smbus_write_word_data(client, 0x27, swab16(fpaddr)) == -1) {
98 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
99 return -1;
100 }
101
102 if (vpx3220_fp_status(sd) < 0)
103 return -1;
104
105
106 if (i2c_smbus_write_word_data(client, 0x28, swab16(data)) == -1) {
107 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
108 return -1;
109 }
110
111 return 0;
112 }
113
114 static int vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr)
115 {
116 struct i2c_client *client = v4l2_get_subdevdata(sd);
117 s16 data;
118
119
120 if (i2c_smbus_write_word_data(client, 0x26, swab16(fpaddr)) == -1) {
121 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
122 return -1;
123 }
124
125 if (vpx3220_fp_status(sd) < 0)
126 return -1;
127
128
129 data = i2c_smbus_read_word_data(client, 0x28);
130 if (data == -1) {
131 v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
132 return -1;
133 }
134
135 return swab16(data);
136 }
137
138 static int vpx3220_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len)
139 {
140 u8 reg;
141 int ret = -1;
142
143 while (len >= 2) {
144 reg = *data++;
145 ret = vpx3220_write(sd, reg, *data++);
146 if (ret < 0)
147 break;
148 len -= 2;
149 }
150
151 return ret;
152 }
153
154 static int vpx3220_write_fp_block(struct v4l2_subdev *sd,
155 const u16 *data, unsigned int len)
156 {
157 u8 reg;
158 int ret = 0;
159
160 while (len > 1) {
161 reg = *data++;
162 ret |= vpx3220_fp_write(sd, reg, *data++);
163 len -= 2;
164 }
165
166 return ret;
167 }
168
169
170
171 static const unsigned short init_ntsc[] = {
172 0x1c, 0x00,
173 0x88, 17,
174 0x89, 240,
175 0x8a, 240,
176 0x8b, 000,
177 0x8c, 640,
178 0x8d, 640,
179 0x8f, 0xc00,
180 0xf0, 0x73,
181
182 0xf2, 0x13,
183 0xe7, 0x1e1,
184
185 };
186
187 static const unsigned short init_pal[] = {
188 0x88, 23,
189 0x89, 288,
190
191 0x8a, 288,
192
193 0x8b, 16,
194 0x8c, 768,
195 0x8d, 784,
196
197 0x8f, 0xc00,
198 0xf0, 0x77,
199
200 0xf2, 0x3d1,
201 0xe7, 0x241,
202 };
203
204 static const unsigned short init_secam[] = {
205 0x88, 23,
206 0x89, 288,
207
208 0x8a, 288,
209
210 0x8b, 16,
211 0x8c, 768,
212 0x8d, 784,
213
214 0x8f, 0xc00,
215 0xf0, 0x77,
216
217 0xf2, 0x3d5,
218 0xe7, 0x241,
219 };
220
221 static const unsigned char init_common[] = {
222 0xf2, 0x00,
223 0x33, 0x0d,
224
225 0xd8, 0xa8,
226
227 0x20, 0x03,
228 0xe0, 0xff,
229 0xe1, 0x00,
230 0xe2, 0x7f,
231 0xe3, 0x80,
232 0xe4, 0x7f,
233 0xe5, 0x80,
234 0xe6, 0x00,
235 0xe7, 0xe0,
236
237 0xe8, 0xf8,
238
239 0xea, 0x18,
240
241 0xf0, 0x8a,
242
243 0xf1, 0x18,
244
245 0xf8, 0x12,
246
247 0xf9, 0x24,
248
249 };
250
251 static const unsigned short init_fp[] = {
252 0x59, 0,
253 0xa0, 2070,
254 0xa3, 0,
255 0xa4, 0,
256 0xa8, 30,
257 0xb2, 768,
258 0xbe, 27,
259 0x58, 0,
260 0x26, 0,
261 0x4b, 0x298,
262 };
263
264
265 static int vpx3220_init(struct v4l2_subdev *sd, u32 val)
266 {
267 struct vpx3220 *decoder = to_vpx3220(sd);
268
269 vpx3220_write_block(sd, init_common, sizeof(init_common));
270 vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1);
271 if (decoder->norm & V4L2_STD_NTSC)
272 vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1);
273 else if (decoder->norm & V4L2_STD_PAL)
274 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
275 else if (decoder->norm & V4L2_STD_SECAM)
276 vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1);
277 else
278 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
279 return 0;
280 }
281
282 static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
283 {
284 int res = V4L2_IN_ST_NO_SIGNAL, status;
285 v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL;
286
287 status = vpx3220_fp_read(sd, 0x0f3);
288
289 v4l2_dbg(1, debug, sd, "status: 0x%04x\n", status);
290
291 if (status < 0)
292 return status;
293
294 if ((status & 0x20) == 0) {
295 res = 0;
296
297 switch (status & 0x18) {
298 case 0x00:
299 case 0x10:
300 case 0x14:
301 case 0x18:
302 std &= V4L2_STD_PAL;
303 break;
304
305 case 0x08:
306 std &= V4L2_STD_SECAM;
307 break;
308
309 case 0x04:
310 case 0x0c:
311 case 0x1c:
312 std &= V4L2_STD_NTSC;
313 break;
314 }
315 } else {
316 std = V4L2_STD_UNKNOWN;
317 }
318 if (pstd)
319 *pstd = std;
320 if (pstatus)
321 *pstatus = res;
322 return 0;
323 }
324
325 static int vpx3220_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
326 {
327 v4l2_dbg(1, debug, sd, "querystd\n");
328 return vpx3220_status(sd, NULL, std);
329 }
330
331 static int vpx3220_g_input_status(struct v4l2_subdev *sd, u32 *status)
332 {
333 v4l2_dbg(1, debug, sd, "g_input_status\n");
334 return vpx3220_status(sd, status, NULL);
335 }
336
337 static int vpx3220_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
338 {
339 struct vpx3220 *decoder = to_vpx3220(sd);
340 int temp_input;
341
342
343
344
345 temp_input = vpx3220_fp_read(sd, 0xf2);
346
347 v4l2_dbg(1, debug, sd, "s_std %llx\n", (unsigned long long)std);
348 if (std & V4L2_STD_NTSC) {
349 vpx3220_write_fp_block(sd, init_ntsc, sizeof(init_ntsc) >> 1);
350 v4l2_dbg(1, debug, sd, "norm switched to NTSC\n");
351 } else if (std & V4L2_STD_PAL) {
352 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
353 v4l2_dbg(1, debug, sd, "norm switched to PAL\n");
354 } else if (std & V4L2_STD_SECAM) {
355 vpx3220_write_fp_block(sd, init_secam, sizeof(init_secam) >> 1);
356 v4l2_dbg(1, debug, sd, "norm switched to SECAM\n");
357 } else {
358 return -EINVAL;
359 }
360
361 decoder->norm = std;
362
363
364 vpx3220_fp_write(sd, 0xf2, temp_input | 0x0010);
365 udelay(10);
366 return 0;
367 }
368
369 static int vpx3220_s_routing(struct v4l2_subdev *sd,
370 u32 input, u32 output, u32 config)
371 {
372 int data;
373
374
375
376
377
378 const int input_vals[3][2] = {
379 {0x0c, 0},
380 {0x0d, 0},
381 {0x0e, 1}
382 };
383
384 if (input > 2)
385 return -EINVAL;
386
387 v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[input]);
388
389 vpx3220_write(sd, 0x33, input_vals[input][0]);
390
391 data = vpx3220_fp_read(sd, 0xf2) & ~(0x0020);
392 if (data < 0)
393 return data;
394
395 vpx3220_fp_write(sd, 0xf2,
396 data | (input_vals[input][1] << 5) | 0x0010);
397
398 udelay(10);
399 return 0;
400 }
401
402 static int vpx3220_s_stream(struct v4l2_subdev *sd, int enable)
403 {
404 v4l2_dbg(1, debug, sd, "s_stream %s\n", enable ? "on" : "off");
405
406 vpx3220_write(sd, 0xf2, (enable ? 0x1b : 0x00));
407 return 0;
408 }
409
410 static int vpx3220_s_ctrl(struct v4l2_ctrl *ctrl)
411 {
412 struct v4l2_subdev *sd = to_sd(ctrl);
413
414 switch (ctrl->id) {
415 case V4L2_CID_BRIGHTNESS:
416 vpx3220_write(sd, 0xe6, ctrl->val);
417 return 0;
418 case V4L2_CID_CONTRAST:
419
420 vpx3220_write(sd, 0xe7, ctrl->val + 192);
421 return 0;
422 case V4L2_CID_SATURATION:
423 vpx3220_fp_write(sd, 0xa0, ctrl->val);
424 return 0;
425 case V4L2_CID_HUE:
426 vpx3220_fp_write(sd, 0x1c, ctrl->val);
427 return 0;
428 }
429 return -EINVAL;
430 }
431
432
433
434 static const struct v4l2_ctrl_ops vpx3220_ctrl_ops = {
435 .s_ctrl = vpx3220_s_ctrl,
436 };
437
438 static const struct v4l2_subdev_core_ops vpx3220_core_ops = {
439 .init = vpx3220_init,
440 };
441
442 static const struct v4l2_subdev_video_ops vpx3220_video_ops = {
443 .s_std = vpx3220_s_std,
444 .s_routing = vpx3220_s_routing,
445 .s_stream = vpx3220_s_stream,
446 .querystd = vpx3220_querystd,
447 .g_input_status = vpx3220_g_input_status,
448 };
449
450 static const struct v4l2_subdev_ops vpx3220_ops = {
451 .core = &vpx3220_core_ops,
452 .video = &vpx3220_video_ops,
453 };
454
455
456
457
458
459 static int vpx3220_probe(struct i2c_client *client,
460 const struct i2c_device_id *id)
461 {
462 struct vpx3220 *decoder;
463 struct v4l2_subdev *sd;
464 const char *name = NULL;
465 u8 ver;
466 u16 pn;
467
468
469 if (!i2c_check_functionality(client->adapter,
470 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
471 return -ENODEV;
472
473 decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
474 if (decoder == NULL)
475 return -ENOMEM;
476 sd = &decoder->sd;
477 v4l2_i2c_subdev_init(sd, client, &vpx3220_ops);
478 decoder->norm = V4L2_STD_PAL;
479 decoder->input = 0;
480 decoder->enable = 1;
481 v4l2_ctrl_handler_init(&decoder->hdl, 4);
482 v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
483 V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
484 v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
485 V4L2_CID_CONTRAST, 0, 63, 1, 32);
486 v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
487 V4L2_CID_SATURATION, 0, 4095, 1, 2048);
488 v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
489 V4L2_CID_HUE, -512, 511, 1, 0);
490 sd->ctrl_handler = &decoder->hdl;
491 if (decoder->hdl.error) {
492 int err = decoder->hdl.error;
493
494 v4l2_ctrl_handler_free(&decoder->hdl);
495 return err;
496 }
497 v4l2_ctrl_handler_setup(&decoder->hdl);
498
499 ver = i2c_smbus_read_byte_data(client, 0x00);
500 pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) +
501 i2c_smbus_read_byte_data(client, 0x01);
502 if (ver == 0xec) {
503 switch (pn) {
504 case 0x4680:
505 name = "vpx3220a";
506 break;
507 case 0x4260:
508 name = "vpx3216b";
509 break;
510 case 0x4280:
511 name = "vpx3214c";
512 break;
513 }
514 }
515 if (name)
516 v4l2_info(sd, "%s found @ 0x%x (%s)\n", name,
517 client->addr << 1, client->adapter->name);
518 else
519 v4l2_info(sd, "chip (%02x:%04x) found @ 0x%x (%s)\n",
520 ver, pn, client->addr << 1, client->adapter->name);
521
522 vpx3220_write_block(sd, init_common, sizeof(init_common));
523 vpx3220_write_fp_block(sd, init_fp, sizeof(init_fp) >> 1);
524
525 vpx3220_write_fp_block(sd, init_pal, sizeof(init_pal) >> 1);
526 return 0;
527 }
528
529 static int vpx3220_remove(struct i2c_client *client)
530 {
531 struct v4l2_subdev *sd = i2c_get_clientdata(client);
532 struct vpx3220 *decoder = to_vpx3220(sd);
533
534 v4l2_device_unregister_subdev(sd);
535 v4l2_ctrl_handler_free(&decoder->hdl);
536
537 return 0;
538 }
539
540 static const struct i2c_device_id vpx3220_id[] = {
541 { "vpx3220a", 0 },
542 { "vpx3216b", 0 },
543 { "vpx3214c", 0 },
544 { }
545 };
546 MODULE_DEVICE_TABLE(i2c, vpx3220_id);
547
548 static struct i2c_driver vpx3220_driver = {
549 .driver = {
550 .name = "vpx3220",
551 },
552 .probe = vpx3220_probe,
553 .remove = vpx3220_remove,
554 .id_table = vpx3220_id,
555 };
556
557 module_i2c_driver(vpx3220_driver);