diff options
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 185 |
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) | |||
592 | static void eld_proc_free(struct hdmi_spec_per_pin *per_pin) | 592 | static 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 | ||
2087 | static int generic_hdmi_build_controls(struct hda_codec *codec) | 2085 | static 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 | */ | ||
2974 | static 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 | |||
3015 | static 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 | |||
3034 | static 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 | |||
3044 | static 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 | |||
3059 | static 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 | |||
3084 | static 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 }, |