Commit 1ee2a322b058f6399dc900603f9ebb392037ff77

Authored by Takashi Iwai
1 parent 64931a4be0

ALSA: ps3: Add support for SPDIF/HDMI passthru

Add support for SPDIF/HDMI pass-through support of PS3 audio driver.

Signed-off-by: Masakazu Mokuno <mokuno@sm.sony.co.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

Showing 2 changed files with 91 additions and 6 deletions Side-by-side Diff

... ... @@ -666,6 +666,7 @@
666 666 card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16;
667 667 card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM;
668 668 card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
  669 + memcpy(card->avs.avs_cs_info, ps3av_mode_cs_info, 8);
669 670  
670 671 ret = snd_ps3_change_avsetting(card);
671 672  
... ... @@ -685,6 +686,7 @@
685 686 {
686 687 struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
687 688 struct snd_ps3_avsetting_info avs;
  689 + int ret;
688 690  
689 691 avs = card->avs;
690 692  
691 693  
692 694  
693 695  
694 696  
695 697  
... ... @@ -729,19 +731,92 @@
729 731 return 1;
730 732 }
731 733  
732   - if ((card->avs.avs_audio_width != avs.avs_audio_width) ||
733   - (card->avs.avs_audio_rate != avs.avs_audio_rate)) {
734   - card->avs = avs;
735   - snd_ps3_change_avsetting(card);
  734 + memcpy(avs.avs_cs_info, ps3av_mode_cs_info, 8);
736 735  
  736 + if (memcmp(&card->avs, &avs, sizeof(avs))) {
737 737 pr_debug("%s: after freq=%d width=%d\n", __func__,
738 738 card->avs.avs_audio_rate, card->avs.avs_audio_width);
739 739  
740   - return 0;
  740 + card->avs = avs;
  741 + snd_ps3_change_avsetting(card);
  742 + ret = 0;
741 743 } else
  744 + ret = 1;
  745 +
  746 + /* check CS non-audio bit and mute accordingly */
  747 + if (avs.avs_cs_info[0] & 0x02)
  748 + ps3av_audio_mute_analog(1); /* mute if non-audio */
  749 + else
  750 + ps3av_audio_mute_analog(0);
  751 +
  752 + return ret;
  753 +}
  754 +
  755 +/*
  756 + * SPDIF status bits controls
  757 + */
  758 +static int snd_ps3_spdif_mask_info(struct snd_kcontrol *kcontrol,
  759 + struct snd_ctl_elem_info *uinfo)
  760 +{
  761 + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
  762 + uinfo->count = 1;
  763 + return 0;
  764 +}
  765 +
  766 +/* FIXME: ps3av_set_audio_mode() assumes only consumer mode */
  767 +static int snd_ps3_spdif_cmask_get(struct snd_kcontrol *kcontrol,
  768 + struct snd_ctl_elem_value *ucontrol)
  769 +{
  770 + memset(ucontrol->value.iec958.status, 0xff, 8);
  771 + return 0;
  772 +}
  773 +
  774 +static int snd_ps3_spdif_pmask_get(struct snd_kcontrol *kcontrol,
  775 + struct snd_ctl_elem_value *ucontrol)
  776 +{
  777 + return 0;
  778 +}
  779 +
  780 +static int snd_ps3_spdif_default_get(struct snd_kcontrol *kcontrol,
  781 + struct snd_ctl_elem_value *ucontrol)
  782 +{
  783 + memcpy(ucontrol->value.iec958.status, ps3av_mode_cs_info, 8);
  784 + return 0;
  785 +}
  786 +
  787 +static int snd_ps3_spdif_default_put(struct snd_kcontrol *kcontrol,
  788 + struct snd_ctl_elem_value *ucontrol)
  789 +{
  790 + if (memcmp(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8)) {
  791 + memcpy(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8);
742 792 return 1;
  793 + }
  794 + return 0;
743 795 }
744 796  
  797 +static struct snd_kcontrol_new spdif_ctls[] = {
  798 + {
  799 + .access = SNDRV_CTL_ELEM_ACCESS_READ,
  800 + .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  801 + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
  802 + .info = snd_ps3_spdif_mask_info,
  803 + .get = snd_ps3_spdif_cmask_get,
  804 + },
  805 + {
  806 + .access = SNDRV_CTL_ELEM_ACCESS_READ,
  807 + .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  808 + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
  809 + .info = snd_ps3_spdif_mask_info,
  810 + .get = snd_ps3_spdif_pmask_get,
  811 + },
  812 + {
  813 + .iface = SNDRV_CTL_ELEM_IFACE_PCM,
  814 + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
  815 + .info = snd_ps3_spdif_mask_info,
  816 + .get = snd_ps3_spdif_default_get,
  817 + .put = snd_ps3_spdif_default_put,
  818 + },
  819 +};
745 820  
746 821  
747 822 static int snd_ps3_map_mmio(void)
... ... @@ -842,7 +917,7 @@
842 917  
843 918 static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
844 919 {
845   - int ret;
  920 + int i, ret;
846 921 u64 lpar_addr, lpar_size;
847 922  
848 923 BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1));
... ... @@ -903,6 +978,15 @@
903 978 strcpy(the_card.card->driver, "PS3");
904 979 strcpy(the_card.card->shortname, "PS3");
905 980 strcpy(the_card.card->longname, "PS3 sound");
  981 +
  982 + /* create control elements */
  983 + for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) {
  984 + ret = snd_ctl_add(the_card.card,
  985 + snd_ctl_new1(&spdif_ctls[i], &the_card));
  986 + if (ret < 0)
  987 + goto clean_card;
  988 + }
  989 +
906 990 /* create PCM devices instance */
907 991 /* NOTE:this driver works assuming pcm:substream = 1:1 */
908 992 ret = snd_pcm_new(the_card.card,
... ... @@ -51,6 +51,7 @@
51 51 uint32_t avs_audio_width;
52 52 uint32_t avs_audio_format; /* fixed */
53 53 uint32_t avs_audio_source; /* fixed */
  54 + unsigned char avs_cs_info[8];
54 55 };
55 56 /*
56 57 * PS3 audio 'card' instance