diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2009-01-14 04:54:38 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:42:22 -0400 |
commit | 5b73e98c83fc5087f591c9b12ee546b97e9283d4 (patch) | |
tree | 555244e0ac94e8428f7fa58154df59dcc3f0aad4 /drivers/media/video/saa7134/saa6752hs.c | |
parent | b634a93f783dbd4be31f3cc9b2292eddfb496d10 (diff) |
V4L/DVB (10246): saa6752hs: convert to v4l2_subdev.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/saa7134/saa6752hs.c')
-rw-r--r-- | drivers/media/video/saa7134/saa6752hs.c | 566 |
1 files changed, 333 insertions, 233 deletions
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 1fee6e84a512..25e6ab28a0a3 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
35 | #include <linux/videodev2.h> | 35 | #include <linux/videodev2.h> |
36 | #include <media/v4l2-device.h> | ||
36 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
37 | #include <media/v4l2-chip-ident.h> | 38 | #include <media/v4l2-chip-ident.h> |
38 | #include <media/v4l2-i2c-drv-legacy.h> | 39 | #include <media/v4l2-i2c-drv-legacy.h> |
@@ -95,6 +96,7 @@ static const struct v4l2_format v4l2_format_table[] = | |||
95 | }; | 96 | }; |
96 | 97 | ||
97 | struct saa6752hs_state { | 98 | struct saa6752hs_state { |
99 | struct v4l2_subdev sd; | ||
98 | int chip; | 100 | int chip; |
99 | u32 revision; | 101 | u32 revision; |
100 | int has_ac3; | 102 | int has_ac3; |
@@ -115,6 +117,11 @@ enum saa6752hs_command { | |||
115 | SAA6752HS_COMMAND_MAX | 117 | SAA6752HS_COMMAND_MAX |
116 | }; | 118 | }; |
117 | 119 | ||
120 | static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd) | ||
121 | { | ||
122 | return container_of(sd, struct saa6752hs_state, sd); | ||
123 | } | ||
124 | |||
118 | /* ---------------------------------------------------------------------- */ | 125 | /* ---------------------------------------------------------------------- */ |
119 | 126 | ||
120 | static u8 PAT[] = { | 127 | static u8 PAT[] = { |
@@ -360,185 +367,191 @@ static int saa6752hs_set_bitrate(struct i2c_client *client, | |||
360 | return 0; | 367 | return 0; |
361 | } | 368 | } |
362 | 369 | ||
363 | static void saa6752hs_set_subsampling(struct i2c_client *client, | ||
364 | struct v4l2_format *f) | ||
365 | { | ||
366 | struct saa6752hs_state *h = i2c_get_clientdata(client); | ||
367 | int dist_352, dist_480, dist_720; | ||
368 | |||
369 | /* | ||
370 | FIXME: translate and round width/height into EMPRESS | ||
371 | subsample type: | ||
372 | 370 | ||
373 | type | PAL | NTSC | 371 | static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, |
374 | --------------------------- | 372 | struct v4l2_ext_control *ctrl) |
375 | SIF | 352x288 | 352x240 | 373 | { |
376 | 1/2 D1 | 352x576 | 352x480 | 374 | switch (ctrl->id) { |
377 | 2/3 D1 | 480x576 | 480x480 | 375 | case V4L2_CID_MPEG_STREAM_TYPE: |
378 | D1 | 720x576 | 720x480 | 376 | ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; |
379 | */ | 377 | break; |
380 | 378 | case V4L2_CID_MPEG_STREAM_PID_PMT: | |
381 | dist_352 = abs(f->fmt.pix.width - 352); | 379 | ctrl->value = params->ts_pid_pmt; |
382 | dist_480 = abs(f->fmt.pix.width - 480); | 380 | break; |
383 | dist_720 = abs(f->fmt.pix.width - 720); | 381 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: |
384 | if (dist_720 < dist_480) { | 382 | ctrl->value = params->ts_pid_audio; |
385 | f->fmt.pix.width = 720; | 383 | break; |
386 | f->fmt.pix.height = 576; | 384 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: |
387 | h->video_format = SAA6752HS_VF_D1; | 385 | ctrl->value = params->ts_pid_video; |
388 | } | 386 | break; |
389 | else if (dist_480 < dist_352) { | 387 | case V4L2_CID_MPEG_STREAM_PID_PCR: |
390 | f->fmt.pix.width = 480; | 388 | ctrl->value = params->ts_pid_pcr; |
391 | f->fmt.pix.height = 576; | 389 | break; |
392 | h->video_format = SAA6752HS_VF_2_3_D1; | 390 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
393 | } | 391 | ctrl->value = params->au_encoding; |
394 | else { | 392 | break; |
395 | f->fmt.pix.width = 352; | 393 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
396 | if (abs(f->fmt.pix.height - 576) < | 394 | ctrl->value = params->au_l2_bitrate; |
397 | abs(f->fmt.pix.height - 288)) { | 395 | break; |
398 | f->fmt.pix.height = 576; | 396 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: |
399 | h->video_format = SAA6752HS_VF_1_2_D1; | 397 | if (!has_ac3) |
400 | } | 398 | return -EINVAL; |
401 | else { | 399 | ctrl->value = params->au_ac3_bitrate; |
402 | f->fmt.pix.height = 288; | 400 | break; |
403 | h->video_format = SAA6752HS_VF_SIF; | 401 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
404 | } | 402 | ctrl->value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; |
403 | break; | ||
404 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
405 | ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; | ||
406 | break; | ||
407 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
408 | ctrl->value = params->vi_aspect; | ||
409 | break; | ||
410 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
411 | ctrl->value = params->vi_bitrate * 1000; | ||
412 | break; | ||
413 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
414 | ctrl->value = params->vi_bitrate_peak * 1000; | ||
415 | break; | ||
416 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
417 | ctrl->value = params->vi_bitrate_mode; | ||
418 | break; | ||
419 | default: | ||
420 | return -EINVAL; | ||
405 | } | 421 | } |
422 | return 0; | ||
406 | } | 423 | } |
407 | 424 | ||
408 | |||
409 | static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, | 425 | static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, |
410 | struct v4l2_ext_control *ctrl, unsigned int cmd) | 426 | struct v4l2_ext_control *ctrl, int set) |
411 | { | 427 | { |
412 | int old = 0, new; | 428 | int old = 0, new; |
413 | int set = (cmd == VIDIOC_S_EXT_CTRLS); | ||
414 | 429 | ||
415 | new = ctrl->value; | 430 | new = ctrl->value; |
416 | switch (ctrl->id) { | 431 | switch (ctrl->id) { |
417 | case V4L2_CID_MPEG_STREAM_TYPE: | 432 | case V4L2_CID_MPEG_STREAM_TYPE: |
418 | old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; | 433 | old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; |
419 | if (set && new != old) | 434 | if (set && new != old) |
420 | return -ERANGE; | 435 | return -ERANGE; |
421 | new = old; | 436 | new = old; |
422 | break; | 437 | break; |
423 | case V4L2_CID_MPEG_STREAM_PID_PMT: | 438 | case V4L2_CID_MPEG_STREAM_PID_PMT: |
424 | old = params->ts_pid_pmt; | 439 | old = params->ts_pid_pmt; |
425 | if (set && new > MPEG_PID_MAX) | 440 | if (set && new > MPEG_PID_MAX) |
426 | return -ERANGE; | 441 | return -ERANGE; |
427 | if (new > MPEG_PID_MAX) | 442 | if (new > MPEG_PID_MAX) |
428 | new = MPEG_PID_MAX; | 443 | new = MPEG_PID_MAX; |
429 | params->ts_pid_pmt = new; | 444 | params->ts_pid_pmt = new; |
430 | break; | 445 | break; |
431 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: | 446 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: |
432 | old = params->ts_pid_audio; | 447 | old = params->ts_pid_audio; |
433 | if (set && new > MPEG_PID_MAX) | 448 | if (set && new > MPEG_PID_MAX) |
434 | return -ERANGE; | 449 | return -ERANGE; |
435 | if (new > MPEG_PID_MAX) | 450 | if (new > MPEG_PID_MAX) |
436 | new = MPEG_PID_MAX; | 451 | new = MPEG_PID_MAX; |
437 | params->ts_pid_audio = new; | 452 | params->ts_pid_audio = new; |
438 | break; | 453 | break; |
439 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: | 454 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: |
440 | old = params->ts_pid_video; | 455 | old = params->ts_pid_video; |
441 | if (set && new > MPEG_PID_MAX) | 456 | if (set && new > MPEG_PID_MAX) |
442 | return -ERANGE; | 457 | return -ERANGE; |
443 | if (new > MPEG_PID_MAX) | 458 | if (new > MPEG_PID_MAX) |
444 | new = MPEG_PID_MAX; | 459 | new = MPEG_PID_MAX; |
445 | params->ts_pid_video = new; | 460 | params->ts_pid_video = new; |
446 | break; | 461 | break; |
447 | case V4L2_CID_MPEG_STREAM_PID_PCR: | 462 | case V4L2_CID_MPEG_STREAM_PID_PCR: |
448 | old = params->ts_pid_pcr; | 463 | old = params->ts_pid_pcr; |
449 | if (set && new > MPEG_PID_MAX) | 464 | if (set && new > MPEG_PID_MAX) |
450 | return -ERANGE; | 465 | return -ERANGE; |
451 | if (new > MPEG_PID_MAX) | 466 | if (new > MPEG_PID_MAX) |
452 | new = MPEG_PID_MAX; | 467 | new = MPEG_PID_MAX; |
453 | params->ts_pid_pcr = new; | 468 | params->ts_pid_pcr = new; |
454 | break; | 469 | break; |
455 | case V4L2_CID_MPEG_AUDIO_ENCODING: | 470 | case V4L2_CID_MPEG_AUDIO_ENCODING: |
456 | old = params->au_encoding; | 471 | old = params->au_encoding; |
457 | if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && | 472 | if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && |
458 | (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) | 473 | (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) |
459 | return -ERANGE; | 474 | return -ERANGE; |
460 | new = old; | 475 | new = old; |
461 | break; | 476 | break; |
462 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | 477 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: |
463 | old = params->au_l2_bitrate; | 478 | old = params->au_l2_bitrate; |
464 | if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K && | 479 | if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K && |
465 | new != V4L2_MPEG_AUDIO_L2_BITRATE_384K) | 480 | new != V4L2_MPEG_AUDIO_L2_BITRATE_384K) |
466 | return -ERANGE; | 481 | return -ERANGE; |
467 | if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K) | 482 | if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K) |
468 | new = V4L2_MPEG_AUDIO_L2_BITRATE_256K; | 483 | new = V4L2_MPEG_AUDIO_L2_BITRATE_256K; |
469 | else | 484 | else |
470 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; | 485 | new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; |
471 | params->au_l2_bitrate = new; | 486 | params->au_l2_bitrate = new; |
472 | break; | 487 | break; |
473 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: | 488 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: |
474 | if (!has_ac3) | 489 | if (!has_ac3) |
475 | return -EINVAL; | ||
476 | old = params->au_ac3_bitrate; | ||
477 | if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && | ||
478 | new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) | ||
479 | return -ERANGE; | ||
480 | if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | ||
481 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; | ||
482 | else | ||
483 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; | ||
484 | params->au_ac3_bitrate = new; | ||
485 | break; | ||
486 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
487 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; | ||
488 | if (set && new != old) | ||
489 | return -ERANGE; | ||
490 | new = old; | ||
491 | break; | ||
492 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
493 | old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; | ||
494 | if (set && new != old) | ||
495 | return -ERANGE; | ||
496 | new = old; | ||
497 | break; | ||
498 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
499 | old = params->vi_aspect; | ||
500 | if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && | ||
501 | new != V4L2_MPEG_VIDEO_ASPECT_4x3) | ||
502 | return -ERANGE; | ||
503 | if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) | ||
504 | new = V4L2_MPEG_VIDEO_ASPECT_4x3; | ||
505 | params->vi_aspect = new; | ||
506 | break; | ||
507 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
508 | old = params->vi_bitrate * 1000; | ||
509 | new = 1000 * (new / 1000); | ||
510 | if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
511 | return -ERANGE; | ||
512 | if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
513 | new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; | ||
514 | params->vi_bitrate = new / 1000; | ||
515 | break; | ||
516 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
517 | old = params->vi_bitrate_peak * 1000; | ||
518 | new = 1000 * (new / 1000); | ||
519 | if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
520 | return -ERANGE; | ||
521 | if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
522 | new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; | ||
523 | params->vi_bitrate_peak = new / 1000; | ||
524 | break; | ||
525 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
526 | old = params->vi_bitrate_mode; | ||
527 | params->vi_bitrate_mode = new; | ||
528 | break; | ||
529 | default: | ||
530 | return -EINVAL; | 490 | return -EINVAL; |
491 | old = params->au_ac3_bitrate; | ||
492 | if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && | ||
493 | new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) | ||
494 | return -ERANGE; | ||
495 | if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | ||
496 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; | ||
497 | else | ||
498 | new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; | ||
499 | params->au_ac3_bitrate = new; | ||
500 | break; | ||
501 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | ||
502 | old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; | ||
503 | if (set && new != old) | ||
504 | return -ERANGE; | ||
505 | new = old; | ||
506 | break; | ||
507 | case V4L2_CID_MPEG_VIDEO_ENCODING: | ||
508 | old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; | ||
509 | if (set && new != old) | ||
510 | return -ERANGE; | ||
511 | new = old; | ||
512 | break; | ||
513 | case V4L2_CID_MPEG_VIDEO_ASPECT: | ||
514 | old = params->vi_aspect; | ||
515 | if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && | ||
516 | new != V4L2_MPEG_VIDEO_ASPECT_4x3) | ||
517 | return -ERANGE; | ||
518 | if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) | ||
519 | new = V4L2_MPEG_VIDEO_ASPECT_4x3; | ||
520 | params->vi_aspect = new; | ||
521 | break; | ||
522 | case V4L2_CID_MPEG_VIDEO_BITRATE: | ||
523 | old = params->vi_bitrate * 1000; | ||
524 | new = 1000 * (new / 1000); | ||
525 | if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
526 | return -ERANGE; | ||
527 | if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
528 | new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; | ||
529 | params->vi_bitrate = new / 1000; | ||
530 | break; | ||
531 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: | ||
532 | old = params->vi_bitrate_peak * 1000; | ||
533 | new = 1000 * (new / 1000); | ||
534 | if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
535 | return -ERANGE; | ||
536 | if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) | ||
537 | new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; | ||
538 | params->vi_bitrate_peak = new / 1000; | ||
539 | break; | ||
540 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | ||
541 | old = params->vi_bitrate_mode; | ||
542 | params->vi_bitrate_mode = new; | ||
543 | break; | ||
544 | default: | ||
545 | return -EINVAL; | ||
531 | } | 546 | } |
532 | if (cmd == VIDIOC_G_EXT_CTRLS) | 547 | ctrl->value = new; |
533 | ctrl->value = old; | ||
534 | else | ||
535 | ctrl->value = new; | ||
536 | return 0; | 548 | return 0; |
537 | } | 549 | } |
538 | 550 | ||
539 | static int saa6752hs_qctrl(struct saa6752hs_state *h, | 551 | |
540 | struct v4l2_queryctrl *qctrl) | 552 | static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) |
541 | { | 553 | { |
554 | struct saa6752hs_state *h = to_state(sd); | ||
542 | struct saa6752hs_mpeg_params *params = &h->params; | 555 | struct saa6752hs_mpeg_params *params = &h->params; |
543 | int err; | 556 | int err; |
544 | 557 | ||
@@ -610,8 +623,7 @@ static int saa6752hs_qctrl(struct saa6752hs_state *h, | |||
610 | return -EINVAL; | 623 | return -EINVAL; |
611 | } | 624 | } |
612 | 625 | ||
613 | static int saa6752hs_qmenu(struct saa6752hs_state *h, | 626 | static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu) |
614 | struct v4l2_querymenu *qmenu) | ||
615 | { | 627 | { |
616 | static const u32 mpeg_audio_encoding[] = { | 628 | static const u32 mpeg_audio_encoding[] = { |
617 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, | 629 | V4L2_MPEG_AUDIO_ENCODING_LAYER_2, |
@@ -632,11 +644,12 @@ static int saa6752hs_qmenu(struct saa6752hs_state *h, | |||
632 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, | 644 | V4L2_MPEG_AUDIO_AC3_BITRATE_384K, |
633 | V4L2_CTRL_MENU_IDS_END | 645 | V4L2_CTRL_MENU_IDS_END |
634 | }; | 646 | }; |
647 | struct saa6752hs_state *h = to_state(sd); | ||
635 | struct v4l2_queryctrl qctrl; | 648 | struct v4l2_queryctrl qctrl; |
636 | int err; | 649 | int err; |
637 | 650 | ||
638 | qctrl.id = qmenu->id; | 651 | qctrl.id = qmenu->id; |
639 | err = saa6752hs_qctrl(h, &qctrl); | 652 | err = saa6752hs_queryctrl(sd, &qctrl); |
640 | if (err) | 653 | if (err) |
641 | return err; | 654 | return err; |
642 | switch (qmenu->id) { | 655 | switch (qmenu->id) { |
@@ -656,17 +669,16 @@ static int saa6752hs_qmenu(struct saa6752hs_state *h, | |||
656 | return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); | 669 | return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); |
657 | } | 670 | } |
658 | 671 | ||
659 | static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) | 672 | static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) |
660 | { | 673 | { |
661 | unsigned char buf[9], buf2[4]; | 674 | unsigned char buf[9], buf2[4]; |
662 | struct saa6752hs_state *h; | 675 | struct saa6752hs_state *h = to_state(sd); |
676 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
663 | unsigned size; | 677 | unsigned size; |
664 | u32 crc; | 678 | u32 crc; |
665 | unsigned char localPAT[256]; | 679 | unsigned char localPAT[256]; |
666 | unsigned char localPMT[256]; | 680 | unsigned char localPMT[256]; |
667 | 681 | ||
668 | h = i2c_get_clientdata(client); | ||
669 | |||
670 | /* Set video format - must be done first as it resets other settings */ | 682 | /* Set video format - must be done first as it resets other settings */ |
671 | set_reg8(client, 0x41, h->video_format); | 683 | set_reg8(client, 0x41, h->video_format); |
672 | 684 | ||
@@ -762,7 +774,7 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) | |||
762 | buf[3] = 0x82; | 774 | buf[3] = 0x82; |
763 | buf[4] = 0xB0; | 775 | buf[4] = 0xB0; |
764 | buf[5] = buf2[0]; | 776 | buf[5] = buf2[0]; |
765 | switch(h->params.vi_aspect) { | 777 | switch (h->params.vi_aspect) { |
766 | case V4L2_MPEG_VIDEO_ASPECT_16x9: | 778 | case V4L2_MPEG_VIDEO_ASPECT_16x9: |
767 | buf[6] = buf2[1] | 0x40; | 779 | buf[6] = buf2[1] | 0x40; |
768 | break; | 780 | break; |
@@ -770,7 +782,6 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) | |||
770 | default: | 782 | default: |
771 | buf[6] = buf2[1] & 0xBF; | 783 | buf[6] = buf2[1] & 0xBF; |
772 | break; | 784 | break; |
773 | break; | ||
774 | } | 785 | } |
775 | buf[7] = buf2[2]; | 786 | buf[7] = buf2[2]; |
776 | buf[8] = buf2[3]; | 787 | buf[8] = buf2[3]; |
@@ -779,81 +790,167 @@ static int saa6752hs_init(struct i2c_client *client, u32 leading_null_bytes) | |||
779 | return 0; | 790 | return 0; |
780 | } | 791 | } |
781 | 792 | ||
782 | static int | 793 | static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set) |
783 | saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
784 | { | 794 | { |
785 | struct saa6752hs_state *h = i2c_get_clientdata(client); | 795 | struct saa6752hs_state *h = to_state(sd); |
786 | struct v4l2_ext_controls *ctrls = arg; | ||
787 | struct saa6752hs_mpeg_params params; | 796 | struct saa6752hs_mpeg_params params; |
788 | int err = 0; | ||
789 | int i; | 797 | int i; |
790 | 798 | ||
791 | switch (cmd) { | 799 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
792 | case VIDIOC_INT_INIT: | 800 | return -EINVAL; |
793 | /* apply settings and start encoder */ | 801 | |
794 | saa6752hs_init(client, *(u32 *)arg); | 802 | params = h->params; |
795 | break; | 803 | for (i = 0; i < ctrls->count; i++) { |
796 | case VIDIOC_S_EXT_CTRLS: | 804 | int err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, set); |
797 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 805 | |
798 | return -EINVAL; | 806 | if (err) { |
799 | /* fall through */ | 807 | ctrls->error_idx = i; |
800 | case VIDIOC_TRY_EXT_CTRLS: | 808 | return err; |
801 | case VIDIOC_G_EXT_CTRLS: | ||
802 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | ||
803 | return -EINVAL; | ||
804 | params = h->params; | ||
805 | for (i = 0; i < ctrls->count; i++) { | ||
806 | err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, cmd); | ||
807 | if (err) { | ||
808 | ctrls->error_idx = i; | ||
809 | return err; | ||
810 | } | ||
811 | } | 809 | } |
812 | h->params = params; | ||
813 | break; | ||
814 | case VIDIOC_QUERYCTRL: | ||
815 | return saa6752hs_qctrl(h, arg); | ||
816 | case VIDIOC_QUERYMENU: | ||
817 | return saa6752hs_qmenu(h, arg); | ||
818 | case VIDIOC_G_FMT: | ||
819 | { | ||
820 | struct v4l2_format *f = arg; | ||
821 | |||
822 | if (h->video_format == SAA6752HS_VF_UNKNOWN) | ||
823 | h->video_format = SAA6752HS_VF_D1; | ||
824 | f->fmt.pix.width = | ||
825 | v4l2_format_table[h->video_format].fmt.pix.width; | ||
826 | f->fmt.pix.height = | ||
827 | v4l2_format_table[h->video_format].fmt.pix.height; | ||
828 | break ; | ||
829 | } | 810 | } |
830 | case VIDIOC_S_FMT: | 811 | if (set) |
831 | { | 812 | h->params = params; |
832 | struct v4l2_format *f = arg; | 813 | return 0; |
814 | } | ||
833 | 815 | ||
834 | saa6752hs_set_subsampling(client, f); | 816 | static int saa6752hs_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) |
835 | break; | 817 | { |
818 | return saa6752hs_do_ext_ctrls(sd, ctrls, 1); | ||
819 | } | ||
820 | |||
821 | static int saa6752hs_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) | ||
822 | { | ||
823 | return saa6752hs_do_ext_ctrls(sd, ctrls, 0); | ||
824 | } | ||
825 | |||
826 | static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) | ||
827 | { | ||
828 | struct saa6752hs_state *h = to_state(sd); | ||
829 | int i; | ||
830 | |||
831 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | ||
832 | return -EINVAL; | ||
833 | |||
834 | for (i = 0; i < ctrls->count; i++) { | ||
835 | int err = get_ctrl(h->has_ac3, &h->params, ctrls->controls + i); | ||
836 | |||
837 | if (err) { | ||
838 | ctrls->error_idx = i; | ||
839 | return err; | ||
840 | } | ||
836 | } | 841 | } |
837 | case VIDIOC_S_STD: | 842 | return 0; |
838 | h->standard = *((v4l2_std_id *) arg); | 843 | } |
839 | break; | ||
840 | 844 | ||
841 | case VIDIOC_DBG_G_CHIP_IDENT: | 845 | static int saa6752hs_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) |
842 | return v4l2_chip_ident_i2c_client(client, | 846 | { |
843 | arg, h->chip, h->revision); | 847 | struct saa6752hs_state *h = to_state(sd); |
844 | 848 | ||
845 | default: | 849 | if (h->video_format == SAA6752HS_VF_UNKNOWN) |
846 | /* nothing */ | 850 | h->video_format = SAA6752HS_VF_D1; |
847 | break; | 851 | f->fmt.pix.width = |
852 | v4l2_format_table[h->video_format].fmt.pix.width; | ||
853 | f->fmt.pix.height = | ||
854 | v4l2_format_table[h->video_format].fmt.pix.height; | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | static int saa6752hs_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f) | ||
859 | { | ||
860 | struct saa6752hs_state *h = to_state(sd); | ||
861 | int dist_352, dist_480, dist_720; | ||
862 | |||
863 | /* | ||
864 | FIXME: translate and round width/height into EMPRESS | ||
865 | subsample type: | ||
866 | |||
867 | type | PAL | NTSC | ||
868 | --------------------------- | ||
869 | SIF | 352x288 | 352x240 | ||
870 | 1/2 D1 | 352x576 | 352x480 | ||
871 | 2/3 D1 | 480x576 | 480x480 | ||
872 | D1 | 720x576 | 720x480 | ||
873 | */ | ||
874 | |||
875 | dist_352 = abs(f->fmt.pix.width - 352); | ||
876 | dist_480 = abs(f->fmt.pix.width - 480); | ||
877 | dist_720 = abs(f->fmt.pix.width - 720); | ||
878 | if (dist_720 < dist_480) { | ||
879 | f->fmt.pix.width = 720; | ||
880 | f->fmt.pix.height = 576; | ||
881 | h->video_format = SAA6752HS_VF_D1; | ||
882 | } else if (dist_480 < dist_352) { | ||
883 | f->fmt.pix.width = 480; | ||
884 | f->fmt.pix.height = 576; | ||
885 | h->video_format = SAA6752HS_VF_2_3_D1; | ||
886 | } else { | ||
887 | f->fmt.pix.width = 352; | ||
888 | if (abs(f->fmt.pix.height - 576) < | ||
889 | abs(f->fmt.pix.height - 288)) { | ||
890 | f->fmt.pix.height = 576; | ||
891 | h->video_format = SAA6752HS_VF_1_2_D1; | ||
892 | } else { | ||
893 | f->fmt.pix.height = 288; | ||
894 | h->video_format = SAA6752HS_VF_SIF; | ||
895 | } | ||
848 | } | 896 | } |
897 | return 0; | ||
898 | } | ||
899 | |||
900 | static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | ||
901 | { | ||
902 | struct saa6752hs_state *h = to_state(sd); | ||
903 | |||
904 | h->standard = std; | ||
905 | return 0; | ||
906 | } | ||
907 | |||
908 | static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) | ||
909 | { | ||
910 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
911 | struct saa6752hs_state *h = to_state(sd); | ||
912 | |||
913 | return v4l2_chip_ident_i2c_client(client, | ||
914 | chip, h->chip, h->revision); | ||
915 | } | ||
849 | 916 | ||
850 | return err; | 917 | static int saa6752hs_command(struct i2c_client *client, unsigned cmd, void *arg) |
918 | { | ||
919 | return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); | ||
851 | } | 920 | } |
852 | 921 | ||
922 | /* ----------------------------------------------------------------------- */ | ||
923 | |||
924 | static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { | ||
925 | .g_chip_ident = saa6752hs_g_chip_ident, | ||
926 | .init = saa6752hs_init, | ||
927 | .queryctrl = saa6752hs_queryctrl, | ||
928 | .querymenu = saa6752hs_querymenu, | ||
929 | .g_ext_ctrls = saa6752hs_g_ext_ctrls, | ||
930 | .s_ext_ctrls = saa6752hs_s_ext_ctrls, | ||
931 | .try_ext_ctrls = saa6752hs_try_ext_ctrls, | ||
932 | }; | ||
933 | |||
934 | static const struct v4l2_subdev_tuner_ops saa6752hs_tuner_ops = { | ||
935 | .s_std = saa6752hs_s_std, | ||
936 | }; | ||
937 | |||
938 | static const struct v4l2_subdev_video_ops saa6752hs_video_ops = { | ||
939 | .s_fmt = saa6752hs_s_fmt, | ||
940 | .g_fmt = saa6752hs_g_fmt, | ||
941 | }; | ||
942 | |||
943 | static const struct v4l2_subdev_ops saa6752hs_ops = { | ||
944 | .core = &saa6752hs_core_ops, | ||
945 | .tuner = &saa6752hs_tuner_ops, | ||
946 | .video = &saa6752hs_video_ops, | ||
947 | }; | ||
948 | |||
853 | static int saa6752hs_probe(struct i2c_client *client, | 949 | static int saa6752hs_probe(struct i2c_client *client, |
854 | const struct i2c_device_id *id) | 950 | const struct i2c_device_id *id) |
855 | { | 951 | { |
856 | struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); | 952 | struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); |
953 | struct v4l2_subdev *sd; | ||
857 | u8 addr = 0x13; | 954 | u8 addr = 0x13; |
858 | u8 data[12]; | 955 | u8 data[12]; |
859 | 956 | ||
@@ -861,6 +958,8 @@ static int saa6752hs_probe(struct i2c_client *client, | |||
861 | client->addr << 1, client->adapter->name); | 958 | client->addr << 1, client->adapter->name); |
862 | if (h == NULL) | 959 | if (h == NULL) |
863 | return -ENOMEM; | 960 | return -ENOMEM; |
961 | sd = &h->sd; | ||
962 | v4l2_i2c_subdev_init(sd, client, &saa6752hs_ops); | ||
864 | 963 | ||
865 | i2c_master_send(client, &addr, 1); | 964 | i2c_master_send(client, &addr, 1); |
866 | i2c_master_recv(client, data, sizeof(data)); | 965 | i2c_master_recv(client, data, sizeof(data)); |
@@ -874,14 +973,15 @@ static int saa6752hs_probe(struct i2c_client *client, | |||
874 | } | 973 | } |
875 | h->params = param_defaults; | 974 | h->params = param_defaults; |
876 | h->standard = 0; /* Assume 625 input lines */ | 975 | h->standard = 0; /* Assume 625 input lines */ |
877 | |||
878 | i2c_set_clientdata(client, h); | ||
879 | return 0; | 976 | return 0; |
880 | } | 977 | } |
881 | 978 | ||
882 | static int saa6752hs_remove(struct i2c_client *client) | 979 | static int saa6752hs_remove(struct i2c_client *client) |
883 | { | 980 | { |
884 | kfree(i2c_get_clientdata(client)); | 981 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
982 | |||
983 | v4l2_device_unregister_subdev(sd); | ||
984 | kfree(to_state(sd)); | ||
885 | return 0; | 985 | return 0; |
886 | } | 986 | } |
887 | 987 | ||