asoc: Add msm_common.c for I2S, TDM and AUXPCM interfaces
Change-Id: I675ec1f266a68c87882094d64055481305c6bdfb Signed-off-by: Rohit kumar <rohitkr@codeaurora.org>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
ebf0162590
commit
f6eb3aac0f
@@ -104,6 +104,8 @@ COMMON_INC := -I$(AUDIO_ROOT)/$(COMMON_DIR)
|
|||||||
|
|
||||||
############ ASoC Drivers ############
|
############ ASoC Drivers ############
|
||||||
|
|
||||||
|
MACHINE_OBJS += msm_common.o
|
||||||
|
|
||||||
# for SM8150 sound card driver
|
# for SM8150 sound card driver
|
||||||
ifdef CONFIG_SND_SOC_SM8150
|
ifdef CONFIG_SND_SOC_SM8150
|
||||||
MACHINE_OBJS += sm8150.o
|
MACHINE_OBJS += sm8150.o
|
||||||
|
159
asoc/msm_common.c
Normal file
159
asoc/msm_common.c
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include "asoc/msm-cdc-pinctrl.h"
|
||||||
|
#include "msm_common.h"
|
||||||
|
|
||||||
|
static int get_intf_index(const char *stream_name)
|
||||||
|
{
|
||||||
|
if (strnstr(stream_name, "PRIMARY", strlen("PRIMARY")))
|
||||||
|
return PRI_MI2S_TDM_AUXPCM;
|
||||||
|
else if (strnstr(stream_name, "SECONDARY", strlen("SECONDARY")))
|
||||||
|
return SEC_MI2S_TDM_AUXPCM;
|
||||||
|
else if (strnstr(stream_name, "TERTIARY", strlen("TERTIARY")))
|
||||||
|
return TER_MI2S_TDM_AUXPCM;
|
||||||
|
else if (strnstr(stream_name, "QUATERNARY", strlen("QUATERNARY")))
|
||||||
|
return QUAT_MI2S_TDM_AUXPCM;
|
||||||
|
else if (strnstr(stream_name, "QUINARY", strlen("QUINARY")))
|
||||||
|
return QUIN_MI2S_TDM_AUXPCM;
|
||||||
|
else if (strnstr(stream_name, "SENARY", strlen("SENARY")))
|
||||||
|
return SEN_MI2S_TDM_AUXPCM;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int msm_common_snd_startup(struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
struct snd_soc_card *card = rtd->card;
|
||||||
|
struct msm_common_pdata *pdata = msm_common_get_pdata(card);
|
||||||
|
const char *stream_name = rtd->dai_link->stream_name;
|
||||||
|
int index = get_intf_index(stream_name);
|
||||||
|
|
||||||
|
dev_dbg(rtd->card->dev,
|
||||||
|
"%s: substream = %s stream = %d\n",
|
||||||
|
__func__, substream->name, substream->stream);
|
||||||
|
|
||||||
|
if (!pdata) {
|
||||||
|
dev_err(rtd->card->dev, "%s: pdata is NULL\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
dev_err(rtd->card->dev,
|
||||||
|
"%s: Invalid Backend interface %d\n", __func__, index);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&pdata->lock[index]);
|
||||||
|
if (pdata->mi2s_gpio_p[index]) {
|
||||||
|
if (atomic_read(&(pdata->mi2s_gpio_ref_cnt[index])) == 0) {
|
||||||
|
ret = msm_cdc_pinctrl_select_active_state(
|
||||||
|
pdata->mi2s_gpio_p[index]);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: GPIO pinctrl set active failed with %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
atomic_inc(&(pdata->mi2s_gpio_ref_cnt[index]));
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
mutex_unlock(&pdata->lock[index]);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void msm_common_snd_shutdown(struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
struct snd_soc_card *card = rtd->card;
|
||||||
|
struct msm_common_pdata *pdata = msm_common_get_pdata(card);
|
||||||
|
const char *stream_name = rtd->dai_link->stream_name;
|
||||||
|
int index = get_intf_index(stream_name);
|
||||||
|
|
||||||
|
pr_debug("%s(): substream = %s stream = %d\n", __func__,
|
||||||
|
substream->name, substream->stream);
|
||||||
|
|
||||||
|
if (!pdata) {
|
||||||
|
dev_err(card->dev, "%s: pdata is NULL\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
dev_err(card->dev,
|
||||||
|
"%s: Invalid Backend interface %d\n", __func__, index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&pdata->lock[index]);
|
||||||
|
if (pdata->mi2s_gpio_p[index]) {
|
||||||
|
atomic_dec(&pdata->mi2s_gpio_ref_cnt[index]);
|
||||||
|
if (atomic_read(&pdata->mi2s_gpio_ref_cnt[index]) == 0) {
|
||||||
|
ret = msm_cdc_pinctrl_select_active_state(
|
||||||
|
pdata->mi2s_gpio_p[index]);
|
||||||
|
if (ret)
|
||||||
|
dev_err(card->dev, "%s: GPIO pinctrl set active failed with %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&pdata->lock[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int msm_common_snd_init(struct platform_device *pdev, struct snd_soc_card *card)
|
||||||
|
{
|
||||||
|
struct msm_common_pdata *common_pdata = NULL;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
common_pdata = kcalloc(1, sizeof(struct msm_common_pdata), GFP_KERNEL);
|
||||||
|
if (!common_pdata)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (count = 0; count < MI2S_TDM_AUXPCM_MAX; count++) {
|
||||||
|
mutex_init(&common_pdata->lock[count]);
|
||||||
|
atomic_set(&common_pdata->mi2s_gpio_ref_cnt[count], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
common_pdata->mi2s_gpio_p[PRI_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
|
||||||
|
"qcom,pri-mi2s-gpios", 0);
|
||||||
|
common_pdata->mi2s_gpio_p[SEC_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
|
||||||
|
"qcom,sec-mi2s-gpios", 0);
|
||||||
|
common_pdata->mi2s_gpio_p[TER_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
|
||||||
|
"qcom,tert-mi2s-gpios", 0);
|
||||||
|
common_pdata->mi2s_gpio_p[QUAT_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
|
||||||
|
"qcom,quat-mi2s-gpios", 0);
|
||||||
|
common_pdata->mi2s_gpio_p[QUIN_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
|
||||||
|
"qcom,quin-mi2s-gpios", 0);
|
||||||
|
common_pdata->mi2s_gpio_p[SEN_MI2S_TDM_AUXPCM] = of_parse_phandle(pdev->dev.of_node,
|
||||||
|
"qcom,sen-mi2s-gpios", 0);
|
||||||
|
|
||||||
|
msm_common_set_pdata(card, common_pdata);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void msm_common_snd_deinit(struct msm_common_pdata *common_pdata)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
|
||||||
|
if (!common_pdata)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (count = 0; count < MI2S_TDM_AUXPCM_MAX; count++) {
|
||||||
|
mutex_destroy(&common_pdata->lock[count]);
|
||||||
|
}
|
||||||
|
}
|
53
asoc/msm_common.h
Normal file
53
asoc/msm_common.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#ifndef _MSM_COMMON_H_
|
||||||
|
#define _MSM_COMMON_H_
|
||||||
|
|
||||||
|
#include <sound/soc.h>
|
||||||
|
#include <sound/pcm.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MI2S = 0,
|
||||||
|
TDM,
|
||||||
|
AUXPCM,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PRI_MI2S_TDM_AUXPCM = 0,
|
||||||
|
SEC_MI2S_TDM_AUXPCM,
|
||||||
|
TER_MI2S_TDM_AUXPCM,
|
||||||
|
QUAT_MI2S_TDM_AUXPCM,
|
||||||
|
QUIN_MI2S_TDM_AUXPCM,
|
||||||
|
SEN_MI2S_TDM_AUXPCM,
|
||||||
|
MI2S_TDM_AUXPCM_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msm_common_pdata {
|
||||||
|
struct device_node *mi2s_gpio_p[MI2S_TDM_AUXPCM_MAX];
|
||||||
|
struct mutex lock[MI2S_TDM_AUXPCM_MAX];
|
||||||
|
atomic_t mi2s_gpio_ref_cnt[MI2S_TDM_AUXPCM_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msm_common_pdata *msm_common_get_pdata(struct snd_soc_card *card);
|
||||||
|
|
||||||
|
void msm_common_set_pdata(struct snd_soc_card *card,
|
||||||
|
struct msm_common_pdata *pdata);
|
||||||
|
|
||||||
|
int msm_common_snd_startup(struct snd_pcm_substream *substream);
|
||||||
|
|
||||||
|
void msm_common_snd_shutdown(struct snd_pcm_substream *substream);
|
||||||
|
|
||||||
|
int msm_common_snd_init(struct platform_device *pdev,
|
||||||
|
struct snd_soc_card *card);
|
||||||
|
|
||||||
|
void msm_common_snd_deinit(struct msm_common_pdata *pdata);
|
||||||
|
#endif
|
Reference in New Issue
Block a user