|
@@ -43,8 +43,12 @@ enum {
|
|
|
DP_STREAM_MAX,
|
|
|
};
|
|
|
|
|
|
+/*
|
|
|
+ * Dai id cannot be zero, if component has more than one dai and dai id
|
|
|
+ * is used to differentiate between them
|
|
|
+ */
|
|
|
enum {
|
|
|
- DP_DAI1 = 0,
|
|
|
+ DP_DAI1 = 1,
|
|
|
DP_DAI2,
|
|
|
HDMI_DAI,
|
|
|
DP_DAI_MAX,
|
|
@@ -54,16 +58,16 @@ static const char *const ext_disp_audio_type_text[] = {"None", "HDMI", "DP"};
|
|
|
static const char *const ext_disp_audio_ack_text[] = {"Disconnect", "Connect",
|
|
|
"Ack_Enable"};
|
|
|
|
|
|
-SOC_EXT_DISP_AUDIO_TYPE(0);
|
|
|
-SOC_EXT_DISP_AUDIO_ACK_STATE(0);
|
|
|
SOC_EXT_DISP_AUDIO_TYPE(1);
|
|
|
SOC_EXT_DISP_AUDIO_ACK_STATE(1);
|
|
|
+SOC_EXT_DISP_AUDIO_TYPE(2);
|
|
|
+SOC_EXT_DISP_AUDIO_ACK_STATE(2);
|
|
|
|
|
|
struct msm_ext_disp_audio_codec_rx_data {
|
|
|
struct platform_device *ext_disp_core_pdev;
|
|
|
struct msm_ext_disp_audio_codec_ops ext_disp_ops;
|
|
|
- int cable_status;
|
|
|
struct mutex dp_ops_lock;
|
|
|
+ int cable_status[DP_DAI_MAX];
|
|
|
int stream[DP_DAI_MAX];
|
|
|
int ctl[DP_DAI_MAX];
|
|
|
};
|
|
@@ -80,25 +84,25 @@ static int msm_ext_disp_edid_ctl_info(struct snd_kcontrol *kcontrol,
|
|
|
int dai_id = kcontrol->private_value;
|
|
|
|
|
|
codec_data = snd_soc_component_get_drvdata(component);
|
|
|
-
|
|
|
if (!codec_data) {
|
|
|
dev_err(component->dev, "%s: codec_data is NULL\n", __func__);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
|
|
|
+ codec_data->ctl[dai_id], codec_data->stream[dai_id]);
|
|
|
+
|
|
|
+ mutex_lock(&codec_data->dp_ops_lock);
|
|
|
+ SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
|
|
|
if (!codec_data->ext_disp_ops.get_audio_edid_blk) {
|
|
|
dev_dbg(component->dev, "%s: get_audio_edid_blk() is NULL\n",
|
|
|
__func__);
|
|
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
|
|
uinfo->count = 0;
|
|
|
- return 0;
|
|
|
+ mutex_unlock(&codec_data->dp_ops_lock);
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
|
|
|
- codec_data->ctl[dai_id], codec_data->stream[dai_id]);
|
|
|
-
|
|
|
- mutex_lock(&codec_data->dp_ops_lock);
|
|
|
- SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
|
|
|
rc = codec_data->ext_disp_ops.get_audio_edid_blk(
|
|
|
codec_data->ext_disp_core_pdev, &edid_blk);
|
|
|
mutex_unlock(&codec_data->dp_ops_lock);
|
|
@@ -124,8 +128,8 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
|
|
|
int dai_id = kcontrol->private_value;
|
|
|
|
|
|
codec_data = snd_soc_component_get_drvdata(component);
|
|
|
- if (!codec_data || !codec_data->ext_disp_ops.get_audio_edid_blk) {
|
|
|
- dev_err(component->dev, "%s: codec_data or get_audio_edid_blk() is NULL\n",
|
|
|
+ if (!codec_data) {
|
|
|
+ dev_err(component->dev, "%s: codec_data is NULL\n",
|
|
|
__func__);
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -135,6 +139,13 @@ static int msm_ext_disp_edid_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
|
mutex_lock(&codec_data->dp_ops_lock);
|
|
|
SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
|
|
|
+ if (!codec_data->ext_disp_ops.get_audio_edid_blk) {
|
|
|
+ dev_err(component->dev, "%s: codec_data or get_audio_edid_blk() is NULL\n",
|
|
|
+ __func__);
|
|
|
+ mutex_unlock(&codec_data->dp_ops_lock);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
rc = codec_data->ext_disp_ops.get_audio_edid_blk(
|
|
|
codec_data->ext_disp_core_pdev, &edid_blk);
|
|
|
mutex_unlock(&codec_data->dp_ops_lock);
|
|
@@ -177,10 +188,8 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
|
|
|
int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
|
|
|
|
|
|
codec_data = snd_soc_component_get_drvdata(component);
|
|
|
- if (!codec_data ||
|
|
|
- !codec_data->ext_disp_ops.get_audio_edid_blk ||
|
|
|
- !codec_data->ext_disp_ops.get_intf_id) {
|
|
|
- dev_err(component->dev, "%s: codec_data, get_audio_edid_blk() or get_intf_id is NULL\n",
|
|
|
+ if (!codec_data) {
|
|
|
+ dev_err(component->dev, "%s: codec_data is NULL\n",
|
|
|
__func__);
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -190,6 +199,15 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
|
|
|
|
|
|
mutex_lock(&codec_data->dp_ops_lock);
|
|
|
SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
|
|
|
+
|
|
|
+ if (!codec_data->ext_disp_ops.get_audio_edid_blk ||
|
|
|
+ !codec_data->ext_disp_ops.get_intf_id) {
|
|
|
+ dev_err(component->dev, "%s: get_audio_edid_blk() or get_intf_id is NULL\n",
|
|
|
+ __func__);
|
|
|
+ rc = -EINVAL;
|
|
|
+ goto cable_err;
|
|
|
+ }
|
|
|
+
|
|
|
cable_state = codec_data->ext_disp_ops.cable_status(
|
|
|
codec_data->ext_disp_core_pdev, 1);
|
|
|
if (cable_state < 0) {
|
|
@@ -199,7 +217,7 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
|
|
|
goto cable_err;
|
|
|
}
|
|
|
|
|
|
- codec_data->cable_status = cable_state;
|
|
|
+ codec_data->cable_status[dai_id] = cable_state;
|
|
|
if (cable_state == EXT_DISPLAY_CABLE_DISCONNECT) {
|
|
|
dev_err(component->dev, "%s: Display cable disconnected\n",
|
|
|
__func__);
|
|
@@ -254,18 +272,27 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
|
|
|
int dai_id = ((struct soc_enum *) kcontrol->private_value)->shift_l;
|
|
|
|
|
|
codec_data = snd_soc_component_get_drvdata(component);
|
|
|
- if (!codec_data ||
|
|
|
- !codec_data->ext_disp_ops.acknowledge) {
|
|
|
+ if (!codec_data) {
|
|
|
dev_err(component->dev,
|
|
|
- "%s: codec_data or ops acknowledge() is NULL\n",
|
|
|
+ "%s: codec_data is NULL\n",
|
|
|
__func__);
|
|
|
- rc = -EINVAL;
|
|
|
- goto done;
|
|
|
+ return -EINVAL;
|
|
|
}
|
|
|
|
|
|
dev_dbg(component->dev, "%s: DP ctl id %d Stream id %d\n", __func__,
|
|
|
codec_data->ctl[dai_id], codec_data->stream[dai_id]);
|
|
|
|
|
|
+ mutex_lock(&codec_data->dp_ops_lock);
|
|
|
+ SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
|
|
|
+
|
|
|
+ if (!codec_data->ext_disp_ops.acknowledge) {
|
|
|
+ dev_err(component->dev,
|
|
|
+ "%s: codec_data ops acknowledge() is NULL\n",
|
|
|
+ __func__);
|
|
|
+ rc = -EINVAL;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
switch (ucontrol->value.enumerated.item[0]) {
|
|
|
case 0:
|
|
|
ack_state = AUD_EXT_DISP_ACK_DISCONNECT;
|
|
@@ -281,13 +308,11 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
|
|
|
dev_err(component->dev,
|
|
|
"%s: invalid value %d for mixer ctl\n",
|
|
|
__func__, ucontrol->value.enumerated.item[0]);
|
|
|
- goto done;
|
|
|
+ goto err;
|
|
|
}
|
|
|
dev_dbg(component->dev, "%s: control %d, ack set value 0x%x\n",
|
|
|
__func__, ucontrol->value.enumerated.item[0], ack_state);
|
|
|
|
|
|
- mutex_lock(&codec_data->dp_ops_lock);
|
|
|
- SWITCH_DP_CODEC(codec_info, codec_data, dai_id);
|
|
|
rc = codec_data->ext_disp_ops.acknowledge(
|
|
|
codec_data->ext_disp_core_pdev, ack_state);
|
|
|
mutex_unlock(&codec_data->dp_ops_lock);
|
|
@@ -295,8 +320,10 @@ static int msm_ext_disp_audio_ack_set(struct snd_kcontrol *kcontrol,
|
|
|
dev_err(component->dev, "%s: error from acknowledge(), err:%d\n",
|
|
|
__func__, rc);
|
|
|
}
|
|
|
+ return rc;
|
|
|
|
|
|
-done:
|
|
|
+err:
|
|
|
+ mutex_unlock(&codec_data->dp_ops_lock);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -407,16 +434,16 @@ static const struct snd_kcontrol_new msm_ext_disp_codec_rx_controls[] = {
|
|
|
.private_value = DP_DAI2,
|
|
|
},
|
|
|
SOC_ENUM_EXT("External Display Type",
|
|
|
- ext_disp_audio_type0,
|
|
|
+ ext_disp_audio_type1,
|
|
|
msm_ext_disp_audio_type_get, NULL),
|
|
|
SOC_ENUM_EXT("External Display1 Type",
|
|
|
- ext_disp_audio_type1,
|
|
|
+ ext_disp_audio_type2,
|
|
|
msm_ext_disp_audio_type_get, NULL),
|
|
|
SOC_ENUM_EXT("External Display Audio Ack",
|
|
|
- ext_disp_audio_ack_state0,
|
|
|
+ ext_disp_audio_ack_state1,
|
|
|
NULL, msm_ext_disp_audio_ack_set),
|
|
|
SOC_ENUM_EXT("External Display1 Audio Ack",
|
|
|
- ext_disp_audio_ack_state1,
|
|
|
+ ext_disp_audio_ack_state2,
|
|
|
NULL, msm_ext_disp_audio_ack_set),
|
|
|
|
|
|
SOC_SINGLE_MULTI_EXT("External Display Audio Device",
|
|
@@ -438,8 +465,8 @@ static int msm_ext_disp_audio_codec_rx_dai_startup(
|
|
|
struct msm_ext_disp_audio_codec_rx_data *codec_data =
|
|
|
dev_get_drvdata(dai->component->dev);
|
|
|
|
|
|
- if (!codec_data || !codec_data->ext_disp_ops.cable_status) {
|
|
|
- dev_err(dai->dev, "%s() codec_data or cable_status is null\n",
|
|
|
+ if (!codec_data) {
|
|
|
+ dev_err(dai->dev, "%s() codec_data is null\n",
|
|
|
__func__);
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -450,19 +477,27 @@ static int msm_ext_disp_audio_codec_rx_dai_startup(
|
|
|
|
|
|
mutex_lock(&codec_data->dp_ops_lock);
|
|
|
SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
|
|
|
- codec_data->cable_status =
|
|
|
+
|
|
|
+ if (!codec_data->ext_disp_ops.cable_status) {
|
|
|
+ dev_err(dai->dev, "%s() cable_status is null\n",
|
|
|
+ __func__);
|
|
|
+ mutex_unlock(&codec_data->dp_ops_lock);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ codec_data->cable_status[dai->id] =
|
|
|
codec_data->ext_disp_ops.cable_status(
|
|
|
codec_data->ext_disp_core_pdev, 1);
|
|
|
mutex_unlock(&codec_data->dp_ops_lock);
|
|
|
- if (codec_data->cable_status < 0) {
|
|
|
+ if (codec_data->cable_status[dai->id] < 0) {
|
|
|
dev_err(dai->dev,
|
|
|
"%s() ext disp core is not ready (ret val = %d)\n",
|
|
|
- __func__, codec_data->cable_status);
|
|
|
- ret = codec_data->cable_status;
|
|
|
- } else if (!codec_data->cable_status) {
|
|
|
+ __func__, codec_data->cable_status[dai->id]);
|
|
|
+ ret = codec_data->cable_status[dai->id];
|
|
|
+ } else if (!codec_data->cable_status[dai->id]) {
|
|
|
dev_err(dai->dev,
|
|
|
"%s() ext disp cable is not connected (ret val = %d)\n",
|
|
|
- __func__, codec_data->cable_status);
|
|
|
+ __func__, codec_data->cable_status[dai->id]);
|
|
|
ret = -ENODEV;
|
|
|
}
|
|
|
|
|
@@ -485,8 +520,8 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
|
|
|
struct msm_ext_disp_audio_codec_rx_data *codec_data =
|
|
|
dev_get_drvdata(dai->component->dev);
|
|
|
|
|
|
- if (!codec_data || !codec_data->ext_disp_ops.audio_info_setup) {
|
|
|
- dev_err(dai->dev, "%s: codec_data or audio_info_setup is null\n",
|
|
|
+ if (!codec_data) {
|
|
|
+ dev_err(dai->dev, "%s() codec_data is null\n",
|
|
|
__func__);
|
|
|
return -EINVAL;
|
|
|
}
|
|
@@ -495,15 +530,26 @@ static int msm_ext_disp_audio_codec_rx_dai_hw_params(
|
|
|
__func__,
|
|
|
codec_data->ctl[dai->id], codec_data->stream[dai->id]);
|
|
|
|
|
|
- if (codec_data->cable_status < 0) {
|
|
|
+ mutex_lock(&codec_data->dp_ops_lock);
|
|
|
+ SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
|
|
|
+
|
|
|
+ if (!codec_data->ext_disp_ops.audio_info_setup) {
|
|
|
+ dev_err(dai->dev, "%s: audio_info_setup is null\n",
|
|
|
+ __func__);
|
|
|
+ mutex_unlock(&codec_data->dp_ops_lock);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ mutex_unlock(&codec_data->dp_ops_lock);
|
|
|
+
|
|
|
+ if (codec_data->cable_status[dai->id] < 0) {
|
|
|
dev_err_ratelimited(dai->dev,
|
|
|
"%s() ext disp core is not ready (ret val = %d)\n",
|
|
|
- __func__, codec_data->cable_status);
|
|
|
- return codec_data->cable_status;
|
|
|
- } else if (!codec_data->cable_status) {
|
|
|
+ __func__, codec_data->cable_status[dai->id]);
|
|
|
+ return codec_data->cable_status[dai->id];
|
|
|
+ } else if (!codec_data->cable_status[dai->id]) {
|
|
|
dev_err_ratelimited(dai->dev,
|
|
|
"%s() ext disp cable is not connected (ret val = %d)\n",
|
|
|
- __func__, codec_data->cable_status);
|
|
|
+ __func__, codec_data->cable_status[dai->id]);
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
|
|
@@ -576,9 +622,8 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
|
|
|
struct msm_ext_disp_audio_codec_rx_data *codec_data =
|
|
|
dev_get_drvdata(dai->component->dev);
|
|
|
|
|
|
- if (!codec_data || !codec_data->ext_disp_ops.teardown_done ||
|
|
|
- !codec_data->ext_disp_ops.cable_status) {
|
|
|
- dev_err(dai->dev, "%s: codec data or teardown_done or cable_status is null\n",
|
|
|
+ if (!codec_data) {
|
|
|
+ dev_err(dai->dev, "%s() codec_data is null\n",
|
|
|
__func__);
|
|
|
return;
|
|
|
}
|
|
@@ -589,6 +634,15 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
|
|
|
|
|
|
mutex_lock(&codec_data->dp_ops_lock);
|
|
|
SWITCH_DP_CODEC(codec_info, codec_data, dai->id);
|
|
|
+
|
|
|
+ if (!codec_data->ext_disp_ops.teardown_done ||
|
|
|
+ !codec_data->ext_disp_ops.cable_status) {
|
|
|
+ dev_err(dai->dev, "%s: teardown_done or cable_status is null\n",
|
|
|
+ __func__);
|
|
|
+ mutex_unlock(&codec_data->dp_ops_lock);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
rc = codec_data->ext_disp_ops.cable_status(
|
|
|
codec_data->ext_disp_core_pdev, 0);
|
|
|
if (rc < 0) {
|