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.c92
1 files changed, 81 insertions, 11 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 31df7747990d..f29b97b5de8f 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -31,10 +31,15 @@
31#include <linux/init.h> 31#include <linux/init.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/moduleparam.h>
34#include <sound/core.h> 35#include <sound/core.h>
35#include "hda_codec.h" 36#include "hda_codec.h"
36#include "hda_local.h" 37#include "hda_local.h"
37 38
39static bool static_hdmi_pcm;
40module_param(static_hdmi_pcm, bool, 0644);
41MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
42
38/* 43/*
39 * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device 44 * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
40 * could support two independent pipes, each of them can be connected to one or 45 * could support two independent pipes, each of them can be connected to one or
@@ -827,7 +832,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
827 *codec_pars = *hinfo; 832 *codec_pars = *hinfo;
828 833
829 eld = &spec->sink_eld[idx]; 834 eld = &spec->sink_eld[idx];
830 if (eld->sad_count > 0) { 835 if (!static_hdmi_pcm && eld->eld_valid && eld->sad_count > 0) {
831 hdmi_eld_update_pcm_info(eld, hinfo, codec_pars); 836 hdmi_eld_update_pcm_info(eld, hinfo, codec_pars);
832 if (hinfo->channels_min > hinfo->channels_max || 837 if (hinfo->channels_min > hinfo->channels_max ||
833 !hinfo->rates || !hinfo->formats) 838 !hinfo->rates || !hinfo->formats)
@@ -904,23 +909,28 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
904 spec->pin[spec->num_pins] = pin_nid; 909 spec->pin[spec->num_pins] = pin_nid;
905 spec->num_pins++; 910 spec->num_pins++;
906 911
907 /*
908 * It is assumed that converter nodes come first in the node list and
909 * hence have been registered and usable now.
910 */
911 return hdmi_read_pin_conn(codec, pin_nid); 912 return hdmi_read_pin_conn(codec, pin_nid);
912} 913}
913 914
914static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) 915static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
915{ 916{
917 int i, found_pin = 0;
916 struct hdmi_spec *spec = codec->spec; 918 struct hdmi_spec *spec = codec->spec;
917 919
918 if (spec->num_cvts >= MAX_HDMI_CVTS) { 920 for (i = 0; i < spec->num_pins; i++)
919 snd_printk(KERN_WARNING 921 if (nid == spec->pin_cvt[i]) {
920 "HDMI: no space for converter %d\n", nid); 922 found_pin = 1;
921 return -E2BIG; 923 break;
924 }
925
926 if (!found_pin) {
927 snd_printdd("HDMI: Skipping node %d (no connection)\n", nid);
928 return -EINVAL;
922 } 929 }
923 930
931 if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS))
932 return -E2BIG;
933
924 spec->cvt[spec->num_cvts] = nid; 934 spec->cvt[spec->num_cvts] = nid;
925 spec->num_cvts++; 935 spec->num_cvts++;
926 936
@@ -931,6 +941,8 @@ static int hdmi_parse_codec(struct hda_codec *codec)
931{ 941{
932 hda_nid_t nid; 942 hda_nid_t nid;
933 int i, nodes; 943 int i, nodes;
944 int num_tmp_cvts = 0;
945 hda_nid_t tmp_cvt[MAX_HDMI_CVTS];
934 946
935 nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); 947 nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
936 if (!nid || nodes < 0) { 948 if (!nid || nodes < 0) {
@@ -941,6 +953,7 @@ static int hdmi_parse_codec(struct hda_codec *codec)
941 for (i = 0; i < nodes; i++, nid++) { 953 for (i = 0; i < nodes; i++, nid++) {
942 unsigned int caps; 954 unsigned int caps;
943 unsigned int type; 955 unsigned int type;
956 unsigned int config;
944 957
945 caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); 958 caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
946 type = get_wcaps_type(caps); 959 type = get_wcaps_type(caps);
@@ -950,17 +963,32 @@ static int hdmi_parse_codec(struct hda_codec *codec)
950 963
951 switch (type) { 964 switch (type) {
952 case AC_WID_AUD_OUT: 965 case AC_WID_AUD_OUT:
953 hdmi_add_cvt(codec, nid); 966 if (num_tmp_cvts >= MAX_HDMI_CVTS) {
967 snd_printk(KERN_WARNING
968 "HDMI: no space for converter %d\n", nid);
969 continue;
970 }
971 tmp_cvt[num_tmp_cvts] = nid;
972 num_tmp_cvts++;
954 break; 973 break;
955 case AC_WID_PIN: 974 case AC_WID_PIN:
956 caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); 975 caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
957 if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) 976 if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
958 continue; 977 continue;
978
979 config = snd_hda_codec_read(codec, nid, 0,
980 AC_VERB_GET_CONFIG_DEFAULT, 0);
981 if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
982 continue;
983
959 hdmi_add_pin(codec, nid); 984 hdmi_add_pin(codec, nid);
960 break; 985 break;
961 } 986 }
962 } 987 }
963 988
989 for (i = 0; i < num_tmp_cvts; i++)
990 hdmi_add_cvt(codec, tmp_cvt[i]);
991
964 /* 992 /*
965 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event 993 * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
966 * can be lost and presence sense verb will become inaccurate if the 994 * can be lost and presence sense verb will become inaccurate if the
@@ -1165,11 +1193,53 @@ static int nvhdmi_7x_init(struct hda_codec *codec)
1165 return 0; 1193 return 0;
1166} 1194}
1167 1195
1196static unsigned int channels_2_6_8[] = {
1197 2, 6, 8
1198};
1199
1200static unsigned int channels_2_8[] = {
1201 2, 8
1202};
1203
1204static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = {
1205 .count = ARRAY_SIZE(channels_2_6_8),
1206 .list = channels_2_6_8,
1207 .mask = 0,
1208};
1209
1210static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = {
1211 .count = ARRAY_SIZE(channels_2_8),
1212 .list = channels_2_8,
1213 .mask = 0,
1214};
1215
1168static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, 1216static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo,
1169 struct hda_codec *codec, 1217 struct hda_codec *codec,
1170 struct snd_pcm_substream *substream) 1218 struct snd_pcm_substream *substream)
1171{ 1219{
1172 struct hdmi_spec *spec = codec->spec; 1220 struct hdmi_spec *spec = codec->spec;
1221 struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL;
1222
1223 switch (codec->preset->id) {
1224 case 0x10de0002:
1225 case 0x10de0003:
1226 case 0x10de0005:
1227 case 0x10de0006:
1228 hw_constraints_channels = &hw_constraints_2_8_channels;
1229 break;
1230 case 0x10de0007:
1231 hw_constraints_channels = &hw_constraints_2_6_8_channels;
1232 break;
1233 default:
1234 break;
1235 }
1236
1237 if (hw_constraints_channels != NULL) {
1238 snd_pcm_hw_constraint_list(substream->runtime, 0,
1239 SNDRV_PCM_HW_PARAM_CHANNELS,
1240 hw_constraints_channels);
1241 }
1242
1173 return snd_hda_multi_out_dig_open(codec, &spec->multiout); 1243 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
1174} 1244}
1175 1245
@@ -1532,7 +1602,7 @@ static struct hda_codec_preset snd_hda_preset_hdmi[] = {
1532{ .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, 1602{ .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi },
1533{ .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, 1603{ .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi },
1534{ .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, 1604{ .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi },
1535{ .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi }, 1605{ .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_generic_hdmi },
1536{ .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, 1606{ .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi },
1537{ .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, 1607{ .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi },
1538{ .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, 1608{ .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi },