xref: /linux/sound/hda/codecs/hdmi/nvhdmi-mcp.c (revision ad781b550f9a8829e3dae4bd3d18c4a126a53d04)
173cd0490STakashi Iwai // SPDX-License-Identifier: GPL-2.0-or-later
273cd0490STakashi Iwai /*
373cd0490STakashi Iwai  * Legacy Nvidia HDMI codec support
473cd0490STakashi Iwai  */
573cd0490STakashi Iwai 
673cd0490STakashi Iwai #include <linux/init.h>
773cd0490STakashi Iwai #include <linux/slab.h>
873cd0490STakashi Iwai #include <linux/module.h>
973cd0490STakashi Iwai #include <sound/core.h>
1073cd0490STakashi Iwai #include <sound/hdaudio.h>
1173cd0490STakashi Iwai #include <sound/hda_codec.h>
1273cd0490STakashi Iwai #include "hda_local.h"
1373cd0490STakashi Iwai #include "hdmi_local.h"
1473cd0490STakashi Iwai 
15*ad781b55STakashi Iwai enum { MODEL_2CH, MODEL_8CH };
16*ad781b55STakashi Iwai 
1773cd0490STakashi Iwai #define Nv_VERB_SET_Channel_Allocation          0xF79
1873cd0490STakashi Iwai #define Nv_VERB_SET_Info_Frame_Checksum         0xF7A
1973cd0490STakashi Iwai #define Nv_VERB_SET_Audio_Protection_On         0xF98
2073cd0490STakashi Iwai #define Nv_VERB_SET_Audio_Protection_Off        0xF99
2173cd0490STakashi Iwai 
2273cd0490STakashi Iwai #define nvhdmi_master_con_nid_7x	0x04
2373cd0490STakashi Iwai #define nvhdmi_master_pin_nid_7x	0x05
2473cd0490STakashi Iwai 
2573cd0490STakashi Iwai static const hda_nid_t nvhdmi_con_nids_7x[4] = {
2673cd0490STakashi Iwai 	/*front, rear, clfe, rear_surr */
2773cd0490STakashi Iwai 	0x6, 0x8, 0xa, 0xc,
2873cd0490STakashi Iwai };
2973cd0490STakashi Iwai 
3073cd0490STakashi Iwai static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = {
3173cd0490STakashi Iwai 	/* set audio protect on */
3273cd0490STakashi Iwai 	{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
3373cd0490STakashi Iwai 	/* enable digital output on pin widget */
3473cd0490STakashi Iwai 	{ 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
3573cd0490STakashi Iwai 	{} /* terminator */
3673cd0490STakashi Iwai };
3773cd0490STakashi Iwai 
3873cd0490STakashi Iwai static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = {
3973cd0490STakashi Iwai 	/* set audio protect on */
4073cd0490STakashi Iwai 	{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
4173cd0490STakashi Iwai 	/* enable digital output on pin widget */
4273cd0490STakashi Iwai 	{ 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
4373cd0490STakashi Iwai 	{ 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
4473cd0490STakashi Iwai 	{ 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
4573cd0490STakashi Iwai 	{ 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
4673cd0490STakashi Iwai 	{ 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
4773cd0490STakashi Iwai 	{} /* terminator */
4873cd0490STakashi Iwai };
4973cd0490STakashi Iwai 
50*ad781b55STakashi Iwai static int nvhdmi_mcp_init(struct hda_codec *codec)
5173cd0490STakashi Iwai {
52*ad781b55STakashi Iwai 	struct hdmi_spec *spec = codec->spec;
5373cd0490STakashi Iwai 
54*ad781b55STakashi Iwai 	if (spec->multiout.max_channels == 2)
55*ad781b55STakashi Iwai 		snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch);
56*ad781b55STakashi Iwai 	else
5773cd0490STakashi Iwai 		snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch);
5873cd0490STakashi Iwai 	return 0;
5973cd0490STakashi Iwai }
6073cd0490STakashi Iwai 
6173cd0490STakashi Iwai static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec,
6273cd0490STakashi Iwai 						    int channels)
6373cd0490STakashi Iwai {
6473cd0490STakashi Iwai 	unsigned int chanmask;
6573cd0490STakashi Iwai 	int chan = channels ? (channels - 1) : 1;
6673cd0490STakashi Iwai 
6773cd0490STakashi Iwai 	switch (channels) {
6873cd0490STakashi Iwai 	default:
6973cd0490STakashi Iwai 	case 0:
7073cd0490STakashi Iwai 	case 2:
7173cd0490STakashi Iwai 		chanmask = 0x00;
7273cd0490STakashi Iwai 		break;
7373cd0490STakashi Iwai 	case 4:
7473cd0490STakashi Iwai 		chanmask = 0x08;
7573cd0490STakashi Iwai 		break;
7673cd0490STakashi Iwai 	case 6:
7773cd0490STakashi Iwai 		chanmask = 0x0b;
7873cd0490STakashi Iwai 		break;
7973cd0490STakashi Iwai 	case 8:
8073cd0490STakashi Iwai 		chanmask = 0x13;
8173cd0490STakashi Iwai 		break;
8273cd0490STakashi Iwai 	}
8373cd0490STakashi Iwai 
8473cd0490STakashi Iwai 	/* Set the audio infoframe channel allocation and checksum fields.  The
8573cd0490STakashi Iwai 	 * channel count is computed implicitly by the hardware.
8673cd0490STakashi Iwai 	 */
8773cd0490STakashi Iwai 	snd_hda_codec_write(codec, 0x1, 0,
8873cd0490STakashi Iwai 			Nv_VERB_SET_Channel_Allocation, chanmask);
8973cd0490STakashi Iwai 
9073cd0490STakashi Iwai 	snd_hda_codec_write(codec, 0x1, 0,
9173cd0490STakashi Iwai 			Nv_VERB_SET_Info_Frame_Checksum,
9273cd0490STakashi Iwai 			(0x71 - chan - chanmask));
9373cd0490STakashi Iwai }
9473cd0490STakashi Iwai 
9573cd0490STakashi Iwai static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
9673cd0490STakashi Iwai 				   struct hda_codec *codec,
9773cd0490STakashi Iwai 				   struct snd_pcm_substream *substream)
9873cd0490STakashi Iwai {
9973cd0490STakashi Iwai 	struct hdmi_spec *spec = codec->spec;
10073cd0490STakashi Iwai 	int i;
10173cd0490STakashi Iwai 
10273cd0490STakashi Iwai 	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
10373cd0490STakashi Iwai 			0, AC_VERB_SET_CHANNEL_STREAMID, 0);
10473cd0490STakashi Iwai 	for (i = 0; i < 4; i++) {
10573cd0490STakashi Iwai 		/* set the stream id */
10673cd0490STakashi Iwai 		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
10773cd0490STakashi Iwai 				AC_VERB_SET_CHANNEL_STREAMID, 0);
10873cd0490STakashi Iwai 		/* set the stream format */
10973cd0490STakashi Iwai 		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
11073cd0490STakashi Iwai 				AC_VERB_SET_STREAM_FORMAT, 0);
11173cd0490STakashi Iwai 	}
11273cd0490STakashi Iwai 
11373cd0490STakashi Iwai 	/* The audio hardware sends a channel count of 0x7 (8ch) when all the
11473cd0490STakashi Iwai 	 * streams are disabled.
11573cd0490STakashi Iwai 	 */
11673cd0490STakashi Iwai 	nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
11773cd0490STakashi Iwai 
11873cd0490STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
11973cd0490STakashi Iwai }
12073cd0490STakashi Iwai 
12173cd0490STakashi Iwai static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
12273cd0490STakashi Iwai 				     struct hda_codec *codec,
12373cd0490STakashi Iwai 				     unsigned int stream_tag,
12473cd0490STakashi Iwai 				     unsigned int format,
12573cd0490STakashi Iwai 				     struct snd_pcm_substream *substream)
12673cd0490STakashi Iwai {
12773cd0490STakashi Iwai 	int chs;
12873cd0490STakashi Iwai 	unsigned int dataDCC2, channel_id;
12973cd0490STakashi Iwai 	int i;
13073cd0490STakashi Iwai 	struct hdmi_spec *spec = codec->spec;
13173cd0490STakashi Iwai 	struct hda_spdif_out *spdif;
13273cd0490STakashi Iwai 	struct hdmi_spec_per_cvt *per_cvt;
13373cd0490STakashi Iwai 
13473cd0490STakashi Iwai 	mutex_lock(&codec->spdif_mutex);
13573cd0490STakashi Iwai 	per_cvt = get_cvt(spec, 0);
13673cd0490STakashi Iwai 	spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid);
13773cd0490STakashi Iwai 
13873cd0490STakashi Iwai 	chs = substream->runtime->channels;
13973cd0490STakashi Iwai 
14073cd0490STakashi Iwai 	dataDCC2 = 0x2;
14173cd0490STakashi Iwai 
14273cd0490STakashi Iwai 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
14373cd0490STakashi Iwai 	if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
14473cd0490STakashi Iwai 		snd_hda_codec_write(codec,
14573cd0490STakashi Iwai 				nvhdmi_master_con_nid_7x,
14673cd0490STakashi Iwai 				0,
14773cd0490STakashi Iwai 				AC_VERB_SET_DIGI_CONVERT_1,
14873cd0490STakashi Iwai 				spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
14973cd0490STakashi Iwai 
15073cd0490STakashi Iwai 	/* set the stream id */
15173cd0490STakashi Iwai 	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
15273cd0490STakashi Iwai 			AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
15373cd0490STakashi Iwai 
15473cd0490STakashi Iwai 	/* set the stream format */
15573cd0490STakashi Iwai 	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
15673cd0490STakashi Iwai 			AC_VERB_SET_STREAM_FORMAT, format);
15773cd0490STakashi Iwai 
15873cd0490STakashi Iwai 	/* turn on again (if needed) */
15973cd0490STakashi Iwai 	/* enable and set the channel status audio/data flag */
16073cd0490STakashi Iwai 	if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) {
16173cd0490STakashi Iwai 		snd_hda_codec_write(codec,
16273cd0490STakashi Iwai 				nvhdmi_master_con_nid_7x,
16373cd0490STakashi Iwai 				0,
16473cd0490STakashi Iwai 				AC_VERB_SET_DIGI_CONVERT_1,
16573cd0490STakashi Iwai 				spdif->ctls & 0xff);
16673cd0490STakashi Iwai 		snd_hda_codec_write(codec,
16773cd0490STakashi Iwai 				nvhdmi_master_con_nid_7x,
16873cd0490STakashi Iwai 				0,
16973cd0490STakashi Iwai 				AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
17073cd0490STakashi Iwai 	}
17173cd0490STakashi Iwai 
17273cd0490STakashi Iwai 	for (i = 0; i < 4; i++) {
17373cd0490STakashi Iwai 		if (chs == 2)
17473cd0490STakashi Iwai 			channel_id = 0;
17573cd0490STakashi Iwai 		else
17673cd0490STakashi Iwai 			channel_id = i * 2;
17773cd0490STakashi Iwai 
17873cd0490STakashi Iwai 		/* turn off SPDIF once;
17973cd0490STakashi Iwai 		 *otherwise the IEC958 bits won't be updated
18073cd0490STakashi Iwai 		 */
18173cd0490STakashi Iwai 		if (codec->spdif_status_reset &&
18273cd0490STakashi Iwai 		(spdif->ctls & AC_DIG1_ENABLE))
18373cd0490STakashi Iwai 			snd_hda_codec_write(codec,
18473cd0490STakashi Iwai 				nvhdmi_con_nids_7x[i],
18573cd0490STakashi Iwai 				0,
18673cd0490STakashi Iwai 				AC_VERB_SET_DIGI_CONVERT_1,
18773cd0490STakashi Iwai 				spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
18873cd0490STakashi Iwai 		/* set the stream id */
18973cd0490STakashi Iwai 		snd_hda_codec_write(codec,
19073cd0490STakashi Iwai 				nvhdmi_con_nids_7x[i],
19173cd0490STakashi Iwai 				0,
19273cd0490STakashi Iwai 				AC_VERB_SET_CHANNEL_STREAMID,
19373cd0490STakashi Iwai 				(stream_tag << 4) | channel_id);
19473cd0490STakashi Iwai 		/* set the stream format */
19573cd0490STakashi Iwai 		snd_hda_codec_write(codec,
19673cd0490STakashi Iwai 				nvhdmi_con_nids_7x[i],
19773cd0490STakashi Iwai 				0,
19873cd0490STakashi Iwai 				AC_VERB_SET_STREAM_FORMAT,
19973cd0490STakashi Iwai 				format);
20073cd0490STakashi Iwai 		/* turn on again (if needed) */
20173cd0490STakashi Iwai 		/* enable and set the channel status audio/data flag */
20273cd0490STakashi Iwai 		if (codec->spdif_status_reset &&
20373cd0490STakashi Iwai 		(spdif->ctls & AC_DIG1_ENABLE)) {
20473cd0490STakashi Iwai 			snd_hda_codec_write(codec,
20573cd0490STakashi Iwai 					nvhdmi_con_nids_7x[i],
20673cd0490STakashi Iwai 					0,
20773cd0490STakashi Iwai 					AC_VERB_SET_DIGI_CONVERT_1,
20873cd0490STakashi Iwai 					spdif->ctls & 0xff);
20973cd0490STakashi Iwai 			snd_hda_codec_write(codec,
21073cd0490STakashi Iwai 					nvhdmi_con_nids_7x[i],
21173cd0490STakashi Iwai 					0,
21273cd0490STakashi Iwai 					AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
21373cd0490STakashi Iwai 		}
21473cd0490STakashi Iwai 	}
21573cd0490STakashi Iwai 
21673cd0490STakashi Iwai 	nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs);
21773cd0490STakashi Iwai 
21873cd0490STakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
21973cd0490STakashi Iwai 	return 0;
22073cd0490STakashi Iwai }
22173cd0490STakashi Iwai 
22273cd0490STakashi Iwai static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
22373cd0490STakashi Iwai 	.substreams = 1,
22473cd0490STakashi Iwai 	.channels_min = 2,
22573cd0490STakashi Iwai 	.channels_max = 8,
22673cd0490STakashi Iwai 	.nid = nvhdmi_master_con_nid_7x,
22773cd0490STakashi Iwai 	.rates = SUPPORTED_RATES,
22873cd0490STakashi Iwai 	.maxbps = SUPPORTED_MAXBPS,
22973cd0490STakashi Iwai 	.formats = SUPPORTED_FORMATS,
23073cd0490STakashi Iwai 	.ops = {
23173cd0490STakashi Iwai 		.open = snd_hda_hdmi_simple_pcm_open,
23273cd0490STakashi Iwai 		.close = nvhdmi_8ch_7x_pcm_close,
23373cd0490STakashi Iwai 		.prepare = nvhdmi_8ch_7x_pcm_prepare
23473cd0490STakashi Iwai 	},
23573cd0490STakashi Iwai };
23673cd0490STakashi Iwai 
237*ad781b55STakashi Iwai static int nvhdmi_mcp_build_pcms(struct hda_codec *codec)
23873cd0490STakashi Iwai {
23973cd0490STakashi Iwai 	struct hdmi_spec *spec = codec->spec;
24073cd0490STakashi Iwai 	int err;
24173cd0490STakashi Iwai 
24273cd0490STakashi Iwai 	err = snd_hda_hdmi_simple_build_pcms(codec);
243*ad781b55STakashi Iwai 	if (!err && spec->multiout.max_channels == 8) {
24473cd0490STakashi Iwai 		struct hda_pcm *info = get_pcm_rec(spec, 0);
24573cd0490STakashi Iwai 
24673cd0490STakashi Iwai 		info->own_chmap = true;
24773cd0490STakashi Iwai 	}
24873cd0490STakashi Iwai 	return err;
24973cd0490STakashi Iwai }
25073cd0490STakashi Iwai 
251*ad781b55STakashi Iwai static int nvhdmi_mcp_build_controls(struct hda_codec *codec)
25273cd0490STakashi Iwai {
25373cd0490STakashi Iwai 	struct hdmi_spec *spec = codec->spec;
25473cd0490STakashi Iwai 	struct hda_pcm *info;
25573cd0490STakashi Iwai 	struct snd_pcm_chmap *chmap;
25673cd0490STakashi Iwai 	int err;
25773cd0490STakashi Iwai 
25873cd0490STakashi Iwai 	err = snd_hda_hdmi_simple_build_controls(codec);
25973cd0490STakashi Iwai 	if (err < 0)
26073cd0490STakashi Iwai 		return err;
26173cd0490STakashi Iwai 
262*ad781b55STakashi Iwai 	if (spec->multiout.max_channels != 8)
263*ad781b55STakashi Iwai 		return 0;
264*ad781b55STakashi Iwai 
26573cd0490STakashi Iwai 	/* add channel maps */
26673cd0490STakashi Iwai 	info = get_pcm_rec(spec, 0);
26773cd0490STakashi Iwai 	err = snd_pcm_add_chmap_ctls(info->pcm,
26873cd0490STakashi Iwai 				     SNDRV_PCM_STREAM_PLAYBACK,
26973cd0490STakashi Iwai 				     snd_pcm_alt_chmaps, 8, 0, &chmap);
27073cd0490STakashi Iwai 	if (err < 0)
27173cd0490STakashi Iwai 		return err;
27273cd0490STakashi Iwai 	switch (codec->preset->vendor_id) {
27373cd0490STakashi Iwai 	case 0x10de0002:
27473cd0490STakashi Iwai 	case 0x10de0003:
27573cd0490STakashi Iwai 	case 0x10de0005:
27673cd0490STakashi Iwai 	case 0x10de0006:
27773cd0490STakashi Iwai 		chmap->channel_mask = (1U << 2) | (1U << 8);
27873cd0490STakashi Iwai 		break;
27973cd0490STakashi Iwai 	case 0x10de0007:
28073cd0490STakashi Iwai 		chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8);
28173cd0490STakashi Iwai 	}
28273cd0490STakashi Iwai 	return 0;
28373cd0490STakashi Iwai }
28473cd0490STakashi Iwai 
28573cd0490STakashi Iwai static const unsigned int channels_2_6_8[] = {
28673cd0490STakashi Iwai 	2, 6, 8
28773cd0490STakashi Iwai };
28873cd0490STakashi Iwai 
28973cd0490STakashi Iwai static const unsigned int channels_2_8[] = {
29073cd0490STakashi Iwai 	2, 8
29173cd0490STakashi Iwai };
29273cd0490STakashi Iwai 
29373cd0490STakashi Iwai static const struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = {
29473cd0490STakashi Iwai 	.count = ARRAY_SIZE(channels_2_6_8),
29573cd0490STakashi Iwai 	.list = channels_2_6_8,
29673cd0490STakashi Iwai 	.mask = 0,
29773cd0490STakashi Iwai };
29873cd0490STakashi Iwai 
29973cd0490STakashi Iwai static const struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = {
30073cd0490STakashi Iwai 	.count = ARRAY_SIZE(channels_2_8),
30173cd0490STakashi Iwai 	.list = channels_2_8,
30273cd0490STakashi Iwai 	.mask = 0,
30373cd0490STakashi Iwai };
30473cd0490STakashi Iwai 
305*ad781b55STakashi Iwai static int nvhdmi_mcp_probe(struct hda_codec *codec,
306*ad781b55STakashi Iwai 			    const struct hda_device_id *id)
30773cd0490STakashi Iwai {
30873cd0490STakashi Iwai 	struct hdmi_spec *spec;
30973cd0490STakashi Iwai 	int err;
31073cd0490STakashi Iwai 
311*ad781b55STakashi Iwai 	err = snd_hda_hdmi_simple_probe(codec, nvhdmi_master_con_nid_7x,
312*ad781b55STakashi Iwai 					nvhdmi_master_pin_nid_7x);
31373cd0490STakashi Iwai 	if (err < 0)
31473cd0490STakashi Iwai 		return err;
315*ad781b55STakashi Iwai 
316*ad781b55STakashi Iwai 	/* override the PCM rates, etc, as the codec doesn't give full list */
31773cd0490STakashi Iwai 	spec = codec->spec;
318*ad781b55STakashi Iwai 	spec->pcm_playback.rates = SUPPORTED_RATES;
319*ad781b55STakashi Iwai 	spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
320*ad781b55STakashi Iwai 	spec->pcm_playback.formats = SUPPORTED_FORMATS;
321*ad781b55STakashi Iwai 	spec->nv_dp_workaround = true;
322*ad781b55STakashi Iwai 
323*ad781b55STakashi Iwai 	if (id->driver_data == MODEL_2CH)
324*ad781b55STakashi Iwai 		return 0;
325*ad781b55STakashi Iwai 
32673cd0490STakashi Iwai 	spec->multiout.max_channels = 8;
32773cd0490STakashi Iwai 	spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x;
32873cd0490STakashi Iwai 
32973cd0490STakashi Iwai 	switch (codec->preset->vendor_id) {
33073cd0490STakashi Iwai 	case 0x10de0002:
33173cd0490STakashi Iwai 	case 0x10de0003:
33273cd0490STakashi Iwai 	case 0x10de0005:
33373cd0490STakashi Iwai 	case 0x10de0006:
33473cd0490STakashi Iwai 		spec->hw_constraints_channels = &hw_constraints_2_8_channels;
33573cd0490STakashi Iwai 		break;
33673cd0490STakashi Iwai 	case 0x10de0007:
33773cd0490STakashi Iwai 		spec->hw_constraints_channels = &hw_constraints_2_6_8_channels;
33873cd0490STakashi Iwai 		break;
33973cd0490STakashi Iwai 	default:
34073cd0490STakashi Iwai 		break;
34173cd0490STakashi Iwai 	}
34273cd0490STakashi Iwai 
34373cd0490STakashi Iwai 	/* Initialize the audio infoframe channel mask and checksum to something
34473cd0490STakashi Iwai 	 * valid
34573cd0490STakashi Iwai 	 */
34673cd0490STakashi Iwai 	nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
34773cd0490STakashi Iwai 
34873cd0490STakashi Iwai 	return 0;
34973cd0490STakashi Iwai }
35073cd0490STakashi Iwai 
351*ad781b55STakashi Iwai static const struct hda_codec_ops nvhdmi_mcp_codec_ops = {
352*ad781b55STakashi Iwai 	.probe = nvhdmi_mcp_probe,
353*ad781b55STakashi Iwai 	.remove = snd_hda_hdmi_simple_remove,
354*ad781b55STakashi Iwai 	.build_controls = nvhdmi_mcp_build_pcms,
355*ad781b55STakashi Iwai 	.build_pcms = nvhdmi_mcp_build_controls,
356*ad781b55STakashi Iwai 	.init = nvhdmi_mcp_init,
357*ad781b55STakashi Iwai 	.unsol_event = snd_hda_hdmi_simple_unsol_event,
358*ad781b55STakashi Iwai };
359*ad781b55STakashi Iwai 
36073cd0490STakashi Iwai static const struct hda_device_id snd_hda_id_nvhdmi_mcp[] = {
361*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de0001, "MCP73 HDMI",	MODEL_2CH),
362*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de0002, "MCP77/78 HDMI",	MODEL_8CH),
363*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de0003, "MCP77/78 HDMI",	MODEL_8CH),
364*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de0004, "GPU 04 HDMI",	MODEL_8CH),
365*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de0005, "MCP77/78 HDMI",	MODEL_8CH),
366*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de0006, "MCP77/78 HDMI",	MODEL_8CH),
367*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de0007, "MCP79/7A HDMI",	MODEL_8CH),
368*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de0067, "MCP67 HDMI",	MODEL_2CH),
369*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de8001, "MCP73 HDMI",	MODEL_2CH),
370*ad781b55STakashi Iwai 	HDA_CODEC_ID_MODEL(0x10de8067, "MCP67/68 HDMI",	MODEL_2CH),
37173cd0490STakashi Iwai 	{} /* terminator */
37273cd0490STakashi Iwai };
37373cd0490STakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_nvhdmi_mcp);
37473cd0490STakashi Iwai 
37573cd0490STakashi Iwai MODULE_LICENSE("GPL");
37673cd0490STakashi Iwai MODULE_DESCRIPTION("Legacy Nvidia HDMI HD-audio codec");
37773cd0490STakashi Iwai MODULE_IMPORT_NS("SND_HDA_CODEC_HDMI");
37873cd0490STakashi Iwai 
37973cd0490STakashi Iwai static struct hda_codec_driver nvhdmi_mcp_driver = {
38073cd0490STakashi Iwai 	.id = snd_hda_id_nvhdmi_mcp,
381*ad781b55STakashi Iwai 	.ops = &nvhdmi_mcp_codec_ops,
38273cd0490STakashi Iwai };
38373cd0490STakashi Iwai 
38473cd0490STakashi Iwai module_hda_codec_driver(nvhdmi_mcp_driver);
385