]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | Subject: ALSA: ps3: Add support for SPDIF/HDMI passthru |
2 | From: Takashi Iwai tiwai@suse.de Mon Oct 20 08:06:39 2008 +0200 | |
3 | Date: Mon Oct 20 08:06:39 2008 +0200: | |
4 | Git: 1ee2a322b058f6399dc900603f9ebb392037ff77 | |
5 | ||
6 | Add support for SPDIF/HDMI pass-through support of PS3 audio driver. | |
7 | ||
8 | Signed-off-by: Masakazu Mokuno <mokuno@sm.sony.co.jp> | |
9 | Signed-off-by: Takashi Iwai <tiwai@suse.de> | |
10 | Signed-off-by: Stefan Assmann <sassmann@suse.de> | |
11 | ||
12 | diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c | |
13 | index 20d0e32..8f9e385 100644 | |
14 | --- a/sound/ppc/snd_ps3.c | |
15 | +++ b/sound/ppc/snd_ps3.c | |
16 | @@ -666,6 +666,7 @@ static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card) | |
17 | card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16; | |
18 | card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM; | |
19 | card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL; | |
20 | + memcpy(card->avs.avs_cs_info, ps3av_mode_cs_info, 8); | |
21 | ||
22 | ret = snd_ps3_change_avsetting(card); | |
23 | ||
24 | @@ -685,6 +686,7 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream) | |
25 | { | |
26 | struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); | |
27 | struct snd_ps3_avsetting_info avs; | |
28 | + int ret; | |
29 | ||
30 | avs = card->avs; | |
31 | ||
32 | @@ -729,19 +731,92 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream) | |
33 | return 1; | |
34 | } | |
35 | ||
36 | - if ((card->avs.avs_audio_width != avs.avs_audio_width) || | |
37 | - (card->avs.avs_audio_rate != avs.avs_audio_rate)) { | |
38 | - card->avs = avs; | |
39 | - snd_ps3_change_avsetting(card); | |
40 | + memcpy(avs.avs_cs_info, ps3av_mode_cs_info, 8); | |
41 | ||
42 | + if (memcmp(&card->avs, &avs, sizeof(avs))) { | |
43 | pr_debug("%s: after freq=%d width=%d\n", __func__, | |
44 | card->avs.avs_audio_rate, card->avs.avs_audio_width); | |
45 | ||
46 | - return 0; | |
47 | + card->avs = avs; | |
48 | + snd_ps3_change_avsetting(card); | |
49 | + ret = 0; | |
50 | } else | |
51 | + ret = 1; | |
52 | + | |
53 | + /* check CS non-audio bit and mute accordingly */ | |
54 | + if (avs.avs_cs_info[0] & 0x02) | |
55 | + ps3av_audio_mute_analog(1); /* mute if non-audio */ | |
56 | + else | |
57 | + ps3av_audio_mute_analog(0); | |
58 | + | |
59 | + return ret; | |
60 | +} | |
61 | + | |
62 | +/* | |
63 | + * SPDIF status bits controls | |
64 | + */ | |
65 | +static int snd_ps3_spdif_mask_info(struct snd_kcontrol *kcontrol, | |
66 | + struct snd_ctl_elem_info *uinfo) | |
67 | +{ | |
68 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | |
69 | + uinfo->count = 1; | |
70 | + return 0; | |
71 | +} | |
72 | + | |
73 | +/* FIXME: ps3av_set_audio_mode() assumes only consumer mode */ | |
74 | +static int snd_ps3_spdif_cmask_get(struct snd_kcontrol *kcontrol, | |
75 | + struct snd_ctl_elem_value *ucontrol) | |
76 | +{ | |
77 | + memset(ucontrol->value.iec958.status, 0xff, 8); | |
78 | + return 0; | |
79 | +} | |
80 | + | |
81 | +static int snd_ps3_spdif_pmask_get(struct snd_kcontrol *kcontrol, | |
82 | + struct snd_ctl_elem_value *ucontrol) | |
83 | +{ | |
84 | + return 0; | |
85 | +} | |
86 | + | |
87 | +static int snd_ps3_spdif_default_get(struct snd_kcontrol *kcontrol, | |
88 | + struct snd_ctl_elem_value *ucontrol) | |
89 | +{ | |
90 | + memcpy(ucontrol->value.iec958.status, ps3av_mode_cs_info, 8); | |
91 | + return 0; | |
92 | +} | |
93 | + | |
94 | +static int snd_ps3_spdif_default_put(struct snd_kcontrol *kcontrol, | |
95 | + struct snd_ctl_elem_value *ucontrol) | |
96 | +{ | |
97 | + if (memcmp(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8)) { | |
98 | + memcpy(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8); | |
99 | return 1; | |
100 | + } | |
101 | + return 0; | |
102 | } | |
103 | ||
104 | +static struct snd_kcontrol_new spdif_ctls[] = { | |
105 | + { | |
106 | + .access = SNDRV_CTL_ELEM_ACCESS_READ, | |
107 | + .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
108 | + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), | |
109 | + .info = snd_ps3_spdif_mask_info, | |
110 | + .get = snd_ps3_spdif_cmask_get, | |
111 | + }, | |
112 | + { | |
113 | + .access = SNDRV_CTL_ELEM_ACCESS_READ, | |
114 | + .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
115 | + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), | |
116 | + .info = snd_ps3_spdif_mask_info, | |
117 | + .get = snd_ps3_spdif_pmask_get, | |
118 | + }, | |
119 | + { | |
120 | + .iface = SNDRV_CTL_ELEM_IFACE_PCM, | |
121 | + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | |
122 | + .info = snd_ps3_spdif_mask_info, | |
123 | + .get = snd_ps3_spdif_default_get, | |
124 | + .put = snd_ps3_spdif_default_put, | |
125 | + }, | |
126 | +}; | |
127 | ||
128 | ||
129 | static int snd_ps3_map_mmio(void) | |
130 | @@ -842,7 +917,7 @@ static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start) | |
131 | ||
132 | static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev) | |
133 | { | |
134 | - int ret; | |
135 | + int i, ret; | |
136 | u64 lpar_addr, lpar_size; | |
137 | ||
138 | BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1)); | |
139 | @@ -903,6 +978,15 @@ static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev) | |
140 | strcpy(the_card.card->driver, "PS3"); | |
141 | strcpy(the_card.card->shortname, "PS3"); | |
142 | strcpy(the_card.card->longname, "PS3 sound"); | |
143 | + | |
144 | + /* create control elements */ | |
145 | + for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) { | |
146 | + ret = snd_ctl_add(the_card.card, | |
147 | + snd_ctl_new1(&spdif_ctls[i], &the_card)); | |
148 | + if (ret < 0) | |
149 | + goto clean_card; | |
150 | + } | |
151 | + | |
152 | /* create PCM devices instance */ | |
153 | /* NOTE:this driver works assuming pcm:substream = 1:1 */ | |
154 | ret = snd_pcm_new(the_card.card, | |
155 | diff --git a/sound/ppc/snd_ps3.h b/sound/ppc/snd_ps3.h | |
156 | index 4b7e6fb..326fb29 100644 | |
157 | --- a/sound/ppc/snd_ps3.h | |
158 | +++ b/sound/ppc/snd_ps3.h | |
159 | @@ -51,6 +51,7 @@ struct snd_ps3_avsetting_info { | |
160 | uint32_t avs_audio_width; | |
161 | uint32_t avs_audio_format; /* fixed */ | |
162 | uint32_t avs_audio_source; /* fixed */ | |
163 | + unsigned char avs_cs_info[8]; | |
164 | }; | |
165 | /* | |
166 | * PS3 audio 'card' instance |