diff options
Diffstat (limited to 'sound/pci/hda/patch_nvhdmi.c')
| -rw-r--r-- | sound/pci/hda/patch_nvhdmi.c | 275 |
1 files changed, 216 insertions, 59 deletions
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 6afdab09bab7..70669a246902 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c | |||
| @@ -29,13 +29,23 @@ | |||
| 29 | #include "hda_codec.h" | 29 | #include "hda_codec.h" |
| 30 | #include "hda_local.h" | 30 | #include "hda_local.h" |
| 31 | 31 | ||
| 32 | #define MAX_HDMI_CVTS 1 | ||
| 33 | #define MAX_HDMI_PINS 1 | ||
| 34 | |||
| 35 | #include "patch_hdmi.c" | ||
| 36 | |||
| 37 | static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
| 38 | "NVIDIA HDMI", | ||
| 39 | }; | ||
| 40 | |||
| 32 | /* define below to restrict the supported rates and formats */ | 41 | /* define below to restrict the supported rates and formats */ |
| 33 | /* #define LIMITED_RATE_FMT_SUPPORT */ | 42 | /* #define LIMITED_RATE_FMT_SUPPORT */ |
| 34 | 43 | ||
| 35 | struct nvhdmi_spec { | 44 | enum HDACodec { |
| 36 | struct hda_multi_out multiout; | 45 | HDA_CODEC_NVIDIA_MCP7X, |
| 37 | 46 | HDA_CODEC_NVIDIA_MCP89, | |
| 38 | struct hda_pcm pcm_rec; | 47 | HDA_CODEC_NVIDIA_GT21X, |
| 48 | HDA_CODEC_INVALID | ||
| 39 | }; | 49 | }; |
| 40 | 50 | ||
| 41 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | 51 | #define Nv_VERB_SET_Channel_Allocation 0xF79 |
| @@ -43,15 +53,18 @@ struct nvhdmi_spec { | |||
| 43 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | 53 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 |
| 44 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | 54 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 |
| 45 | 55 | ||
| 46 | #define Nv_Master_Convert_nid 0x04 | 56 | #define nvhdmi_master_con_nid_7x 0x04 |
| 47 | #define Nv_Master_Pin_nid 0x05 | 57 | #define nvhdmi_master_pin_nid_7x 0x05 |
| 48 | 58 | ||
| 49 | static hda_nid_t nvhdmi_convert_nids[4] = { | 59 | #define nvhdmi_master_con_nid_89 0x04 |
| 60 | #define nvhdmi_master_pin_nid_89 0x05 | ||
| 61 | |||
| 62 | static hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
| 50 | /*front, rear, clfe, rear_surr */ | 63 | /*front, rear, clfe, rear_surr */ |
| 51 | 0x6, 0x8, 0xa, 0xc, | 64 | 0x6, 0x8, 0xa, 0xc, |
| 52 | }; | 65 | }; |
| 53 | 66 | ||
| 54 | static struct hda_verb nvhdmi_basic_init[] = { | 67 | static struct hda_verb nvhdmi_basic_init_7x[] = { |
| 55 | /* set audio protect on */ | 68 | /* set audio protect on */ |
| 56 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 69 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
| 57 | /* enable digital output on pin widget */ | 70 | /* enable digital output on pin widget */ |
| @@ -84,22 +97,60 @@ static struct hda_verb nvhdmi_basic_init[] = { | |||
| 84 | */ | 97 | */ |
| 85 | static int nvhdmi_build_controls(struct hda_codec *codec) | 98 | static int nvhdmi_build_controls(struct hda_codec *codec) |
| 86 | { | 99 | { |
| 87 | struct nvhdmi_spec *spec = codec->spec; | 100 | struct hdmi_spec *spec = codec->spec; |
| 88 | int err; | 101 | int err; |
| 102 | int i; | ||
| 89 | 103 | ||
| 90 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 104 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) |
| 91 | if (err < 0) | 105 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { |
| 92 | return err; | 106 | for (i = 0; i < codec->num_pcms; i++) { |
| 107 | err = snd_hda_create_spdif_out_ctls(codec, | ||
| 108 | spec->cvt[i]); | ||
| 109 | if (err < 0) | ||
| 110 | return err; | ||
| 111 | } | ||
| 112 | } else { | ||
| 113 | err = snd_hda_create_spdif_out_ctls(codec, | ||
| 114 | spec->multiout.dig_out_nid); | ||
| 115 | if (err < 0) | ||
| 116 | return err; | ||
| 117 | } | ||
| 93 | 118 | ||
| 94 | return 0; | 119 | return 0; |
| 95 | } | 120 | } |
| 96 | 121 | ||
| 97 | static int nvhdmi_init(struct hda_codec *codec) | 122 | static int nvhdmi_init(struct hda_codec *codec) |
| 98 | { | 123 | { |
| 99 | snd_hda_sequence_write(codec, nvhdmi_basic_init); | 124 | struct hdmi_spec *spec = codec->spec; |
| 125 | int i; | ||
| 126 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
| 127 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
| 128 | for (i = 0; spec->pin[i]; i++) { | ||
| 129 | hdmi_enable_output(codec, spec->pin[i]); | ||
| 130 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
| 131 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
| 132 | AC_USRSP_EN | spec->pin[i]); | ||
| 133 | } | ||
| 134 | } else { | ||
| 135 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
| 136 | } | ||
| 100 | return 0; | 137 | return 0; |
| 101 | } | 138 | } |
| 102 | 139 | ||
| 140 | static void nvhdmi_free(struct hda_codec *codec) | ||
| 141 | { | ||
| 142 | struct hdmi_spec *spec = codec->spec; | ||
| 143 | int i; | ||
| 144 | |||
| 145 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
| 146 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
| 147 | for (i = 0; i < spec->num_pins; i++) | ||
| 148 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
| 149 | } | ||
| 150 | |||
| 151 | kfree(spec); | ||
| 152 | } | ||
| 153 | |||
| 103 | /* | 154 | /* |
| 104 | * Digital out | 155 | * Digital out |
| 105 | */ | 156 | */ |
| @@ -107,25 +158,25 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | |||
| 107 | struct hda_codec *codec, | 158 | struct hda_codec *codec, |
| 108 | struct snd_pcm_substream *substream) | 159 | struct snd_pcm_substream *substream) |
| 109 | { | 160 | { |
| 110 | struct nvhdmi_spec *spec = codec->spec; | 161 | struct hdmi_spec *spec = codec->spec; |
| 111 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 162 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); |
| 112 | } | 163 | } |
| 113 | 164 | ||
| 114 | static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo, | 165 | static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, |
| 115 | struct hda_codec *codec, | 166 | struct hda_codec *codec, |
| 116 | struct snd_pcm_substream *substream) | 167 | struct snd_pcm_substream *substream) |
| 117 | { | 168 | { |
| 118 | struct nvhdmi_spec *spec = codec->spec; | 169 | struct hdmi_spec *spec = codec->spec; |
| 119 | int i; | 170 | int i; |
| 120 | 171 | ||
| 121 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, | 172 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, |
| 122 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | 173 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); |
| 123 | for (i = 0; i < 4; i++) { | 174 | for (i = 0; i < 4; i++) { |
| 124 | /* set the stream id */ | 175 | /* set the stream id */ |
| 125 | snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, | 176 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
| 126 | AC_VERB_SET_CHANNEL_STREAMID, 0); | 177 | AC_VERB_SET_CHANNEL_STREAMID, 0); |
| 127 | /* set the stream format */ | 178 | /* set the stream format */ |
| 128 | snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, | 179 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
| 129 | AC_VERB_SET_STREAM_FORMAT, 0); | 180 | AC_VERB_SET_STREAM_FORMAT, 0); |
| 130 | } | 181 | } |
| 131 | 182 | ||
| @@ -136,10 +187,25 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, | |||
| 136 | struct hda_codec *codec, | 187 | struct hda_codec *codec, |
| 137 | struct snd_pcm_substream *substream) | 188 | struct snd_pcm_substream *substream) |
| 138 | { | 189 | { |
| 139 | struct nvhdmi_spec *spec = codec->spec; | 190 | struct hdmi_spec *spec = codec->spec; |
| 140 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 191 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
| 141 | } | 192 | } |
| 142 | 193 | ||
| 194 | static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, | ||
| 195 | struct hda_codec *codec, | ||
| 196 | unsigned int stream_tag, | ||
| 197 | unsigned int format, | ||
| 198 | struct snd_pcm_substream *substream) | ||
| 199 | { | ||
| 200 | hdmi_set_channel_count(codec, hinfo->nid, | ||
| 201 | substream->runtime->channels); | ||
| 202 | |||
| 203 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
| 204 | |||
| 205 | hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 143 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | 209 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, |
| 144 | struct hda_codec *codec, | 210 | struct hda_codec *codec, |
| 145 | unsigned int stream_tag, | 211 | unsigned int stream_tag, |
| @@ -181,29 +247,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
| 181 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 247 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
| 182 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | 248 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) |
| 183 | snd_hda_codec_write(codec, | 249 | snd_hda_codec_write(codec, |
| 184 | Nv_Master_Convert_nid, | 250 | nvhdmi_master_con_nid_7x, |
| 185 | 0, | 251 | 0, |
| 186 | AC_VERB_SET_DIGI_CONVERT_1, | 252 | AC_VERB_SET_DIGI_CONVERT_1, |
| 187 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | 253 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); |
| 188 | 254 | ||
| 189 | /* set the stream id */ | 255 | /* set the stream id */ |
| 190 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, | 256 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
| 191 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | 257 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); |
| 192 | 258 | ||
| 193 | /* set the stream format */ | 259 | /* set the stream format */ |
| 194 | snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, | 260 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
| 195 | AC_VERB_SET_STREAM_FORMAT, format); | 261 | AC_VERB_SET_STREAM_FORMAT, format); |
| 196 | 262 | ||
| 197 | /* turn on again (if needed) */ | 263 | /* turn on again (if needed) */ |
| 198 | /* enable and set the channel status audio/data flag */ | 264 | /* enable and set the channel status audio/data flag */ |
| 199 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | 265 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { |
| 200 | snd_hda_codec_write(codec, | 266 | snd_hda_codec_write(codec, |
| 201 | Nv_Master_Convert_nid, | 267 | nvhdmi_master_con_nid_7x, |
| 202 | 0, | 268 | 0, |
| 203 | AC_VERB_SET_DIGI_CONVERT_1, | 269 | AC_VERB_SET_DIGI_CONVERT_1, |
| 204 | codec->spdif_ctls & 0xff); | 270 | codec->spdif_ctls & 0xff); |
| 205 | snd_hda_codec_write(codec, | 271 | snd_hda_codec_write(codec, |
| 206 | Nv_Master_Convert_nid, | 272 | nvhdmi_master_con_nid_7x, |
| 207 | 0, | 273 | 0, |
| 208 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 274 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
| 209 | } | 275 | } |
| @@ -220,19 +286,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
| 220 | if (codec->spdif_status_reset && | 286 | if (codec->spdif_status_reset && |
| 221 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | 287 | (codec->spdif_ctls & AC_DIG1_ENABLE)) |
| 222 | snd_hda_codec_write(codec, | 288 | snd_hda_codec_write(codec, |
| 223 | nvhdmi_convert_nids[i], | 289 | nvhdmi_con_nids_7x[i], |
| 224 | 0, | 290 | 0, |
| 225 | AC_VERB_SET_DIGI_CONVERT_1, | 291 | AC_VERB_SET_DIGI_CONVERT_1, |
| 226 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | 292 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); |
| 227 | /* set the stream id */ | 293 | /* set the stream id */ |
| 228 | snd_hda_codec_write(codec, | 294 | snd_hda_codec_write(codec, |
| 229 | nvhdmi_convert_nids[i], | 295 | nvhdmi_con_nids_7x[i], |
| 230 | 0, | 296 | 0, |
| 231 | AC_VERB_SET_CHANNEL_STREAMID, | 297 | AC_VERB_SET_CHANNEL_STREAMID, |
| 232 | (stream_tag << 4) | channel_id); | 298 | (stream_tag << 4) | channel_id); |
| 233 | /* set the stream format */ | 299 | /* set the stream format */ |
| 234 | snd_hda_codec_write(codec, | 300 | snd_hda_codec_write(codec, |
| 235 | nvhdmi_convert_nids[i], | 301 | nvhdmi_con_nids_7x[i], |
| 236 | 0, | 302 | 0, |
| 237 | AC_VERB_SET_STREAM_FORMAT, | 303 | AC_VERB_SET_STREAM_FORMAT, |
| 238 | format); | 304 | format); |
| @@ -241,12 +307,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
| 241 | if (codec->spdif_status_reset && | 307 | if (codec->spdif_status_reset && |
| 242 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | 308 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { |
| 243 | snd_hda_codec_write(codec, | 309 | snd_hda_codec_write(codec, |
| 244 | nvhdmi_convert_nids[i], | 310 | nvhdmi_con_nids_7x[i], |
| 245 | 0, | 311 | 0, |
| 246 | AC_VERB_SET_DIGI_CONVERT_1, | 312 | AC_VERB_SET_DIGI_CONVERT_1, |
| 247 | codec->spdif_ctls & 0xff); | 313 | codec->spdif_ctls & 0xff); |
| 248 | snd_hda_codec_write(codec, | 314 | snd_hda_codec_write(codec, |
| 249 | nvhdmi_convert_nids[i], | 315 | nvhdmi_con_nids_7x[i], |
| 250 | 0, | 316 | 0, |
| 251 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 317 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
| 252 | } | 318 | } |
| @@ -261,28 +327,47 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | |||
| 261 | return 0; | 327 | return 0; |
| 262 | } | 328 | } |
| 263 | 329 | ||
| 330 | static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
| 331 | struct hda_codec *codec, | ||
| 332 | struct snd_pcm_substream *substream) | ||
| 333 | { | ||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 264 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, | 337 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, |
| 265 | struct hda_codec *codec, | 338 | struct hda_codec *codec, |
| 266 | unsigned int stream_tag, | 339 | unsigned int stream_tag, |
| 267 | unsigned int format, | 340 | unsigned int format, |
| 268 | struct snd_pcm_substream *substream) | 341 | struct snd_pcm_substream *substream) |
| 269 | { | 342 | { |
| 270 | struct nvhdmi_spec *spec = codec->spec; | 343 | struct hdmi_spec *spec = codec->spec; |
| 271 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | 344 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, |
| 272 | format, substream); | 345 | format, substream); |
| 273 | } | 346 | } |
| 274 | 347 | ||
| 275 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = { | 348 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { |
| 349 | .substreams = 1, | ||
| 350 | .channels_min = 2, | ||
| 351 | .rates = SUPPORTED_RATES, | ||
| 352 | .maxbps = SUPPORTED_MAXBPS, | ||
| 353 | .formats = SUPPORTED_FORMATS, | ||
| 354 | .ops = { | ||
| 355 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, | ||
| 356 | .cleanup = nvhdmi_playback_pcm_cleanup, | ||
| 357 | }, | ||
| 358 | }; | ||
| 359 | |||
| 360 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = { | ||
| 276 | .substreams = 1, | 361 | .substreams = 1, |
| 277 | .channels_min = 2, | 362 | .channels_min = 2, |
| 278 | .channels_max = 8, | 363 | .channels_max = 8, |
| 279 | .nid = Nv_Master_Convert_nid, | 364 | .nid = nvhdmi_master_con_nid_7x, |
| 280 | .rates = SUPPORTED_RATES, | 365 | .rates = SUPPORTED_RATES, |
| 281 | .maxbps = SUPPORTED_MAXBPS, | 366 | .maxbps = SUPPORTED_MAXBPS, |
| 282 | .formats = SUPPORTED_FORMATS, | 367 | .formats = SUPPORTED_FORMATS, |
| 283 | .ops = { | 368 | .ops = { |
| 284 | .open = nvhdmi_dig_playback_pcm_open, | 369 | .open = nvhdmi_dig_playback_pcm_open, |
| 285 | .close = nvhdmi_dig_playback_pcm_close_8ch, | 370 | .close = nvhdmi_dig_playback_pcm_close_8ch_7x, |
| 286 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch | 371 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch |
| 287 | }, | 372 | }, |
| 288 | }; | 373 | }; |
| @@ -291,7 +376,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | |||
| 291 | .substreams = 1, | 376 | .substreams = 1, |
| 292 | .channels_min = 2, | 377 | .channels_min = 2, |
| 293 | .channels_max = 2, | 378 | .channels_max = 2, |
| 294 | .nid = Nv_Master_Convert_nid, | 379 | .nid = nvhdmi_master_con_nid_7x, |
| 295 | .rates = SUPPORTED_RATES, | 380 | .rates = SUPPORTED_RATES, |
| 296 | .maxbps = SUPPORTED_MAXBPS, | 381 | .maxbps = SUPPORTED_MAXBPS, |
| 297 | .formats = SUPPORTED_FORMATS, | 382 | .formats = SUPPORTED_FORMATS, |
| @@ -302,10 +387,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | |||
| 302 | }, | 387 | }, |
| 303 | }; | 388 | }; |
| 304 | 389 | ||
| 305 | static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) | 390 | static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) |
| 391 | { | ||
| 392 | struct hdmi_spec *spec = codec->spec; | ||
| 393 | struct hda_pcm *info = spec->pcm_rec; | ||
| 394 | int i; | ||
| 395 | |||
| 396 | codec->num_pcms = spec->num_cvts; | ||
| 397 | codec->pcm_info = info; | ||
| 398 | |||
| 399 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
| 400 | unsigned int chans; | ||
| 401 | |||
| 402 | chans = get_wcaps(codec, spec->cvt[i]); | ||
| 403 | chans = get_wcaps_channels(chans); | ||
| 404 | |||
| 405 | info->name = nvhdmi_pcm_names[i]; | ||
| 406 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
| 407 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
| 408 | = nvhdmi_pcm_digital_playback_8ch_89; | ||
| 409 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; | ||
| 410 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
| 411 | } | ||
| 412 | |||
| 413 | return 0; | ||
| 414 | } | ||
| 415 | |||
| 416 | static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) | ||
| 306 | { | 417 | { |
| 307 | struct nvhdmi_spec *spec = codec->spec; | 418 | struct hdmi_spec *spec = codec->spec; |
| 308 | struct hda_pcm *info = &spec->pcm_rec; | 419 | struct hda_pcm *info = spec->pcm_rec; |
| 309 | 420 | ||
| 310 | codec->num_pcms = 1; | 421 | codec->num_pcms = 1; |
| 311 | codec->pcm_info = info; | 422 | codec->pcm_info = info; |
| @@ -313,15 +424,15 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) | |||
| 313 | info->name = "NVIDIA HDMI"; | 424 | info->name = "NVIDIA HDMI"; |
| 314 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 425 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
| 315 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | 426 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] |
| 316 | = nvhdmi_pcm_digital_playback_8ch; | 427 | = nvhdmi_pcm_digital_playback_8ch_7x; |
| 317 | 428 | ||
| 318 | return 0; | 429 | return 0; |
| 319 | } | 430 | } |
| 320 | 431 | ||
| 321 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | 432 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) |
| 322 | { | 433 | { |
| 323 | struct nvhdmi_spec *spec = codec->spec; | 434 | struct hdmi_spec *spec = codec->spec; |
| 324 | struct hda_pcm *info = &spec->pcm_rec; | 435 | struct hda_pcm *info = spec->pcm_rec; |
| 325 | 436 | ||
| 326 | codec->num_pcms = 1; | 437 | codec->num_pcms = 1; |
| 327 | codec->pcm_info = info; | 438 | codec->pcm_info = info; |
| @@ -334,14 +445,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | |||
| 334 | return 0; | 445 | return 0; |
| 335 | } | 446 | } |
| 336 | 447 | ||
| 337 | static void nvhdmi_free(struct hda_codec *codec) | 448 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { |
| 338 | { | 449 | .build_controls = nvhdmi_build_controls, |
| 339 | kfree(codec->spec); | 450 | .build_pcms = nvhdmi_build_pcms_8ch_89, |
| 340 | } | 451 | .init = nvhdmi_init, |
| 452 | .free = nvhdmi_free, | ||
| 453 | .unsol_event = hdmi_unsol_event, | ||
| 454 | }; | ||
| 341 | 455 | ||
| 342 | static struct hda_codec_ops nvhdmi_patch_ops_8ch = { | 456 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { |
| 343 | .build_controls = nvhdmi_build_controls, | 457 | .build_controls = nvhdmi_build_controls, |
| 344 | .build_pcms = nvhdmi_build_pcms_8ch, | 458 | .build_pcms = nvhdmi_build_pcms_8ch_7x, |
| 345 | .init = nvhdmi_init, | 459 | .init = nvhdmi_init, |
| 346 | .free = nvhdmi_free, | 460 | .free = nvhdmi_free, |
| 347 | }; | 461 | }; |
| @@ -353,9 +467,36 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = { | |||
| 353 | .free = nvhdmi_free, | 467 | .free = nvhdmi_free, |
| 354 | }; | 468 | }; |
| 355 | 469 | ||
| 356 | static int patch_nvhdmi_8ch(struct hda_codec *codec) | 470 | static int patch_nvhdmi_8ch_89(struct hda_codec *codec) |
| 471 | { | ||
| 472 | struct hdmi_spec *spec; | ||
| 473 | int i; | ||
| 474 | |||
| 475 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 476 | if (spec == NULL) | ||
| 477 | return -ENOMEM; | ||
| 478 | |||
| 479 | codec->spec = spec; | ||
| 480 | spec->codec_type = HDA_CODEC_NVIDIA_MCP89; | ||
| 481 | |||
| 482 | if (hdmi_parse_codec(codec) < 0) { | ||
| 483 | codec->spec = NULL; | ||
| 484 | kfree(spec); | ||
| 485 | return -EINVAL; | ||
| 486 | } | ||
| 487 | codec->patch_ops = nvhdmi_patch_ops_8ch_89; | ||
| 488 | |||
| 489 | for (i = 0; i < spec->num_pins; i++) | ||
| 490 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
| 491 | |||
| 492 | init_channel_allocations(); | ||
| 493 | |||
| 494 | return 0; | ||
| 495 | } | ||
| 496 | |||
| 497 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
| 357 | { | 498 | { |
| 358 | struct nvhdmi_spec *spec; | 499 | struct hdmi_spec *spec; |
| 359 | 500 | ||
| 360 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 501 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
| 361 | if (spec == NULL) | 502 | if (spec == NULL) |
| @@ -365,16 +506,17 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec) | |||
| 365 | 506 | ||
| 366 | spec->multiout.num_dacs = 0; /* no analog */ | 507 | spec->multiout.num_dacs = 0; /* no analog */ |
| 367 | spec->multiout.max_channels = 8; | 508 | spec->multiout.max_channels = 8; |
| 368 | spec->multiout.dig_out_nid = Nv_Master_Convert_nid; | 509 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
| 510 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
| 369 | 511 | ||
| 370 | codec->patch_ops = nvhdmi_patch_ops_8ch; | 512 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; |
| 371 | 513 | ||
| 372 | return 0; | 514 | return 0; |
| 373 | } | 515 | } |
| 374 | 516 | ||
| 375 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | 517 | static int patch_nvhdmi_2ch(struct hda_codec *codec) |
| 376 | { | 518 | { |
| 377 | struct nvhdmi_spec *spec; | 519 | struct hdmi_spec *spec; |
| 378 | 520 | ||
| 379 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 521 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
| 380 | if (spec == NULL) | 522 | if (spec == NULL) |
| @@ -384,7 +526,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
| 384 | 526 | ||
| 385 | spec->multiout.num_dacs = 0; /* no analog */ | 527 | spec->multiout.num_dacs = 0; /* no analog */ |
| 386 | spec->multiout.max_channels = 2; | 528 | spec->multiout.max_channels = 2; |
| 387 | spec->multiout.dig_out_nid = Nv_Master_Convert_nid; | 529 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; |
| 530 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
| 388 | 531 | ||
| 389 | codec->patch_ops = nvhdmi_patch_ops_2ch; | 532 | codec->patch_ops = nvhdmi_patch_ops_2ch; |
| 390 | 533 | ||
| @@ -395,13 +538,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
| 395 | * patch entries | 538 | * patch entries |
| 396 | */ | 539 | */ |
| 397 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { | 540 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { |
| 398 | { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
| 399 | { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
| 400 | { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
| 401 | { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, | ||
| 402 | { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch }, | ||
| 403 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 541 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
| 404 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 542 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
| 543 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", | ||
| 544 | .patch = patch_nvhdmi_8ch_7x }, | ||
| 545 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", | ||
| 546 | .patch = patch_nvhdmi_8ch_7x }, | ||
| 547 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", | ||
| 548 | .patch = patch_nvhdmi_8ch_7x }, | ||
| 549 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", | ||
| 550 | .patch = patch_nvhdmi_8ch_7x }, | ||
| 551 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", | ||
| 552 | .patch = patch_nvhdmi_8ch_7x }, | ||
| 553 | { .id = 0x10de000c, .name = "MCP89 HDMI", | ||
| 554 | .patch = patch_nvhdmi_8ch_89 }, | ||
| 555 | { .id = 0x10de000b, .name = "GT21x HDMI", | ||
| 556 | .patch = patch_nvhdmi_8ch_89 }, | ||
| 557 | { .id = 0x10de000d, .name = "GT240 HDMI", | ||
| 558 | .patch = patch_nvhdmi_8ch_89 }, | ||
| 405 | {} /* terminator */ | 559 | {} /* terminator */ |
| 406 | }; | 560 | }; |
| 407 | 561 | ||
| @@ -412,9 +566,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006"); | |||
| 412 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | 566 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); |
| 413 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 567 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
| 414 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 568 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
| 569 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
| 570 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
| 571 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
| 415 | 572 | ||
| 416 | MODULE_LICENSE("GPL"); | 573 | MODULE_LICENSE("GPL"); |
| 417 | MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec"); | 574 | MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec"); |
| 418 | 575 | ||
| 419 | static struct hda_codec_preset_list nvhdmi_list = { | 576 | static struct hda_codec_preset_list nvhdmi_list = { |
| 420 | .preset = snd_hda_preset_nvhdmi, | 577 | .preset = snd_hda_preset_nvhdmi, |
