1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2013 Red Hat 4 * Author: Rob Clark <robdclark@gmail.com> 5 */ 6 7 #include <drm/display/drm_hdmi_helper.h> 8 #include <drm/display/drm_hdmi_state_helper.h> 9 10 #include <linux/hdmi.h> 11 12 #include <sound/hdmi-codec.h> 13 14 #include "hdmi.h" 15 16 int msm_hdmi_audio_update(struct hdmi *hdmi) 17 { 18 struct hdmi_audio *audio = &hdmi->audio; 19 bool enabled = audio->enabled; 20 uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl; 21 uint32_t audio_config; 22 23 if (!hdmi->connector->display_info.is_hdmi) 24 return -EINVAL; 25 26 DBG("audio: enabled=%d, channels=%d, rate=%d", 27 audio->enabled, audio->channels, audio->rate); 28 29 DBG("video: power_on=%d, pixclock=%lu", hdmi->power_on, hdmi->pixclock); 30 31 if (enabled && !(hdmi->power_on && hdmi->pixclock)) { 32 DBG("disabling audio: no video"); 33 enabled = false; 34 } 35 36 /* Read first before writing */ 37 acr_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_ACR_PKT_CTRL); 38 vbi_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_VBI_PKT_CTRL); 39 aud_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_AUDIO_PKT_CTRL1); 40 audio_config = hdmi_read(hdmi, REG_HDMI_AUDIO_CFG); 41 42 /* Clear N/CTS selection bits */ 43 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SELECT__MASK; 44 45 if (enabled) { 46 uint32_t n, cts, multiplier; 47 enum hdmi_acr_cts select; 48 49 drm_hdmi_acr_get_n_cts(hdmi->pixclock, audio->rate, &n, &cts); 50 51 if (audio->rate == 192000 || audio->rate == 176400) { 52 multiplier = 4; 53 n >>= 2; /* divide N by 4 and use multiplier */ 54 } else if (audio->rate == 96000 || audio->rate == 88200) { 55 multiplier = 2; 56 n >>= 1; /* divide N by 2 and use multiplier */ 57 } else { 58 multiplier = 1; 59 } 60 61 DBG("n=%u, cts=%u, multiplier=%u", n, cts, multiplier); 62 63 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SOURCE; 64 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_AUDIO_PRIORITY; 65 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_N_MULTIPLIER(multiplier); 66 67 if (audio->rate == 48000 || audio->rate == 96000 || 68 audio->rate == 192000) 69 select = ACR_48; 70 else if (audio->rate == 44100 || audio->rate == 88200 || 71 audio->rate == 176400) 72 select = ACR_44; 73 else /* default to 32k */ 74 select = ACR_32; 75 76 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SELECT(select); 77 78 hdmi_write(hdmi, REG_HDMI_ACR_0(select - 1), 79 HDMI_ACR_0_CTS(cts)); 80 hdmi_write(hdmi, REG_HDMI_ACR_1(select - 1), 81 HDMI_ACR_1_N(n)); 82 83 hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL2, 84 COND(audio->channels != 2, HDMI_AUDIO_PKT_CTRL2_LAYOUT) | 85 HDMI_AUDIO_PKT_CTRL2_OVERRIDE); 86 87 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_CONT; 88 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SEND; 89 90 hdmi_write(hdmi, REG_HDMI_GC, 0); 91 92 vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_ENABLE; 93 vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME; 94 95 aud_pkt_ctrl |= HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND; 96 97 audio_config &= ~HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK; 98 audio_config |= HDMI_AUDIO_CFG_FIFO_WATERMARK(4); 99 audio_config |= HDMI_AUDIO_CFG_ENGINE_ENABLE; 100 } else { 101 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_CONT; 102 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SEND; 103 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_ENABLE; 104 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME; 105 aud_pkt_ctrl &= ~HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND; 106 audio_config &= ~HDMI_AUDIO_CFG_ENGINE_ENABLE; 107 } 108 109 hdmi_write(hdmi, REG_HDMI_ACR_PKT_CTRL, acr_pkt_ctrl); 110 hdmi_write(hdmi, REG_HDMI_VBI_PKT_CTRL, vbi_pkt_ctrl); 111 hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL1, aud_pkt_ctrl); 112 113 hdmi_write(hdmi, REG_HDMI_AUD_INT, 114 COND(enabled, HDMI_AUD_INT_AUD_FIFO_URUN_INT) | 115 COND(enabled, HDMI_AUD_INT_AUD_SAM_DROP_INT)); 116 117 hdmi_write(hdmi, REG_HDMI_AUDIO_CFG, audio_config); 118 119 120 DBG("audio %sabled", enabled ? "en" : "dis"); 121 122 return 0; 123 } 124 125 int msm_hdmi_bridge_audio_prepare(struct drm_connector *connector, 126 struct drm_bridge *bridge, 127 struct hdmi_codec_daifmt *daifmt, 128 struct hdmi_codec_params *params) 129 { 130 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 131 struct hdmi *hdmi = hdmi_bridge->hdmi; 132 int ret; 133 134 drm_dbg_driver(bridge->dev, "%u Hz, %d bit, %d channels\n", 135 params->sample_rate, 136 params->sample_width, 137 params->cea.channels); 138 139 switch (params->sample_rate) { 140 case 32000: 141 case 44100: 142 case 48000: 143 case 88200: 144 case 96000: 145 case 176400: 146 case 192000: 147 break; 148 default: 149 drm_err(bridge->dev, "rate[%d] not supported!\n", 150 params->sample_rate); 151 return -EINVAL; 152 } 153 154 ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(connector, 155 ¶ms->cea); 156 if (ret) 157 return ret; 158 159 hdmi->audio.rate = params->sample_rate; 160 hdmi->audio.channels = params->cea.channels; 161 hdmi->audio.enabled = true; 162 163 return msm_hdmi_audio_update(hdmi); 164 } 165 166 void msm_hdmi_bridge_audio_shutdown(struct drm_connector *connector, 167 struct drm_bridge *bridge) 168 { 169 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); 170 struct hdmi *hdmi = hdmi_bridge->hdmi; 171 172 drm_atomic_helper_connector_hdmi_clear_audio_infoframe(connector); 173 174 hdmi->audio.rate = 0; 175 hdmi->audio.channels = 2; 176 hdmi->audio.enabled = false; 177 178 msm_hdmi_audio_update(hdmi); 179 } 180