aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx25840/cx25840-audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx25840/cx25840-audio.c')
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c144
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
477static 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
494static void set_volume(struct i2c_client *client, int volume) 477static 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
520static 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
530static 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
536static 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
546static 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
552static 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
566static void set_balance(struct i2c_client *client, int balance) 497static 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
582static 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
589static 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
607int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq) 513int 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
627int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 533static 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
653int cx25840_audio_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 565const 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}