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