Lines Matching +full:codec +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * ATI/AMD codec support
17 #define is_amdhdmi_rev3_or_later(codec) \ argument
18 ((codec)->core.vendor_id == 0x1002aa01 && \
19 ((codec)->core.revision_id & 0xff00) >= 0x0300)
20 #define has_amd_full_remap_support(codec) is_amdhdmi_rev3_or_later(codec) argument
23 #define ATI_VERB_SET_CHANNEL_ALLOCATION 0x771
24 #define ATI_VERB_SET_DOWNMIX_INFO 0x772
25 #define ATI_VERB_SET_MULTICHANNEL_01 0x777
26 #define ATI_VERB_SET_MULTICHANNEL_23 0x778
27 #define ATI_VERB_SET_MULTICHANNEL_45 0x779
28 #define ATI_VERB_SET_MULTICHANNEL_67 0x77a
29 #define ATI_VERB_SET_HBR_CONTROL 0x77c
30 #define ATI_VERB_SET_MULTICHANNEL_1 0x785
31 #define ATI_VERB_SET_MULTICHANNEL_3 0x786
32 #define ATI_VERB_SET_MULTICHANNEL_5 0x787
33 #define ATI_VERB_SET_MULTICHANNEL_7 0x788
34 #define ATI_VERB_SET_MULTICHANNEL_MODE 0x789
35 #define ATI_VERB_GET_CHANNEL_ALLOCATION 0xf71
36 #define ATI_VERB_GET_DOWNMIX_INFO 0xf72
37 #define ATI_VERB_GET_MULTICHANNEL_01 0xf77
38 #define ATI_VERB_GET_MULTICHANNEL_23 0xf78
39 #define ATI_VERB_GET_MULTICHANNEL_45 0xf79
40 #define ATI_VERB_GET_MULTICHANNEL_67 0xf7a
41 #define ATI_VERB_GET_HBR_CONTROL 0xf7c
42 #define ATI_VERB_GET_MULTICHANNEL_1 0xf85
43 #define ATI_VERB_GET_MULTICHANNEL_3 0xf86
44 #define ATI_VERB_GET_MULTICHANNEL_5 0xf87
45 #define ATI_VERB_GET_MULTICHANNEL_7 0xf88
46 #define ATI_VERB_GET_MULTICHANNEL_MODE 0xf89
49 #define ATI_VERB_SET_RAMP_RATE 0x770
50 #define ATI_VERB_GET_RAMP_RATE 0xf70
52 #define ATI_OUT_ENABLE 0x1
54 #define ATI_MULTICHANNEL_MODE_PAIRED 0
57 #define ATI_HBR_CAPABLE 0x01
58 #define ATI_HBR_ENABLE 0x10
62 #define ATI_VERB_SET_AUDIO_DESCRIPTOR 0x776
63 #define ATI_VERB_SET_SINK_INFO_INDEX 0x780
64 #define ATI_VERB_GET_SPEAKER_ALLOCATION 0xf70
65 #define ATI_VERB_GET_AUDIO_DESCRIPTOR 0xf76
66 #define ATI_VERB_GET_AUDIO_VIDEO_DELAY 0xf7b
67 #define ATI_VERB_GET_SINK_INFO_INDEX 0xf80
68 #define ATI_VERB_GET_SINK_INFO_DATA 0xf81
70 #define ATI_SPKALLOC_SPKALLOC 0x007f
71 #define ATI_SPKALLOC_TYPE_HDMI 0x0100
72 #define ATI_SPKALLOC_TYPE_DISPLAYPORT 0x0200
75 #define ATI_AUDIODESC_CHANNELS 0x00000007
76 #define ATI_AUDIODESC_RATES 0x0000ff00
77 #define ATI_AUDIODESC_LPCM_STEREO_RATES 0xff000000
80 #define ATI_DELAY_VIDEO_LATENCY 0x000000ff
81 #define ATI_DELAY_AUDIO_LATENCY 0x0000ff00
84 ATI_INFO_IDX_MANUFACTURER_ID = 0,
93 static int get_eld_ati(struct hda_codec *codec, hda_nid_t nid, in get_eld_ati() argument
97 int sink_desc_len = 0; in get_eld_ati()
102 spkalloc = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SPEAKER_ALLOCATION, 0); in get_eld_ati()
104 if (spkalloc <= 0) { in get_eld_ati()
105 codec_info(codec, "HDMI ATI/AMD: no speaker allocation for ELD\n"); in get_eld_ati()
106 return -EINVAL; in get_eld_ati()
109 memset(buf, 0, ELD_FIXED_BYTES + ELD_MAX_MNL + ELD_MAX_SAD * 3); in get_eld_ati()
112 buf[0] = ELD_VER_CEA_861D << 3; in get_eld_ati()
119 buf[5] |= 0x04; in get_eld_ati()
126 snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PORT_ID_LOW); in get_eld_ati()
127 sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0); in get_eld_ati()
130 snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PORT_ID_HIGH); in get_eld_ati()
131 sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0); in get_eld_ati()
134 snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_MANUFACTURER_ID); in get_eld_ati()
135 sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0); in get_eld_ati()
138 snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PRODUCT_ID); in get_eld_ati()
139 sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0); in get_eld_ati()
142 snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_SINK_DESC_LEN); in get_eld_ati()
143 sink_desc_len = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0); in get_eld_ati()
146 codec_info(codec, "HDMI ATI/AMD: Truncating HDMI sink description with length %d\n", in get_eld_ati()
153 for (i = 0; i < sink_desc_len; i++) { in get_eld_ati()
154 …snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_SINK_DESC_FIRST + i); in get_eld_ati()
155 buf[pos++] = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0); in get_eld_ati()
163 snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_AUDIO_DESCRIPTOR, i << 3); in get_eld_ati()
164 ati_sad = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_DESCRIPTOR, 0); in get_eld_ati()
166 if (ati_sad <= 0) in get_eld_ati()
170 /* format is supported, copy SAD as-is */ in get_eld_ati()
171 buf[pos++] = (ati_sad & 0x0000ff) >> 0; in get_eld_ati()
172 buf[pos++] = (ati_sad & 0x00ff00) >> 8; in get_eld_ati()
173 buf[pos++] = (ati_sad & 0xff0000) >> 16; in get_eld_ati()
180 buf[pos++] = ((ati_sad & 0x000000ff) & ~ATI_AUDIODESC_CHANNELS) | 0x1; in get_eld_ati()
182 buf[pos++] = (ati_sad & 0xff000000) >> 24; in get_eld_ati()
183 buf[pos++] = (ati_sad & 0x00ff0000) >> 16; in get_eld_ati()
188 codec_info(codec, "HDMI ATI/AMD: no audio descriptors for ELD\n"); in get_eld_ati()
189 return -EINVAL; in get_eld_ati()
195 * 0 field not valid or unknown latency in get_eld_ati()
196 * [1..251] msecs = (x-1)*2 (max 500ms with x = 251 = 0xfb) in get_eld_ati()
201 * 0 unknown or 0ms in get_eld_ati()
202 * [1..250] msecs = x*2 (max 500ms with x = 250 = 0xfa) in get_eld_ati()
205 aud_synch = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_VIDEO_DELAY, 0); in get_eld_ati()
210 if (video_latency_hdmi <= 0xfb && audio_latency_hdmi <= 0xfb && in get_eld_ati()
212 buf[6] = video_latency_hdmi - audio_latency_hdmi; in get_eld_ati()
213 /* else unknown/invalid or 0ms or video ahead of audio, so use zero */ in get_eld_ati()
217 buf[5] |= ((pos - ELD_FIXED_BYTES - sink_desc_len) / 3) << 4; in get_eld_ati()
219 /* Baseline ELD block length is 4-byte aligned */ in get_eld_ati()
222 /* Baseline ELD length (4-byte header is not counted in) */ in get_eld_ati()
223 buf[2] = (pos - 4) / 4; in get_eld_ati()
227 return 0; in get_eld_ati()
230 static int atihdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid, in atihdmi_pin_get_eld() argument
233 WARN_ON(dev_id != 0); in atihdmi_pin_get_eld()
234 /* call hda_eld.c ATI/AMD-specific function */ in atihdmi_pin_get_eld()
235 return get_eld_ati(codec, nid, buf, eld_size, in atihdmi_pin_get_eld()
236 is_amdhdmi_rev3_or_later(codec)); in atihdmi_pin_get_eld()
239 static void atihdmi_pin_setup_infoframe(struct hda_codec *codec, in atihdmi_pin_setup_infoframe() argument
243 WARN_ON(dev_id != 0); in atihdmi_pin_setup_infoframe()
244 snd_hda_codec_write(codec, pin_nid, 0, ATI_VERB_SET_CHANNEL_ALLOCATION, ca); in atihdmi_pin_setup_infoframe()
250 * ATI/AMD have automatic FC/LFE swap built-in in atihdmi_paired_swap_fc_lfe()
268 /* check that only channel pairs need to be remapped on old pre-rev3 ATI/AMD */ in atihdmi_paired_chmap_validate()
271 for (i = 0; i < chs; ++i) { in atihdmi_paired_chmap_validate()
279 for (j = 0 + i % 2; j < 8; j += 2) { in atihdmi_paired_chmap_validate()
280 int chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j); in atihdmi_paired_chmap_validate()
282 if (cap->speakers[chan_idx] == mask) { in atihdmi_paired_chmap_validate()
286 if (i % 2 == 0 && i + 1 < chs) { in atihdmi_paired_chmap_validate()
288 int comp_chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j + 1); in atihdmi_paired_chmap_validate()
290 int comp_mask_act = cap->speakers[comp_chan_idx]; in atihdmi_paired_chmap_validate()
295 return -EINVAL; in atihdmi_paired_chmap_validate()
302 return -EINVAL; in atihdmi_paired_chmap_validate()
308 return 0; in atihdmi_paired_chmap_validate()
314 struct hda_codec *codec = hdac_to_hda_codec(hdac); in atihdmi_pin_set_slot_channel() local
316 int ati_channel_setup = 0; in atihdmi_pin_set_slot_channel()
319 return -EINVAL; in atihdmi_pin_set_slot_channel()
321 if (!has_amd_full_remap_support(codec)) { in atihdmi_pin_set_slot_channel()
329 if (hdmi_slot % 2 != 0 && stream_channel == 0xf) in atihdmi_pin_set_slot_channel()
330 return 0; in atihdmi_pin_set_slot_channel()
332 hdmi_slot -= hdmi_slot % 2; in atihdmi_pin_set_slot_channel()
334 if (stream_channel != 0xf) in atihdmi_pin_set_slot_channel()
335 stream_channel -= stream_channel % 2; in atihdmi_pin_set_slot_channel()
338 verb = ATI_VERB_SET_MULTICHANNEL_01 + hdmi_slot/2 + (hdmi_slot % 2) * 0x00e; in atihdmi_pin_set_slot_channel()
340 /* ati_channel_setup format: [7..4] = stream_channel_id, [1] = mute, [0] = enable */ in atihdmi_pin_set_slot_channel()
342 if (stream_channel != 0xf) in atihdmi_pin_set_slot_channel()
345 return snd_hda_codec_write(codec, pin_nid, 0, verb, ati_channel_setup); in atihdmi_pin_set_slot_channel()
351 struct hda_codec *codec = hdac_to_hda_codec(hdac); in atihdmi_pin_get_slot_channel() local
358 return -EINVAL; in atihdmi_pin_get_slot_channel()
360 if (!has_amd_full_remap_support(codec)) { in atihdmi_pin_get_slot_channel()
362 if (ati_asp_slot % 2 != 0) { in atihdmi_pin_get_slot_channel()
363 ati_asp_slot -= 1; in atihdmi_pin_get_slot_channel()
368 verb = ATI_VERB_GET_MULTICHANNEL_01 + ati_asp_slot/2 + (ati_asp_slot % 2) * 0x00e; in atihdmi_pin_get_slot_channel()
370 ati_channel_setup = snd_hda_codec_read(codec, pin_nid, 0, verb, 0); in atihdmi_pin_get_slot_channel()
373 return 0xf; in atihdmi_pin_get_slot_channel()
375 return ((ati_channel_setup & 0xf0) >> 4) + !!was_odd; in atihdmi_pin_get_slot_channel()
386 * Pre-rev3 ATI/AMD codecs operate in a paired channel mode, so in atihdmi_paired_chmap_cea_alloc_validate_get_type()
391 int chanpairs = 0; in atihdmi_paired_chmap_cea_alloc_validate_get_type()
393 /* We only produce even-numbered channel count TLVs */ in atihdmi_paired_chmap_cea_alloc_validate_get_type()
394 if ((channels % 2) != 0) in atihdmi_paired_chmap_cea_alloc_validate_get_type()
395 return -1; in atihdmi_paired_chmap_cea_alloc_validate_get_type()
397 for (c = 0; c < 7; c += 2) { in atihdmi_paired_chmap_cea_alloc_validate_get_type()
398 if (cap->speakers[c] || cap->speakers[c+1]) in atihdmi_paired_chmap_cea_alloc_validate_get_type()
403 return -1; in atihdmi_paired_chmap_cea_alloc_validate_get_type()
412 /* produce paired maps for pre-rev3 ATI/AMD codecs */ in atihdmi_paired_cea_alloc_to_tlv_chmap()
413 int count = 0; in atihdmi_paired_cea_alloc_to_tlv_chmap()
416 for (c = 7; c >= 0; c--) { in atihdmi_paired_cea_alloc_to_tlv_chmap()
417 int chan = 7 - atihdmi_paired_swap_fc_lfe(7 - c); in atihdmi_paired_cea_alloc_to_tlv_chmap()
418 int spk = cap->speakers[chan]; in atihdmi_paired_cea_alloc_to_tlv_chmap()
422 if (cap->speakers[chan + (chan % 2 ? -1 : 1)]) in atihdmi_paired_cea_alloc_to_tlv_chmap()
434 static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, in atihdmi_pin_hbr_setup() argument
439 WARN_ON(dev_id != 0); in atihdmi_pin_hbr_setup()
441 hbr_ctl = snd_hda_codec_read(codec, pin_nid, 0, ATI_VERB_GET_HBR_CONTROL, 0); in atihdmi_pin_hbr_setup()
442 if (hbr_ctl >= 0 && (hbr_ctl & ATI_HBR_CAPABLE)) { in atihdmi_pin_hbr_setup()
448 codec_dbg(codec, in atihdmi_pin_hbr_setup()
449 "%s: NID=0x%x, %shbr-ctl=0x%x\n", in atihdmi_pin_hbr_setup()
452 hbr_ctl == hbr_ctl_new ? "" : "new-", in atihdmi_pin_hbr_setup()
456 snd_hda_codec_write(codec, pin_nid, 0, in atihdmi_pin_hbr_setup()
461 return -EINVAL; in atihdmi_pin_hbr_setup()
463 return 0; in atihdmi_pin_hbr_setup()
466 static int atihdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, in atihdmi_setup_stream() argument
470 if (is_amdhdmi_rev3_or_later(codec)) { in atihdmi_setup_stream()
472 /* disable ramp-up/down for non-pcm as per AMD spec */ in atihdmi_setup_stream()
474 ramp_rate = 0; in atihdmi_setup_stream()
476 snd_hda_codec_write(codec, cvt_nid, 0, ATI_VERB_SET_RAMP_RATE, ramp_rate); in atihdmi_setup_stream()
479 return snd_hda_hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, in atihdmi_setup_stream()
484 static int atihdmi_init(struct hda_codec *codec) in atihdmi_init() argument
486 struct hdmi_spec *spec = codec->spec; in atihdmi_init()
489 err = snd_hda_hdmi_generic_init(codec); in atihdmi_init()
494 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { in atihdmi_init()
498 snd_hda_codec_write(codec, per_pin->pin_nid, 0, ATI_VERB_SET_DOWNMIX_INFO, 0); in atihdmi_init()
500 /* enable channel-wise remap mode if supported */ in atihdmi_init()
501 if (has_amd_full_remap_support(codec)) in atihdmi_init()
502 snd_hda_codec_write(codec, per_pin->pin_nid, 0, in atihdmi_init()
506 codec->auto_runtime_pm = 1; in atihdmi_init()
508 return 0; in atihdmi_init()
511 /* map from pin NID to port; port is 0-based */
515 return pin_nid / 2 - 1; in atihdmi_pin2port()
518 /* reverse-map from port to pin NID: see above */
519 static int atihdmi_port2pin(struct hda_codec *codec, int port) in atihdmi_port2pin() argument
531 static int atihdmi_probe(struct hda_codec *codec, const struct hda_device_id *id) in atihdmi_probe() argument
537 err = snd_hda_hdmi_generic_probe(codec); in atihdmi_probe()
541 spec = codec->spec; in atihdmi_probe()
543 spec->static_pcm_mapping = true; in atihdmi_probe()
545 spec->ops.pin_get_eld = atihdmi_pin_get_eld; in atihdmi_probe()
546 spec->ops.pin_setup_infoframe = atihdmi_pin_setup_infoframe; in atihdmi_probe()
547 spec->ops.pin_hbr_setup = atihdmi_pin_hbr_setup; in atihdmi_probe()
548 spec->ops.setup_stream = atihdmi_setup_stream; in atihdmi_probe()
550 spec->chmap.ops.pin_get_slot_channel = atihdmi_pin_get_slot_channel; in atihdmi_probe()
551 spec->chmap.ops.pin_set_slot_channel = atihdmi_pin_set_slot_channel; in atihdmi_probe()
553 if (!has_amd_full_remap_support(codec)) { in atihdmi_probe()
554 /* override to ATI/AMD-specific versions with pairwise mapping */ in atihdmi_probe()
555 spec->chmap.ops.chmap_cea_alloc_validate_get_type = in atihdmi_probe()
557 spec->chmap.ops.cea_alloc_to_tlv_chmap = in atihdmi_probe()
559 spec->chmap.ops.chmap_validate = atihdmi_paired_chmap_validate; in atihdmi_probe()
563 for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { in atihdmi_probe()
565 per_cvt->channels_max = max(per_cvt->channels_max, 8u); in atihdmi_probe()
566 per_cvt->rates |= SUPPORTED_RATES; in atihdmi_probe()
567 per_cvt->formats |= SUPPORTED_FORMATS; in atihdmi_probe()
568 per_cvt->maxbps = max(per_cvt->maxbps, 24u); in atihdmi_probe()
571 spec->chmap.channels_max = max(spec->chmap.channels_max, 8u); in atihdmi_probe()
574 * the link-down as is. Tell the core to allow it. in atihdmi_probe()
576 codec->link_down_at_suspend = 1; in atihdmi_probe()
578 snd_hda_hdmi_acomp_init(codec, &atihdmi_audio_ops, atihdmi_port2pin); in atihdmi_probe()
580 return 0; in atihdmi_probe()
598 HDA_CODEC_ID(0x1002793c, "RS600 HDMI"),
599 HDA_CODEC_ID(0x10027919, "RS600 HDMI"),
600 HDA_CODEC_ID(0x1002791a, "RS690/780 HDMI"),
601 HDA_CODEC_ID(0x1002aa01, "R6xx HDMI"),
607 MODULE_DESCRIPTION("AMD/ATI HDMI HD-audio codec");