xref: /linux/drivers/gpu/drm/msm/hdmi/hdmi_audio.c (revision 53597deca0e38c30e6cd4ba2114fa42d2bcd85bb)
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 								      &params->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