Merge branch 'for-next' into for-linus
This commit is contained in:
@@ -114,6 +114,9 @@ struct hdmi_ops {
|
||||
int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid,
|
||||
hda_nid_t pin_nid, u32 stream_tag, int format);
|
||||
|
||||
void (*pin_cvt_fixup)(struct hda_codec *codec,
|
||||
struct hdmi_spec_per_pin *per_pin,
|
||||
hda_nid_t cvt_nid);
|
||||
};
|
||||
|
||||
struct hdmi_pcm {
|
||||
@@ -684,7 +687,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
|
||||
if (!channels)
|
||||
return;
|
||||
|
||||
if (is_haswell_plus(codec))
|
||||
/* 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,
|
||||
AC_VERB_SET_AMP_GAIN_MUTE,
|
||||
AMP_OUT_UNMUTE);
|
||||
@@ -864,9 +868,6 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
int err;
|
||||
|
||||
if (is_haswell_plus(codec))
|
||||
haswell_verify_D0(codec, cvt_nid, pin_nid);
|
||||
|
||||
err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format));
|
||||
|
||||
if (err) {
|
||||
@@ -884,7 +885,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
|
||||
* of the pin.
|
||||
*/
|
||||
static int hdmi_choose_cvt(struct hda_codec *codec,
|
||||
int pin_idx, int *cvt_id, int *mux_id)
|
||||
int pin_idx, int *cvt_id)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hdmi_spec_per_pin *per_pin;
|
||||
@@ -925,8 +926,6 @@ static int hdmi_choose_cvt(struct hda_codec *codec,
|
||||
|
||||
if (cvt_id)
|
||||
*cvt_id = cvt_idx;
|
||||
if (mux_id)
|
||||
*mux_id = mux_idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1019,9 +1018,6 @@ static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec,
|
||||
int mux_idx;
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
|
||||
if (!is_haswell_plus(codec) && !is_valleyview_plus(codec))
|
||||
return;
|
||||
|
||||
/* On Intel platform, the mapping of converter nid to
|
||||
* mux index of the pins are always the same.
|
||||
* The pin nid may be 0, this means all pins will not
|
||||
@@ -1032,6 +1028,17 @@ static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec,
|
||||
intel_not_share_assigned_cvt(codec, pin_nid, mux_idx);
|
||||
}
|
||||
|
||||
/* skeleton caller of pin_cvt_fixup ops */
|
||||
static void pin_cvt_fixup(struct hda_codec *codec,
|
||||
struct hdmi_spec_per_pin *per_pin,
|
||||
hda_nid_t cvt_nid)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
|
||||
if (spec->ops.pin_cvt_fixup)
|
||||
spec->ops.pin_cvt_fixup(codec, per_pin, cvt_nid);
|
||||
}
|
||||
|
||||
/* called in hdmi_pcm_open when no pin is assigned to the PCM
|
||||
* in dyn_pcm_assign mode.
|
||||
*/
|
||||
@@ -1049,7 +1056,7 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo,
|
||||
if (pcm_idx < 0)
|
||||
return -EINVAL;
|
||||
|
||||
err = hdmi_choose_cvt(codec, -1, &cvt_idx, NULL);
|
||||
err = hdmi_choose_cvt(codec, -1, &cvt_idx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1057,7 +1064,7 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo,
|
||||
per_cvt->assigned = 1;
|
||||
hinfo->nid = per_cvt->cvt_nid;
|
||||
|
||||
intel_not_share_assigned_cvt_nid(codec, 0, per_cvt->cvt_nid);
|
||||
pin_cvt_fixup(codec, NULL, per_cvt->cvt_nid);
|
||||
|
||||
set_bit(pcm_idx, &spec->pcm_in_use);
|
||||
/* todo: setup spdif ctls assign */
|
||||
@@ -1089,7 +1096,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
int pin_idx, cvt_idx, pcm_idx, mux_idx = 0;
|
||||
int pin_idx, cvt_idx, pcm_idx;
|
||||
struct hdmi_spec_per_pin *per_pin;
|
||||
struct hdmi_eld *eld;
|
||||
struct hdmi_spec_per_cvt *per_cvt = NULL;
|
||||
@@ -1118,7 +1125,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
|
||||
}
|
||||
}
|
||||
|
||||
err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx);
|
||||
err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&spec->pcm_lock);
|
||||
return err;
|
||||
@@ -1135,11 +1142,10 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
|
||||
|
||||
snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
|
||||
AC_VERB_SET_CONNECT_SEL,
|
||||
mux_idx);
|
||||
per_pin->mux_idx);
|
||||
|
||||
/* configure unused pins to choose other converters */
|
||||
if (is_haswell_plus(codec) || is_valleyview_plus(codec))
|
||||
intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx);
|
||||
pin_cvt_fixup(codec, per_pin, 0);
|
||||
|
||||
snd_hda_spdif_ctls_assign(codec, pcm_idx, per_cvt->cvt_nid);
|
||||
|
||||
@@ -1372,12 +1378,7 @@ static void update_eld(struct hda_codec *codec,
|
||||
* and this can make HW reset converter selection on a pin.
|
||||
*/
|
||||
if (eld->eld_valid && !old_eld_valid && per_pin->setup) {
|
||||
if (is_haswell_plus(codec) || is_valleyview_plus(codec)) {
|
||||
intel_verify_pin_cvt_connect(codec, per_pin);
|
||||
intel_not_share_assigned_cvt(codec, per_pin->pin_nid,
|
||||
per_pin->mux_idx);
|
||||
}
|
||||
|
||||
pin_cvt_fixup(codec, per_pin, 0);
|
||||
hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
|
||||
}
|
||||
|
||||
@@ -1484,7 +1485,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
|
||||
|
||||
mutex_lock(&per_pin->lock);
|
||||
eld->monitor_present = false;
|
||||
size = snd_hdac_acomp_get_eld(&codec->bus->core, per_pin->pin_nid,
|
||||
size = snd_hdac_acomp_get_eld(&codec->core, per_pin->pin_nid,
|
||||
&eld->monitor_present, eld->eld_buffer,
|
||||
ELD_MAX_SIZE);
|
||||
if (size > 0) {
|
||||
@@ -1711,7 +1712,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
||||
* skip pin setup and return 0 to make audio playback
|
||||
* be ongoing
|
||||
*/
|
||||
intel_not_share_assigned_cvt_nid(codec, 0, cvt_nid);
|
||||
pin_cvt_fixup(codec, NULL, cvt_nid);
|
||||
snd_hda_codec_setup_stream(codec, cvt_nid,
|
||||
stream_tag, 0, format);
|
||||
mutex_unlock(&spec->pcm_lock);
|
||||
@@ -1724,23 +1725,21 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
||||
}
|
||||
per_pin = get_pin(spec, pin_idx);
|
||||
pin_nid = per_pin->pin_nid;
|
||||
if (is_haswell_plus(codec) || is_valleyview_plus(codec)) {
|
||||
/* Verify pin:cvt selections to avoid silent audio after S3.
|
||||
* After S3, the audio driver restores pin:cvt selections
|
||||
* but this can happen before gfx is ready and such selection
|
||||
* is overlooked by HW. Thus multiple pins can share a same
|
||||
* default convertor and mute control will affect each other,
|
||||
* which can cause a resumed audio playback become silent
|
||||
* after S3.
|
||||
*/
|
||||
intel_verify_pin_cvt_connect(codec, per_pin);
|
||||
intel_not_share_assigned_cvt(codec, pin_nid, per_pin->mux_idx);
|
||||
}
|
||||
|
||||
/* Verify pin:cvt selections to avoid silent audio after S3.
|
||||
* After S3, the audio driver restores pin:cvt selections
|
||||
* but this can happen before gfx is ready and such selection
|
||||
* is overlooked by HW. Thus multiple pins can share a same
|
||||
* default convertor and mute control will affect each other,
|
||||
* which can cause a resumed audio playback become silent
|
||||
* after S3.
|
||||
*/
|
||||
pin_cvt_fixup(codec, per_pin, 0);
|
||||
|
||||
/* 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->bus->core, pin_nid, runtime->rate);
|
||||
snd_hdac_sync_audio_rate(&codec->core, pin_nid, runtime->rate);
|
||||
|
||||
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
|
||||
mutex_lock(&per_pin->lock);
|
||||
@@ -1837,6 +1836,18 @@ static const struct hda_pcm_ops generic_ops = {
|
||||
.cleanup = generic_hdmi_playback_pcm_cleanup,
|
||||
};
|
||||
|
||||
static int hdmi_get_spk_alloc(struct hdac_device *hdac, int pcm_idx)
|
||||
{
|
||||
struct hda_codec *codec = container_of(hdac, struct hda_codec, core);
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx);
|
||||
|
||||
if (!per_pin)
|
||||
return 0;
|
||||
|
||||
return per_pin->sink_eld.info.spk_alloc;
|
||||
}
|
||||
|
||||
static void hdmi_get_chmap(struct hdac_device *hdac, int pcm_idx,
|
||||
unsigned char *chmap)
|
||||
{
|
||||
@@ -2075,6 +2086,20 @@ static void hdmi_array_free(struct hdmi_spec *spec)
|
||||
snd_array_free(&spec->cvts);
|
||||
}
|
||||
|
||||
static void generic_spec_free(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
|
||||
if (spec) {
|
||||
if (spec->i915_bound)
|
||||
snd_hdac_i915_exit(&codec->bus->core);
|
||||
hdmi_array_free(spec);
|
||||
kfree(spec);
|
||||
codec->spec = NULL;
|
||||
}
|
||||
codec->dp_mst = false;
|
||||
}
|
||||
|
||||
static void generic_hdmi_free(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
@@ -2099,10 +2124,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
|
||||
spec->pcm_rec[pcm_idx].jack = NULL;
|
||||
}
|
||||
|
||||
if (spec->i915_bound)
|
||||
snd_hdac_i915_exit(&codec->bus->core);
|
||||
hdmi_array_free(spec);
|
||||
kfree(spec);
|
||||
generic_spec_free(codec);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@@ -2140,6 +2162,55 @@ static const struct hdmi_ops generic_standard_hdmi_ops = {
|
||||
.setup_stream = hdmi_setup_stream,
|
||||
};
|
||||
|
||||
/* allocate codec->spec and assign/initialize generic parser ops */
|
||||
static int alloc_generic_hdmi(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec;
|
||||
|
||||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
|
||||
spec->ops = generic_standard_hdmi_ops;
|
||||
mutex_init(&spec->pcm_lock);
|
||||
snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);
|
||||
|
||||
spec->chmap.ops.get_chmap = hdmi_get_chmap;
|
||||
spec->chmap.ops.set_chmap = hdmi_set_chmap;
|
||||
spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached;
|
||||
spec->chmap.ops.get_spk_alloc = hdmi_get_spk_alloc,
|
||||
|
||||
codec->spec = spec;
|
||||
hdmi_array_init(spec, 4);
|
||||
|
||||
codec->patch_ops = generic_hdmi_patch_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* generic HDMI parser */
|
||||
static int patch_generic_hdmi(struct hda_codec *codec)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = alloc_generic_hdmi(codec);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = hdmi_parse_codec(codec);
|
||||
if (err < 0) {
|
||||
generic_spec_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
generic_hdmi_init_per_pins(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Intel codec parsers and helpers
|
||||
*/
|
||||
|
||||
static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
|
||||
hda_nid_t nid)
|
||||
{
|
||||
@@ -2217,12 +2288,23 @@ static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
|
||||
static void intel_pin_eld_notify(void *audio_ptr, int port)
|
||||
{
|
||||
struct hda_codec *codec = audio_ptr;
|
||||
int pin_nid = port + 0x04;
|
||||
int pin_nid;
|
||||
|
||||
/* we assume only from port-B to port-D */
|
||||
if (port < 1 || port > 3)
|
||||
return;
|
||||
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x80860054: /* ILK */
|
||||
case 0x80862804: /* ILK */
|
||||
case 0x80862882: /* VLV */
|
||||
pin_nid = port + 0x03;
|
||||
break;
|
||||
default:
|
||||
pin_nid = port + 0x04;
|
||||
break;
|
||||
}
|
||||
|
||||
/* skip notification during system suspend (but not in runtime PM);
|
||||
* the state will be updated at resume
|
||||
*/
|
||||
@@ -2236,95 +2318,161 @@ static void intel_pin_eld_notify(void *audio_ptr, int port)
|
||||
check_presence_and_report(codec, pin_nid);
|
||||
}
|
||||
|
||||
static int patch_generic_hdmi(struct hda_codec *codec)
|
||||
/* register i915 component pin_eld_notify callback */
|
||||
static void register_i915_notifier(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
|
||||
spec->use_acomp_notifier = true;
|
||||
spec->i915_audio_ops.audio_ptr = codec;
|
||||
/* intel_audio_codec_enable() or intel_audio_codec_disable()
|
||||
* will call pin_eld_notify with using audio_ptr pointer
|
||||
* We need make sure audio_ptr is really setup
|
||||
*/
|
||||
wmb();
|
||||
spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
|
||||
snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
haswell_verify_D0(codec, cvt_nid, pin_nid);
|
||||
return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
|
||||
}
|
||||
|
||||
/* pin_cvt_fixup ops override for HSW+ and VLV+ */
|
||||
static void i915_pin_cvt_fixup(struct hda_codec *codec,
|
||||
struct hdmi_spec_per_pin *per_pin,
|
||||
hda_nid_t cvt_nid)
|
||||
{
|
||||
if (per_pin) {
|
||||
intel_verify_pin_cvt_connect(codec, per_pin);
|
||||
intel_not_share_assigned_cvt(codec, per_pin->pin_nid,
|
||||
per_pin->mux_idx);
|
||||
} else {
|
||||
intel_not_share_assigned_cvt_nid(codec, 0, cvt_nid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Intel Haswell and onwards; audio component with eld notifier */
|
||||
static int patch_i915_hsw_hdmi(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec;
|
||||
int err;
|
||||
|
||||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (spec == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
spec->ops = generic_standard_hdmi_ops;
|
||||
mutex_init(&spec->pcm_lock);
|
||||
snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);
|
||||
|
||||
spec->chmap.ops.get_chmap = hdmi_get_chmap;
|
||||
spec->chmap.ops.set_chmap = hdmi_set_chmap;
|
||||
spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached;
|
||||
|
||||
codec->spec = spec;
|
||||
hdmi_array_init(spec, 4);
|
||||
|
||||
#ifdef CONFIG_SND_HDA_I915
|
||||
/* Try to bind with i915 for Intel HSW+ codecs (if not done yet) */
|
||||
if ((codec->core.vendor_id >> 16) == 0x8086 &&
|
||||
is_haswell_plus(codec)) {
|
||||
#if 0
|
||||
/* on-demand binding leads to an unbalanced refcount when
|
||||
* both i915 and hda drivers are probed concurrently;
|
||||
* disabled temporarily for now
|
||||
*/
|
||||
if (!codec->bus->core.audio_component)
|
||||
if (!snd_hdac_i915_init(&codec->bus->core))
|
||||
spec->i915_bound = true;
|
||||
#endif
|
||||
/* use i915 audio component notifier for hotplug */
|
||||
if (codec->bus->core.audio_component)
|
||||
spec->use_acomp_notifier = true;
|
||||
/* HSW+ requires i915 binding */
|
||||
if (!codec->bus->core.audio_component) {
|
||||
codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_haswell_plus(codec)) {
|
||||
intel_haswell_enable_all_pins(codec, true);
|
||||
intel_haswell_fixup_enable_dp12(codec);
|
||||
err = alloc_generic_hdmi(codec);
|
||||
if (err < 0)
|
||||
return err;
|
||||
spec = codec->spec;
|
||||
|
||||
intel_haswell_enable_all_pins(codec, true);
|
||||
intel_haswell_fixup_enable_dp12(codec);
|
||||
|
||||
/* For Haswell/Broadwell, the controller is also in the power well and
|
||||
* can cover the codec power request, and so need not set this flag.
|
||||
*/
|
||||
if (!is_haswell(codec) && !is_broadwell(codec))
|
||||
codec->core.link_power_control = 1;
|
||||
|
||||
codec->patch_ops.set_power_state = haswell_set_power_state;
|
||||
codec->dp_mst = true;
|
||||
codec->depop_delay = 0;
|
||||
codec->auto_runtime_pm = 1;
|
||||
|
||||
spec->ops.setup_stream = i915_hsw_setup_stream;
|
||||
spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;
|
||||
|
||||
err = hdmi_parse_codec(codec);
|
||||
if (err < 0) {
|
||||
generic_spec_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
generic_hdmi_init_per_pins(codec);
|
||||
register_i915_notifier(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Intel Baytrail and Braswell; with eld notifier */
|
||||
static int patch_i915_byt_hdmi(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec;
|
||||
int err;
|
||||
|
||||
/* requires i915 binding */
|
||||
if (!codec->bus->core.audio_component) {
|
||||
codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
err = alloc_generic_hdmi(codec);
|
||||
if (err < 0)
|
||||
return err;
|
||||
spec = codec->spec;
|
||||
|
||||
/* For Valleyview/Cherryview, only the display codec is in the display
|
||||
* power well and can use link_power ops to request/release the power.
|
||||
* For Haswell/Broadwell, the controller is also in the power well and
|
||||
* can cover the codec power request, and so need not set this flag.
|
||||
* For previous platforms, there is no such power well feature.
|
||||
*/
|
||||
if (is_valleyview_plus(codec) || is_skylake(codec) ||
|
||||
is_broxton(codec))
|
||||
codec->core.link_power_control = 1;
|
||||
codec->core.link_power_control = 1;
|
||||
|
||||
if (hdmi_parse_codec(codec) < 0) {
|
||||
if (spec->i915_bound)
|
||||
snd_hdac_i915_exit(&codec->bus->core);
|
||||
codec->spec = NULL;
|
||||
kfree(spec);
|
||||
return -EINVAL;
|
||||
}
|
||||
codec->patch_ops = generic_hdmi_patch_ops;
|
||||
if (is_haswell_plus(codec)) {
|
||||
codec->patch_ops.set_power_state = haswell_set_power_state;
|
||||
codec->dp_mst = true;
|
||||
}
|
||||
codec->depop_delay = 0;
|
||||
codec->auto_runtime_pm = 1;
|
||||
|
||||
/* Enable runtime pm for HDMI audio codec of HSW/BDW/SKL/BYT/BSW */
|
||||
if (is_haswell_plus(codec) || is_valleyview_plus(codec))
|
||||
codec->auto_runtime_pm = 1;
|
||||
spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup;
|
||||
|
||||
err = hdmi_parse_codec(codec);
|
||||
if (err < 0) {
|
||||
generic_spec_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
generic_hdmi_init_per_pins(codec);
|
||||
|
||||
|
||||
if (codec_has_acomp(codec)) {
|
||||
codec->depop_delay = 0;
|
||||
spec->i915_audio_ops.audio_ptr = codec;
|
||||
/* intel_audio_codec_enable() or intel_audio_codec_disable()
|
||||
* will call pin_eld_notify with using audio_ptr pointer
|
||||
* We need make sure audio_ptr is really setup
|
||||
*/
|
||||
wmb();
|
||||
spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
|
||||
snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
|
||||
}
|
||||
|
||||
WARN_ON(spec->dyn_pcm_assign && !codec_has_acomp(codec));
|
||||
register_i915_notifier(codec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */
|
||||
static int patch_i915_cpt_hdmi(struct hda_codec *codec)
|
||||
{
|
||||
struct hdmi_spec *spec;
|
||||
int err;
|
||||
|
||||
/* no i915 component should have been bound before this */
|
||||
if (WARN_ON(codec->bus->core.audio_component))
|
||||
return -EBUSY;
|
||||
|
||||
err = alloc_generic_hdmi(codec);
|
||||
if (err < 0)
|
||||
return err;
|
||||
spec = codec->spec;
|
||||
|
||||
/* Try to bind with i915 now */
|
||||
err = snd_hdac_i915_init(&codec->bus->core);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
spec->i915_bound = true;
|
||||
|
||||
err = hdmi_parse_codec(codec);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
generic_hdmi_init_per_pins(codec);
|
||||
register_i915_notifier(codec);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
generic_spec_free(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shared non-generic implementations
|
||||
*/
|
||||
@@ -3492,21 +3640,21 @@ HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP", patch_via_hdmi),
|
||||
HDA_CODEC_ENTRY(0x11069f81, "VX900 HDMI/DP", patch_via_hdmi),
|
||||
HDA_CODEC_ENTRY(0x11069f84, "VX11 HDMI/DP", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x11069f85, "VX11 HDMI/DP", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80860054, "IbexPeak HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80860054, "IbexPeak HDMI", patch_i915_cpt_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862801, "Bearlake HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862802, "Cantiga HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862803, "Eaglelake HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862804, "IbexPeak HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862805, "CougarPoint HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862806, "PantherPoint HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862804, "IbexPeak HDMI", patch_i915_cpt_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862805, "CougarPoint HDMI", patch_i915_cpt_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862806, "PantherPoint HDMI", patch_i915_cpt_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_i915_hsw_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI", patch_i915_hsw_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_i915_hsw_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_i915_hsw_hdmi),
|
||||
HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_i915_hsw_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_generic_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),
|
||||
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
|
||||
HDA_CODEC_ENTRY(0x808629fb, "Crestline HDMI", patch_generic_hdmi),
|
||||
/* special ID for generic HDMI */
|
||||
HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC_HDMI, "Generic HDMI", patch_generic_hdmi),
|
||||
|
Reference in New Issue
Block a user