aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_hdmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r--sound/pci/hda/patch_hdmi.c185
1 files changed, 180 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 5f44f60a6389..ef8a5627a281 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -592,7 +592,7 @@ static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index)
592static void eld_proc_free(struct hdmi_spec_per_pin *per_pin) 592static void eld_proc_free(struct hdmi_spec_per_pin *per_pin)
593{ 593{
594 if (!per_pin->codec->bus->shutdown && per_pin->proc_entry) { 594 if (!per_pin->codec->bus->shutdown && per_pin->proc_entry) {
595 snd_device_free(per_pin->codec->card, per_pin->proc_entry); 595 snd_info_free_entry(per_pin->proc_entry);
596 per_pin->proc_entry = NULL; 596 per_pin->proc_entry = NULL;
597 } 597 }
598} 598}
@@ -2049,9 +2049,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
2049 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { 2049 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
2050 struct hda_pcm *info; 2050 struct hda_pcm *info;
2051 struct hda_pcm_stream *pstr; 2051 struct hda_pcm_stream *pstr;
2052 struct hdmi_spec_per_pin *per_pin;
2053 2052
2054 per_pin = get_pin(spec, pin_idx);
2055 info = snd_hda_codec_pcm_new(codec, "HDMI %d", pin_idx); 2053 info = snd_hda_codec_pcm_new(codec, "HDMI %d", pin_idx);
2056 if (!info) 2054 if (!info)
2057 return -ENOMEM; 2055 return -ENOMEM;
@@ -2081,7 +2079,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
2081 strncat(hdmi_str, " Phantom", 2079 strncat(hdmi_str, " Phantom",
2082 sizeof(hdmi_str) - strlen(hdmi_str) - 1); 2080 sizeof(hdmi_str) - strlen(hdmi_str) - 1);
2083 2081
2084 return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0); 2082 return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str);
2085} 2083}
2086 2084
2087static int generic_hdmi_build_controls(struct hda_codec *codec) 2085static int generic_hdmi_build_controls(struct hda_codec *codec)
@@ -2335,6 +2333,15 @@ static int patch_generic_hdmi(struct hda_codec *codec)
2335 intel_haswell_fixup_enable_dp12(codec); 2333 intel_haswell_fixup_enable_dp12(codec);
2336 } 2334 }
2337 2335
2336 /* For Valleyview/Cherryview, only the display codec is in the display
2337 * power well and can use link_power ops to request/release the power.
2338 * For Haswell/Broadwell, the controller is also in the power well and
2339 * can cover the codec power request, and so need not set this flag.
2340 * For previous platforms, there is no such power well feature.
2341 */
2342 if (is_valleyview_plus(codec))
2343 codec->core.link_power_control = 1;
2344
2338 if (is_haswell_plus(codec) || is_valleyview_plus(codec)) 2345 if (is_haswell_plus(codec) || is_valleyview_plus(codec))
2339 codec->depop_delay = 0; 2346 codec->depop_delay = 0;
2340 2347
@@ -2923,6 +2930,171 @@ static int patch_nvhdmi(struct hda_codec *codec)
2923} 2930}
2924 2931
2925/* 2932/*
2933 * The HDA codec on NVIDIA Tegra contains two scratch registers that are
2934 * accessed using vendor-defined verbs. These registers can be used for
2935 * interoperability between the HDA and HDMI drivers.
2936 */
2937
2938/* Audio Function Group node */
2939#define NVIDIA_AFG_NID 0x01
2940
2941/*
2942 * The SCRATCH0 register is used to notify the HDMI codec of changes in audio
2943 * format. On Tegra, bit 31 is used as a trigger that causes an interrupt to
2944 * be raised in the HDMI codec. The remainder of the bits is arbitrary. This
2945 * implementation stores the HDA format (see AC_FMT_*) in bits [15:0] and an
2946 * additional bit (at position 30) to signal the validity of the format.
2947 *
2948 * | 31 | 30 | 29 16 | 15 0 |
2949 * +---------+-------+--------+--------+
2950 * | TRIGGER | VALID | UNUSED | FORMAT |
2951 * +-----------------------------------|
2952 *
2953 * Note that for the trigger bit to take effect it needs to change value
2954 * (i.e. it needs to be toggled).
2955 */
2956#define NVIDIA_GET_SCRATCH0 0xfa6
2957#define NVIDIA_SET_SCRATCH0_BYTE0 0xfa7
2958#define NVIDIA_SET_SCRATCH0_BYTE1 0xfa8
2959#define NVIDIA_SET_SCRATCH0_BYTE2 0xfa9
2960#define NVIDIA_SET_SCRATCH0_BYTE3 0xfaa
2961#define NVIDIA_SCRATCH_TRIGGER (1 << 7)
2962#define NVIDIA_SCRATCH_VALID (1 << 6)
2963
2964#define NVIDIA_GET_SCRATCH1 0xfab
2965#define NVIDIA_SET_SCRATCH1_BYTE0 0xfac
2966#define NVIDIA_SET_SCRATCH1_BYTE1 0xfad
2967#define NVIDIA_SET_SCRATCH1_BYTE2 0xfae
2968#define NVIDIA_SET_SCRATCH1_BYTE3 0xfaf
2969
2970/*
2971 * The format parameter is the HDA audio format (see AC_FMT_*). If set to 0,
2972 * the format is invalidated so that the HDMI codec can be disabled.
2973 */
2974static void tegra_hdmi_set_format(struct hda_codec *codec, unsigned int format)
2975{
2976 unsigned int value;
2977
2978 /* bits [31:30] contain the trigger and valid bits */
2979 value = snd_hda_codec_read(codec, NVIDIA_AFG_NID, 0,
2980 NVIDIA_GET_SCRATCH0, 0);
2981 value = (value >> 24) & 0xff;
2982
2983 /* bits [15:0] are used to store the HDA format */
2984 snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0,
2985 NVIDIA_SET_SCRATCH0_BYTE0,
2986 (format >> 0) & 0xff);
2987 snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0,
2988 NVIDIA_SET_SCRATCH0_BYTE1,
2989 (format >> 8) & 0xff);
2990
2991 /* bits [16:24] are unused */
2992 snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0,
2993 NVIDIA_SET_SCRATCH0_BYTE2, 0);
2994
2995 /*
2996 * Bit 30 signals that the data is valid and hence that HDMI audio can
2997 * be enabled.
2998 */
2999 if (format == 0)
3000 value &= ~NVIDIA_SCRATCH_VALID;
3001 else
3002 value |= NVIDIA_SCRATCH_VALID;
3003
3004 /*
3005 * Whenever the trigger bit is toggled, an interrupt is raised in the
3006 * HDMI codec. The HDMI driver will use that as trigger to update its
3007 * configuration.
3008 */
3009 value ^= NVIDIA_SCRATCH_TRIGGER;
3010
3011 snd_hda_codec_write(codec, NVIDIA_AFG_NID, 0,
3012 NVIDIA_SET_SCRATCH0_BYTE3, value);
3013}
3014
3015static int tegra_hdmi_pcm_prepare(struct hda_pcm_stream *hinfo,
3016 struct hda_codec *codec,
3017 unsigned int stream_tag,
3018 unsigned int format,
3019 struct snd_pcm_substream *substream)
3020{
3021 int err;
3022
3023 err = generic_hdmi_playback_pcm_prepare(hinfo, codec, stream_tag,
3024 format, substream);
3025 if (err < 0)
3026 return err;
3027
3028 /* notify the HDMI codec of the format change */
3029 tegra_hdmi_set_format(codec, format);
3030
3031 return 0;
3032}
3033
3034static int tegra_hdmi_pcm_cleanup(struct hda_pcm_stream *hinfo,
3035 struct hda_codec *codec,
3036 struct snd_pcm_substream *substream)
3037{
3038 /* invalidate the format in the HDMI codec */
3039 tegra_hdmi_set_format(codec, 0);
3040
3041 return generic_hdmi_playback_pcm_cleanup(hinfo, codec, substream);
3042}
3043
3044static struct hda_pcm *hda_find_pcm_by_type(struct hda_codec *codec, int type)
3045{
3046 struct hdmi_spec *spec = codec->spec;
3047 unsigned int i;
3048
3049 for (i = 0; i < spec->num_pins; i++) {
3050 struct hda_pcm *pcm = get_pcm_rec(spec, i);
3051
3052 if (pcm->pcm_type == type)
3053 return pcm;
3054 }
3055
3056 return NULL;
3057}
3058
3059static int tegra_hdmi_build_pcms(struct hda_codec *codec)
3060{
3061 struct hda_pcm_stream *stream;
3062 struct hda_pcm *pcm;
3063 int err;
3064
3065 err = generic_hdmi_build_pcms(codec);
3066 if (err < 0)
3067 return err;
3068
3069 pcm = hda_find_pcm_by_type(codec, HDA_PCM_TYPE_HDMI);
3070 if (!pcm)
3071 return -ENODEV;
3072
3073 /*
3074 * Override ->prepare() and ->cleanup() operations to notify the HDMI
3075 * codec about format changes.
3076 */
3077 stream = &pcm->stream[SNDRV_PCM_STREAM_PLAYBACK];
3078 stream->ops.prepare = tegra_hdmi_pcm_prepare;
3079 stream->ops.cleanup = tegra_hdmi_pcm_cleanup;
3080
3081 return 0;
3082}
3083
3084static int patch_tegra_hdmi(struct hda_codec *codec)
3085{
3086 int err;
3087
3088 err = patch_generic_hdmi(codec);
3089 if (err)
3090 return err;
3091
3092 codec->patch_ops.build_pcms = tegra_hdmi_build_pcms;
3093
3094 return 0;
3095}
3096
3097/*
2926 * ATI/AMD-specific implementations 3098 * ATI/AMD-specific implementations
2927 */ 3099 */
2928 3100
@@ -3321,7 +3493,10 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
3321{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi }, 3493{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi },
3322{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi }, 3494{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi },
3323{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi }, 3495{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi },
3324{ .id = 0x10de0028, .name = "Tegra12x HDMI", .patch = patch_nvhdmi }, 3496{ .id = 0x10de0020, .name = "Tegra30 HDMI", .patch = patch_tegra_hdmi },
3497{ .id = 0x10de0022, .name = "Tegra114 HDMI", .patch = patch_tegra_hdmi },
3498{ .id = 0x10de0028, .name = "Tegra124 HDMI", .patch = patch_tegra_hdmi },
3499{ .id = 0x10de0029, .name = "Tegra210 HDMI/DP", .patch = patch_tegra_hdmi },
3325{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi }, 3500{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi },
3326{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi }, 3501{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi },
3327{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi }, 3502{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi },