ALSA: hda: hdmi - fix port numbering for ICL and TGL platforms
[linux-2.6-block.git] / sound / pci / hda / patch_hdmi.c
index bca5de78e9ad577a08d885e1c519383797f4a3c9..dec90f931baefad50c8ebb94f2dd8bd72ae51173 100644 (file)
@@ -37,23 +37,6 @@ static bool static_hdmi_pcm;
 module_param(static_hdmi_pcm, bool, 0644);
 MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
 
-#define is_haswell(codec)  ((codec)->core.vendor_id == 0x80862807)
-#define is_broadwell(codec)    ((codec)->core.vendor_id == 0x80862808)
-#define is_skylake(codec) ((codec)->core.vendor_id == 0x80862809)
-#define is_broxton(codec) ((codec)->core.vendor_id == 0x8086280a)
-#define is_kabylake(codec) ((codec)->core.vendor_id == 0x8086280b)
-#define is_geminilake(codec) (((codec)->core.vendor_id == 0x8086280d) || \
-                               ((codec)->core.vendor_id == 0x80862800))
-#define is_cannonlake(codec) ((codec)->core.vendor_id == 0x8086280c)
-#define is_icelake(codec) ((codec)->core.vendor_id == 0x8086280f)
-#define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \
-                               || is_skylake(codec) || is_broxton(codec) \
-                               || is_kabylake(codec) || is_geminilake(codec) \
-                               || is_cannonlake(codec) || is_icelake(codec))
-#define is_valleyview(codec) ((codec)->core.vendor_id == 0x80862882)
-#define is_cherryview(codec) ((codec)->core.vendor_id == 0x80862883)
-#define is_valleyview_plus(codec) (is_valleyview(codec) || is_cherryview(codec))
-
 struct hdmi_spec_per_cvt {
        hda_nid_t cvt_nid;
        int assigned;
@@ -145,6 +128,7 @@ struct hdmi_spec {
        struct snd_array pins; /* struct hdmi_spec_per_pin */
        struct hdmi_pcm pcm_rec[16];
        struct mutex pcm_lock;
+       struct mutex bind_lock; /* for audio component binding */
        /* pcm_bitmap means which pcms have been assigned to pins*/
        unsigned long pcm_bitmap;
        int pcm_used;   /* counter of pcm_rec[] */
@@ -159,6 +143,7 @@ struct hdmi_spec {
 
        bool dyn_pin_out;
        bool dyn_pcm_assign;
+       bool intel_hsw_fixup;   /* apply Intel platform-specific fixups */
        /*
         * Non-generic VIA/NVIDIA specific
         */
@@ -922,7 +907,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
                return err;
        }
 
-       if (is_haswell_plus(codec)) {
+       if (spec->intel_hsw_fixup) {
 
                /*
                 * on recent platforms IEC Coding Type is required for HBR
@@ -1706,7 +1691,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
         * To simplify the implementation, malloc all
         * the virtual pins in the initialization statically
         */
-       if (is_haswell_plus(codec)) {
+       if (spec->intel_hsw_fixup) {
                /*
                 * On Intel platforms, device entries number is
                 * changed dynamically. If there is a DP MST
@@ -1755,7 +1740,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
                per_pin->dev_id = i;
                per_pin->non_pcm = false;
                snd_hda_set_dev_select(codec, pin_nid, i);
-               if (is_haswell_plus(codec))
+               if (spec->intel_hsw_fixup)
                        intel_haswell_fixup_connect_list(codec, pin_nid);
                err = hdmi_read_pin_conn(codec, pin_idx);
                if (err < 0)
@@ -2072,15 +2057,24 @@ static bool is_hdmi_pcm_attached(struct hdac_device *hdac, int pcm_idx)
 static int generic_hdmi_build_pcms(struct hda_codec *codec)
 {
        struct hdmi_spec *spec = codec->spec;
-       int idx;
+       int idx, pcm_num;
 
        /*
         * for non-mst mode, pcm number is the same as before
-        * for DP MST mode, pcm number is (nid number + dev_num - 1)
-        *  dev_num is the device entry number in a pin
-        *
+        * for DP MST mode without extra PCM, pcm number is same
+        * for DP MST mode with extra PCMs, pcm number is
+        *  (nid number + dev_num - 1)
+        * dev_num is the device entry number in a pin
         */
-       for (idx = 0; idx < spec->num_nids + spec->dev_num - 1; idx++) {
+
+       if (codec->mst_no_extra_pcms)
+               pcm_num = spec->num_nids;
+       else
+               pcm_num = spec->num_nids + spec->dev_num - 1;
+
+       codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num);
+
+       for (idx = 0; idx < pcm_num; idx++) {
                struct hda_pcm *info;
                struct hda_pcm_stream *pstr;
 
@@ -2258,7 +2252,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
        struct hdmi_spec *spec = codec->spec;
        int pin_idx;
 
-       mutex_lock(&spec->pcm_lock);
+       mutex_lock(&spec->bind_lock);
        spec->use_jack_detect = !codec->jackpoll_interval;
        for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
                struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
@@ -2275,7 +2269,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
                        snd_hda_jack_detect_enable_callback(codec, pin_nid,
                                                            jack_callback);
        }
-       mutex_unlock(&spec->pcm_lock);
+       mutex_unlock(&spec->bind_lock);
        return 0;
 }
 
@@ -2382,6 +2376,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec)
        spec->ops = generic_standard_hdmi_ops;
        spec->dev_num = 1;      /* initialize to 1 */
        mutex_init(&spec->pcm_lock);
+       mutex_init(&spec->bind_lock);
        snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);
 
        spec->chmap.ops.get_chmap = hdmi_get_chmap;
@@ -2451,7 +2446,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
        int i;
 
        spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops);
-       mutex_lock(&spec->pcm_lock);
+       mutex_lock(&spec->bind_lock);
        spec->use_acomp_notifier = use_acomp;
        spec->codec->relaxed_resume = use_acomp;
        /* reprogram each jack detection logic depending on the notifier */
@@ -2461,7 +2456,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
                                              get_pin(spec, i)->pin_nid,
                                              use_acomp);
        }
-       mutex_unlock(&spec->pcm_lock);
+       mutex_unlock(&spec->bind_lock);
 }
 
 /* enable / disable the notifier via master bind / unbind */
@@ -2669,7 +2664,7 @@ static int intel_pin2port(void *audio_ptr, int pin_nid)
         */
        for (i = 0; i < spec->port_num; i++) {
                if (pin_nid == spec->port_map[i])
-                       return i + 1;
+                       return i;
        }
 
        /* return -1 if pin number exceeds our expectation */
@@ -2689,9 +2684,9 @@ static int intel_port2pin(struct hda_codec *codec, int port)
                return port + intel_base_nid(codec) - 1;
        }
 
-       if (port < 1 || port > spec->port_num)
+       if (port < 0 || port >= spec->port_num)
                return 0;
-       return spec->port_map[port - 1];
+       return spec->port_map[port];
 }
 
 static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
@@ -2812,6 +2807,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
        spec->vendor_nid = vendor_nid;
        spec->port_map = port_map;
        spec->port_num = port_num;
+       spec->intel_hsw_fixup = true;
 
        intel_haswell_enable_all_pins(codec, true);
        intel_haswell_fixup_enable_dp12(codec);
@@ -2842,13 +2838,25 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec)
 {
        /*
         * pin to port mapping table where the value indicate the pin number and
-        * the index indicate the port number with 1 base.
+        * the index indicate the port number.
         */
-       static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb};
+       static const int map[] = {0x0, 0x4, 0x6, 0x8, 0xa, 0xb};
 
        return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map));
 }
 
+static int patch_i915_tgl_hdmi(struct hda_codec *codec)
+{
+       /*
+        * pin to port mapping table where the value indicate the pin number and
+        * the index indicate the port number.
+        */
+       static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+
+       return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map));
+}
+
+
 /* Intel Baytrail and Braswell; with eld notifier */
 static int patch_i915_byt_hdmi(struct hda_codec *codec)
 {
@@ -3474,6 +3482,8 @@ static int patch_nvhdmi(struct hda_codec *codec)
                nvhdmi_chmap_cea_alloc_validate_get_type;
        spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate;
 
+       codec->link_down_at_suspend = 1;
+
        generic_acomp_init(codec, &nvhdmi_audio_ops, nvhdmi_port2pin);
 
        return 0;
@@ -4149,6 +4159,7 @@ HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI",      patch_i915_hsw_hdmi),
 HDA_CODEC_ENTRY(0x8086280c, "Cannonlake HDMI", patch_i915_glk_hdmi),
 HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi),
 HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI",    patch_i915_icl_hdmi),
+HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI",  patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
 HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI",        patch_i915_byt_hdmi),
 HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI",   patch_i915_byt_hdmi),