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