diff options
Diffstat (limited to 'drivers/media/video/cx25840/cx25840-audio.c')
-rw-r--r-- | drivers/media/video/cx25840/cx25840-audio.c | 144 |
1 files changed, 17 insertions, 127 deletions
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index 45608d50529c..6faad34df3ac 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -474,33 +474,10 @@ void cx25840_audio_set_path(struct i2c_client *client) | |||
474 | cx25840_and_or(client, 0x803, ~0x10, 0x10); | 474 | cx25840_and_or(client, 0x803, ~0x10, 0x10); |
475 | } | 475 | } |
476 | 476 | ||
477 | static int get_volume(struct i2c_client *client) | ||
478 | { | ||
479 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
480 | int vol; | ||
481 | |||
482 | if (state->unmute_volume >= 0) | ||
483 | return state->unmute_volume; | ||
484 | |||
485 | /* Volume runs +18dB to -96dB in 1/2dB steps | ||
486 | * change to fit the msp3400 -114dB to +12dB range */ | ||
487 | |||
488 | /* check PATH1_VOLUME */ | ||
489 | vol = 228 - cx25840_read(client, 0x8d4); | ||
490 | vol = (vol / 2) + 23; | ||
491 | return vol << 9; | ||
492 | } | ||
493 | |||
494 | static void set_volume(struct i2c_client *client, int volume) | 477 | static void set_volume(struct i2c_client *client, int volume) |
495 | { | 478 | { |
496 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
497 | int vol; | 479 | int vol; |
498 | 480 | ||
499 | if (state->unmute_volume >= 0) { | ||
500 | state->unmute_volume = volume; | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | /* Convert the volume to msp3400 values (0-127) */ | 481 | /* Convert the volume to msp3400 values (0-127) */ |
505 | vol = volume >> 9; | 482 | vol = volume >> 9; |
506 | 483 | ||
@@ -517,52 +494,6 @@ static void set_volume(struct i2c_client *client, int volume) | |||
517 | cx25840_write(client, 0x8d4, 228 - (vol * 2)); | 494 | cx25840_write(client, 0x8d4, 228 - (vol * 2)); |
518 | } | 495 | } |
519 | 496 | ||
520 | static int get_bass(struct i2c_client *client) | ||
521 | { | ||
522 | /* bass is 49 steps +12dB to -12dB */ | ||
523 | |||
524 | /* check PATH1_EQ_BASS_VOL */ | ||
525 | int bass = cx25840_read(client, 0x8d9) & 0x3f; | ||
526 | bass = (((48 - bass) * 0xffff) + 47) / 48; | ||
527 | return bass; | ||
528 | } | ||
529 | |||
530 | static void set_bass(struct i2c_client *client, int bass) | ||
531 | { | ||
532 | /* PATH1_EQ_BASS_VOL */ | ||
533 | cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff)); | ||
534 | } | ||
535 | |||
536 | static int get_treble(struct i2c_client *client) | ||
537 | { | ||
538 | /* treble is 49 steps +12dB to -12dB */ | ||
539 | |||
540 | /* check PATH1_EQ_TREBLE_VOL */ | ||
541 | int treble = cx25840_read(client, 0x8db) & 0x3f; | ||
542 | treble = (((48 - treble) * 0xffff) + 47) / 48; | ||
543 | return treble; | ||
544 | } | ||
545 | |||
546 | static void set_treble(struct i2c_client *client, int treble) | ||
547 | { | ||
548 | /* PATH1_EQ_TREBLE_VOL */ | ||
549 | cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff)); | ||
550 | } | ||
551 | |||
552 | static int get_balance(struct i2c_client *client) | ||
553 | { | ||
554 | /* balance is 7 bit, 0 to -96dB */ | ||
555 | |||
556 | /* check PATH1_BAL_LEVEL */ | ||
557 | int balance = cx25840_read(client, 0x8d5) & 0x7f; | ||
558 | /* check PATH1_BAL_LEFT */ | ||
559 | if ((cx25840_read(client, 0x8d5) & 0x80) == 0) | ||
560 | balance = 0x80 - balance; | ||
561 | else | ||
562 | balance = 0x80 + balance; | ||
563 | return balance << 8; | ||
564 | } | ||
565 | |||
566 | static void set_balance(struct i2c_client *client, int balance) | 497 | static void set_balance(struct i2c_client *client, int balance) |
567 | { | 498 | { |
568 | int bal = balance >> 8; | 499 | int bal = balance >> 8; |
@@ -579,31 +510,6 @@ static void set_balance(struct i2c_client *client, int balance) | |||
579 | } | 510 | } |
580 | } | 511 | } |
581 | 512 | ||
582 | static int get_mute(struct i2c_client *client) | ||
583 | { | ||
584 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
585 | |||
586 | return state->unmute_volume >= 0; | ||
587 | } | ||
588 | |||
589 | static void set_mute(struct i2c_client *client, int mute) | ||
590 | { | ||
591 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
592 | |||
593 | if (mute && state->unmute_volume == -1) { | ||
594 | int vol = get_volume(client); | ||
595 | |||
596 | set_volume(client, 0); | ||
597 | state->unmute_volume = vol; | ||
598 | } | ||
599 | else if (!mute && state->unmute_volume != -1) { | ||
600 | int vol = state->unmute_volume; | ||
601 | |||
602 | state->unmute_volume = -1; | ||
603 | set_volume(client, vol); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) | 513 | int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) |
608 | { | 514 | { |
609 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 515 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
@@ -624,25 +530,31 @@ int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) | |||
624 | return retval; | 530 | return retval; |
625 | } | 531 | } |
626 | 532 | ||
627 | int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 533 | static int cx25840_audio_s_ctrl(struct v4l2_ctrl *ctrl) |
628 | { | 534 | { |
535 | struct v4l2_subdev *sd = to_sd(ctrl); | ||
536 | struct cx25840_state *state = to_state(sd); | ||
629 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 537 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
630 | 538 | ||
631 | switch (ctrl->id) { | 539 | switch (ctrl->id) { |
632 | case V4L2_CID_AUDIO_VOLUME: | 540 | case V4L2_CID_AUDIO_VOLUME: |
633 | ctrl->value = get_volume(client); | 541 | if (state->mute->val) |
542 | set_volume(client, 0); | ||
543 | else | ||
544 | set_volume(client, state->volume->val); | ||
634 | break; | 545 | break; |
635 | case V4L2_CID_AUDIO_BASS: | 546 | case V4L2_CID_AUDIO_BASS: |
636 | ctrl->value = get_bass(client); | 547 | /* PATH1_EQ_BASS_VOL */ |
548 | cx25840_and_or(client, 0x8d9, ~0x3f, | ||
549 | 48 - (ctrl->val * 48 / 0xffff)); | ||
637 | break; | 550 | break; |
638 | case V4L2_CID_AUDIO_TREBLE: | 551 | case V4L2_CID_AUDIO_TREBLE: |
639 | ctrl->value = get_treble(client); | 552 | /* PATH1_EQ_TREBLE_VOL */ |
553 | cx25840_and_or(client, 0x8db, ~0x3f, | ||
554 | 48 - (ctrl->val * 48 / 0xffff)); | ||
640 | break; | 555 | break; |
641 | case V4L2_CID_AUDIO_BALANCE: | 556 | case V4L2_CID_AUDIO_BALANCE: |
642 | ctrl->value = get_balance(client); | 557 | set_balance(client, ctrl->val); |
643 | break; | ||
644 | case V4L2_CID_AUDIO_MUTE: | ||
645 | ctrl->value = get_mute(client); | ||
646 | break; | 558 | break; |
647 | default: | 559 | default: |
648 | return -EINVAL; | 560 | return -EINVAL; |
@@ -650,28 +562,6 @@ int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | |||
650 | return 0; | 562 | return 0; |
651 | } | 563 | } |
652 | 564 | ||
653 | int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) | 565 | const struct v4l2_ctrl_ops cx25840_audio_ctrl_ops = { |
654 | { | 566 | .s_ctrl = cx25840_audio_s_ctrl, |
655 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 567 | }; |
656 | |||
657 | switch (ctrl->id) { | ||
658 | case V4L2_CID_AUDIO_VOLUME: | ||
659 | set_volume(client, ctrl->value); | ||
660 | break; | ||
661 | case V4L2_CID_AUDIO_BASS: | ||
662 | set_bass(client, ctrl->value); | ||
663 | break; | ||
664 | case V4L2_CID_AUDIO_TREBLE: | ||
665 | set_treble(client, ctrl->value); | ||
666 | break; | ||
667 | case V4L2_CID_AUDIO_BALANCE: | ||
668 | set_balance(client, ctrl->value); | ||
669 | break; | ||
670 | case V4L2_CID_AUDIO_MUTE: | ||
671 | set_mute(client, ctrl->value); | ||
672 | break; | ||
673 | default: | ||
674 | return -EINVAL; | ||
675 | } | ||
676 | return 0; | ||
677 | } | ||