diff options
Diffstat (limited to 'sound/pci/hda/patch_atihdmi.c')
-rw-r--r-- | sound/pci/hda/patch_atihdmi.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index 12272508b11..ba61575983f 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c | |||
@@ -35,6 +35,9 @@ struct atihdmi_spec { | |||
35 | struct hda_pcm pcm_rec; | 35 | struct hda_pcm pcm_rec; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | #define CVT_NID 0x02 /* audio converter */ | ||
39 | #define PIN_NID 0x03 /* HDMI output pin */ | ||
40 | |||
38 | static struct hda_verb atihdmi_basic_init[] = { | 41 | static struct hda_verb atihdmi_basic_init[] = { |
39 | /* enable digital output on pin widget */ | 42 | /* enable digital output on pin widget */ |
40 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | 43 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
@@ -60,8 +63,9 @@ static int atihdmi_init(struct hda_codec *codec) | |||
60 | { | 63 | { |
61 | snd_hda_sequence_write(codec, atihdmi_basic_init); | 64 | snd_hda_sequence_write(codec, atihdmi_basic_init); |
62 | /* SI codec requires to unmute the pin */ | 65 | /* SI codec requires to unmute the pin */ |
63 | if (get_wcaps(codec, 0x03) & AC_WCAP_OUT_AMP) | 66 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) |
64 | snd_hda_codec_write(codec, 0x03, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 67 | snd_hda_codec_write(codec, PIN_NID, 0, |
68 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
65 | AMP_OUT_UNMUTE); | 69 | AMP_OUT_UNMUTE); |
66 | return 0; | 70 | return 0; |
67 | } | 71 | } |
@@ -92,15 +96,29 @@ static int atihdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
92 | struct snd_pcm_substream *substream) | 96 | struct snd_pcm_substream *substream) |
93 | { | 97 | { |
94 | struct atihdmi_spec *spec = codec->spec; | 98 | struct atihdmi_spec *spec = codec->spec; |
95 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | 99 | int chans = substream->runtime->channels; |
96 | format, substream); | 100 | int i, err; |
101 | |||
102 | err = snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
103 | format, substream); | ||
104 | if (err < 0) | ||
105 | return err; | ||
106 | snd_hda_codec_write(codec, CVT_NID, 0, AC_VERB_SET_CVT_CHAN_COUNT, | ||
107 | chans - 1); | ||
108 | /* FIXME: XXX */ | ||
109 | for (i = 0; i < chans; i++) { | ||
110 | snd_hda_codec_write(codec, CVT_NID, 0, | ||
111 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
112 | (i << 4) | i); | ||
113 | } | ||
114 | return 0; | ||
97 | } | 115 | } |
98 | 116 | ||
99 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { | 117 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { |
100 | .substreams = 1, | 118 | .substreams = 1, |
101 | .channels_min = 2, | 119 | .channels_min = 2, |
102 | .channels_max = 2, | 120 | .channels_max = 2, |
103 | .nid = 0x2, /* NID to query formats and rates and setup streams */ | 121 | .nid = CVT_NID, /* NID to query formats and rates and setup streams */ |
104 | .ops = { | 122 | .ops = { |
105 | .open = atihdmi_dig_playback_pcm_open, | 123 | .open = atihdmi_dig_playback_pcm_open, |
106 | .close = atihdmi_dig_playback_pcm_close, | 124 | .close = atihdmi_dig_playback_pcm_close, |
@@ -112,6 +130,7 @@ static int atihdmi_build_pcms(struct hda_codec *codec) | |||
112 | { | 130 | { |
113 | struct atihdmi_spec *spec = codec->spec; | 131 | struct atihdmi_spec *spec = codec->spec; |
114 | struct hda_pcm *info = &spec->pcm_rec; | 132 | struct hda_pcm *info = &spec->pcm_rec; |
133 | unsigned int chans; | ||
115 | 134 | ||
116 | codec->num_pcms = 1; | 135 | codec->num_pcms = 1; |
117 | codec->pcm_info = info; | 136 | codec->pcm_info = info; |
@@ -120,6 +139,13 @@ static int atihdmi_build_pcms(struct hda_codec *codec) | |||
120 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 139 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
121 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback; | 140 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback; |
122 | 141 | ||
142 | /* FIXME: we must check ELD and change the PCM parameters dynamically | ||
143 | */ | ||
144 | chans = get_wcaps(codec, CVT_NID); | ||
145 | chans = (chans & AC_WCAP_CHAN_CNT_EXT) >> 13; | ||
146 | chans = ((chans << 1) | 1) + 1; | ||
147 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
148 | |||
123 | return 0; | 149 | return 0; |
124 | } | 150 | } |
125 | 151 | ||
@@ -147,9 +173,11 @@ static int patch_atihdmi(struct hda_codec *codec) | |||
147 | 173 | ||
148 | spec->multiout.num_dacs = 0; /* no analog */ | 174 | spec->multiout.num_dacs = 0; /* no analog */ |
149 | spec->multiout.max_channels = 2; | 175 | spec->multiout.max_channels = 2; |
150 | spec->multiout.dig_out_nid = 0x2; /* NID for copying analog to digital, | 176 | /* NID for copying analog to digital, |
151 | * seems to be unused in pure-digital | 177 | * seems to be unused in pure-digital |
152 | * case. */ | 178 | * case. |
179 | */ | ||
180 | spec->multiout.dig_out_nid = CVT_NID; | ||
153 | 181 | ||
154 | codec->patch_ops = atihdmi_patch_ops; | 182 | codec->patch_ops = atihdmi_patch_ops; |
155 | 183 | ||
@@ -164,6 +192,7 @@ struct hda_codec_preset snd_hda_preset_atihdmi[] = { | |||
164 | { .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, | 192 | { .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, |
165 | { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi }, | 193 | { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi }, |
166 | { .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi }, | 194 | { .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi }, |
195 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_atihdmi }, | ||
167 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi }, | 196 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi }, |
168 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi }, | 197 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi }, |
169 | {} /* terminator */ | 198 | {} /* terminator */ |