~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/sound/pci/hda/patch_atihdmi.c

Version: ~ [ 2.4.21-47.EL ] ~ [ 2.6.9-67.EL ] ~ [ 2.6.18-128.el5 ] ~ [ 2.6.18-164.el5 ] ~
Architecture: ~ [ i386 ] ~ [ x86_64 ] ~

  1 /*
  2  * Universal Interface for Intel High Definition Audio Codec
  3  *
  4  * HD audio interface patch for ATI HDMI codecs
  5  *
  6  * Copyright (c) 2006 ATI Technologies Inc.
  7  *
  8  *
  9  *  This driver is free software; you can redistribute it and/or modify
 10  *  it under the terms of the GNU General Public License as published by
 11  *  the Free Software Foundation; either version 2 of the License, or
 12  *  (at your option) any later version.
 13  *
 14  *  This driver is distributed in the hope that it will be useful,
 15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17  *  GNU General Public License for more details.
 18  *
 19  *  You should have received a copy of the GNU General Public License
 20  *  along with this program; if not, write to the Free Software
 21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 22  */
 23 
 24 #include <sound/driver.h>
 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 #include "hda_patch.h"
 32 
 33 struct atihdmi_spec {
 34         struct hda_multi_out multiout;
 35 
 36         struct hda_pcm pcm_rec;
 37 };
 38 
 39 static struct hda_verb atihdmi_basic_init[] = {
 40         /* enable digital output on pin widget */
 41         { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 42         {} /* terminator */
 43 };
 44 
 45 /*
 46  * Controls
 47  */
 48 static int atihdmi_build_controls(struct hda_codec *codec)
 49 {
 50         struct atihdmi_spec *spec = codec->spec;
 51         int err;
 52 
 53         err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
 54         if (err < 0)
 55                 return err;
 56 
 57         return 0;
 58 }
 59 
 60 static int atihdmi_init(struct hda_codec *codec)
 61 {
 62         snd_hda_sequence_write(codec, atihdmi_basic_init);
 63         /* SI codec requires to unmute the pin */
 64         if (get_wcaps(codec, 0x03) & AC_WCAP_OUT_AMP)
 65                 snd_hda_codec_write(codec, 0x03, 0, AC_VERB_SET_AMP_GAIN_MUTE,
 66                                     AMP_OUT_UNMUTE);
 67         return 0;
 68 }
 69 
 70 /*
 71  * Digital out
 72  */
 73 static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
 74                                      struct hda_codec *codec,
 75                                      struct snd_pcm_substream *substream)
 76 {
 77         struct atihdmi_spec *spec = codec->spec;
 78         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 79 }
 80 
 81 static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 82                                       struct hda_codec *codec,
 83                                       struct snd_pcm_substream *substream)
 84 {
 85         struct atihdmi_spec *spec = codec->spec;
 86         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 87 }
 88 
 89 static int atihdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
 90                                             struct hda_codec *codec,
 91                                             unsigned int stream_tag,
 92                                             unsigned int format,
 93                                             struct snd_pcm_substream *substream)
 94 {
 95         struct atihdmi_spec *spec = codec->spec;
 96         return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
 97                                              format, substream);
 98 }
 99 
100 static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
101         .substreams = 1,
102         .channels_min = 2,
103         .channels_max = 2,
104         .nid = 0x2, /* NID to query formats and rates and setup streams */
105         .ops = {
106                 .open = atihdmi_dig_playback_pcm_open,
107                 .close = atihdmi_dig_playback_pcm_close,
108                 .prepare = atihdmi_dig_playback_pcm_prepare
109         },
110 };
111 
112 static int atihdmi_build_pcms(struct hda_codec *codec)
113 {
114         struct atihdmi_spec *spec = codec->spec;
115         struct hda_pcm *info = &spec->pcm_rec;
116 
117         codec->num_pcms = 1;
118         codec->pcm_info = info;
119 
120         info->name = "ATI HDMI";
121         info->pcm_type = HDA_PCM_TYPE_HDMI;
122         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
123 
124         return 0;
125 }
126 
127 static void atihdmi_free(struct hda_codec *codec)
128 {
129         kfree(codec->spec);
130 }
131 
132 static struct hda_codec_ops atihdmi_patch_ops = {
133         .build_controls = atihdmi_build_controls,
134         .build_pcms = atihdmi_build_pcms,
135         .init = atihdmi_init,
136         .free = atihdmi_free,
137 };
138 
139 static int patch_atihdmi(struct hda_codec *codec)
140 {
141         struct atihdmi_spec *spec;
142 
143         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
144         if (spec == NULL)
145                 return -ENOMEM;
146 
147         codec->spec = spec;
148 
149         spec->multiout.num_dacs = 0;      /* no analog */
150         spec->multiout.max_channels = 2;
151         spec->multiout.dig_out_nid = 0x2; /* NID for copying analog to digital,
152                                            * seems to be unused in pure-digital
153                                            * case. */
154 
155         codec->patch_ops = atihdmi_patch_ops;
156 
157         return 0;
158 }
159 
160 /*
161  * patch entries
162  */
163 struct hda_codec_preset snd_hda_preset_atihdmi[] = {
164         { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
165         { .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
166         { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
167         { .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi },
168         { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi },
169         { .id = 0x17e80047, .name = "Chrontel HDMI",  .patch = patch_atihdmi },
170         {} /* terminator */
171 };
172 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.