linux/sound/pci/hda/patch_intelhdmi.c
<<
>>
Prefs
   1/*
   2 *
   3 *  patch_intelhdmi.c - Patch for Intel HDMI codecs
   4 *
   5 *  Copyright(c) 2008 Intel Corporation. All rights reserved.
   6 *
   7 *  Authors:
   8 *                      Jiang Zhe <zhe.jiang@intel.com>
   9 *                      Wu Fengguang <wfg@linux.intel.com>
  10 *
  11 *  Maintained by:
  12 *                      Wu Fengguang <wfg@linux.intel.com>
  13 *
  14 *  This program is free software; you can redistribute it and/or modify it
  15 *  under the terms of the GNU General Public License as published by the Free
  16 *  Software Foundation; either version 2 of the License, or (at your option)
  17 *  any later version.
  18 *
  19 *  This program is distributed in the hope that it will be useful, but
  20 *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  21 *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  22 *  for more details.
  23 *
  24 *  You should have received a copy of the GNU General Public License
  25 *  along with this program; if not, write to the Free Software Foundation,
  26 *  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  27 */
  28
  29#include <linux/init.h>
  30#include <linux/delay.h>
  31#include <linux/slab.h>
  32#include <sound/core.h>
  33#include "hda_codec.h"
  34#include "hda_local.h"
  35
  36/*
  37 * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
  38 * could support two independent pipes, each of them can be connected to one or
  39 * more ports (DVI, HDMI or DisplayPort).
  40 *
  41 * The HDA correspondence of pipes/ports are converter/pin nodes.
  42 */
  43#define MAX_HDMI_CVTS   3
  44#define MAX_HDMI_PINS   3
  45
  46#include "patch_hdmi.c"
  47
  48static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
  49        "INTEL HDMI 0",
  50        "INTEL HDMI 1",
  51        "INTEL HDMI 2",
  52};
  53
  54/*
  55 * HDMI callbacks
  56 */
  57
  58static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
  59                                           struct hda_codec *codec,
  60                                           unsigned int stream_tag,
  61                                           unsigned int format,
  62                                           struct snd_pcm_substream *substream)
  63{
  64        hdmi_set_channel_count(codec, hinfo->nid,
  65                               substream->runtime->channels);
  66
  67        hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
  68
  69        hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
  70        return 0;
  71}
  72
  73static int intel_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
  74                                           struct hda_codec *codec,
  75                                           struct snd_pcm_substream *substream)
  76{
  77        return 0;
  78}
  79
  80static struct hda_pcm_stream intel_hdmi_pcm_playback = {
  81        .substreams = 1,
  82        .channels_min = 2,
  83        .ops = {
  84                .prepare = intel_hdmi_playback_pcm_prepare,
  85                .cleanup = intel_hdmi_playback_pcm_cleanup,
  86        },
  87};
  88
  89static int intel_hdmi_build_pcms(struct hda_codec *codec)
  90{
  91        struct hdmi_spec *spec = codec->spec;
  92        struct hda_pcm *info = spec->pcm_rec;
  93        int i;
  94
  95        codec->num_pcms = spec->num_cvts;
  96        codec->pcm_info = info;
  97
  98        for (i = 0; i < codec->num_pcms; i++, info++) {
  99                unsigned int chans;
 100
 101                chans = get_wcaps(codec, spec->cvt[i]);
 102                chans = get_wcaps_channels(chans);
 103
 104                info->name = intel_hdmi_pcm_names[i];
 105                info->pcm_type = HDA_PCM_TYPE_HDMI;
 106                info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
 107                                                        intel_hdmi_pcm_playback;
 108                info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
 109                info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
 110        }
 111
 112        return 0;
 113}
 114
 115static int intel_hdmi_build_controls(struct hda_codec *codec)
 116{
 117        struct hdmi_spec *spec = codec->spec;
 118        int err;
 119        int i;
 120
 121        for (i = 0; i < codec->num_pcms; i++) {
 122                err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]);
 123                if (err < 0)
 124                        return err;
 125        }
 126
 127        return 0;
 128}
 129
 130static int intel_hdmi_init(struct hda_codec *codec)
 131{
 132        struct hdmi_spec *spec = codec->spec;
 133        int i;
 134
 135        for (i = 0; spec->pin[i]; i++) {
 136                hdmi_enable_output(codec, spec->pin[i]);
 137                snd_hda_codec_write(codec, spec->pin[i], 0,
 138                                    AC_VERB_SET_UNSOLICITED_ENABLE,
 139                                    AC_USRSP_EN | spec->pin[i]);
 140        }
 141        return 0;
 142}
 143
 144static void intel_hdmi_free(struct hda_codec *codec)
 145{
 146        struct hdmi_spec *spec = codec->spec;
 147        int i;
 148
 149        for (i = 0; i < spec->num_pins; i++)
 150                snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
 151
 152        kfree(spec);
 153}
 154
 155static struct hda_codec_ops intel_hdmi_patch_ops = {
 156        .init                   = intel_hdmi_init,
 157        .free                   = intel_hdmi_free,
 158        .build_pcms             = intel_hdmi_build_pcms,
 159        .build_controls         = intel_hdmi_build_controls,
 160        .unsol_event            = hdmi_unsol_event,
 161};
 162
 163static int patch_intel_hdmi(struct hda_codec *codec)
 164{
 165        struct hdmi_spec *spec;
 166        int i;
 167
 168        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
 169        if (spec == NULL)
 170                return -ENOMEM;
 171
 172        codec->spec = spec;
 173        if (hdmi_parse_codec(codec) < 0) {
 174                codec->spec = NULL;
 175                kfree(spec);
 176                return -EINVAL;
 177        }
 178        codec->patch_ops = intel_hdmi_patch_ops;
 179
 180        for (i = 0; i < spec->num_pins; i++)
 181                snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
 182
 183        init_channel_allocations();
 184
 185        return 0;
 186}
 187
 188static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
 189{ .id = 0x808629fb, .name = "Crestline HDMI",   .patch = patch_intel_hdmi },
 190{ .id = 0x80862801, .name = "Bearlake HDMI",    .patch = patch_intel_hdmi },
 191{ .id = 0x80862802, .name = "Cantiga HDMI",     .patch = patch_intel_hdmi },
 192{ .id = 0x80862803, .name = "Eaglelake HDMI",   .patch = patch_intel_hdmi },
 193{ .id = 0x80862804, .name = "IbexPeak HDMI",    .patch = patch_intel_hdmi },
 194{ .id = 0x80860054, .name = "IbexPeak HDMI",    .patch = patch_intel_hdmi },
 195{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_intel_hdmi },
 196{ .id = 0x10951392, .name = "SiI1392 HDMI",     .patch = patch_intel_hdmi },
 197{} /* terminator */
 198};
 199
 200MODULE_ALIAS("snd-hda-codec-id:808629fb");
 201MODULE_ALIAS("snd-hda-codec-id:80862801");
 202MODULE_ALIAS("snd-hda-codec-id:80862802");
 203MODULE_ALIAS("snd-hda-codec-id:80862803");
 204MODULE_ALIAS("snd-hda-codec-id:80862804");
 205MODULE_ALIAS("snd-hda-codec-id:80862805");
 206MODULE_ALIAS("snd-hda-codec-id:80860054");
 207MODULE_ALIAS("snd-hda-codec-id:10951392");
 208
 209MODULE_LICENSE("GPL");
 210MODULE_DESCRIPTION("Intel HDMI HD-audio codec");
 211
 212static struct hda_codec_preset_list intel_list = {
 213        .preset = snd_hda_preset_intelhdmi,
 214        .owner = THIS_MODULE,
 215};
 216
 217static int __init patch_intelhdmi_init(void)
 218{
 219        return snd_hda_add_codec_preset(&intel_list);
 220}
 221
 222static void __exit patch_intelhdmi_exit(void)
 223{
 224        snd_hda_delete_codec_preset(&intel_list);
 225}
 226
 227module_init(patch_intelhdmi_init)
 228module_exit(patch_intelhdmi_exit)
 229
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.