xref: /linux/sound/hda/codecs/hdmi/nvhdmi-mcp.c (revision 73cd0490819d2a693928c5977280dd31b756cb42)
1*73cd0490STakashi Iwai // SPDX-License-Identifier: GPL-2.0-or-later
2*73cd0490STakashi Iwai /*
3*73cd0490STakashi Iwai  * Legacy Nvidia HDMI codec support
4*73cd0490STakashi Iwai  */
5*73cd0490STakashi Iwai 
6*73cd0490STakashi Iwai #include <linux/init.h>
7*73cd0490STakashi Iwai #include <linux/slab.h>
8*73cd0490STakashi Iwai #include <linux/module.h>
9*73cd0490STakashi Iwai #include <sound/core.h>
10*73cd0490STakashi Iwai #include <sound/hdaudio.h>
11*73cd0490STakashi Iwai #include <sound/hda_codec.h>
12*73cd0490STakashi Iwai #include "hda_local.h"
13*73cd0490STakashi Iwai #include "hdmi_local.h"
14*73cd0490STakashi Iwai 
15*73cd0490STakashi Iwai #define Nv_VERB_SET_Channel_Allocation          0xF79
16*73cd0490STakashi Iwai #define Nv_VERB_SET_Info_Frame_Checksum         0xF7A
17*73cd0490STakashi Iwai #define Nv_VERB_SET_Audio_Protection_On         0xF98
18*73cd0490STakashi Iwai #define Nv_VERB_SET_Audio_Protection_Off        0xF99
19*73cd0490STakashi Iwai 
20*73cd0490STakashi Iwai #define nvhdmi_master_con_nid_7x	0x04
21*73cd0490STakashi Iwai #define nvhdmi_master_pin_nid_7x	0x05
22*73cd0490STakashi Iwai 
23*73cd0490STakashi Iwai static const hda_nid_t nvhdmi_con_nids_7x[4] = {
24*73cd0490STakashi Iwai 	/*front, rear, clfe, rear_surr */
25*73cd0490STakashi Iwai 	0x6, 0x8, 0xa, 0xc,
26*73cd0490STakashi Iwai };
27*73cd0490STakashi Iwai 
28*73cd0490STakashi Iwai static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = {
29*73cd0490STakashi Iwai 	/* set audio protect on */
30*73cd0490STakashi Iwai 	{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
31*73cd0490STakashi Iwai 	/* enable digital output on pin widget */
32*73cd0490STakashi Iwai 	{ 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
33*73cd0490STakashi Iwai 	{} /* terminator */
34*73cd0490STakashi Iwai };
35*73cd0490STakashi Iwai 
36*73cd0490STakashi Iwai static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = {
37*73cd0490STakashi Iwai 	/* set audio protect on */
38*73cd0490STakashi Iwai 	{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
39*73cd0490STakashi Iwai 	/* enable digital output on pin widget */
40*73cd0490STakashi Iwai 	{ 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
41*73cd0490STakashi Iwai 	{ 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
42*73cd0490STakashi Iwai 	{ 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
43*73cd0490STakashi Iwai 	{ 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
44*73cd0490STakashi Iwai 	{ 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
45*73cd0490STakashi Iwai 	{} /* terminator */
46*73cd0490STakashi Iwai };
47*73cd0490STakashi Iwai 
48*73cd0490STakashi Iwai static int nvhdmi_7x_init_2ch(struct hda_codec *codec)
49*73cd0490STakashi Iwai {
50*73cd0490STakashi Iwai 	snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch);
51*73cd0490STakashi Iwai 	return 0;
52*73cd0490STakashi Iwai }
53*73cd0490STakashi Iwai 
54*73cd0490STakashi Iwai static int nvhdmi_7x_init_8ch(struct hda_codec *codec)
55*73cd0490STakashi Iwai {
56*73cd0490STakashi Iwai 	snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch);
57*73cd0490STakashi Iwai 	return 0;
58*73cd0490STakashi Iwai }
59*73cd0490STakashi Iwai 
60*73cd0490STakashi Iwai static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec,
61*73cd0490STakashi Iwai 						    int channels)
62*73cd0490STakashi Iwai {
63*73cd0490STakashi Iwai 	unsigned int chanmask;
64*73cd0490STakashi Iwai 	int chan = channels ? (channels - 1) : 1;
65*73cd0490STakashi Iwai 
66*73cd0490STakashi Iwai 	switch (channels) {
67*73cd0490STakashi Iwai 	default:
68*73cd0490STakashi Iwai 	case 0:
69*73cd0490STakashi Iwai 	case 2:
70*73cd0490STakashi Iwai 		chanmask = 0x00;
71*73cd0490STakashi Iwai 		break;
72*73cd0490STakashi Iwai 	case 4:
73*73cd0490STakashi Iwai 		chanmask = 0x08;
74*73cd0490STakashi Iwai 		break;
75*73cd0490STakashi Iwai 	case 6:
76*73cd0490STakashi Iwai 		chanmask = 0x0b;
77*73cd0490STakashi Iwai 		break;
78*73cd0490STakashi Iwai 	case 8:
79*73cd0490STakashi Iwai 		chanmask = 0x13;
80*73cd0490STakashi Iwai 		break;
81*73cd0490STakashi Iwai 	}
82*73cd0490STakashi Iwai 
83*73cd0490STakashi Iwai 	/* Set the audio infoframe channel allocation and checksum fields.  The
84*73cd0490STakashi Iwai 	 * channel count is computed implicitly by the hardware.
85*73cd0490STakashi Iwai 	 */
86*73cd0490STakashi Iwai 	snd_hda_codec_write(codec, 0x1, 0,
87*73cd0490STakashi Iwai 			Nv_VERB_SET_Channel_Allocation, chanmask);
88*73cd0490STakashi Iwai 
89*73cd0490STakashi Iwai 	snd_hda_codec_write(codec, 0x1, 0,
90*73cd0490STakashi Iwai 			Nv_VERB_SET_Info_Frame_Checksum,
91*73cd0490STakashi Iwai 			(0x71 - chan - chanmask));
92*73cd0490STakashi Iwai }
93*73cd0490STakashi Iwai 
94*73cd0490STakashi Iwai static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
95*73cd0490STakashi Iwai 				   struct hda_codec *codec,
96*73cd0490STakashi Iwai 				   struct snd_pcm_substream *substream)
97*73cd0490STakashi Iwai {
98*73cd0490STakashi Iwai 	struct hdmi_spec *spec = codec->spec;
99*73cd0490STakashi Iwai 	int i;
100*73cd0490STakashi Iwai 
101*73cd0490STakashi Iwai 	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
102*73cd0490STakashi Iwai 			0, AC_VERB_SET_CHANNEL_STREAMID, 0);
103*73cd0490STakashi Iwai 	for (i = 0; i < 4; i++) {
104*73cd0490STakashi Iwai 		/* set the stream id */
105*73cd0490STakashi Iwai 		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
106*73cd0490STakashi Iwai 				AC_VERB_SET_CHANNEL_STREAMID, 0);
107*73cd0490STakashi Iwai 		/* set the stream format */
108*73cd0490STakashi Iwai 		snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
109*73cd0490STakashi Iwai 				AC_VERB_SET_STREAM_FORMAT, 0);
110*73cd0490STakashi Iwai 	}
111*73cd0490STakashi Iwai 
112*73cd0490STakashi Iwai 	/* The audio hardware sends a channel count of 0x7 (8ch) when all the
113*73cd0490STakashi Iwai 	 * streams are disabled.
114*73cd0490STakashi Iwai 	 */
115*73cd0490STakashi Iwai 	nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
116*73cd0490STakashi Iwai 
117*73cd0490STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
118*73cd0490STakashi Iwai }
119*73cd0490STakashi Iwai 
120*73cd0490STakashi Iwai static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
121*73cd0490STakashi Iwai 				     struct hda_codec *codec,
122*73cd0490STakashi Iwai 				     unsigned int stream_tag,
123*73cd0490STakashi Iwai 				     unsigned int format,
124*73cd0490STakashi Iwai 				     struct snd_pcm_substream *substream)
125*73cd0490STakashi Iwai {
126*73cd0490STakashi Iwai 	int chs;
127*73cd0490STakashi Iwai 	unsigned int dataDCC2, channel_id;
128*73cd0490STakashi Iwai 	int i;
129*73cd0490STakashi Iwai 	struct hdmi_spec *spec = codec->spec;
130*73cd0490STakashi Iwai 	struct hda_spdif_out *spdif;
131*73cd0490STakashi Iwai 	struct hdmi_spec_per_cvt *per_cvt;
132*73cd0490STakashi Iwai 
133*73cd0490STakashi Iwai 	mutex_lock(&codec->spdif_mutex);
134*73cd0490STakashi Iwai 	per_cvt = get_cvt(spec, 0);
135*73cd0490STakashi Iwai 	spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid);
136*73cd0490STakashi Iwai 
137*73cd0490STakashi Iwai 	chs = substream->runtime->channels;
138*73cd0490STakashi Iwai 
139*73cd0490STakashi Iwai 	dataDCC2 = 0x2;
140*73cd0490STakashi Iwai 
141*73cd0490STakashi Iwai 	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
142*73cd0490STakashi Iwai 	if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
143*73cd0490STakashi Iwai 		snd_hda_codec_write(codec,
144*73cd0490STakashi Iwai 				nvhdmi_master_con_nid_7x,
145*73cd0490STakashi Iwai 				0,
146*73cd0490STakashi Iwai 				AC_VERB_SET_DIGI_CONVERT_1,
147*73cd0490STakashi Iwai 				spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
148*73cd0490STakashi Iwai 
149*73cd0490STakashi Iwai 	/* set the stream id */
150*73cd0490STakashi Iwai 	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
151*73cd0490STakashi Iwai 			AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
152*73cd0490STakashi Iwai 
153*73cd0490STakashi Iwai 	/* set the stream format */
154*73cd0490STakashi Iwai 	snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
155*73cd0490STakashi Iwai 			AC_VERB_SET_STREAM_FORMAT, format);
156*73cd0490STakashi Iwai 
157*73cd0490STakashi Iwai 	/* turn on again (if needed) */
158*73cd0490STakashi Iwai 	/* enable and set the channel status audio/data flag */
159*73cd0490STakashi Iwai 	if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) {
160*73cd0490STakashi Iwai 		snd_hda_codec_write(codec,
161*73cd0490STakashi Iwai 				nvhdmi_master_con_nid_7x,
162*73cd0490STakashi Iwai 				0,
163*73cd0490STakashi Iwai 				AC_VERB_SET_DIGI_CONVERT_1,
164*73cd0490STakashi Iwai 				spdif->ctls & 0xff);
165*73cd0490STakashi Iwai 		snd_hda_codec_write(codec,
166*73cd0490STakashi Iwai 				nvhdmi_master_con_nid_7x,
167*73cd0490STakashi Iwai 				0,
168*73cd0490STakashi Iwai 				AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
169*73cd0490STakashi Iwai 	}
170*73cd0490STakashi Iwai 
171*73cd0490STakashi Iwai 	for (i = 0; i < 4; i++) {
172*73cd0490STakashi Iwai 		if (chs == 2)
173*73cd0490STakashi Iwai 			channel_id = 0;
174*73cd0490STakashi Iwai 		else
175*73cd0490STakashi Iwai 			channel_id = i * 2;
176*73cd0490STakashi Iwai 
177*73cd0490STakashi Iwai 		/* turn off SPDIF once;
178*73cd0490STakashi Iwai 		 *otherwise the IEC958 bits won't be updated
179*73cd0490STakashi Iwai 		 */
180*73cd0490STakashi Iwai 		if (codec->spdif_status_reset &&
181*73cd0490STakashi Iwai 		(spdif->ctls & AC_DIG1_ENABLE))
182*73cd0490STakashi Iwai 			snd_hda_codec_write(codec,
183*73cd0490STakashi Iwai 				nvhdmi_con_nids_7x[i],
184*73cd0490STakashi Iwai 				0,
185*73cd0490STakashi Iwai 				AC_VERB_SET_DIGI_CONVERT_1,
186*73cd0490STakashi Iwai 				spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
187*73cd0490STakashi Iwai 		/* set the stream id */
188*73cd0490STakashi Iwai 		snd_hda_codec_write(codec,
189*73cd0490STakashi Iwai 				nvhdmi_con_nids_7x[i],
190*73cd0490STakashi Iwai 				0,
191*73cd0490STakashi Iwai 				AC_VERB_SET_CHANNEL_STREAMID,
192*73cd0490STakashi Iwai 				(stream_tag << 4) | channel_id);
193*73cd0490STakashi Iwai 		/* set the stream format */
194*73cd0490STakashi Iwai 		snd_hda_codec_write(codec,
195*73cd0490STakashi Iwai 				nvhdmi_con_nids_7x[i],
196*73cd0490STakashi Iwai 				0,
197*73cd0490STakashi Iwai 				AC_VERB_SET_STREAM_FORMAT,
198*73cd0490STakashi Iwai 				format);
199*73cd0490STakashi Iwai 		/* turn on again (if needed) */
200*73cd0490STakashi Iwai 		/* enable and set the channel status audio/data flag */
201*73cd0490STakashi Iwai 		if (codec->spdif_status_reset &&
202*73cd0490STakashi Iwai 		(spdif->ctls & AC_DIG1_ENABLE)) {
203*73cd0490STakashi Iwai 			snd_hda_codec_write(codec,
204*73cd0490STakashi Iwai 					nvhdmi_con_nids_7x[i],
205*73cd0490STakashi Iwai 					0,
206*73cd0490STakashi Iwai 					AC_VERB_SET_DIGI_CONVERT_1,
207*73cd0490STakashi Iwai 					spdif->ctls & 0xff);
208*73cd0490STakashi Iwai 			snd_hda_codec_write(codec,
209*73cd0490STakashi Iwai 					nvhdmi_con_nids_7x[i],
210*73cd0490STakashi Iwai 					0,
211*73cd0490STakashi Iwai 					AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
212*73cd0490STakashi Iwai 		}
213*73cd0490STakashi Iwai 	}
214*73cd0490STakashi Iwai 
215*73cd0490STakashi Iwai 	nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs);
216*73cd0490STakashi Iwai 
217*73cd0490STakashi Iwai 	mutex_unlock(&codec->spdif_mutex);
218*73cd0490STakashi Iwai 	return 0;
219*73cd0490STakashi Iwai }
220*73cd0490STakashi Iwai 
221*73cd0490STakashi Iwai static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
222*73cd0490STakashi Iwai 	.substreams = 1,
223*73cd0490STakashi Iwai 	.channels_min = 2,
224*73cd0490STakashi Iwai 	.channels_max = 8,
225*73cd0490STakashi Iwai 	.nid = nvhdmi_master_con_nid_7x,
226*73cd0490STakashi Iwai 	.rates = SUPPORTED_RATES,
227*73cd0490STakashi Iwai 	.maxbps = SUPPORTED_MAXBPS,
228*73cd0490STakashi Iwai 	.formats = SUPPORTED_FORMATS,
229*73cd0490STakashi Iwai 	.ops = {
230*73cd0490STakashi Iwai 		.open = snd_hda_hdmi_simple_pcm_open,
231*73cd0490STakashi Iwai 		.close = nvhdmi_8ch_7x_pcm_close,
232*73cd0490STakashi Iwai 		.prepare = nvhdmi_8ch_7x_pcm_prepare
233*73cd0490STakashi Iwai 	},
234*73cd0490STakashi Iwai };
235*73cd0490STakashi Iwai 
236*73cd0490STakashi Iwai static int patch_nvhdmi_2ch(struct hda_codec *codec)
237*73cd0490STakashi Iwai {
238*73cd0490STakashi Iwai 	struct hdmi_spec *spec;
239*73cd0490STakashi Iwai 	int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x,
240*73cd0490STakashi Iwai 				    nvhdmi_master_pin_nid_7x);
241*73cd0490STakashi Iwai 	if (err < 0)
242*73cd0490STakashi Iwai 		return err;
243*73cd0490STakashi Iwai 
244*73cd0490STakashi Iwai 	codec->patch_ops.init = nvhdmi_7x_init_2ch;
245*73cd0490STakashi Iwai 	/* override the PCM rates, etc, as the codec doesn't give full list */
246*73cd0490STakashi Iwai 	spec = codec->spec;
247*73cd0490STakashi Iwai 	spec->pcm_playback.rates = SUPPORTED_RATES;
248*73cd0490STakashi Iwai 	spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
249*73cd0490STakashi Iwai 	spec->pcm_playback.formats = SUPPORTED_FORMATS;
250*73cd0490STakashi Iwai 	spec->nv_dp_workaround = true;
251*73cd0490STakashi Iwai 	return 0;
252*73cd0490STakashi Iwai }
253*73cd0490STakashi Iwai 
254*73cd0490STakashi Iwai static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec)
255*73cd0490STakashi Iwai {
256*73cd0490STakashi Iwai 	struct hdmi_spec *spec = codec->spec;
257*73cd0490STakashi Iwai 	int err;
258*73cd0490STakashi Iwai 
259*73cd0490STakashi Iwai 	err = snd_hda_hdmi_simple_build_pcms(codec);
260*73cd0490STakashi Iwai 	if (!err) {
261*73cd0490STakashi Iwai 		struct hda_pcm *info = get_pcm_rec(spec, 0);
262*73cd0490STakashi Iwai 
263*73cd0490STakashi Iwai 		info->own_chmap = true;
264*73cd0490STakashi Iwai 	}
265*73cd0490STakashi Iwai 	return err;
266*73cd0490STakashi Iwai }
267*73cd0490STakashi Iwai 
268*73cd0490STakashi Iwai static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
269*73cd0490STakashi Iwai {
270*73cd0490STakashi Iwai 	struct hdmi_spec *spec = codec->spec;
271*73cd0490STakashi Iwai 	struct hda_pcm *info;
272*73cd0490STakashi Iwai 	struct snd_pcm_chmap *chmap;
273*73cd0490STakashi Iwai 	int err;
274*73cd0490STakashi Iwai 
275*73cd0490STakashi Iwai 	err = snd_hda_hdmi_simple_build_controls(codec);
276*73cd0490STakashi Iwai 	if (err < 0)
277*73cd0490STakashi Iwai 		return err;
278*73cd0490STakashi Iwai 
279*73cd0490STakashi Iwai 	/* add channel maps */
280*73cd0490STakashi Iwai 	info = get_pcm_rec(spec, 0);
281*73cd0490STakashi Iwai 	err = snd_pcm_add_chmap_ctls(info->pcm,
282*73cd0490STakashi Iwai 				     SNDRV_PCM_STREAM_PLAYBACK,
283*73cd0490STakashi Iwai 				     snd_pcm_alt_chmaps, 8, 0, &chmap);
284*73cd0490STakashi Iwai 	if (err < 0)
285*73cd0490STakashi Iwai 		return err;
286*73cd0490STakashi Iwai 	switch (codec->preset->vendor_id) {
287*73cd0490STakashi Iwai 	case 0x10de0002:
288*73cd0490STakashi Iwai 	case 0x10de0003:
289*73cd0490STakashi Iwai 	case 0x10de0005:
290*73cd0490STakashi Iwai 	case 0x10de0006:
291*73cd0490STakashi Iwai 		chmap->channel_mask = (1U << 2) | (1U << 8);
292*73cd0490STakashi Iwai 		break;
293*73cd0490STakashi Iwai 	case 0x10de0007:
294*73cd0490STakashi Iwai 		chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8);
295*73cd0490STakashi Iwai 	}
296*73cd0490STakashi Iwai 	return 0;
297*73cd0490STakashi Iwai }
298*73cd0490STakashi Iwai 
299*73cd0490STakashi Iwai static const unsigned int channels_2_6_8[] = {
300*73cd0490STakashi Iwai 	2, 6, 8
301*73cd0490STakashi Iwai };
302*73cd0490STakashi Iwai 
303*73cd0490STakashi Iwai static const unsigned int channels_2_8[] = {
304*73cd0490STakashi Iwai 	2, 8
305*73cd0490STakashi Iwai };
306*73cd0490STakashi Iwai 
307*73cd0490STakashi Iwai static const struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = {
308*73cd0490STakashi Iwai 	.count = ARRAY_SIZE(channels_2_6_8),
309*73cd0490STakashi Iwai 	.list = channels_2_6_8,
310*73cd0490STakashi Iwai 	.mask = 0,
311*73cd0490STakashi Iwai };
312*73cd0490STakashi Iwai 
313*73cd0490STakashi Iwai static const struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = {
314*73cd0490STakashi Iwai 	.count = ARRAY_SIZE(channels_2_8),
315*73cd0490STakashi Iwai 	.list = channels_2_8,
316*73cd0490STakashi Iwai 	.mask = 0,
317*73cd0490STakashi Iwai };
318*73cd0490STakashi Iwai 
319*73cd0490STakashi Iwai static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
320*73cd0490STakashi Iwai {
321*73cd0490STakashi Iwai 	struct hdmi_spec *spec;
322*73cd0490STakashi Iwai 	int err;
323*73cd0490STakashi Iwai 
324*73cd0490STakashi Iwai 	err = patch_nvhdmi_2ch(codec);
325*73cd0490STakashi Iwai 	if (err < 0)
326*73cd0490STakashi Iwai 		return err;
327*73cd0490STakashi Iwai 	spec = codec->spec;
328*73cd0490STakashi Iwai 	spec->multiout.max_channels = 8;
329*73cd0490STakashi Iwai 	spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x;
330*73cd0490STakashi Iwai 	codec->patch_ops.init = nvhdmi_7x_init_8ch;
331*73cd0490STakashi Iwai 	codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms;
332*73cd0490STakashi Iwai 	codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls;
333*73cd0490STakashi Iwai 
334*73cd0490STakashi Iwai 	switch (codec->preset->vendor_id) {
335*73cd0490STakashi Iwai 	case 0x10de0002:
336*73cd0490STakashi Iwai 	case 0x10de0003:
337*73cd0490STakashi Iwai 	case 0x10de0005:
338*73cd0490STakashi Iwai 	case 0x10de0006:
339*73cd0490STakashi Iwai 		spec->hw_constraints_channels = &hw_constraints_2_8_channels;
340*73cd0490STakashi Iwai 		break;
341*73cd0490STakashi Iwai 	case 0x10de0007:
342*73cd0490STakashi Iwai 		spec->hw_constraints_channels = &hw_constraints_2_6_8_channels;
343*73cd0490STakashi Iwai 		break;
344*73cd0490STakashi Iwai 	default:
345*73cd0490STakashi Iwai 		break;
346*73cd0490STakashi Iwai 	}
347*73cd0490STakashi Iwai 
348*73cd0490STakashi Iwai 	/* Initialize the audio infoframe channel mask and checksum to something
349*73cd0490STakashi Iwai 	 * valid
350*73cd0490STakashi Iwai 	 */
351*73cd0490STakashi Iwai 	nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
352*73cd0490STakashi Iwai 
353*73cd0490STakashi Iwai 	return 0;
354*73cd0490STakashi Iwai }
355*73cd0490STakashi Iwai 
356*73cd0490STakashi Iwai /*
357*73cd0490STakashi Iwai  * patch entries
358*73cd0490STakashi Iwai  */
359*73cd0490STakashi Iwai static const struct hda_device_id snd_hda_id_nvhdmi_mcp[] = {
360*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de0001, "MCP73 HDMI",	patch_nvhdmi_2ch),
361*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de0002, "MCP77/78 HDMI",	patch_nvhdmi_8ch_7x),
362*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de0003, "MCP77/78 HDMI",	patch_nvhdmi_8ch_7x),
363*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de0004, "GPU 04 HDMI",	patch_nvhdmi_8ch_7x),
364*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de0005, "MCP77/78 HDMI",	patch_nvhdmi_8ch_7x),
365*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de0006, "MCP77/78 HDMI",	patch_nvhdmi_8ch_7x),
366*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de0007, "MCP79/7A HDMI",	patch_nvhdmi_8ch_7x),
367*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de0067, "MCP67 HDMI",	patch_nvhdmi_2ch),
368*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI",	patch_nvhdmi_2ch),
369*73cd0490STakashi Iwai HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI",	patch_nvhdmi_2ch),
370*73cd0490STakashi Iwai {} /* terminator */
371*73cd0490STakashi Iwai };
372*73cd0490STakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_nvhdmi_mcp);
373*73cd0490STakashi Iwai 
374*73cd0490STakashi Iwai MODULE_LICENSE("GPL");
375*73cd0490STakashi Iwai MODULE_DESCRIPTION("Legacy Nvidia HDMI HD-audio codec");
376*73cd0490STakashi Iwai MODULE_IMPORT_NS("SND_HDA_CODEC_HDMI");
377*73cd0490STakashi Iwai 
378*73cd0490STakashi Iwai static struct hda_codec_driver nvhdmi_mcp_driver = {
379*73cd0490STakashi Iwai 	.id = snd_hda_id_nvhdmi_mcp,
380*73cd0490STakashi Iwai };
381*73cd0490STakashi Iwai 
382*73cd0490STakashi Iwai module_hda_codec_driver(nvhdmi_mcp_driver);
383