Commit ad781b55 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda/hdmi: Rewrite to new probe method



Convert the HDMI codec drivers to use the new hda_codec_ops probe.

The Intel and Nvidia-MCP HDMI drivers needed slightly more changes to
deal with the unified callbacks among all models.

Also another non-trivial change is Intel driver's set_power_state
callback.  An additional NULL check of codec->spec is needed there
since the set_power_state() may be called before the probe gets called
(e.g. in ASoC hda codec hda_codec_probe()).

Other than that, no functional changes.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20250709160434.1859-24-tiwai@suse.de
parent 6cce0812
Loading
Loading
Loading
Loading
+20 −11
Original line number Diff line number Diff line
@@ -528,19 +528,16 @@ static const struct drm_audio_component_audio_ops atihdmi_audio_ops = {
	.master_unbind = snd_hda_hdmi_acomp_master_unbind,
};

static int patch_atihdmi(struct hda_codec *codec)
static int atihdmi_probe(struct hda_codec *codec, const struct hda_device_id *id)
{
	struct hdmi_spec *spec;
	struct hdmi_spec_per_cvt *per_cvt;
	int err, cvt_idx;

	err = patch_generic_hdmi(codec);

	err = snd_hda_hdmi_generic_probe(codec);
	if (err)
		return err;

	codec->patch_ops.init = atihdmi_init;

	spec = codec->spec;

	spec->static_pcm_mapping = true;
@@ -583,14 +580,25 @@ static int patch_atihdmi(struct hda_codec *codec)
	return 0;
}

static const struct hda_codec_ops atihdmi_codec_ops = {
	.probe = atihdmi_probe,
	.remove = snd_hda_hdmi_generic_remove,
	.init = atihdmi_init,
	.build_pcms = snd_hda_hdmi_generic_build_pcms,
	.build_controls = snd_hda_hdmi_generic_build_controls,
	.unsol_event = snd_hda_hdmi_generic_unsol_event,
	.suspend = snd_hda_hdmi_generic_suspend,
	.resume	 = snd_hda_hdmi_generic_resume,
};

/*
 * patch entries
 * driver entries
 */
static const struct hda_device_id snd_hda_id_atihdmi[] = {
HDA_CODEC_ENTRY(0x1002793c, "RS600 HDMI",	patch_atihdmi),
HDA_CODEC_ENTRY(0x10027919, "RS600 HDMI",	patch_atihdmi),
HDA_CODEC_ENTRY(0x1002791a, "RS690/780 HDMI",	patch_atihdmi),
HDA_CODEC_ENTRY(0x1002aa01, "R6xx HDMI",	patch_atihdmi),
	HDA_CODEC_ID(0x1002793c, "RS600 HDMI"),
	HDA_CODEC_ID(0x10027919, "RS600 HDMI"),
	HDA_CODEC_ID(0x1002791a, "RS690/780 HDMI"),
	HDA_CODEC_ID(0x1002aa01, "R6xx HDMI"),
	{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_atihdmi);
@@ -601,6 +609,7 @@ MODULE_IMPORT_NS("SND_HDA_CODEC_HDMI");

static struct hda_codec_driver atihdmi_driver = {
	.id = snd_hda_id_atihdmi,
	.ops = &atihdmi_codec_ops,
};

module_hda_codec_driver(atihdmi_driver);
+66 −60
Original line number Diff line number Diff line
@@ -2087,7 +2087,7 @@ void snd_hda_hdmi_generic_spec_free(struct hda_codec *codec)
}
EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_generic_spec_free, "SND_HDA_CODEC_HDMI");

void snd_hda_hdmi_generic_free(struct hda_codec *codec)
void snd_hda_hdmi_generic_remove(struct hda_codec *codec)
{
	struct hdmi_spec *spec = codec->spec;
	int pin_idx, pcm_idx;
@@ -2113,7 +2113,7 @@ void snd_hda_hdmi_generic_free(struct hda_codec *codec)

	snd_hda_hdmi_generic_spec_free(codec);
}
EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_generic_free, "SND_HDA_CODEC_HDMI");
EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_generic_remove, "SND_HDA_CODEC_HDMI");

int snd_hda_hdmi_generic_suspend(struct hda_codec *codec)
{
@@ -2133,7 +2133,7 @@ int snd_hda_hdmi_generic_resume(struct hda_codec *codec)
	struct hdmi_spec *spec = codec->spec;
	int pin_idx;

	codec->patch_ops.init(codec);
	snd_hda_codec_init(codec);
	snd_hda_regmap_sync(codec);

	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
@@ -2144,16 +2144,6 @@ int snd_hda_hdmi_generic_resume(struct hda_codec *codec)
}
EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_generic_resume, "SND_HDA_CODEC_HDMI");

static const struct hda_codec_ops generic_hdmi_patch_ops = {
	.init			= snd_hda_hdmi_generic_init,
	.free			= snd_hda_hdmi_generic_free,
	.build_pcms		= snd_hda_hdmi_generic_build_pcms,
	.build_controls		= snd_hda_hdmi_generic_build_controls,
	.unsol_event		= snd_hda_hdmi_generic_unsol_event,
	.suspend		= snd_hda_hdmi_generic_suspend,
	.resume			= snd_hda_hdmi_generic_resume,
};

static const struct hdmi_ops generic_standard_hdmi_ops = {
	.pin_get_eld				= hdmi_pin_get_eld,
	.pin_setup_infoframe			= hdmi_pin_setup_infoframe,
@@ -2185,14 +2175,12 @@ int snd_hda_hdmi_generic_alloc(struct hda_codec *codec)
	codec->spec = spec;
	hdmi_array_init(spec, 4);

	codec->patch_ops = generic_hdmi_patch_ops;

	return 0;
}
EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_generic_alloc, "SND_HDA_CODEC_HDMI");

/* generic HDMI parser */
int patch_generic_hdmi(struct hda_codec *codec)
int snd_hda_hdmi_generic_probe(struct hda_codec *codec)
{
	int err;

@@ -2209,7 +2197,7 @@ int patch_generic_hdmi(struct hda_codec *codec)
	snd_hda_hdmi_generic_init_per_pins(codec);
	return 0;
}
EXPORT_SYMBOL_NS_GPL(patch_generic_hdmi, "SND_HDA_CODEC_HDMI");
EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_generic_probe, "SND_HDA_CODEC_HDMI");

/*
 * generic audio component binding
@@ -2346,65 +2334,83 @@ EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_acomp_init, "SND_HDA_CODEC_HDMI");
/*
 */

static int patch_gf_hdmi(struct hda_codec *codec)
enum {
	MODEL_GENERIC,
	MODEL_GF,
};

static int generichdmi_probe(struct hda_codec *codec,
			     const struct hda_device_id *id)
{
	int err;

	err = patch_generic_hdmi(codec);
	if (err)
	err = snd_hda_hdmi_generic_probe(codec);
	if (err < 0)
		return err;

	/*
	 * Glenfly GPUs have two codecs, stream switches from one codec to
	 * another, need to do actual clean-ups in codec_cleanup_stream
	 */
	if (id->driver_data == MODEL_GF)
		codec->no_sticky_stream = 1;

	return 0;
}

static const struct hda_codec_ops generichdmi_codec_ops = {
	.probe = generichdmi_probe,
	.remove = snd_hda_hdmi_generic_remove,
	.init = snd_hda_hdmi_generic_init,
	.build_pcms = snd_hda_hdmi_generic_build_pcms,
	.build_controls = snd_hda_hdmi_generic_build_controls,
	.unsol_event = snd_hda_hdmi_generic_unsol_event,
	.suspend = snd_hda_hdmi_generic_suspend,
	.resume	 = snd_hda_hdmi_generic_resume,
};

/*
 * patch entries
 */
static const struct hda_device_id snd_hda_id_hdmi[] = {
HDA_CODEC_ENTRY(0x00147a47, "Loongson HDMI",	patch_generic_hdmi),
HDA_CODEC_ENTRY(0x10951390, "SiI1390 HDMI",	patch_generic_hdmi),
HDA_CODEC_ENTRY(0x10951392, "SiI1392 HDMI",	patch_generic_hdmi),
HDA_CODEC_ENTRY(0x17e80047, "Chrontel HDMI",	patch_generic_hdmi),
HDA_CODEC_ENTRY(0x67663d82, "Arise 82 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x67663d83, "Arise 83 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x67663d84, "Arise 84 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x67663d85, "Arise 85 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x67663d86, "Arise 86 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x67663d87, "Arise 87 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x11069f84, "VX11 HDMI/DP",	patch_generic_hdmi),
HDA_CODEC_ENTRY(0x11069f85, "VX11 HDMI/DP",	patch_generic_hdmi),
HDA_CODEC_ENTRY(0x1d179f86, "ZX-100S HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f87, "ZX-100S HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f88, "KX-5000 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f89, "KX-5000 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f8a, "KX-6000 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f8b, "KX-6000 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f8c, "KX-6000G HDMI/DP", patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f8d, "KX-6000G HDMI/DP", patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f8e, "KX-7000 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f8f, "KX-7000 HDMI/DP",	patch_gf_hdmi),
HDA_CODEC_ENTRY(0x1d179f90, "KX-7000 HDMI/DP",	patch_gf_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(0x80862880, "CedarTrail HDMI",	patch_generic_hdmi),
HDA_CODEC_ENTRY(0x808629fb, "Crestline HDMI",	patch_generic_hdmi),
static const struct hda_device_id snd_hda_id_generichdmi[] = {
	HDA_CODEC_ID_MODEL(0x00147a47, "Loongson HDMI",		MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x10951390, "SiI1390 HDMI",		MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x10951392, "SiI1392 HDMI",		MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x11069f84, "VX11 HDMI/DP",		MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x11069f85, "VX11 HDMI/DP",		MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x17e80047, "Chrontel HDMI",		MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x1d179f86, "ZX-100S HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f87, "ZX-100S HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f88, "KX-5000 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f89, "KX-5000 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f8a, "KX-6000 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f8b, "KX-6000 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f8c, "KX-6000G HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f8d, "KX-6000G HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f8e, "KX-7000 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f8f, "KX-7000 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x1d179f90, "KX-7000 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x67663d82, "Arise 82 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x67663d83, "Arise 83 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x67663d84, "Arise 84 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x67663d85, "Arise 85 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x67663d86, "Arise 86 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x67663d87, "Arise 87 HDMI/DP",	MODEL_GF),
	HDA_CODEC_ID_MODEL(0x80862801, "Bearlake HDMI",		MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x80862802, "Cantiga HDMI",		MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x80862803, "Eaglelake HDMI",	MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x80862880, "CedarTrail HDMI",	MODEL_GENERIC),
	HDA_CODEC_ID_MODEL(0x808629fb, "Crestline HDMI",	MODEL_GENERIC),
	/* special ID for generic HDMI */
HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC_HDMI, "Generic HDMI", patch_generic_hdmi),
	HDA_CODEC_ID_MODEL(HDA_CODEC_ID_GENERIC_HDMI, "Generic HDMI", MODEL_GENERIC),
	{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_hdmi);
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generichdmi);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("HDMI HD-audio codec");
MODULE_DESCRIPTION("Generic HDMI HD-audio codec");

static struct hda_codec_driver hdmi_driver = {
	.id = snd_hda_id_hdmi,
static struct hda_codec_driver generichdmi_driver = {
	.id = snd_hda_id_generichdmi,
	.ops = &generichdmi_codec_ops,
};

module_hda_codec_driver(hdmi_driver);
module_hda_codec_driver(generichdmi_driver);
+5 −5
Original line number Diff line number Diff line
@@ -237,8 +237,8 @@ union audio_infoframe {
/* Generic HDMI codec support */
int snd_hda_hdmi_generic_alloc(struct hda_codec *codec);
int snd_hda_hdmi_parse_codec(struct hda_codec *codec);
int patch_generic_hdmi(struct hda_codec *codec);
void snd_hda_hdmi_generic_free(struct hda_codec *codec);
int snd_hda_hdmi_generic_probe(struct hda_codec *codec);
void snd_hda_hdmi_generic_remove(struct hda_codec *codec);

int snd_hda_hdmi_generic_build_pcms(struct hda_codec *codec);
int snd_hda_hdmi_generic_build_controls(struct hda_codec *codec);
@@ -286,9 +286,9 @@ void snd_hda_hdmi_acomp_master_unbind(struct device *dev,
				      struct drm_audio_component *acomp);

/* Simple / legacy HDMI codec support */
int patch_simple_hdmi(struct hda_codec *codec,
int snd_hda_hdmi_simple_probe(struct hda_codec *codec,
			      hda_nid_t cvt_nid, hda_nid_t pin_nid);
void snd_hda_hdmi_simple_free(struct hda_codec *codec);
void snd_hda_hdmi_simple_remove(struct hda_codec *codec);

int snd_hda_hdmi_simple_build_pcms(struct hda_codec *codec);
int snd_hda_hdmi_simple_build_controls(struct hda_codec *codec);
+118 −67
Original line number Diff line number Diff line
@@ -18,6 +18,16 @@ IS_ENABLED(CONFIG_SND_HDA_INTEL_HDMI_SILENT_STREAM);
module_param(enable_silent_stream, bool, 0644);
MODULE_PARM_DESC(enable_silent_stream, "Enable Silent Stream for HDMI devices");

enum {
	MODEL_HSW,
	MODEL_GLK,
	MODEL_ICL,
	MODEL_TGL,
	MODEL_ADLP,
	MODEL_BYT,
	MODEL_CPT,
};

#define INTEL_GET_VENDOR_VERB	0xf81
#define INTEL_SET_VENDOR_VERB	0x781
#define INTEL_EN_DP12		0x02	/* enable DP 1.2 features */
@@ -67,10 +77,13 @@ static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec)
static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
				unsigned int power_state)
{
	/* check codec->spec: it can be called before the probe gets called */
	if (codec->spec) {
		if (power_state == AC_PWRST_D0) {
			intel_haswell_enable_all_pins(codec, false);
			intel_haswell_fixup_enable_dp12(codec);
		}
	}

	snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state);
	snd_hda_codec_set_power_to_all(codec, fg, power_state);
@@ -456,13 +469,15 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec,
	}
}

static int i915_adlp_hdmi_suspend(struct hda_codec *codec)
static int i915_hdmi_suspend(struct hda_codec *codec)
{
	struct hdmi_spec *spec = codec->spec;
	bool silent_streams = false;
	int pin_idx, res;

	res = snd_hda_hdmi_generic_suspend(codec);
	if (spec->silent_stream_type != SILENT_STREAM_KAE)
		return res;

	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
		struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
@@ -495,12 +510,14 @@ static int i915_adlp_hdmi_suspend(struct hda_codec *codec)
	return res;
}

static int i915_adlp_hdmi_resume(struct hda_codec *codec)
static int i915_hdmi_resume(struct hda_codec *codec)
{
	struct hdmi_spec *spec = codec->spec;
	int pin_idx, res;

	res = snd_hda_hdmi_generic_resume(codec);
	if (spec->silent_stream_type != SILENT_STREAM_KAE)
		return res;

	/* KAE not programmed at suspend, nothing to do here */
	if (!codec->no_stream_clean_at_suspend)
@@ -539,8 +556,6 @@ static int i915_adlp_hdmi_resume(struct hda_codec *codec)
/* precondition and allocation for Intel codecs */
static int alloc_intel_hdmi(struct hda_codec *codec)
{
	int err;

	/* requires i915 binding */
	if (!codec->bus->core.audio_component) {
		codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
@@ -549,12 +564,7 @@ static int alloc_intel_hdmi(struct hda_codec *codec)
		return -ENODEV;
	}

	err = snd_hda_hdmi_generic_alloc(codec);
	if (err < 0)
		return err;
	/* no need to handle unsol events */
	codec->patch_ops.unsol_event = NULL;
	return 0;
	return snd_hda_hdmi_generic_alloc(codec);
}

/* parse and post-process for Intel codecs */
@@ -580,11 +590,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
				 bool send_silent_stream)
{
	struct hdmi_spec *spec;
	int err;

	err = alloc_intel_hdmi(codec);
	if (err < 0)
		return err;
	spec = codec->spec;
	codec->dp_mst = true;
	spec->vendor_nid = vendor_nid;
@@ -598,7 +604,6 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,

	codec->display_power_control = 1;

	codec->patch_ops.set_power_state = haswell_set_power_state;
	codec->depop_delay = 0;
	codec->auto_runtime_pm = 1;

@@ -616,13 +621,13 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
	return parse_intel_hdmi(codec);
}

static int patch_i915_hsw_hdmi(struct hda_codec *codec)
static int probe_i915_hsw_hdmi(struct hda_codec *codec)
{
	return intel_hsw_common_init(codec, 0x08, NULL, 0, 3,
				     enable_silent_stream);
}

static int patch_i915_glk_hdmi(struct hda_codec *codec)
static int probe_i915_glk_hdmi(struct hda_codec *codec)
{
	/*
	 * Silent stream calls audio component .get_power() from
@@ -632,7 +637,7 @@ static int patch_i915_glk_hdmi(struct hda_codec *codec)
	return intel_hsw_common_init(codec, 0x0b, NULL, 0, 3, false);
}

static int patch_i915_icl_hdmi(struct hda_codec *codec)
static int probe_i915_icl_hdmi(struct hda_codec *codec)
{
	/*
	 * pin to port mapping table where the value indicate the pin number and
@@ -644,7 +649,7 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec)
				     enable_silent_stream);
}

static int patch_i915_tgl_hdmi(struct hda_codec *codec)
static int probe_i915_tgl_hdmi(struct hda_codec *codec)
{
	/*
	 * pin to port mapping table where the value indicate the pin number and
@@ -656,35 +661,27 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec)
				     enable_silent_stream);
}

static int patch_i915_adlp_hdmi(struct hda_codec *codec)
static int probe_i915_adlp_hdmi(struct hda_codec *codec)
{
	struct hdmi_spec *spec;
	int res;

	res = patch_i915_tgl_hdmi(codec);
	res = probe_i915_tgl_hdmi(codec);
	if (!res) {
		spec = codec->spec;

		if (spec->silent_stream_type) {
		if (spec->silent_stream_type)
			spec->silent_stream_type = SILENT_STREAM_KAE;

			codec->patch_ops.resume = i915_adlp_hdmi_resume;
			codec->patch_ops.suspend = i915_adlp_hdmi_suspend;
		}
	}

	return res;
}

/* Intel Baytrail and Braswell; with eld notifier */
static int patch_i915_byt_hdmi(struct hda_codec *codec)
static int probe_i915_byt_hdmi(struct hda_codec *codec)
{
	struct hdmi_spec *spec;
	int err;

	err = alloc_intel_hdmi(codec);
	if (err < 0)
		return err;
	spec = codec->spec;

	/* For Valleyview/Cherryview, only the display codec is in the display
@@ -701,50 +698,103 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec)
}

/* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */
static int patch_i915_cpt_hdmi(struct hda_codec *codec)
static int probe_i915_cpt_hdmi(struct hda_codec *codec)
{
	return parse_intel_hdmi(codec);
}

/*
 * common driver probe
 */
static int intelhdmi_probe(struct hda_codec *codec, const struct hda_device_id *id)
{
	int err;

	err = alloc_intel_hdmi(codec);
	if (err < 0)
		return err;
	return parse_intel_hdmi(codec);

	switch (id->driver_data) {
	case MODEL_HSW:
		err = probe_i915_hsw_hdmi(codec);
		break;
	case MODEL_GLK:
		err = probe_i915_glk_hdmi(codec);
		break;
	case MODEL_ICL:
		err = probe_i915_icl_hdmi(codec);
		break;
	case MODEL_TGL:
		err = probe_i915_tgl_hdmi(codec);
		break;
	case MODEL_ADLP:
		err = probe_i915_adlp_hdmi(codec);
		break;
	case MODEL_BYT:
		err = probe_i915_byt_hdmi(codec);
		break;
	case MODEL_CPT:
		err = probe_i915_cpt_hdmi(codec);
		break;
	default:
		err = -EINVAL;
		break;
	}

	if (err < 0) {
		snd_hda_hdmi_generic_spec_free(codec);
		return err;
	}

	return 0;
}

static const struct hda_codec_ops intelhdmi_codec_ops = {
	.probe = intelhdmi_probe,
	.remove = snd_hda_hdmi_generic_remove,
	.init = snd_hda_hdmi_generic_init,
	.build_pcms = snd_hda_hdmi_generic_build_pcms,
	.build_controls = snd_hda_hdmi_generic_build_controls,
	.unsol_event = snd_hda_hdmi_generic_unsol_event,
	.suspend = i915_hdmi_suspend,
	.resume = i915_hdmi_resume,
	.set_power_state = haswell_set_power_state,
};

/*
 * driver entries
 */
static const struct hda_device_id snd_hda_id_intelhdmi[] = {
HDA_CODEC_ENTRY(0x80860054, "IbexPeak HDMI",	patch_i915_cpt_hdmi),
HDA_CODEC_ENTRY(0x80862800, "Geminilake HDMI",	patch_i915_glk_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(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(0x80862814, "DG1 HDMI",	patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI",	patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI",	patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862818, "Raptorlake HDMI",	patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862819, "DG2 HDMI",	patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI",	patch_i915_icl_hdmi),
HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI",	patch_i915_icl_hdmi),
HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x8086281d, "Meteor Lake HDMI",	patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x8086281e, "Battlemage HDMI",	patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x8086281f, "Raptor Lake P HDMI",	patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x80862820, "Lunar Lake HDMI",	patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x80862822, "Panther Lake HDMI",	patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x80862823, "Wildcat Lake HDMI",	patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI",	patch_i915_byt_hdmi),
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI",	patch_i915_byt_hdmi),
	HDA_CODEC_ID_MODEL(0x80860054, "IbexPeak HDMI",		MODEL_CPT),
	HDA_CODEC_ID_MODEL(0x80862800, "Geminilake HDMI",	MODEL_GLK),
	HDA_CODEC_ID_MODEL(0x80862804, "IbexPeak HDMI",		MODEL_CPT),
	HDA_CODEC_ID_MODEL(0x80862805, "CougarPoint HDMI",	MODEL_CPT),
	HDA_CODEC_ID_MODEL(0x80862806, "PantherPoint HDMI",	MODEL_CPT),
	HDA_CODEC_ID_MODEL(0x80862807, "Haswell HDMI",		MODEL_HSW),
	HDA_CODEC_ID_MODEL(0x80862808, "Broadwell HDMI",	MODEL_HSW),
	HDA_CODEC_ID_MODEL(0x80862809, "Skylake HDMI",		MODEL_HSW),
	HDA_CODEC_ID_MODEL(0x8086280a, "Broxton HDMI",		MODEL_HSW),
	HDA_CODEC_ID_MODEL(0x8086280b, "Kabylake HDMI",		MODEL_HSW),
	HDA_CODEC_ID_MODEL(0x8086280c, "Cannonlake HDMI",	MODEL_GLK),
	HDA_CODEC_ID_MODEL(0x8086280d, "Geminilake HDMI",	MODEL_GLK),
	HDA_CODEC_ID_MODEL(0x8086280f, "Icelake HDMI",		MODEL_ICL),
	HDA_CODEC_ID_MODEL(0x80862812, "Tigerlake HDMI",	MODEL_TGL),
	HDA_CODEC_ID_MODEL(0x80862814, "DG1 HDMI",		MODEL_TGL),
	HDA_CODEC_ID_MODEL(0x80862815, "Alderlake HDMI",	MODEL_TGL),
	HDA_CODEC_ID_MODEL(0x80862816, "Rocketlake HDMI",	MODEL_TGL),
	HDA_CODEC_ID_MODEL(0x80862818, "Raptorlake HDMI",	MODEL_TGL),
	HDA_CODEC_ID_MODEL(0x80862819, "DG2 HDMI",		MODEL_TGL),
	HDA_CODEC_ID_MODEL(0x8086281a, "Jasperlake HDMI",	MODEL_ICL),
	HDA_CODEC_ID_MODEL(0x8086281b, "Elkhartlake HDMI",	MODEL_ICL),
	HDA_CODEC_ID_MODEL(0x8086281c, "Alderlake-P HDMI",	MODEL_ADLP),
	HDA_CODEC_ID_MODEL(0x8086281d, "Meteor Lake HDMI",	MODEL_ADLP),
	HDA_CODEC_ID_MODEL(0x8086281e, "Battlemage HDMI",	MODEL_ADLP),
	HDA_CODEC_ID_MODEL(0x8086281f, "Raptor Lake P HDMI",	MODEL_ADLP),
	HDA_CODEC_ID_MODEL(0x80862820, "Lunar Lake HDMI",	MODEL_ADLP),
	HDA_CODEC_ID_MODEL(0x80862822, "Panther Lake HDMI",	MODEL_ADLP),
	HDA_CODEC_ID_MODEL(0x80862823, "Wildcat Lake HDMI",	MODEL_ADLP),
	HDA_CODEC_ID_MODEL(0x80862882, "Valleyview2 HDMI",	MODEL_BYT),
	HDA_CODEC_ID_MODEL(0x80862883, "Braswell HDMI",		MODEL_BYT),
	{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_intelhdmi);
@@ -755,6 +805,7 @@ MODULE_IMPORT_NS("SND_HDA_CODEC_HDMI");

static struct hda_codec_driver intelhdmi_driver = {
	.id = snd_hda_id_intelhdmi,
	.ops = &intelhdmi_codec_ops,
};

module_hda_codec_driver(intelhdmi_driver);
+49 −47
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@
#include "hda_local.h"
#include "hdmi_local.h"

enum { MODEL_2CH, MODEL_8CH };

#define Nv_VERB_SET_Channel_Allocation          0xF79
#define Nv_VERB_SET_Info_Frame_Checksum         0xF7A
#define Nv_VERB_SET_Audio_Protection_On         0xF98
@@ -45,14 +47,13 @@ static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = {
	{} /* terminator */
};

static int nvhdmi_7x_init_2ch(struct hda_codec *codec)
static int nvhdmi_mcp_init(struct hda_codec *codec)
{
	snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch);
	return 0;
}
	struct hdmi_spec *spec = codec->spec;

static int nvhdmi_7x_init_8ch(struct hda_codec *codec)
{
	if (spec->multiout.max_channels == 2)
		snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch);
	else
		snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch);
	return 0;
}
@@ -233,31 +234,13 @@ static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
	},
};

static int patch_nvhdmi_2ch(struct hda_codec *codec)
{
	struct hdmi_spec *spec;
	int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x,
				    nvhdmi_master_pin_nid_7x);
	if (err < 0)
		return err;

	codec->patch_ops.init = nvhdmi_7x_init_2ch;
	/* override the PCM rates, etc, as the codec doesn't give full list */
	spec = codec->spec;
	spec->pcm_playback.rates = SUPPORTED_RATES;
	spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
	spec->pcm_playback.formats = SUPPORTED_FORMATS;
	spec->nv_dp_workaround = true;
	return 0;
}

static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec)
static int nvhdmi_mcp_build_pcms(struct hda_codec *codec)
{
	struct hdmi_spec *spec = codec->spec;
	int err;

	err = snd_hda_hdmi_simple_build_pcms(codec);
	if (!err) {
	if (!err && spec->multiout.max_channels == 8) {
		struct hda_pcm *info = get_pcm_rec(spec, 0);

		info->own_chmap = true;
@@ -265,7 +248,7 @@ static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec)
	return err;
}

static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
static int nvhdmi_mcp_build_controls(struct hda_codec *codec)
{
	struct hdmi_spec *spec = codec->spec;
	struct hda_pcm *info;
@@ -276,6 +259,9 @@ static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
	if (err < 0)
		return err;

	if (spec->multiout.max_channels != 8)
		return 0;

	/* add channel maps */
	info = get_pcm_rec(spec, 0);
	err = snd_pcm_add_chmap_ctls(info->pcm,
@@ -316,20 +302,29 @@ static const struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = {
	.mask = 0,
};

static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
static int nvhdmi_mcp_probe(struct hda_codec *codec,
			    const struct hda_device_id *id)
{
	struct hdmi_spec *spec;
	int err;

	err = patch_nvhdmi_2ch(codec);
	err = snd_hda_hdmi_simple_probe(codec, nvhdmi_master_con_nid_7x,
					nvhdmi_master_pin_nid_7x);
	if (err < 0)
		return err;

	/* override the PCM rates, etc, as the codec doesn't give full list */
	spec = codec->spec;
	spec->pcm_playback.rates = SUPPORTED_RATES;
	spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
	spec->pcm_playback.formats = SUPPORTED_FORMATS;
	spec->nv_dp_workaround = true;

	if (id->driver_data == MODEL_2CH)
		return 0;

	spec->multiout.max_channels = 8;
	spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x;
	codec->patch_ops.init = nvhdmi_7x_init_8ch;
	codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms;
	codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls;

	switch (codec->preset->vendor_id) {
	case 0x10de0002:
@@ -353,20 +348,26 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
	return 0;
}

/*
 * patch entries
 */
static const struct hda_codec_ops nvhdmi_mcp_codec_ops = {
	.probe = nvhdmi_mcp_probe,
	.remove = snd_hda_hdmi_simple_remove,
	.build_controls = nvhdmi_mcp_build_pcms,
	.build_pcms = nvhdmi_mcp_build_controls,
	.init = nvhdmi_mcp_init,
	.unsol_event = snd_hda_hdmi_simple_unsol_event,
};

static const struct hda_device_id snd_hda_id_nvhdmi_mcp[] = {
HDA_CODEC_ENTRY(0x10de0001, "MCP73 HDMI",	patch_nvhdmi_2ch),
HDA_CODEC_ENTRY(0x10de0002, "MCP77/78 HDMI",	patch_nvhdmi_8ch_7x),
HDA_CODEC_ENTRY(0x10de0003, "MCP77/78 HDMI",	patch_nvhdmi_8ch_7x),
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(0x10de0067, "MCP67 HDMI",	patch_nvhdmi_2ch),
HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI",	patch_nvhdmi_2ch),
HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI",	patch_nvhdmi_2ch),
	HDA_CODEC_ID_MODEL(0x10de0001, "MCP73 HDMI",	MODEL_2CH),
	HDA_CODEC_ID_MODEL(0x10de0002, "MCP77/78 HDMI",	MODEL_8CH),
	HDA_CODEC_ID_MODEL(0x10de0003, "MCP77/78 HDMI",	MODEL_8CH),
	HDA_CODEC_ID_MODEL(0x10de0004, "GPU 04 HDMI",	MODEL_8CH),
	HDA_CODEC_ID_MODEL(0x10de0005, "MCP77/78 HDMI",	MODEL_8CH),
	HDA_CODEC_ID_MODEL(0x10de0006, "MCP77/78 HDMI",	MODEL_8CH),
	HDA_CODEC_ID_MODEL(0x10de0007, "MCP79/7A HDMI",	MODEL_8CH),
	HDA_CODEC_ID_MODEL(0x10de0067, "MCP67 HDMI",	MODEL_2CH),
	HDA_CODEC_ID_MODEL(0x10de8001, "MCP73 HDMI",	MODEL_2CH),
	HDA_CODEC_ID_MODEL(0x10de8067, "MCP67/68 HDMI",	MODEL_2CH),
	{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_nvhdmi_mcp);
@@ -377,6 +378,7 @@ MODULE_IMPORT_NS("SND_HDA_CODEC_HDMI");

static struct hda_codec_driver nvhdmi_mcp_driver = {
	.id = snd_hda_id_nvhdmi_mcp,
	.ops = &nvhdmi_mcp_codec_ops,
};

module_hda_codec_driver(nvhdmi_mcp_driver);
Loading