Merge branch 'fix/soundcore' into for-linus
[linux-2.6] / sound / pci / hda / patch_nvhdmi.c
1 /*
2  * Universal Interface for Intel High Definition Audio Codec
3  *
4  * HD audio interface patch for NVIDIA HDMI codecs
5  *
6  * Copyright (c) 2008 NVIDIA Corp.  All rights reserved.
7  * Copyright (c) 2008 Wei Ni <wni@nvidia.com>
8  *
9  *
10  *  This driver is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This driver is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24
25 #include <linux/init.h>
26 #include <linux/delay.h>
27 #include <linux/slab.h>
28 #include <sound/core.h>
29 #include "hda_codec.h"
30 #include "hda_local.h"
31
32 struct nvhdmi_spec {
33         struct hda_multi_out multiout;
34
35         struct hda_pcm pcm_rec;
36 };
37
38 #define Nv_VERB_SET_Channel_Allocation          0xF79
39 #define Nv_VERB_SET_Info_Frame_Checksum         0xF7A
40 #define Nv_VERB_SET_Audio_Protection_On         0xF98
41 #define Nv_VERB_SET_Audio_Protection_Off        0xF99
42
43 #define Nv_Master_Convert_nid   0x04
44 #define Nv_Master_Pin_nid       0x05
45
46 static hda_nid_t nvhdmi_convert_nids[4] = {
47         /*front, rear, clfe, rear_surr */
48         0x6, 0x8, 0xa, 0xc,
49 };
50
51 static struct hda_verb nvhdmi_basic_init[] = {
52         /* set audio protect on */
53         { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
54         /* enable digital output on pin widget */
55         { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
56         { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
57         { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
58         { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
59         { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
60         {} /* terminator */
61 };
62
63 /*
64  * Controls
65  */
66 static int nvhdmi_build_controls(struct hda_codec *codec)
67 {
68         struct nvhdmi_spec *spec = codec->spec;
69         int err;
70
71         err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
72         if (err < 0)
73                 return err;
74
75         return 0;
76 }
77
78 static int nvhdmi_init(struct hda_codec *codec)
79 {
80         snd_hda_sequence_write(codec, nvhdmi_basic_init);
81         return 0;
82 }
83
84 /*
85  * Digital out
86  */
87 static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
88                                         struct hda_codec *codec,
89                                         struct snd_pcm_substream *substream)
90 {
91         struct nvhdmi_spec *spec = codec->spec;
92         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
93 }
94
95 static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
96                                         struct hda_codec *codec,
97                                         struct snd_pcm_substream *substream)
98 {
99         struct nvhdmi_spec *spec = codec->spec;
100         int i;
101
102         snd_hda_codec_write(codec, Nv_Master_Convert_nid,
103                         0, AC_VERB_SET_CHANNEL_STREAMID, 0);
104         for (i = 0; i < 4; i++) {
105                 /* set the stream id */
106                 snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
107                                 AC_VERB_SET_CHANNEL_STREAMID, 0);
108                 /* set the stream format */
109                 snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
110                                 AC_VERB_SET_STREAM_FORMAT, 0);
111         }
112
113         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
114 }
115
116 static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
117                                         struct hda_codec *codec,
118                                         struct snd_pcm_substream *substream)
119 {
120         struct nvhdmi_spec *spec = codec->spec;
121         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
122 }
123
124 static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
125                                         struct hda_codec *codec,
126                                         unsigned int stream_tag,
127                                         unsigned int format,
128                                         struct snd_pcm_substream *substream)
129 {
130         int chs;
131         unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
132         int i;
133
134         mutex_lock(&codec->spdif_mutex);
135
136         chs = substream->runtime->channels;
137         chan = chs ? (chs - 1) : 1;
138
139         switch (chs) {
140         default:
141         case 0:
142         case 2:
143                 chanmask = 0x00;
144                 break;
145         case 4:
146                 chanmask = 0x08;
147                 break;
148         case 6:
149                 chanmask = 0x0b;
150                 break;
151         case 8:
152                 chanmask = 0x13;
153                 break;
154         }
155         dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
156         dataDCC2 = 0x2;
157
158         /* set the Audio InforFrame Channel Allocation */
159         snd_hda_codec_write(codec, 0x1, 0,
160                         Nv_VERB_SET_Channel_Allocation, chanmask);
161
162         /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
163         if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
164                 snd_hda_codec_write(codec,
165                                 Nv_Master_Convert_nid,
166                                 0,
167                                 AC_VERB_SET_DIGI_CONVERT_1,
168                                 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
169
170         /* set the stream id */
171         snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
172                         AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
173
174         /* set the stream format */
175         snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
176                         AC_VERB_SET_STREAM_FORMAT, format);
177
178         /* turn on again (if needed) */
179         /* enable and set the channel status audio/data flag */
180         if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
181                 snd_hda_codec_write(codec,
182                                 Nv_Master_Convert_nid,
183                                 0,
184                                 AC_VERB_SET_DIGI_CONVERT_1,
185                                 codec->spdif_ctls & 0xff);
186                 snd_hda_codec_write(codec,
187                                 Nv_Master_Convert_nid,
188                                 0,
189                                 AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
190         }
191
192         for (i = 0; i < 4; i++) {
193                 if (chs == 2)
194                         channel_id = 0;
195                 else
196                         channel_id = i * 2;
197
198                 /* turn off SPDIF once;
199                  *otherwise the IEC958 bits won't be updated
200                  */
201                 if (codec->spdif_status_reset &&
202                 (codec->spdif_ctls & AC_DIG1_ENABLE))
203                         snd_hda_codec_write(codec,
204                                 nvhdmi_convert_nids[i],
205                                 0,
206                                 AC_VERB_SET_DIGI_CONVERT_1,
207                                 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
208                 /* set the stream id */
209                 snd_hda_codec_write(codec,
210                                 nvhdmi_convert_nids[i],
211                                 0,
212                                 AC_VERB_SET_CHANNEL_STREAMID,
213                                 (stream_tag << 4) | channel_id);
214                 /* set the stream format */
215                 snd_hda_codec_write(codec,
216                                 nvhdmi_convert_nids[i],
217                                 0,
218                                 AC_VERB_SET_STREAM_FORMAT,
219                                 format);
220                 /* turn on again (if needed) */
221                 /* enable and set the channel status audio/data flag */
222                 if (codec->spdif_status_reset &&
223                 (codec->spdif_ctls & AC_DIG1_ENABLE)) {
224                         snd_hda_codec_write(codec,
225                                         nvhdmi_convert_nids[i],
226                                         0,
227                                         AC_VERB_SET_DIGI_CONVERT_1,
228                                         codec->spdif_ctls & 0xff);
229                         snd_hda_codec_write(codec,
230                                         nvhdmi_convert_nids[i],
231                                         0,
232                                         AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
233                 }
234         }
235
236         /* set the Audio Info Frame Checksum */
237         snd_hda_codec_write(codec, 0x1, 0,
238                         Nv_VERB_SET_Info_Frame_Checksum,
239                         (0x71 - chan - chanmask));
240
241         mutex_unlock(&codec->spdif_mutex);
242         return 0;
243 }
244
245 static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
246                                         struct hda_codec *codec,
247                                         unsigned int stream_tag,
248                                         unsigned int format,
249                                         struct snd_pcm_substream *substream)
250 {
251         struct nvhdmi_spec *spec = codec->spec;
252         return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
253                                         format, substream);
254 }
255
256 static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
257         .substreams = 1,
258         .channels_min = 2,
259         .channels_max = 8,
260         .nid = Nv_Master_Convert_nid,
261         .rates = SNDRV_PCM_RATE_48000,
262         .maxbps = 16,
263         .formats = SNDRV_PCM_FMTBIT_S16_LE,
264         .ops = {
265                 .open = nvhdmi_dig_playback_pcm_open,
266                 .close = nvhdmi_dig_playback_pcm_close_8ch,
267                 .prepare = nvhdmi_dig_playback_pcm_prepare_8ch
268         },
269 };
270
271 static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
272         .substreams = 1,
273         .channels_min = 2,
274         .channels_max = 2,
275         .nid = Nv_Master_Convert_nid,
276         .rates = SNDRV_PCM_RATE_48000,
277         .maxbps = 16,
278         .formats = SNDRV_PCM_FMTBIT_S16_LE,
279         .ops = {
280                 .open = nvhdmi_dig_playback_pcm_open,
281                 .close = nvhdmi_dig_playback_pcm_close_2ch,
282                 .prepare = nvhdmi_dig_playback_pcm_prepare_2ch
283         },
284 };
285
286 static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
287 {
288         struct nvhdmi_spec *spec = codec->spec;
289         struct hda_pcm *info = &spec->pcm_rec;
290
291         codec->num_pcms = 1;
292         codec->pcm_info = info;
293
294         info->name = "NVIDIA HDMI";
295         info->pcm_type = HDA_PCM_TYPE_HDMI;
296         info->stream[SNDRV_PCM_STREAM_PLAYBACK]
297                                         = nvhdmi_pcm_digital_playback_8ch;
298
299         return 0;
300 }
301
302 static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
303 {
304         struct nvhdmi_spec *spec = codec->spec;
305         struct hda_pcm *info = &spec->pcm_rec;
306
307         codec->num_pcms = 1;
308         codec->pcm_info = info;
309
310         info->name = "NVIDIA HDMI";
311         info->pcm_type = HDA_PCM_TYPE_HDMI;
312         info->stream[SNDRV_PCM_STREAM_PLAYBACK]
313                                         = nvhdmi_pcm_digital_playback_2ch;
314
315         return 0;
316 }
317
318 static void nvhdmi_free(struct hda_codec *codec)
319 {
320         kfree(codec->spec);
321 }
322
323 static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
324         .build_controls = nvhdmi_build_controls,
325         .build_pcms = nvhdmi_build_pcms_8ch,
326         .init = nvhdmi_init,
327         .free = nvhdmi_free,
328 };
329
330 static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
331         .build_controls = nvhdmi_build_controls,
332         .build_pcms = nvhdmi_build_pcms_2ch,
333         .init = nvhdmi_init,
334         .free = nvhdmi_free,
335 };
336
337 static int patch_nvhdmi_8ch(struct hda_codec *codec)
338 {
339         struct nvhdmi_spec *spec;
340
341         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
342         if (spec == NULL)
343                 return -ENOMEM;
344
345         codec->spec = spec;
346
347         spec->multiout.num_dacs = 0;  /* no analog */
348         spec->multiout.max_channels = 8;
349         spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
350
351         codec->patch_ops = nvhdmi_patch_ops_8ch;
352
353         return 0;
354 }
355
356 static int patch_nvhdmi_2ch(struct hda_codec *codec)
357 {
358         struct nvhdmi_spec *spec;
359
360         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
361         if (spec == NULL)
362                 return -ENOMEM;
363
364         codec->spec = spec;
365
366         spec->multiout.num_dacs = 0;  /* no analog */
367         spec->multiout.max_channels = 2;
368         spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
369
370         codec->patch_ops = nvhdmi_patch_ops_2ch;
371
372         return 0;
373 }
374
375 /*
376  * patch entries
377  */
378 static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
379         { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
380         { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
381         { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
382         { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
383         { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
384         {} /* terminator */
385 };
386
387 MODULE_ALIAS("snd-hda-codec-id:10de0002");
388 MODULE_ALIAS("snd-hda-codec-id:10de0006");
389 MODULE_ALIAS("snd-hda-codec-id:10de0007");
390 MODULE_ALIAS("snd-hda-codec-id:10de0067");
391 MODULE_ALIAS("snd-hda-codec-id:10de8001");
392
393 MODULE_LICENSE("GPL");
394 MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
395
396 static struct hda_codec_preset_list nvhdmi_list = {
397         .preset = snd_hda_preset_nvhdmi,
398         .owner = THIS_MODULE,
399 };
400
401 static int __init patch_nvhdmi_init(void)
402 {
403         return snd_hda_add_codec_preset(&nvhdmi_list);
404 }
405
406 static void __exit patch_nvhdmi_exit(void)
407 {
408         snd_hda_delete_codec_preset(&nvhdmi_list);
409 }
410
411 module_init(patch_nvhdmi_init)
412 module_exit(patch_nvhdmi_exit)