diff options
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 330 |
1 files changed, 208 insertions, 122 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 78bd2e3722c7..bffde594e204 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -37,25 +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_tigerlake(codec) ((codec)->core.vendor_id == 0x80862812) -#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) \ - || is_tigerlake(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; @@ -99,16 +80,19 @@ struct hdmi_spec_per_pin { /* operations used by generic code that can be overridden by patches */ struct hdmi_ops { int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid, - unsigned char *buf, int *eld_size); + int dev_id, unsigned char *buf, int *eld_size); void (*pin_setup_infoframe)(struct hda_codec *codec, hda_nid_t pin_nid, + int dev_id, int ca, int active_channels, int conn_type); /* enable/disable HBR (HD passthrough) */ - int (*pin_hbr_setup)(struct hda_codec *codec, hda_nid_t pin_nid, bool hbr); + int (*pin_hbr_setup)(struct hda_codec *codec, hda_nid_t pin_nid, + int dev_id, bool hbr); int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid, - hda_nid_t pin_nid, u32 stream_tag, int format); + hda_nid_t pin_nid, int dev_id, u32 stream_tag, + int format); void (*pin_cvt_fixup)(struct hda_codec *codec, struct hdmi_spec_per_pin *per_pin, @@ -162,6 +146,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 */ @@ -654,8 +639,16 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, return true; } +static int hdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid, + int dev_id, unsigned char *buf, int *eld_size) +{ + snd_hda_set_dev_select(codec, nid, dev_id); + + return snd_hdmi_get_eld(codec, nid, buf, eld_size); +} + static void hdmi_pin_setup_infoframe(struct hda_codec *codec, - hda_nid_t pin_nid, + hda_nid_t pin_nid, int dev_id, int ca, int active_channels, int conn_type) { @@ -685,6 +678,8 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, return; } + snd_hda_set_dev_select(codec, pin_nid, dev_id); + /* * sizeof(ai) is used instead of sizeof(*hdmi_ai) or * sizeof(*dp_ai) to avoid partial match/update problems when @@ -710,6 +705,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, struct hdmi_spec *spec = codec->spec; struct hdac_chmap *chmap = &spec->chmap; hda_nid_t pin_nid = per_pin->pin_nid; + int dev_id = per_pin->dev_id; int channels = per_pin->channels; int active_channels; struct hdmi_eld *eld; @@ -718,6 +714,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, if (!channels) return; + snd_hda_set_dev_select(codec, pin_nid, dev_id); + /* some HW (e.g. HSW+) needs reprogramming the amp at each time */ if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) snd_hda_codec_write(codec, pin_nid, 0, @@ -743,8 +741,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, pin_nid, non_pcm, ca, channels, per_pin->chmap, per_pin->chmap_set); - spec->ops.pin_setup_infoframe(codec, pin_nid, ca, active_channels, - eld->info.conn_type); + spec->ops.pin_setup_infoframe(codec, pin_nid, dev_id, + ca, active_channels, eld->info.conn_type); per_pin->non_pcm = non_pcm; } @@ -776,34 +774,32 @@ static void jack_callback(struct hda_codec *codec, if (codec_has_acomp(codec)) return; - /* hda_jack don't support DP MST */ - check_presence_and_report(codec, jack->nid, 0); + check_presence_and_report(codec, jack->nid, jack->dev_id); } static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) { int tag = res >> AC_UNSOL_RES_TAG_SHIFT; struct hda_jack_tbl *jack; - int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; - /* - * assume DP MST uses dyn_pcm_assign and acomp and - * never comes here - * if DP MST supports unsol event, below code need - * consider dev_entry - */ - jack = snd_hda_jack_tbl_get_from_tag(codec, tag); + if (codec->dp_mst) { + int dev_entry = + (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; + + jack = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry); + } else { + jack = snd_hda_jack_tbl_get_from_tag(codec, tag, 0); + } if (!jack) return; jack->jack_dirty = 1; codec_dbg(codec, "HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n", - codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA), + codec->addr, jack->nid, jack->dev_id, !!(res & AC_UNSOL_RES_IA), !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); - /* hda_jack don't support DP MST */ - check_presence_and_report(codec, jack->nid, 0); + check_presence_and_report(codec, jack->nid, jack->dev_id); } static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) @@ -833,11 +829,21 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) { int tag = res >> AC_UNSOL_RES_TAG_SHIFT; int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + struct hda_jack_tbl *jack; if (codec_has_acomp(codec)) return; - if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { + if (codec->dp_mst) { + int dev_entry = + (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; + + jack = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry); + } else { + jack = snd_hda_jack_tbl_get_from_tag(codec, tag, 0); + } + + if (!jack) { codec_dbg(codec, "Unexpected HDMI event tag 0x%x\n", tag); return; } @@ -878,11 +884,12 @@ static void haswell_verify_D0(struct hda_codec *codec, ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7) static int hdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, - bool hbr) + int dev_id, bool hbr) { int pinctl, new_pinctl; if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { + snd_hda_set_dev_select(codec, pin_nid, dev_id); pinctl = snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); @@ -912,20 +919,22 @@ static int hdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, } static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, - hda_nid_t pin_nid, u32 stream_tag, int format) + hda_nid_t pin_nid, int dev_id, + u32 stream_tag, int format) { struct hdmi_spec *spec = codec->spec; unsigned int param; int err; - err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format)); + err = spec->ops.pin_hbr_setup(codec, pin_nid, dev_id, + is_hbr_format(format)); if (err) { codec_dbg(codec, "hdmi_setup_stream: HBR is not supported\n"); return err; } - if (is_haswell_plus(codec)) { + if (spec->intel_hsw_fixup) { /* * on recent platforms IEC Coding Type is required for HBR @@ -1292,6 +1301,7 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); hda_nid_t pin_nid = per_pin->pin_nid; + int dev_id = per_pin->dev_id; if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { codec_warn(codec, @@ -1300,24 +1310,43 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) return -EINVAL; } + snd_hda_set_dev_select(codec, pin_nid, dev_id); + /* all the device entries on the same pin have the same conn list */ - per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid, - per_pin->mux_nids, - HDA_MAX_CONNECTIONS); + per_pin->num_mux_nids = + snd_hda_get_raw_connections(codec, pin_nid, per_pin->mux_nids, + HDA_MAX_CONNECTIONS); return 0; } static int hdmi_find_pcm_slot(struct hdmi_spec *spec, - struct hdmi_spec_per_pin *per_pin) + struct hdmi_spec_per_pin *per_pin) { int i; - /* try the prefer PCM */ - if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap)) + /* + * generic_hdmi_build_pcms() allocates (num_nids + dev_num - 1) + * number of pcms. + * + * The per_pin of pin_nid_idx=n and dev_id=m prefers to get pcm-n + * if m==0. This guarantees that dynamic pcm assignments are compatible + * with the legacy static per_pin-pmc assignment that existed in the + * days before DP-MST. + * + * per_pin of m!=0 prefers to get pcm=(num_nids + (m - 1)). + */ + if (per_pin->dev_id == 0 && + !test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap)) return per_pin->pin_nid_idx; - /* have a second try; check the "reserved area" over num_pins */ + if (per_pin->dev_id != 0 && + !(test_bit(spec->num_nids + (per_pin->dev_id - 1), + &spec->pcm_bitmap))) { + return spec->num_nids + (per_pin->dev_id - 1); + } + + /* have a second try; check the area over num_nids */ for (i = spec->num_nids; i < spec->pcm_used; i++) { if (!test_bit(i, &spec->pcm_bitmap)) return i; @@ -1511,6 +1540,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, struct hdmi_spec *spec = codec->spec; struct hdmi_eld *eld = &spec->temp_eld; hda_nid_t pin_nid = per_pin->pin_nid; + int dev_id = per_pin->dev_id; /* * Always execute a GetPinSense verb here, even when called from * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited @@ -1523,7 +1553,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, bool ret; bool do_repoll = false; - present = snd_hda_pin_sense(codec, pin_nid); + present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id); mutex_lock(&per_pin->lock); eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); @@ -1537,8 +1567,8 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, codec->addr, pin_nid, eld->monitor_present, eld->eld_valid); if (eld->eld_valid) { - if (spec->ops.pin_get_eld(codec, pin_nid, eld->eld_buffer, - &eld->eld_size) < 0) + if (spec->ops.pin_get_eld(codec, pin_nid, dev_id, + eld->eld_buffer, &eld->eld_size) < 0) eld->eld_valid = false; else { if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer, @@ -1556,7 +1586,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, ret = !repoll || !eld->monitor_present || eld->eld_valid; - jack = snd_hda_jack_tbl_get(codec, pin_nid); + jack = snd_hda_jack_tbl_get_mst(codec, pin_nid, per_pin->dev_id); if (jack) { jack->block_report = !ret; jack->pin_sense = (eld->monitor_present && eld->eld_valid) ? @@ -1587,7 +1617,8 @@ static struct snd_jack *pin_idx_to_jack(struct hda_codec *codec, * DP MST will use dyn_pcm_assign, * so DP MST will never come here */ - jack_tbl = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); + jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid, + per_pin->dev_id); if (jack_tbl) jack = jack_tbl->jack; } @@ -1668,7 +1699,8 @@ static void hdmi_repoll_eld(struct work_struct *work) struct hdmi_spec *spec = codec->spec; struct hda_jack_tbl *jack; - jack = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); + jack = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid, + per_pin->dev_id); if (jack) jack->jack_dirty = 1; @@ -1709,7 +1741,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 @@ -1758,7 +1790,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) @@ -1873,7 +1905,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hdmi_spec *spec = codec->spec; int pin_idx; struct hdmi_spec_per_pin *per_pin; - hda_nid_t pin_nid; struct snd_pcm_runtime *runtime = substream->runtime; bool non_pcm; int pinctl, stripe; @@ -1897,7 +1928,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, goto unlock; } per_pin = get_pin(spec, pin_idx); - pin_nid = per_pin->pin_nid; /* Verify pin:cvt selections to avoid silent audio after S3. * After S3, the audio driver restores pin:cvt selections @@ -1912,8 +1942,8 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, /* Call sync_audio_rate to set the N/CTS/M manually if necessary */ /* Todo: add DP1.2 MST audio support later */ if (codec_has_acomp(codec)) - snd_hdac_sync_audio_rate(&codec->core, pin_nid, per_pin->dev_id, - runtime->rate); + snd_hdac_sync_audio_rate(&codec->core, per_pin->pin_nid, + per_pin->dev_id, runtime->rate); non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); mutex_lock(&per_pin->lock); @@ -1931,16 +1961,18 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); mutex_unlock(&per_pin->lock); if (spec->dyn_pin_out) { - pinctl = snd_hda_codec_read(codec, pin_nid, 0, + snd_hda_set_dev_select(codec, per_pin->pin_nid, + per_pin->dev_id); + pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - snd_hda_codec_write(codec, pin_nid, 0, + snd_hda_codec_write(codec, per_pin->pin_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl | PIN_OUT); } /* snd_hda_set_dev_select() has been called before */ - err = spec->ops.setup_stream(codec, cvt_nid, pin_nid, - stream_tag, format); + err = spec->ops.setup_stream(codec, cvt_nid, per_pin->pin_nid, + per_pin->dev_id, stream_tag, format); unlock: mutex_unlock(&spec->pcm_lock); return err; @@ -1992,6 +2024,8 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, per_pin = get_pin(spec, pin_idx); if (spec->dyn_pin_out) { + snd_hda_set_dev_select(codec, per_pin->pin_nid, + per_pin->dev_id); pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); snd_hda_codec_write(codec, per_pin->pin_nid, 0, @@ -2075,15 +2109,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; @@ -2160,11 +2203,13 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) if (phantom_jack) strncat(hdmi_str, " Phantom", sizeof(hdmi_str) - strlen(hdmi_str) - 1); - ret = snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, - phantom_jack, 0, NULL); + ret = snd_hda_jack_add_kctl_mst(codec, per_pin->pin_nid, + per_pin->dev_id, hdmi_str, phantom_jack, + 0, NULL); if (ret < 0) return ret; - jack = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); + jack = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid, + per_pin->dev_id); if (jack == NULL) return 0; /* assign jack->jack to pcm_rec[].jack to @@ -2273,10 +2318,11 @@ static int generic_hdmi_init(struct hda_codec *codec) if (codec_has_acomp(codec)) continue; if (spec->use_jack_detect) - snd_hda_jack_detect_enable(codec, pin_nid); + snd_hda_jack_detect_enable(codec, pin_nid, dev_id); else - snd_hda_jack_detect_enable_callback(codec, pin_nid, - jack_callback); + snd_hda_jack_detect_enable_callback_mst(codec, pin_nid, + dev_id, + jack_callback); } mutex_unlock(&spec->bind_lock); return 0; @@ -2315,8 +2361,8 @@ static void generic_hdmi_free(struct hda_codec *codec) snd_hdac_acomp_exit(&codec->bus->core); } else if (codec_has_acomp(codec)) { snd_hdac_acomp_register_notifier(&codec->bus->core, NULL); - codec->relaxed_resume = 0; } + codec->relaxed_resume = 0; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); @@ -2366,7 +2412,7 @@ static const struct hda_codec_ops generic_hdmi_patch_ops = { }; static const struct hdmi_ops generic_standard_hdmi_ops = { - .pin_get_eld = snd_hdmi_get_eld, + .pin_get_eld = hdmi_pin_get_eld, .pin_setup_infoframe = hdmi_pin_setup_infoframe, .pin_hbr_setup = hdmi_pin_hbr_setup, .setup_stream = hdmi_setup_stream, @@ -2426,11 +2472,11 @@ static int patch_generic_hdmi(struct hda_codec *codec) /* turn on / off the unsol event jack detection dynamically */ static void reprogram_jack_detect(struct hda_codec *codec, hda_nid_t nid, - bool use_acomp) + int dev_id, bool use_acomp) { struct hda_jack_tbl *tbl; - tbl = snd_hda_jack_tbl_get(codec, nid); + tbl = snd_hda_jack_tbl_get_mst(codec, nid, dev_id); if (tbl) { /* clear unsol even if component notifier is used, or re-enable * if notifier is cleared @@ -2443,7 +2489,7 @@ static void reprogram_jack_detect(struct hda_codec *codec, hda_nid_t nid, * at need (i.e. only when notifier is cleared) */ if (!use_acomp) - snd_hda_jack_detect_enable(codec, nid); + snd_hda_jack_detect_enable(codec, nid, dev_id); } } @@ -2463,6 +2509,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp, for (i = 0; i < spec->num_pins; i++) reprogram_jack_detect(spec->codec, get_pin(spec, i)->pin_nid, + get_pin(spec, i)->dev_id, use_acomp); } mutex_unlock(&spec->bind_lock); @@ -2563,7 +2610,8 @@ static void intel_haswell_fixup_connect_list(struct hda_codec *codec, hda_nid_t conns[4]; int nconns; - nconns = snd_hda_get_connections(codec, nid, conns, ARRAY_SIZE(conns)); + nconns = snd_hda_get_raw_connections(codec, nid, conns, + ARRAY_SIZE(conns)); if (nconns == spec->num_cvts && !memcmp(conns, spec->cvt_nids, spec->num_cvts * sizeof(hda_nid_t))) return; @@ -2664,7 +2712,7 @@ static int intel_pin2port(void *audio_ptr, int pin_nid) base_nid = intel_base_nid(codec); if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3)) return -1; - return pin_nid - base_nid + 1; /* intel port is 1-based */ + return pin_nid - base_nid + 1; } /* @@ -2673,10 +2721,9 @@ 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 */ codec_info(codec, "Can't find the HDMI/DP port for pin %d\n", pin_nid); return -1; } @@ -2689,13 +2736,12 @@ static int intel_port2pin(struct hda_codec *codec, int port) /* we assume only from port-B to port-D */ if (port < 1 || port > 3) return 0; - /* intel port is 1-based */ 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) @@ -2741,10 +2787,12 @@ static void register_i915_notifier(struct hda_codec *codec) /* setup_stream ops override for HSW+ */ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, - hda_nid_t pin_nid, u32 stream_tag, int format) + hda_nid_t pin_nid, int dev_id, u32 stream_tag, + int format) { haswell_verify_D0(codec, cvt_nid, pin_nid); - return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); + return hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, + stream_tag, format); } /* pin_cvt_fixup ops override for HSW+ and VLV+ */ @@ -2816,6 +2864,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); @@ -2846,9 +2895,9 @@ 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)); } @@ -2857,14 +2906,13 @@ 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 with 1 base. + * 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) { @@ -2970,7 +3018,7 @@ static int simple_playback_init(struct hda_codec *codec) if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - snd_hda_jack_detect_enable(codec, pin); + snd_hda_jack_detect_enable(codec, pin, per_pin->dev_id); return 0; } @@ -3479,11 +3527,22 @@ static int patch_nvhdmi(struct hda_codec *codec) struct hdmi_spec *spec; int err; - err = patch_generic_hdmi(codec); - if (err) + err = alloc_generic_hdmi(codec); + if (err < 0) return err; + codec->dp_mst = true; spec = codec->spec; + spec->dyn_pcm_assign = true; + + err = hdmi_parse_codec(codec); + if (err < 0) { + generic_spec_free(codec); + return err; + } + + generic_hdmi_init_per_pins(codec); + spec->dyn_pin_out = true; spec->chmap.ops.chmap_cea_alloc_validate_get_type = @@ -3497,6 +3556,27 @@ static int patch_nvhdmi(struct hda_codec *codec) return 0; } +static int patch_nvhdmi_legacy(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + int err; + + err = patch_generic_hdmi(codec); + if (err) + return err; + + spec = codec->spec; + spec->dyn_pin_out = true; + + spec->chmap.ops.chmap_cea_alloc_validate_get_type = + nvhdmi_chmap_cea_alloc_validate_get_type; + spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + + codec->link_down_at_suspend = 1; + + return 0; +} + /* * The HDA codec on NVIDIA Tegra contains two scratch registers that are * accessed using vendor-defined verbs. These registers can be used for @@ -3710,16 +3790,19 @@ static int patch_tegra_hdmi(struct hda_codec *codec) #define ATI_HBR_ENABLE 0x10 static int atihdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid, - unsigned char *buf, int *eld_size) + int dev_id, unsigned char *buf, int *eld_size) { + WARN_ON(dev_id != 0); /* call hda_eld.c ATI/AMD-specific function */ return snd_hdmi_get_eld_ati(codec, nid, buf, eld_size, is_amdhdmi_rev3_or_later(codec)); } -static void atihdmi_pin_setup_infoframe(struct hda_codec *codec, hda_nid_t pin_nid, int ca, +static void atihdmi_pin_setup_infoframe(struct hda_codec *codec, + hda_nid_t pin_nid, int dev_id, int ca, int active_channels, int conn_type) { + WARN_ON(dev_id != 0); snd_hda_codec_write(codec, pin_nid, 0, ATI_VERB_SET_CHANNEL_ALLOCATION, ca); } @@ -3910,10 +3993,12 @@ static void atihdmi_paired_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap, } static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, - bool hbr) + int dev_id, bool hbr) { int hbr_ctl, hbr_ctl_new; + WARN_ON(dev_id != 0); + hbr_ctl = snd_hda_codec_read(codec, pin_nid, 0, ATI_VERB_GET_HBR_CONTROL, 0); if (hbr_ctl >= 0 && (hbr_ctl & ATI_HBR_CAPABLE)) { if (hbr) @@ -3939,9 +4024,9 @@ static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, } static int atihdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, - hda_nid_t pin_nid, u32 stream_tag, int format) + hda_nid_t pin_nid, int dev_id, + u32 stream_tag, int format) { - if (is_amdhdmi_rev3_or_later(codec)) { int ramp_rate = 180; /* default as per AMD spec */ /* disable ramp-up/down for non-pcm as per AMD spec */ @@ -3951,7 +4036,8 @@ static int atihdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, snd_hda_codec_write(codec, cvt_nid, 0, ATI_VERB_SET_RAMP_RATE, ramp_rate); } - return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); + return hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, + stream_tag, format); } @@ -4081,25 +4167,25 @@ HDA_CODEC_ENTRY(0x10de0004, "GPU 04 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0005, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0006, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0007, "MCP79/7A HDMI", patch_nvhdmi_8ch_7x), -HDA_CODEC_ENTRY(0x10de0008, "GPU 08 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0009, "GPU 09 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de000a, "GPU 0a HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de000b, "GPU 0b HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de000c, "MCP89 HDMI", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de000d, "GPU 0d HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0010, "GPU 10 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0011, "GPU 11 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0012, "GPU 12 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0013, "GPU 13 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0014, "GPU 14 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0015, "GPU 15 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0016, "GPU 16 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0008, "GPU 08 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0009, "GPU 09 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de000a, "GPU 0a HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de000b, "GPU 0b HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de000c, "MCP89 HDMI", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de000d, "GPU 0d HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0010, "GPU 10 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0011, "GPU 11 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0012, "GPU 12 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0013, "GPU 13 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0014, "GPU 14 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0015, "GPU 15 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0016, "GPU 16 HDMI/DP", patch_nvhdmi_legacy), /* 17 is known to be absent */ -HDA_CODEC_ENTRY(0x10de0018, "GPU 18 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0019, "GPU 19 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de001a, "GPU 1a HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de001b, "GPU 1b HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de001c, "GPU 1c HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0018, "GPU 18 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0019, "GPU 19 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de001a, "GPU 1a HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de001b, "GPU 1b HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de001c, "GPU 1c HDMI/DP", patch_nvhdmi_legacy), HDA_CODEC_ENTRY(0x10de0020, "Tegra30 HDMI", patch_tegra_hdmi), HDA_CODEC_ENTRY(0x10de0022, "Tegra114 HDMI", patch_tegra_hdmi), HDA_CODEC_ENTRY(0x10de0028, "Tegra124 HDMI", patch_tegra_hdmi), |