blob: 609dd45ea3188b766bd69a6b631d3184ee5d548b [file] [log] [blame]
Meng Wang43bbb872018-12-10 12:32:05 +08001// SPDX-License-Identifier: GPL-2.0-only
Sanjana B63bdc7b2020-01-20 19:31:18 +05302/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
Asish Bhattacharya366f7502017-07-25 15:15:56 +05303 */
4#include <linux/platform_device.h>
5#include <linux/slab.h>
6#include <linux/module.h>
7#include <linux/of_device.h>
8#include <linux/err.h>
9#include <sound/core.h>
10#include <sound/pcm.h>
11#include <sound/soc.h>
12#include <linux/msm_ext_display.h>
13
Meng Wang15c825d2018-09-06 10:49:18 +080014#define DRV_NAME "HDMI_codec"
15
Asish Bhattacharya366f7502017-07-25 15:15:56 +053016#define MSM_EXT_DISP_PCM_RATES SNDRV_PCM_RATE_48000
17#define AUD_EXT_DISP_ACK_DISCONNECT (AUDIO_ACK_CONNECT ^ AUDIO_ACK_CONNECT)
18#define AUD_EXT_DISP_ACK_CONNECT (AUDIO_ACK_CONNECT)
19#define AUD_EXT_DISP_ACK_ENABLE (AUDIO_ACK_SET_ENABLE | AUDIO_ACK_ENABLE)
20
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070021#define SOC_EXT_DISP_AUDIO_TYPE(index) \
22 static SOC_ENUM_SINGLE_DECL(ext_disp_audio_type##index, SND_SOC_NOPM, \
23 index, ext_disp_audio_type_text)
24#define SOC_EXT_DISP_AUDIO_ACK_STATE(index) \
25 static SOC_ENUM_SINGLE_DECL(ext_disp_audio_ack_state##index, \
26 SND_SOC_NOPM, index, ext_disp_audio_ack_text)
27
Sanjana B63bdc7b2020-01-20 19:31:18 +053028#define SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type) \
29 codec_info.type = type; \
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070030 codec_info.ctrl_id = codec_data->ctl[dai_id]; \
31 codec_info.stream_id = codec_data->stream[dai_id]; \
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070032
33enum {
Karthikeyan Mani311bd672019-06-06 13:40:55 -070034 DP_CONTROLLER0 = 0,
35 DP_CONTROLLER_MAX,
36};
37
38enum {
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070039 DP_STREAM0 = 0,
40 DP_STREAM1,
Sanjana B63bdc7b2020-01-20 19:31:18 +053041 HDMI,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070042 DP_STREAM_MAX,
43};
44
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -070045/*
46 * Dai id cannot be zero, if component has more than one dai and dai id
47 * is used to differentiate between them
48 */
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070049enum {
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -070050 DP_DAI1 = 1,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070051 DP_DAI2,
52 HDMI_DAI,
Sanjana B63bdc7b2020-01-20 19:31:18 +053053 HDMI_MS_DAI,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070054 DP_DAI_MAX,
55};
56
Asish Bhattacharya366f7502017-07-25 15:15:56 +053057static const char *const ext_disp_audio_type_text[] = {"None", "HDMI", "DP"};
58static const char *const ext_disp_audio_ack_text[] = {"Disconnect", "Connect",
59 "Ack_Enable"};
60
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070061SOC_EXT_DISP_AUDIO_TYPE(1);
62SOC_EXT_DISP_AUDIO_ACK_STATE(1);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -070063SOC_EXT_DISP_AUDIO_TYPE(2);
64SOC_EXT_DISP_AUDIO_ACK_STATE(2);
Sanjana B63bdc7b2020-01-20 19:31:18 +053065SOC_EXT_DISP_AUDIO_TYPE(3);
66SOC_EXT_DISP_AUDIO_ACK_STATE(3);
Asish Bhattacharya366f7502017-07-25 15:15:56 +053067
68struct msm_ext_disp_audio_codec_rx_data {
69 struct platform_device *ext_disp_core_pdev;
70 struct msm_ext_disp_audio_codec_ops ext_disp_ops;
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070071 struct mutex dp_ops_lock;
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -070072 int cable_status[DP_DAI_MAX];
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070073 int stream[DP_DAI_MAX];
74 int ctl[DP_DAI_MAX];
Asish Bhattacharya366f7502017-07-25 15:15:56 +053075};
76
77static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol,
78 struct snd_ctl_elem_info *uinfo)
79{
Meng Wang15c825d2018-09-06 10:49:18 +080080 struct snd_soc_component *component =
81 snd_soc_kcontrol_component(kcontrol);
Asish Bhattacharya366f7502017-07-25 15:15:56 +053082 struct msm_ext_disp_audio_codec_rx_data *codec_data;
83 struct msm_ext_disp_audio_edid_blk edid_blk;
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070084 int rc = 0;
85 struct msm_ext_disp_codec_id codec_info;
86 int dai_id = kcontrol->private_value;
Sanjana B63bdc7b2020-01-20 19:31:18 +053087 int type;
Asish Bhattacharya366f7502017-07-25 15:15:56 +053088
Meng Wang15c825d2018-09-06 10:49:18 +080089 codec_data = snd_soc_component_get_drvdata(component);
Asish Bhattacharya366f7502017-07-25 15:15:56 +053090 if (!codec_data) {
Meng Wang15c825d2018-09-06 10:49:18 +080091 dev_err(component->dev, "%s: codec_data is NULL\n", __func__);
Asish Bhattacharya366f7502017-07-25 15:15:56 +053092 return -EINVAL;
93 }
94
Meng Wang15c825d2018-09-06 10:49:18 +080095 dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -070096 codec_data->ctl[dai_id], codec_data->stream[dai_id]);
97
98 mutex_lock(&codec_data->dp_ops_lock);
Sanjana B63bdc7b2020-01-20 19:31:18 +053099 if (dai_id == HDMI_MS_DAI)
100 type = EXT_DISPLAY_TYPE_HDMI;
101 else
102 type = EXT_DISPLAY_TYPE_DP;
103 SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type);
Harshal Ahire42adadc2019-11-15 15:52:50 +0530104 rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
105 &codec_info);
106 if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700107 dev_dbg(component->dev, "%s: get_audio_edid_blk() is NULL\n",
108 __func__);
109 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
110 uinfo->count = 0;
111 mutex_unlock(&codec_data->dp_ops_lock);
Meng Wangb5cf4582019-09-04 09:22:07 +0800112 return 0;
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700113 }
114
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530115 rc = codec_data->ext_disp_ops.get_audio_edid_blk(
116 codec_data->ext_disp_core_pdev, &edid_blk);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700117 mutex_unlock(&codec_data->dp_ops_lock);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530118 if (rc >= 0) {
119 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
120 uinfo->count = edid_blk.audio_data_blk_size +
121 edid_blk.spk_alloc_data_blk_size;
122 }
123
Meng Wang15c825d2018-09-06 10:49:18 +0800124 dev_dbg(component->dev, "%s: count: %d\n", __func__, uinfo->count);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530125
126 return rc;
127}
128
129static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
130 struct snd_ctl_elem_value *ucontrol) {
Meng Wang15c825d2018-09-06 10:49:18 +0800131 struct snd_soc_component *component =
132 snd_soc_kcontrol_component(kcontrol);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530133 struct msm_ext_disp_audio_codec_rx_data *codec_data;
134 struct msm_ext_disp_audio_edid_blk edid_blk;
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700135 struct msm_ext_disp_codec_id codec_info;
136 int rc = 0;
137 int dai_id = kcontrol->private_value;
Sanjana B63bdc7b2020-01-20 19:31:18 +0530138 int type;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530139
Meng Wang15c825d2018-09-06 10:49:18 +0800140 codec_data = snd_soc_component_get_drvdata(component);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700141 if (!codec_data) {
142 dev_err(component->dev, "%s: codec_data is NULL\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530143 __func__);
144 return -EINVAL;
145 }
146
Meng Wang15c825d2018-09-06 10:49:18 +0800147 dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700148 codec_data->ctl[dai_id], codec_data->stream[dai_id]);
149
150 mutex_lock(&codec_data->dp_ops_lock);
Sanjana B63bdc7b2020-01-20 19:31:18 +0530151 if (dai_id == HDMI_MS_DAI)
152 type = EXT_DISPLAY_TYPE_HDMI;
153 else
154 type = EXT_DISPLAY_TYPE_DP;
155 SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type);
Harshal Ahire42adadc2019-11-15 15:52:50 +0530156 rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
157 &codec_info);
158 if (!codec_data->ext_disp_ops.get_audio_edid_blk || rc) {
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700159 dev_err(component->dev, "%s: codec_data or get_audio_edid_blk() is NULL\n",
160 __func__);
161 mutex_unlock(&codec_data->dp_ops_lock);
162 return -EINVAL;
163 }
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530164 rc = codec_data->ext_disp_ops.get_audio_edid_blk(
165 codec_data->ext_disp_core_pdev, &edid_blk);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700166 mutex_unlock(&codec_data->dp_ops_lock);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530167 if (rc >= 0) {
168 if (sizeof(ucontrol->value.bytes.data) <
169 (edid_blk.audio_data_blk_size +
170 edid_blk.spk_alloc_data_blk_size)) {
Meng Wang15c825d2018-09-06 10:49:18 +0800171 dev_err(component->dev,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530172 "%s: Not enough memory to copy EDID data\n",
173 __func__);
174 return -ENOMEM;
175 }
176
177 memcpy(ucontrol->value.bytes.data,
178 edid_blk.audio_data_blk,
179 edid_blk.audio_data_blk_size);
180 memcpy((ucontrol->value.bytes.data +
181 edid_blk.audio_data_blk_size),
182 edid_blk.spk_alloc_data_blk,
183 edid_blk.spk_alloc_data_blk_size);
184
Meng Wang15c825d2018-09-06 10:49:18 +0800185 dev_dbg(component->dev, "%s: data_blk_size:%d, spk_alloc_data_blk_size:%d\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530186 __func__, edid_blk.audio_data_blk_size,
187 edid_blk.spk_alloc_data_blk_size);
188 }
189
190 return rc;
191}
192
193static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
194 struct snd_ctl_elem_value *ucontrol)
195{
Meng Wang15c825d2018-09-06 10:49:18 +0800196 struct snd_soc_component *component =
197 snd_soc_kcontrol_component(kcontrol);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530198 struct msm_ext_disp_audio_codec_rx_data *codec_data;
199 enum msm_ext_disp_cable_state cable_state;
200 enum msm_ext_disp_type disp_type;
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700201 struct msm_ext_disp_codec_id codec_info;
202 int rc = 0;
203 int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
Sanjana B63bdc7b2020-01-20 19:31:18 +0530204 int type;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530205
Meng Wang15c825d2018-09-06 10:49:18 +0800206 codec_data = snd_soc_component_get_drvdata(component);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700207 if (!codec_data) {
208 dev_err(component->dev, "%s: codec_data is NULL\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530209 __func__);
210 return -EINVAL;
211 }
212
Meng Wang15c825d2018-09-06 10:49:18 +0800213 dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700214 codec_data->ctl[dai_id], codec_data->stream[dai_id]);
215
216 mutex_lock(&codec_data->dp_ops_lock);
Sanjana B63bdc7b2020-01-20 19:31:18 +0530217 if (dai_id == HDMI_MS_DAI)
218 type = EXT_DISPLAY_TYPE_HDMI;
219 else
220 type = EXT_DISPLAY_TYPE_DP;
221 SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type);
Harshal Ahire42adadc2019-11-15 15:52:50 +0530222 rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
223 &codec_info);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700224
225 if (!codec_data->ext_disp_ops.get_audio_edid_blk ||
Harshal Ahire42adadc2019-11-15 15:52:50 +0530226 !codec_data->ext_disp_ops.get_intf_id || rc) {
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700227 dev_err(component->dev, "%s: get_audio_edid_blk() or get_intf_id is NULL\n",
228 __func__);
229 rc = -EINVAL;
230 goto cable_err;
231 }
232
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530233 cable_state = codec_data->ext_disp_ops.cable_status(
Sanjana B63bdc7b2020-01-20 19:31:18 +0530234 codec_data->ext_disp_core_pdev, 1);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530235 if (cable_state < 0) {
Meng Wang15c825d2018-09-06 10:49:18 +0800236 dev_err(component->dev, "%s: Error retrieving cable state from ext_disp, err:%d\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530237 __func__, cable_state);
238 rc = cable_state;
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700239 goto cable_err;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530240 }
241
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700242 codec_data->cable_status[dai_id] = cable_state;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530243 if (cable_state == EXT_DISPLAY_CABLE_DISCONNECT) {
Meng Wang15c825d2018-09-06 10:49:18 +0800244 dev_err(component->dev, "%s: Display cable disconnected\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530245 __func__);
246 ucontrol->value.integer.value[0] = 0;
247 rc = 0;
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700248 goto cable_err;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530249 }
250
251 disp_type = codec_data->ext_disp_ops.get_intf_id(
252 codec_data->ext_disp_core_pdev);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700253 mutex_unlock(&codec_data->dp_ops_lock);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530254 if (disp_type >= 0) {
255 switch (disp_type) {
256 case EXT_DISPLAY_TYPE_DP:
257 ucontrol->value.integer.value[0] = 2;
258 rc = 0;
259 break;
260 case EXT_DISPLAY_TYPE_HDMI:
261 ucontrol->value.integer.value[0] = 1;
262 rc = 0;
263 break;
264 default:
265 rc = -EINVAL;
Meng Wang15c825d2018-09-06 10:49:18 +0800266 dev_err(component->dev, "%s: Invalid disp_type:%d\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530267 __func__, disp_type);
268 goto done;
269 }
Meng Wang15c825d2018-09-06 10:49:18 +0800270 dev_dbg(component->dev, "%s: Display type: %d\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530271 __func__, disp_type);
272 } else {
Meng Wang15c825d2018-09-06 10:49:18 +0800273 dev_err(component->dev, "%s: Error retrieving disp_type from ext_disp, err:%d\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530274 __func__, disp_type);
275 rc = disp_type;
276 }
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700277 return rc;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530278
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700279cable_err:
280 mutex_unlock(&codec_data->dp_ops_lock);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530281done:
282 return rc;
283}
284
285static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
286 struct snd_ctl_elem_value *ucontrol)
287{
Meng Wang15c825d2018-09-06 10:49:18 +0800288 struct snd_soc_component *component =
289 snd_soc_kcontrol_component(kcontrol);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530290 struct msm_ext_disp_audio_codec_rx_data *codec_data;
291 u32 ack_state = 0;
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700292 struct msm_ext_disp_codec_id codec_info;
293 int rc = 0;
294 int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
Sanjana B63bdc7b2020-01-20 19:31:18 +0530295 int type;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530296
Meng Wang15c825d2018-09-06 10:49:18 +0800297 codec_data = snd_soc_component_get_drvdata(component);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700298 if (!codec_data) {
Meng Wang15c825d2018-09-06 10:49:18 +0800299 dev_err(component->dev,
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700300 "%s: codec_data is NULL\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530301 __func__);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700302 return -EINVAL;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530303 }
304
Meng Wang15c825d2018-09-06 10:49:18 +0800305 dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700306 codec_data->ctl[dai_id], codec_data->stream[dai_id]);
307
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700308 mutex_lock(&codec_data->dp_ops_lock);
Sanjana B63bdc7b2020-01-20 19:31:18 +0530309 if (dai_id == HDMI_MS_DAI)
310 type = EXT_DISPLAY_TYPE_HDMI;
311 else
312 type = EXT_DISPLAY_TYPE_DP;
313 SWITCH_DP_CODEC(codec_info, codec_data, dai_id, type);
Harshal Ahire42adadc2019-11-15 15:52:50 +0530314 rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
315 &codec_info);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700316
Harshal Ahire42adadc2019-11-15 15:52:50 +0530317 if (!codec_data->ext_disp_ops.acknowledge || rc) {
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700318 dev_err(component->dev,
319 "%s: codec_data ops acknowledge() is NULL\n",
320 __func__);
321 rc = -EINVAL;
322 goto err;
323 }
324
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530325 switch (ucontrol->value.enumerated.item[0]) {
326 case 0:
327 ack_state = AUD_EXT_DISP_ACK_DISCONNECT;
328 break;
329 case 1:
330 ack_state = AUD_EXT_DISP_ACK_CONNECT;
331 break;
332 case 2:
333 ack_state = AUD_EXT_DISP_ACK_ENABLE;
334 break;
335 default:
336 rc = -EINVAL;
Meng Wang15c825d2018-09-06 10:49:18 +0800337 dev_err(component->dev,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530338 "%s: invalid value %d for mixer ctl\n",
339 __func__, ucontrol->value.enumerated.item[0]);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700340 goto err;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530341 }
Meng Wang15c825d2018-09-06 10:49:18 +0800342 dev_dbg(component->dev, "%s: control %d, ack set value 0x%x\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530343 __func__, ucontrol->value.enumerated.item[0], ack_state);
344
345 rc = codec_data->ext_disp_ops.acknowledge(
346 codec_data->ext_disp_core_pdev, ack_state);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700347 mutex_unlock(&codec_data->dp_ops_lock);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530348 if (rc < 0) {
Meng Wang15c825d2018-09-06 10:49:18 +0800349 dev_err(component->dev, "%s: error from acknowledge(), err:%d\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530350 __func__, rc);
351 }
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700352 return rc;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530353
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700354err:
355 mutex_unlock(&codec_data->dp_ops_lock);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530356 return rc;
357}
358
Karthikeyan Mani311bd672019-06-06 13:40:55 -0700359static int msm_ext_disp_audio_device_get(struct snd_kcontrol *kcontrol,
360 struct snd_ctl_elem_value *ucontrol)
361{
362 struct snd_soc_component *component =
363 snd_soc_kcontrol_component(kcontrol);
364 struct msm_ext_disp_audio_codec_rx_data *codec_data;
365 int rc = 0;
366 int dai_id = ((struct soc_multi_mixer_control *)
367 kcontrol->private_value)->shift;
368
369 if (dai_id < 0 || dai_id > DP_DAI2) {
370 dev_err(component->dev,
371 "%s: invalid dai id: %d\n", __func__, dai_id);
372 rc = -EINVAL;
373 goto done;
374 }
375
376 codec_data = snd_soc_component_get_drvdata(component);
377 if (!codec_data) {
378 dev_err(component->dev,
379 "%s: codec_data or ops acknowledge() is NULL\n",
380 __func__);
381 rc = -EINVAL;
382 goto done;
383 }
384 ucontrol->value.integer.value[0] = codec_data->ctl[dai_id];
385 ucontrol->value.integer.value[1] = codec_data->stream[dai_id];
386
387done:
388 return rc;
389}
390
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700391static int msm_ext_disp_audio_device_set(struct snd_kcontrol *kcontrol,
392 struct snd_ctl_elem_value *ucontrol)
393{
Meng Wang15c825d2018-09-06 10:49:18 +0800394 struct snd_soc_component *component =
395 snd_soc_kcontrol_component(kcontrol);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700396 struct msm_ext_disp_audio_codec_rx_data *codec_data;
397 int rc = 0;
Karthikeyan Mani311bd672019-06-06 13:40:55 -0700398 int dai_id = ((struct soc_multi_mixer_control *)
399 kcontrol->private_value)->shift;
400
401 if (dai_id < 0 || dai_id > DP_DAI2) {
402 dev_err(component->dev,
403 "%s: invalid dai id: %d\n", __func__, dai_id);
404 rc = -EINVAL;
405 goto done;
406 }
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700407
Meng Wang15c825d2018-09-06 10:49:18 +0800408 codec_data = snd_soc_component_get_drvdata(component);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700409 if (!codec_data) {
Meng Wang15c825d2018-09-06 10:49:18 +0800410 dev_err(component->dev,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700411 "%s: codec_data or ops acknowledge() is NULL\n",
412 __func__);
413 rc = -EINVAL;
414 goto done;
415 }
416
Karthikeyan Mani311bd672019-06-06 13:40:55 -0700417 if ((ucontrol->value.integer.value[0] > (DP_CONTROLLER_MAX - 1)) ||
418 (ucontrol->value.integer.value[1] > (DP_STREAM_MAX - 1)) ||
419 (ucontrol->value.integer.value[0] < 0) ||
420 (ucontrol->value.integer.value[1] < 0)) {
421 dev_err(component->dev,
422 "%s: DP audio control index invalid\n",
423 __func__);
424 rc = -EINVAL;
425 goto done;
426 }
427
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700428 mutex_lock(&codec_data->dp_ops_lock);
Karthikeyan Mani311bd672019-06-06 13:40:55 -0700429 codec_data->ctl[dai_id] = ucontrol->value.integer.value[0];
430 codec_data->stream[dai_id] = ucontrol->value.integer.value[1];
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700431 mutex_unlock(&codec_data->dp_ops_lock);
432
433done:
434 return rc;
435}
436
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530437static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = {
438 {
439 .access = SNDRV_CTL_ELEM_ACCESS_READ |
440 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
441 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
442 .name = "HDMI EDID",
443 .info = msm_ext_disp_edid_ctl_info,
444 .get = msm_ext_disp_edid_get,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700445 .private_value = HDMI_DAI,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530446 },
447 {
448 .access = SNDRV_CTL_ELEM_ACCESS_READ |
449 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
450 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Sanjana B63bdc7b2020-01-20 19:31:18 +0530451 .name = "HDMI MS EDID",
452 .info = msm_ext_disp_edid_ctl_info,
453 .get = msm_ext_disp_edid_get,
454 .private_value = HDMI_MS_DAI,
455 },
456 {
457 .access = SNDRV_CTL_ELEM_ACCESS_READ |
458 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
459 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530460 .name = "Display Port EDID",
461 .info = msm_ext_disp_edid_ctl_info,
462 .get = msm_ext_disp_edid_get,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700463 .private_value = DP_DAI1,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530464 },
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700465 {
466 .access = SNDRV_CTL_ELEM_ACCESS_READ |
467 SNDRV_CTL_ELEM_ACCESS_VOLATILE,
468 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
469 .name = "Display Port1 EDID",
470 .info = msm_ext_disp_edid_ctl_info,
471 .get = msm_ext_disp_edid_get,
472 .private_value = DP_DAI2,
473 },
474 SOC_ENUM_EXT("External Display Type",
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700475 ext_disp_audio_type1,
476 msm_ext_disp_audio_type_get, NULL),
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700477 SOC_ENUM_EXT("External Display1 Type",
478 ext_disp_audio_type2,
479 msm_ext_disp_audio_type_get, NULL),
Sanjana B63bdc7b2020-01-20 19:31:18 +0530480 SOC_ENUM_EXT("External HDMI Type",
481 ext_disp_audio_type3,
482 msm_ext_disp_audio_type_get, NULL),
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700483 SOC_ENUM_EXT("External Display Audio Ack",
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700484 ext_disp_audio_ack_state1,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530485 NULL, msm_ext_disp_audio_ack_set),
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700486 SOC_ENUM_EXT("External Display1 Audio Ack",
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700487 ext_disp_audio_ack_state2,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700488 NULL, msm_ext_disp_audio_ack_set),
Sanjana B63bdc7b2020-01-20 19:31:18 +0530489 SOC_ENUM_EXT("External HDMI Audio Ack",
490 ext_disp_audio_ack_state3,
491 NULL, msm_ext_disp_audio_ack_set),
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700492
Karthikeyan Mani311bd672019-06-06 13:40:55 -0700493 SOC_SINGLE_MULTI_EXT("External Display Audio Device",
494 SND_SOC_NOPM, DP_DAI1, DP_STREAM_MAX - 1, 0, 2,
495 msm_ext_disp_audio_device_get,
496 msm_ext_disp_audio_device_set),
497 SOC_SINGLE_MULTI_EXT("External Display1 Audio Device",
498 SND_SOC_NOPM, DP_DAI2, DP_STREAM_MAX - 1, 0, 2,
499 msm_ext_disp_audio_device_get,
500 msm_ext_disp_audio_device_set),
Sanjana B63bdc7b2020-01-20 19:31:18 +0530501 SOC_SINGLE_MULTI_EXT("External HDMI Device",
502 SND_SOC_NOPM, HDMI_MS_DAI, DP_STREAM_MAX - 1, 0, 2,
503 msm_ext_disp_audio_device_get,
504 msm_ext_disp_audio_device_set),
505
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530506};
507
508static int msm_ext_disp_audio_codec_rx_dai_startup(
509 struct snd_pcm_substream *substream,
510 struct snd_soc_dai *dai)
511{
Harshal Ahire42adadc2019-11-15 15:52:50 +0530512 int ret = 0, rc = 0;
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700513 struct msm_ext_disp_codec_id codec_info;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530514 struct msm_ext_disp_audio_codec_rx_data *codec_data =
Meng Wang15c825d2018-09-06 10:49:18 +0800515 dev_get_drvdata(dai->component->dev);
Sanjana B63bdc7b2020-01-20 19:31:18 +0530516 int type;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530517
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700518 if (!codec_data) {
519 dev_err(dai->dev, "%s() codec_data is null\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530520 __func__);
521 return -EINVAL;
522 }
523
Meng Wang15c825d2018-09-06 10:49:18 +0800524 dev_dbg(dai->component->dev, "%s: DP ctl id %d Stream id %d\n",
525 __func__,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700526 codec_data->ctl[dai->id], codec_data->stream[dai->id]);
527
528 mutex_lock(&codec_data->dp_ops_lock);
Sanjana B63bdc7b2020-01-20 19:31:18 +0530529 if (dai->id == HDMI_MS_DAI)
530 type = EXT_DISPLAY_TYPE_HDMI;
531 else
532 type = EXT_DISPLAY_TYPE_DP;
533 SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
Harshal Ahire42adadc2019-11-15 15:52:50 +0530534 rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
535 &codec_info);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700536
Harshal Ahire42adadc2019-11-15 15:52:50 +0530537 if (!codec_data->ext_disp_ops.cable_status || rc) {
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700538 dev_err(dai->dev, "%s() cable_status is null\n",
539 __func__);
540 mutex_unlock(&codec_data->dp_ops_lock);
541 return -EINVAL;
542 }
543
544 codec_data->cable_status[dai->id] =
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530545 codec_data->ext_disp_ops.cable_status(
546 codec_data->ext_disp_core_pdev, 1);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700547 mutex_unlock(&codec_data->dp_ops_lock);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700548 if (codec_data->cable_status[dai->id] < 0) {
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530549 dev_err(dai->dev,
550 "%s() ext disp core is not ready (ret val = %d)\n",
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700551 __func__, codec_data->cable_status[dai->id]);
552 ret = codec_data->cable_status[dai->id];
553 } else if (!codec_data->cable_status[dai->id]) {
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530554 dev_err(dai->dev,
555 "%s() ext disp cable is not connected (ret val = %d)\n",
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700556 __func__, codec_data->cable_status[dai->id]);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530557 ret = -ENODEV;
558 }
559
560 return ret;
561}
562
563static int msm_ext_disp_audio_codec_rx_dai_hw_params(
564 struct snd_pcm_substream *substream,
565 struct snd_pcm_hw_params *params,
566 struct snd_soc_dai *dai)
567{
568 u32 channel_allocation = 0;
569 u32 level_shift = 0; /* 0dB */
570 bool down_mix = 0;
571 u32 num_channels = params_channels(params);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700572 struct msm_ext_disp_codec_id codec_info;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530573 int rc = 0;
574 struct msm_ext_disp_audio_setup_params audio_setup_params = {0};
Sanjana B63bdc7b2020-01-20 19:31:18 +0530575 int type;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530576 struct msm_ext_disp_audio_codec_rx_data *codec_data =
Meng Wang15c825d2018-09-06 10:49:18 +0800577 dev_get_drvdata(dai->component->dev);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530578
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700579 if (!codec_data) {
580 dev_err(dai->dev, "%s() codec_data is null\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530581 __func__);
582 return -EINVAL;
583 }
584
Meng Wang15c825d2018-09-06 10:49:18 +0800585 dev_dbg(dai->component->dev, "%s: DP ctl id %d Stream id %d\n",
586 __func__,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700587 codec_data->ctl[dai->id], codec_data->stream[dai->id]);
588
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700589 mutex_lock(&codec_data->dp_ops_lock);
Sanjana B63bdc7b2020-01-20 19:31:18 +0530590 if (dai->id == HDMI_MS_DAI)
591 type = EXT_DISPLAY_TYPE_HDMI;
592 else
593 type = EXT_DISPLAY_TYPE_DP;
594 SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
Harshal Ahire42adadc2019-11-15 15:52:50 +0530595 rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
596 &codec_info);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700597
Harshal Ahire42adadc2019-11-15 15:52:50 +0530598 if (!codec_data->ext_disp_ops.audio_info_setup || rc) {
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700599 dev_err(dai->dev, "%s: audio_info_setup is null\n",
600 __func__);
601 mutex_unlock(&codec_data->dp_ops_lock);
602 return -EINVAL;
603 }
604 mutex_unlock(&codec_data->dp_ops_lock);
605
606 if (codec_data->cable_status[dai->id] < 0) {
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530607 dev_err_ratelimited(dai->dev,
608 "%s() ext disp core is not ready (ret val = %d)\n",
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700609 __func__, codec_data->cable_status[dai->id]);
610 return codec_data->cable_status[dai->id];
611 } else if (!codec_data->cable_status[dai->id]) {
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530612 dev_err_ratelimited(dai->dev,
613 "%s() ext disp cable is not connected (ret val = %d)\n",
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700614 __func__, codec_data->cable_status[dai->id]);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530615 return -ENODEV;
616 }
617
618 /*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/
619 switch (num_channels) {
620 case 2:
621 channel_allocation = 0;
622 break;
623 case 3:
624 channel_allocation = 0x02;/*default to FL/FR/FC*/
625 audio_setup_params.sample_present = 0x3;
626 break;
627 case 4:
628 channel_allocation = 0x06;/*default to FL/FR/FC/RC*/
629 audio_setup_params.sample_present = 0x7;
630 break;
631 case 5:
632 channel_allocation = 0x0A;/*default to FL/FR/FC/RR/RL*/
633 audio_setup_params.sample_present = 0x7;
634 break;
635 case 6:
636 channel_allocation = 0x0B;
637 audio_setup_params.sample_present = 0x7;
638 break;
639 case 7:
640 channel_allocation = 0x12;/*default to FL/FR/FC/RL/RR/RRC/RLC*/
641 audio_setup_params.sample_present = 0xf;
642 break;
643 case 8:
644 channel_allocation = 0x13;
645 audio_setup_params.sample_present = 0xf;
646 break;
647 default:
648 dev_err(dai->dev, "invalid Channels = %u\n", num_channels);
649 return -EINVAL;
650 }
651
652 dev_dbg(dai->dev,
653 "%s() num_ch %u samplerate %u channel_allocation = %u\n",
654 __func__, num_channels, params_rate(params),
655 channel_allocation);
656
657 audio_setup_params.sample_rate_hz = params_rate(params);
658 audio_setup_params.num_of_channels = num_channels;
659 audio_setup_params.channel_allocation = channel_allocation;
660 audio_setup_params.level_shift = level_shift;
661 audio_setup_params.down_mix = down_mix;
662
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700663 mutex_lock(&codec_data->dp_ops_lock);
Sanjana B63bdc7b2020-01-20 19:31:18 +0530664 SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
Harshal Ahire42adadc2019-11-15 15:52:50 +0530665 rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
666 &codec_info);
667 if (rc)
668 goto end;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530669 rc = codec_data->ext_disp_ops.audio_info_setup(
670 codec_data->ext_disp_core_pdev, &audio_setup_params);
Harshal Ahire42adadc2019-11-15 15:52:50 +0530671end:
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700672 mutex_unlock(&codec_data->dp_ops_lock);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530673 if (rc < 0) {
674 dev_err_ratelimited(dai->dev,
675 "%s() ext disp core is not ready, rc: %d\n",
676 __func__, rc);
677 }
678
679 return rc;
680}
681
682static void msm_ext_disp_audio_codec_rx_dai_shutdown(
683 struct snd_pcm_substream *substream,
684 struct snd_soc_dai *dai)
685{
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700686 int rc = 0;
687 struct msm_ext_disp_codec_id codec_info;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530688
689 struct msm_ext_disp_audio_codec_rx_data *codec_data =
Meng Wang15c825d2018-09-06 10:49:18 +0800690 dev_get_drvdata(dai->component->dev);
Sanjana B63bdc7b2020-01-20 19:31:18 +0530691 int type;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530692
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700693 if (!codec_data) {
694 dev_err(dai->dev, "%s() codec_data is null\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530695 __func__);
696 return;
697 }
698
Meng Wang15c825d2018-09-06 10:49:18 +0800699 dev_dbg(dai->component->dev, "%s: DP ctl id %d Stream id %d\n",
700 __func__,
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700701 codec_data->ctl[dai->id], codec_data->stream[dai->id]);
702
703 mutex_lock(&codec_data->dp_ops_lock);
Sanjana B63bdc7b2020-01-20 19:31:18 +0530704 if (dai->id == HDMI_MS_DAI)
705 type = EXT_DISPLAY_TYPE_HDMI;
706 else
707 type = EXT_DISPLAY_TYPE_DP;
708 SWITCH_DP_CODEC(codec_info, codec_data, dai->id, type);
Harshal Ahire42adadc2019-11-15 15:52:50 +0530709 rc = msm_ext_disp_select_audio_codec(codec_data->ext_disp_core_pdev,
710 &codec_info);
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700711
712 if (!codec_data->ext_disp_ops.teardown_done ||
Harshal Ahire42adadc2019-11-15 15:52:50 +0530713 !codec_data->ext_disp_ops.cable_status || rc) {
Vignesh Kulothunganf86a3552019-07-11 15:46:25 -0700714 dev_err(dai->dev, "%s: teardown_done or cable_status is null\n",
715 __func__);
716 mutex_unlock(&codec_data->dp_ops_lock);
717 return;
718 }
719
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530720 rc = codec_data->ext_disp_ops.cable_status(
721 codec_data->ext_disp_core_pdev, 0);
722 if (rc < 0) {
723 dev_err(dai->dev,
724 "%s: ext disp core had problems releasing audio flag\n",
725 __func__);
726 }
727
728 codec_data->ext_disp_ops.teardown_done(
729 codec_data->ext_disp_core_pdev);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700730 mutex_unlock(&codec_data->dp_ops_lock);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530731}
732
Meng Wang15c825d2018-09-06 10:49:18 +0800733static int msm_ext_disp_audio_codec_rx_probe(
734 struct snd_soc_component *component)
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530735{
736 struct msm_ext_disp_audio_codec_rx_data *codec_data;
737 struct device_node *of_node_parent = NULL;
738
739 codec_data = kzalloc(sizeof(struct msm_ext_disp_audio_codec_rx_data),
740 GFP_KERNEL);
741
742 if (!codec_data) {
Meng Wang15c825d2018-09-06 10:49:18 +0800743 dev_err(component->dev, "%s(): fail to allocate dai data\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530744 __func__);
745 return -ENOMEM;
746 }
747
Meng Wang15c825d2018-09-06 10:49:18 +0800748 of_node_parent = of_get_parent(component->dev->of_node);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530749 if (!of_node_parent) {
Meng Wang15c825d2018-09-06 10:49:18 +0800750 dev_err(component->dev, "%s(): Parent device tree node not found\n",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530751 __func__);
752 kfree(codec_data);
753 return -ENODEV;
754 }
755
756 codec_data->ext_disp_core_pdev = of_find_device_by_node(of_node_parent);
757 if (!codec_data->ext_disp_core_pdev) {
Meng Wang15c825d2018-09-06 10:49:18 +0800758 dev_err(component->dev, "%s(): can't get parent pdev\n",
759 __func__);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530760 kfree(codec_data);
761 return -ENODEV;
762 }
763
764 if (msm_ext_disp_register_audio_codec(codec_data->ext_disp_core_pdev,
765 &codec_data->ext_disp_ops)) {
Meng Wang15c825d2018-09-06 10:49:18 +0800766 dev_err(component->dev, "%s(): can't register with ext disp core",
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530767 __func__);
768 kfree(codec_data);
769 return -ENODEV;
770 }
771
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700772 mutex_init(&codec_data->dp_ops_lock);
Meng Wang15c825d2018-09-06 10:49:18 +0800773 dev_set_drvdata(component->dev, codec_data);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530774
Meng Wang15c825d2018-09-06 10:49:18 +0800775 dev_dbg(component->dev, "%s(): registered %s with ext disp core\n",
776 __func__, component->name);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530777
778 return 0;
779}
780
Meng Wang15c825d2018-09-06 10:49:18 +0800781static void msm_ext_disp_audio_codec_rx_remove(
782 struct snd_soc_component *component)
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530783{
784 struct msm_ext_disp_audio_codec_rx_data *codec_data;
785
Meng Wang15c825d2018-09-06 10:49:18 +0800786 codec_data = dev_get_drvdata(component->dev);
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700787 mutex_destroy(&codec_data->dp_ops_lock);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530788 kfree(codec_data);
789
Meng Wang15c825d2018-09-06 10:49:18 +0800790 return;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530791}
792
793static struct snd_soc_dai_ops msm_ext_disp_audio_codec_rx_dai_ops = {
794 .startup = msm_ext_disp_audio_codec_rx_dai_startup,
795 .hw_params = msm_ext_disp_audio_codec_rx_dai_hw_params,
796 .shutdown = msm_ext_disp_audio_codec_rx_dai_shutdown
797};
798
799static struct snd_soc_dai_driver msm_ext_disp_audio_codec_rx_dais[] = {
800 {
801 .name = "msm_hdmi_audio_codec_rx_dai",
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700802 .id = HDMI_DAI,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530803 .playback = {
804 .stream_name = "HDMI Playback",
805 .channels_min = 1,
806 .channels_max = 8,
807 .rate_min = 48000,
808 .rate_max = 48000,
809 .rates = MSM_EXT_DISP_PCM_RATES,
810 .formats = SNDRV_PCM_FMTBIT_S16_LE,
811 },
812 .ops = &msm_ext_disp_audio_codec_rx_dai_ops,
813 },
814 {
Sanjana B63bdc7b2020-01-20 19:31:18 +0530815 .name = "msm_hdmi_ms_audio_codec_rx_dai",
816 .id = HDMI_MS_DAI,
817 .playback = {
818 .stream_name = "HDMI MS Playback",
819 .channels_min = 1,
820 .channels_max = 8,
821 .rate_min = 48000,
822 .rate_max = 48000,
823 .rates = MSM_EXT_DISP_PCM_RATES,
824 .formats = SNDRV_PCM_FMTBIT_S16_LE,
825 },
826 .ops = &msm_ext_disp_audio_codec_rx_dai_ops,
827 },
828 {
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530829 .name = "msm_dp_audio_codec_rx_dai",
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700830 .id = DP_DAI1,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530831 .playback = {
832 .stream_name = "Display Port Playback",
833 .channels_min = 1,
834 .channels_max = 8,
835 .rate_min = 48000,
836 .rate_max = 192000,
837 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700838 SNDRV_PCM_RATE_192000,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530839 .formats = SNDRV_PCM_FMTBIT_S16_LE |
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700840 SNDRV_PCM_FMTBIT_S24_LE |
841 SNDRV_PCM_FMTBIT_S24_3LE,
842 },
843 .ops = &msm_ext_disp_audio_codec_rx_dai_ops,
844 },
845 {
846 .name = "msm_dp_audio_codec_rx1_dai",
847 .id = DP_DAI2,
848 .playback = {
849 .stream_name = "Display Port1 Playback",
850 .channels_min = 1,
851 .channels_max = 8,
852 .rate_min = 48000,
853 .rate_max = 192000,
854 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
855 SNDRV_PCM_RATE_192000,
856 .formats = SNDRV_PCM_FMTBIT_S16_LE |
857 SNDRV_PCM_FMTBIT_S24_LE |
858 SNDRV_PCM_FMTBIT_S24_3LE,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530859 },
860 .ops = &msm_ext_disp_audio_codec_rx_dai_ops,
861 },
862};
863
Meng Wang15c825d2018-09-06 10:49:18 +0800864static const struct snd_soc_component_driver msm_ext_disp_codec_rx_driver = {
865 .name = DRV_NAME,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530866 .probe = msm_ext_disp_audio_codec_rx_probe,
867 .remove = msm_ext_disp_audio_codec_rx_remove,
Meng Wang15c825d2018-09-06 10:49:18 +0800868 .controls = msm_ext_disp_codec_rx_controls,
869 .num_controls = ARRAY_SIZE(msm_ext_disp_codec_rx_controls),
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530870};
871
872static int msm_ext_disp_audio_codec_rx_plat_probe(
873 struct platform_device *pdev)
874{
875 dev_dbg(&pdev->dev, "%s(): dev name %s\n", __func__,
876 dev_name(&pdev->dev));
877
Meng Wang15c825d2018-09-06 10:49:18 +0800878 return snd_soc_register_component(&pdev->dev,
879 &msm_ext_disp_codec_rx_driver,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530880 msm_ext_disp_audio_codec_rx_dais,
881 ARRAY_SIZE(msm_ext_disp_audio_codec_rx_dais));
882}
883
884static int msm_ext_disp_audio_codec_rx_plat_remove(
885 struct platform_device *pdev)
886{
Meng Wang15c825d2018-09-06 10:49:18 +0800887 snd_soc_unregister_component(&pdev->dev);
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530888 return 0;
889}
890static const struct of_device_id msm_ext_disp_audio_codec_rx_dt_match[] = {
891 { .compatible = "qcom,msm-ext-disp-audio-codec-rx", },
892 {}
893};
894MODULE_DEVICE_TABLE(of, msm_ext_disp_audio_codec_rx_dt_match);
895
896static struct platform_driver msm_ext_disp_audio_codec_rx_driver = {
897 .driver = {
898 .name = "msm-ext-disp-audio-codec-rx",
899 .owner = THIS_MODULE,
900 .of_match_table = msm_ext_disp_audio_codec_rx_dt_match,
Xiaojun Sang53cd13a2018-06-29 15:14:37 +0800901 .suppress_bind_attrs = true,
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530902 },
903 .probe = msm_ext_disp_audio_codec_rx_plat_probe,
904 .remove = msm_ext_disp_audio_codec_rx_plat_remove,
905};
906
907static int __init msm_ext_disp_audio_codec_rx_init(void)
908{
Karthikeyan Manifc1e9722018-05-03 18:38:56 -0700909 int rc = 0;
Asish Bhattacharya366f7502017-07-25 15:15:56 +0530910
911 rc = platform_driver_register(&msm_ext_disp_audio_codec_rx_driver);
912 if (rc) {
913 pr_err("%s: failed to register ext disp codec driver err:%d\n",
914 __func__, rc);
915 }
916
917 return rc;
918}
919module_init(msm_ext_disp_audio_codec_rx_init);
920
921static void __exit msm_ext_disp_audio_codec_rx_exit(void)
922{
923 platform_driver_unregister(&msm_ext_disp_audio_codec_rx_driver);
924}
925module_exit(msm_ext_disp_audio_codec_rx_exit);
926
927MODULE_DESCRIPTION("MSM External Display Audio CODEC Driver");
928MODULE_LICENSE("GPL v2");