123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
- */
- #include <linux/clk.h>
- #include <linux/delay.h>
- #include <linux/gpio.h>
- #include <linux/of_gpio.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
- #include <linux/io.h>
- #include <linux/module.h>
- #include <linux/input.h>
- #include <linux/of_device.h>
- #include <linux/pm_qos.h>
- #include <sound/core.h>
- #include <sound/soc.h>
- #include <sound/soc-dapm.h>
- #include <sound/pcm.h>
- #include <sound/pcm_params.h>
- #include <sound/info.h>
- #include <dsp/audio_notifier.h>
- #include <dsp/audio_prm.h>
- #include <soc/snd_event.h>
- #include "msm_dailink.h"
- #include "msm_common.h"
- #define DRV_NAME "spf-asoc-snd"
- #define DRV_PINCTRL_NAME "audio-pcm-pinctrl"
- #define __CHIPSET__ "SA8xx5 "
- #define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
- #ifdef CONFIG_MSM_COUPLED_SSR
- enum subsys_state {
- SUBSYS_DOWN = 0,
- SUBSYS_UP = 1
- };
- enum subsys_doamin {
- SUBSYS_DOMAIN_ADSP = 0,
- SUBSYS_DOMAIN_MDSP,
- SUBSYS_DOMAIN_MAX
- };
- static struct dsps_state_t {
- struct mutex lock;
- enum subsys_state states[SUBSYS_DOMAIN_MAX];
- } dsps_state;
- #endif
- enum pinctrl_pin_state {
- STATE_SLEEP = 0, /* All pins are in sleep state */
- STATE_ACTIVE, /* TDM = active */
- };
- struct msm_pinctrl_info {
- struct pinctrl *pinctrl;
- struct pinctrl_state *sleep;
- struct pinctrl_state *active;
- enum pinctrl_pin_state curr_state;
- };
- static const char *const pin_states[] = {"sleep", "active"};
- static const char *const tdm_gpio_phandle[] = {"qcom,pri-tdm-gpios",
- "qcom,sec-tdm-gpios",
- "qcom,tert-tdm-gpios",
- "qcom,quat-tdm-gpios",
- "qcom,quin-tdm-gpios",
- "qcom,sen-tdm-gpios",
- "qcom,sep-tdm-gpios",
- "qcom,oct-tdm-gpios",
- "qcom,hsif0-tdm-gpios",
- "qcom,hsif1-tdm-gpios",
- "qcom,hsif2-tdm-gpios",
- };
- static const char *const mclk_gpio_phandle[] = { "qcom,internal-mclk1-gpios" };
- enum {
- TDM_PRI = 0,
- TDM_SEC,
- TDM_TERT,
- TDM_QUAT,
- TDM_QUIN,
- TDM_SEN,
- TDM_SEP,
- TDM_OCT,
- TDM_HSIF0,
- TDM_HSIF1,
- TDM_HSIF2,
- TDM_INTERFACE_MAX,
- };
- enum {
- IDX_PRIMARY_TDM_RX_0,
- IDX_PRIMARY_TDM_TX_0,
- IDX_SECONDARY_TDM_RX_0,
- IDX_SECONDARY_TDM_TX_0,
- IDX_TERTIARY_TDM_RX_0,
- IDX_TERTIARY_TDM_TX_0,
- IDX_QUATERNARY_TDM_RX_0,
- IDX_QUATERNARY_TDM_TX_0,
- IDX_QUINARY_TDM_RX_0,
- IDX_QUINARY_TDM_TX_0,
- IDX_SENARY_TDM_RX_0,
- IDX_SENARY_TDM_TX_0,
- IDX_SEPTENARY_TDM_RX_0,
- IDX_SEPTENARY_TDM_TX_0,
- IDX_OCTONARY_TDM_RX_0,
- IDX_OCTONARY_TDM_TX_0,
- IDX_HSIF0_TDM_RX_0,
- IDX_HSIF0_TDM_TX_0,
- IDX_HSIF1_TDM_RX_0,
- IDX_HSIF1_TDM_TX_0,
- IDX_HSIF2_TDM_RX_0,
- IDX_HSIF2_TDM_TX_0,
- IDX_HSIF3_TDM_RX_0,
- IDX_HSIF3_TDM_TX_0,
- IDX_HSIF4_TDM_RX_0,
- IDX_HSIF4_TDM_TX_0,
- IDX_QUATERNARY_TDM_RX_DUMMY_0,
- IDX_QUATERNARY_TDM_TX_DUMMY_0,
- IDX_QUINARY_TDM_RX_DUMMY_0,
- IDX_QUINARY_TDM_TX_DUMMY_0,
- IDX_GROUP_TDM_MAX,
- };
- enum msm_mclk_index {
- MCLK_NONE = -1,
- MCLK1 = 0,
- MCLK_MAX,
- };
- enum msm_mclk_status {
- MCLK_DISABLED = 0,
- MCLK_ENABLED,
- };
- struct msm_mclk_conf {
- struct mutex lock;
- enum msm_mclk_status mclk_status;
- };
- struct tdm_conf {
- struct mutex lock;
- u32 ref_cnt;
- };
- struct msm_asoc_mach_data {
- struct msm_common_pdata *common_pdata;
- struct tdm_conf tdm_intf_conf[TDM_INTERFACE_MAX];
- struct msm_pinctrl_info pinctrl_info[TDM_INTERFACE_MAX];
- bool mclk_used;
- struct msm_pinctrl_info mclk_pinctrl_info[MCLK_MAX];
- struct msm_mclk_conf mclk_conf[MCLK_MAX];
- struct snd_pcm_hardware hw_params;
- };
- static struct platform_device *spdev;
- static struct clk_cfg internal_mclk[MCLK_MAX] = {
- {
- CLOCK_ID_MCLK_1,
- IBIT_CLOCK_12_P288_MHZ,
- CLOCK_ATTRIBUTE_COUPLE_NO,
- CLOCK_ROOT_DEFAULT,
- }
- };
- struct snd_soc_card sa8155_snd_soc_card_auto_msm = {
- .name = "sa8155-adp-star-snd-card",
- };
- struct snd_soc_card sa8295_snd_soc_card_auto_msm = {
- .name = "sa8295-adp-star-snd-card",
- };
- struct snd_soc_card sa8255_snd_soc_card_auto_msm = {
- .name = "sa8255-adp-star-snd-card",
- };
- struct snd_soc_card sa7255_snd_soc_card_auto_msm = {
- .name = "sa7255-adp-star-snd-card",
- };
- /* FIXME: it may various on different platform,
- * better to move to dt configuration in future
- */
- static enum msm_mclk_index msm_get_mclk_index(int intf_idx)
- {
- switch (intf_idx) {
- /* for sa8255 */
- #ifdef CONFIG_SND_SOC_SA8255_AUTO_SPF
- case TDM_HSIF2:
- return MCLK1;
- #endif
- /* for sa7255 */
- #ifdef CONFIG_SND_SOC_SA7255_AUTO_SPF
- case TDM_HSIF0:
- return MCLK1;
- #endif
- default: return MCLK_NONE;
- }
- return MCLK_NONE;
- }
- static int msm_tdm_get_intf_idx(u16 id)
- {
- switch (id) {
- case IDX_PRIMARY_TDM_RX_0:
- case IDX_PRIMARY_TDM_TX_0:
- return TDM_PRI;
- case IDX_SECONDARY_TDM_RX_0:
- case IDX_SECONDARY_TDM_TX_0:
- return TDM_SEC;
- case IDX_TERTIARY_TDM_RX_0:
- case IDX_TERTIARY_TDM_TX_0:
- return TDM_TERT;
- case IDX_QUATERNARY_TDM_RX_0:
- case IDX_QUATERNARY_TDM_TX_0:
- case IDX_QUATERNARY_TDM_RX_DUMMY_0:
- case IDX_QUATERNARY_TDM_TX_DUMMY_0:
- return TDM_QUAT;
- case IDX_QUINARY_TDM_RX_0:
- case IDX_QUINARY_TDM_TX_0:
- case IDX_QUINARY_TDM_RX_DUMMY_0:
- case IDX_QUINARY_TDM_TX_DUMMY_0:
- return TDM_QUIN;
- case IDX_SENARY_TDM_RX_0:
- case IDX_SENARY_TDM_TX_0:
- return TDM_SEN;
- case IDX_SEPTENARY_TDM_RX_0:
- case IDX_SEPTENARY_TDM_TX_0:
- return TDM_SEP;
- case IDX_OCTONARY_TDM_RX_0:
- case IDX_OCTONARY_TDM_TX_0:
- return TDM_OCT;
- case IDX_HSIF0_TDM_RX_0:
- case IDX_HSIF0_TDM_TX_0:
- return TDM_HSIF0;
- case IDX_HSIF1_TDM_RX_0:
- case IDX_HSIF1_TDM_TX_0:
- return TDM_HSIF1;
- case IDX_HSIF2_TDM_RX_0:
- case IDX_HSIF2_TDM_TX_0:
- return TDM_HSIF2;
- case IDX_HSIF3_TDM_RX_0:
- case IDX_HSIF3_TDM_TX_0:
- return TDM_SEC; //muxed
- case IDX_HSIF4_TDM_RX_0:
- case IDX_HSIF4_TDM_TX_0:
- return TDM_TERT; //muxed
- default: return -EINVAL;
- }
- }
- #ifdef CONFIG_MSM_COUPLED_SSR
- static void set_subsys_state_l(enum subsys_doamin subsys,
- enum subsys_state state)
- {
- dsps_state.states[subsys] = state;
- }
- static void set_combined_subsystem_state_l(enum subsys_state state)
- {
- int i;
- for (i = 0; i < SUBSYS_DOMAIN_MAX; i++)
- dsps_state.states[i] = state;
- }
- static enum subsys_state get_combined_dsps_state_l(void)
- {
- int i;
- for (i = 0; i < SUBSYS_DOMAIN_MAX; i++) {
- if (!dsps_state.states[i])
- return SUBSYS_DOWN;
- }
- return SUBSYS_UP;
- }
- static int modem_notifier_service_cb(struct notifier_block *this,
- unsigned long opcode, void *data)
- {
- pr_info("%s: modem pdr service opcode 0x%lx\n", __func__, opcode);
- switch (opcode) {
- case AUDIO_NOTIFIER_SERVICE_DOWN:
- mutex_lock(&dsps_state.lock);
- if (get_combined_dsps_state_l() == SUBSYS_UP) {
- set_combined_subsystem_state_l(SUBSYS_DOWN);
- pr_info("%s: setting snd_card to ONLINE\n", __func__);
- snd_card_notify_user(SND_CARD_STATUS_OFFLINE);
- }
- mutex_unlock(&dsps_state.lock);
- break;
- case AUDIO_NOTIFIER_SERVICE_UP:
- mutex_lock(&dsps_state.lock);
- set_subsys_state_l(SUBSYS_DOMAIN_MDSP, SUBSYS_UP);
- if (get_combined_dsps_state_l() == SUBSYS_UP) {
- pr_info("%s: setting snd_card to ONLINE\n", __func__);
- snd_card_notify_user(SND_CARD_STATUS_ONLINE);
- }
- mutex_unlock(&dsps_state.lock);
- break;
- default:
- break;
- }
- return NOTIFY_OK;
- }
- static struct notifier_block modem_service_nb = {
- .notifier_call = modem_notifier_service_cb,
- .priority = 0,
- };
- #endif
- static int auto_adsp_ssr_enable(struct device *dev, void *data)
- {
- struct platform_device *pdev = to_platform_device(dev);
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- int ret = 0;
- if (!card) {
- dev_err(dev, "%s: card is NULL\n", __func__);
- ret = -EINVAL;
- goto err;
- }
- #ifdef CONFIG_MSM_COUPLED_SSR
- mutex_lock(&dsps_state.lock);
- set_subsys_state_l(SUBSYS_DOMAIN_ADSP, SUBSYS_UP);
- if (get_combined_dsps_state_l() == SUBSYS_UP) {
- dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__);
- snd_card_notify_user(SND_CARD_STATUS_ONLINE);
- }
- mutex_unlock(&dsps_state.lock);
- #else
- dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__);
- snd_card_notify_user(SND_CARD_STATUS_ONLINE);
- #endif
- err:
- return ret;
- }
- static void auto_adsp_ssr_disable(struct device *dev, void *data)
- {
- struct platform_device *pdev = to_platform_device(dev);
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- if (!card) {
- dev_err(dev, "%s: card is NULL\n", __func__);
- return;
- }
- #ifdef CONFIG_MSM_COUPLED_SSR
- mutex_lock(&dsps_state.lock);
- if (get_combined_dsps_state_l() == SUBSYS_UP) {
- set_combined_subsystem_state_l(SUBSYS_DOWN);
- dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__);
- snd_card_notify_user(SND_CARD_STATUS_OFFLINE);
- }
- mutex_unlock(&dsps_state.lock);
- #else
- dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__);
- snd_card_notify_user(SND_CARD_STATUS_OFFLINE);
- #endif
- }
- static const struct snd_event_ops auto_adsp_ssr_ops = {
- .enable = auto_adsp_ssr_enable,
- .disable = auto_adsp_ssr_disable,
- };
- static int msm_audio_ssr_compare(struct device *dev, void *data)
- {
- struct device_node *node = data;
- dev_dbg(dev, "%s: dev->of_node = 0x%p, node = 0x%p\n",
- __func__, dev->of_node, node);
- return (dev->of_node && dev->of_node == node);
- }
- static int msm_audio_adsp_ssr_register(struct device *dev)
- {
- struct device_node *np = dev->of_node;
- struct snd_event_clients *ssr_clients = NULL;
- struct device_node *node = NULL;
- int ret = 0;
- int i = 0;
- for (i = 0; ; i++) {
- node = of_parse_phandle(np, "qcom,msm_audio_ssr_devs", i);
- if (!node)
- break;
- snd_event_mstr_add_client(&ssr_clients,
- msm_audio_ssr_compare, node);
- }
- ret = snd_event_master_register(dev, &auto_adsp_ssr_ops,
- ssr_clients, NULL);
- if (!ret)
- snd_event_notify(dev, SND_EVENT_UP);
- return ret;
- }
- static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info,
- enum pinctrl_pin_state new_state)
- {
- int ret = 0;
- int curr_state = 0;
- if (pinctrl_info == NULL) {
- pr_err("%s: pinctrl info is NULL\n", __func__);
- ret = -EINVAL;
- goto err;
- }
- if (pinctrl_info->pinctrl == NULL) {
- pr_err("%s: pinctrl handle is NULL\n", __func__);
- ret = -EINVAL;
- goto err;
- }
- curr_state = pinctrl_info->curr_state;
- pinctrl_info->curr_state = new_state;
- pr_debug("%s: curr_state = %s new_state = %s\n", __func__,
- pin_states[curr_state], pin_states[pinctrl_info->curr_state]);
- if (curr_state == pinctrl_info->curr_state) {
- pr_err("%s: pin already in same state\n", __func__);
- goto err;
- }
- if (curr_state != STATE_SLEEP &&
- pinctrl_info->curr_state != STATE_SLEEP) {
- pr_err("%s: pin state is already active, cannot switch\n",
- __func__);
- ret = -EIO;
- goto err;
- }
- switch (pinctrl_info->curr_state) {
- case STATE_ACTIVE:
- ret = pinctrl_select_state(pinctrl_info->pinctrl,
- pinctrl_info->active);
- if (ret) {
- pr_err("%s: state select to active failed with %d\n",
- __func__, ret);
- ret = -EIO;
- goto err;
- }
- break;
- case STATE_SLEEP:
- ret = pinctrl_select_state(pinctrl_info->pinctrl,
- pinctrl_info->sleep);
- if (ret) {
- pr_err("%s: state select to sleep failed with %d\n",
- __func__, ret);
- ret = -EIO;
- goto err;
- }
- break;
- default:
- pr_err("%s: pin state is invalid\n", __func__);
- return -EINVAL;
- }
- err:
- return ret;
- }
- static int msm_mclk_disable(struct snd_soc_card *card,
- enum msm_mclk_index index)
- {
- struct msm_asoc_mach_data *pdata = NULL;
- struct msm_pinctrl_info *pinctrl_info = NULL;
- int ret = 0;
- if (!card) {
- pr_err("%s: failed to get snd card!\n", __func__);
- return -EINVAL;
- }
- pdata = snd_soc_card_get_drvdata(card);
- if (!pdata) {
- pr_err("%s: no pdata\n", __func__);
- return -EINVAL;
- }
- if (!pdata->mclk_used) {
- pr_info("%s: mclk is not used\n", __func__);
- return 0;
- }
- mutex_lock(&pdata->mclk_conf[index].lock);
- pinctrl_info = &pdata->mclk_pinctrl_info[index];
- if (pinctrl_info && pinctrl_info->pinctrl) {
- ret = msm_set_pinctrl(pinctrl_info, STATE_SLEEP);
- if (ret != 0) {
- pr_err("%s: set pin state to sleep for mclk[%d], failed with %d\n",
- __func__, index, ret);
- }
- pinctrl_info->curr_state = STATE_SLEEP;
- }
- if (pdata->mclk_conf[index].mclk_status == MCLK_ENABLED) {
- ret = audio_prm_set_lpass_clk_cfg(&internal_mclk[index], 0);
- if (ret < 0) {
- pr_err("%s: audio_prm_set_lpass_clk_cfg failed to disable mclk[%d], err:%d\n",
- __func__, index, ret);
- }
- pdata->mclk_conf[index].mclk_status = MCLK_DISABLED;
- } else {
- pr_info("%s: mclk[%d] already disabled\n", __func__, index);
- }
- mutex_unlock(&pdata->mclk_conf[index].lock);
- return ret;
- }
- static int msm_mclk_enable(struct snd_soc_card *card,
- enum msm_mclk_index index)
- {
- struct msm_asoc_mach_data *pdata = NULL;
- struct msm_pinctrl_info *pinctrl_info = NULL;
- int ret = 0;
- if (!card) {
- pr_err("%s: failed to get snd card!\n", __func__);
- return -EINVAL;
- }
- pdata = snd_soc_card_get_drvdata(card);
- if (!pdata) {
- pr_err("%s: no pdata\n", __func__);
- return -EINVAL;
- }
- if (!pdata->mclk_used) {
- pr_info("%s: mclk is not used\n", __func__);
- return 0;
- }
- mutex_lock(&pdata->mclk_conf[index].lock);
- if (pdata->mclk_conf[index].mclk_status == MCLK_DISABLED) {
- ret = audio_prm_set_lpass_clk_cfg(&internal_mclk[index], 1);
- if (ret < 0) {
- pr_err("%s: audio_prm_set_lpass_clk_cfg failed to enable mclk[%d], err:%d\n",
- __func__, index, ret);
- } else {
- pdata->mclk_conf[index].mclk_status = MCLK_ENABLED;
- }
- } else {
- pr_info("%s: mclk[%d] already enabled\n", __func__, index);
- }
- pinctrl_info = &pdata->mclk_pinctrl_info[index];
- if (pinctrl_info && pinctrl_info->pinctrl) {
- ret = msm_set_pinctrl(pinctrl_info, STATE_ACTIVE);
- if (ret != 0) {
- pr_err("%s: set pin state to active for mclk[%d], failed with %d\n",
- __func__, index, ret);
- }
- pinctrl_info->curr_state = STATE_ACTIVE;
- }
- mutex_unlock(&pdata->mclk_conf[index].lock);
- return ret;
- }
- static int tdm_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 snd_soc_dai_link *dai_link = rtd->dai_link;
- struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct tdm_conf *intf_conf = NULL;
- struct msm_pinctrl_info *pinctrl_info = NULL;
- int ret_pinctrl = 0;
- int index, mclk_index;
- if (!dai_link->no_pcm)
- snd_soc_set_runtime_hwparams(substream, &pdata->hw_params);
- index = msm_tdm_get_intf_idx(dai_link->id);
- if (index < 0) {
- ret = -EINVAL;
- pr_err("%s: DAI link id (%d) out of range\n",
- __func__, dai_link->id);
- goto err;
- }
- if (pdata->mclk_used) {
- mclk_index = msm_get_mclk_index(index);
- if (mclk_index != MCLK_NONE)
- msm_mclk_enable(card, mclk_index);
- }
- /*
- * Mutex protection in case the same TDM
- * interface using for both TX and RX so
- * that the same clock won't be enable twice.
- */
- intf_conf = &pdata->tdm_intf_conf[index];
- mutex_lock(&intf_conf->lock);
- if (++intf_conf->ref_cnt == 1) {
- pinctrl_info = &pdata->pinctrl_info[index];
- if (pinctrl_info->pinctrl) {
- ret_pinctrl = msm_set_pinctrl(pinctrl_info,
- STATE_ACTIVE);
- if (ret_pinctrl)
- pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
- __func__, ret_pinctrl);
- }
- }
- mutex_unlock(&intf_conf->lock);
- err:
- return ret;
- }
- static void tdm_snd_shutdown(struct snd_pcm_substream *substream)
- {
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_card *card = rtd->card;
- struct snd_soc_dai_link *dai_link = rtd->dai_link;
- struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct msm_pinctrl_info *pinctrl_info = NULL;
- struct tdm_conf *intf_conf = NULL;
- int ret_pinctrl = 0;
- int index, mclk_index;
- pr_debug("%s: substream = %s, stream = %d\n", __func__,
- substream->name, substream->stream);
- index = msm_tdm_get_intf_idx(dai_link->id);
- if (index < 0) {
- pr_err("%s: DAI link id (%d) out of range\n",
- __func__, dai_link->id);
- return;
- }
- if (pdata->mclk_used) {
- mclk_index = msm_get_mclk_index(index);
- if (mclk_index != MCLK_NONE)
- msm_mclk_disable(card, mclk_index);
- }
- intf_conf = &pdata->tdm_intf_conf[index];
- mutex_lock(&intf_conf->lock);
- if (--intf_conf->ref_cnt == 0) {
- pinctrl_info = &pdata->pinctrl_info[index];
- if (pinctrl_info->pinctrl) {
- ret_pinctrl = msm_set_pinctrl(pinctrl_info,
- STATE_SLEEP);
- if (ret_pinctrl)
- pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
- __func__, ret_pinctrl);
- }
- }
- mutex_unlock(&intf_conf->lock);
- }
- static const struct snd_soc_ops tdm_be_ops = {
- .startup = tdm_snd_startup,
- .shutdown = tdm_snd_shutdown
- };
- /* Digital audio interface glue - connects codec <---> CPU */
- static struct snd_soc_dai_link msm_common_dai_links[] = {
- /* BackEnd DAI Links */
- {
- .name = "LPASS_BE_AUXPCM_RX_DUMMY",
- .stream_name = "AUXPCM-LPAIF-RX-PRIMARY",
- .dpcm_playback = 1,
- .ops = &tdm_be_ops,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_PRIMARY_TDM_RX_0,
- SND_SOC_DAILINK_REG(lpass_be_auxpcm_rx_dummy),
- },
- {
- .name = "LPASS_BE_AUXPCM_TX_DUMMY",
- .stream_name = "AUXPCM-LPAIF-TX-PRIMARY",
- .dpcm_capture = 1,
- .ops = &tdm_be_ops,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_PRIMARY_TDM_TX_0,
- SND_SOC_DAILINK_REG(lpass_be_auxpcm_tx_dummy),
- },
- {
- .name = "SEC_TDM_RX_0",
- .stream_name = "TDM-LPAIF-RX-SECONDARY",
- .dpcm_playback = 1,
- .ops = &tdm_be_ops,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_SECONDARY_TDM_RX_0,
- SND_SOC_DAILINK_REG(sec_tdm_rx_0),
- },
- {
- .name = "SEC_TDM_TX_0",
- .stream_name = "TDM-LPAIF-TX-SECONDARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_SECONDARY_TDM_TX_0,
- SND_SOC_DAILINK_REG(sec_tdm_tx_0),
- },
- {
- .name = "TERT_TDM_RX_0",
- .stream_name = "TDM-LPAIF-RX-TERTIARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_TERTIARY_TDM_RX_0,
- SND_SOC_DAILINK_REG(tert_tdm_rx_0),
- },
- {
- .name = "TERT_TDM_TX_0",
- .stream_name = "TDM-LPAIF-TX-TERTIARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_TERTIARY_TDM_TX_0,
- SND_SOC_DAILINK_REG(tert_tdm_tx_0),
- },
- {
- .name = "QUAT_TDM_RX_0",
- .stream_name = "TDM-LPAIF_RXTX-RX-PRIMARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_QUATERNARY_TDM_RX_0,
- SND_SOC_DAILINK_REG(quat_tdm_rx_0),
- },
- {
- .name = "QUAT_TDM_TX_0",
- .stream_name = "TDM-LPAIF_RXTX-TX-PRIMARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_QUATERNARY_TDM_TX_0,
- SND_SOC_DAILINK_REG(quat_tdm_tx_0),
- },
- {
- .name = "QUIN_TDM_RX_0",
- .stream_name = "TDM-LPAIF_VA-RX-PRIMARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_QUINARY_TDM_RX_0,
- SND_SOC_DAILINK_REG(quin_tdm_rx_0),
- },
- {
- .name = "QUIN_TDM_TX_0",
- .stream_name = "TDM-LPAIF_VA-TX-PRIMARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_QUINARY_TDM_TX_0,
- SND_SOC_DAILINK_REG(quin_tdm_tx_0),
- },
- {
- .name = "SEN_TDM_RX_0",
- .stream_name = "TDM-LPAIF_WSA-RX-PRIMARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_SENARY_TDM_RX_0,
- SND_SOC_DAILINK_REG(sen_tdm_rx_0),
- },
- {
- .name = "SEN_TDM_TX_0",
- .stream_name = "TDM-LPAIF_WSA-TX-PRIMARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_SENARY_TDM_TX_0,
- SND_SOC_DAILINK_REG(sen_tdm_tx_0),
- },
- {
- .name = "SEP_TDM_RX_0",
- .stream_name = "TDM-LPAIF_AUD-RX-PRIMARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_SEPTENARY_TDM_RX_0,
- SND_SOC_DAILINK_REG(sep_tdm_rx_0),
- },
- {
- .name = "SEP_TDM_TX_0",
- .stream_name = "TDM-LPAIF_AUD-TX-PRIMARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_SEPTENARY_TDM_TX_0,
- SND_SOC_DAILINK_REG(sep_tdm_tx_0),
- },
- {
- .name = "OCT_TDM_RX_0",
- .stream_name = "TDM-LPAIF_WSA2-RX-PRIMARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_OCTONARY_TDM_RX_0,
- SND_SOC_DAILINK_REG(oct_tdm_rx_0),
- },
- {
- .name = "OCT_TDM_TX_0",
- .stream_name = "TDM-LPAIF_WSA2-TX-PRIMARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_OCTONARY_TDM_TX_0,
- SND_SOC_DAILINK_REG(oct_tdm_tx_0),
- },
- {
- .name = "HS_IF0_TDM_RX_0",
- .stream_name = "TDM-LPAIF_SDR-RX-PRIMARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF0_TDM_RX_0,
- SND_SOC_DAILINK_REG(hs_if0_tdm_rx_0),
- },
- {
- .name = "HS_IF0_TDM_TX_0",
- .stream_name = "TDM-LPAIF_SDR-TX-PRIMARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF0_TDM_TX_0,
- SND_SOC_DAILINK_REG(hs_if0_tdm_tx_0),
- },
- {
- .name = "HS_IF1_TDM_RX_0",
- .stream_name = "TDM-LPAIF_SDR-RX-SECONDARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF1_TDM_RX_0,
- SND_SOC_DAILINK_REG(hs_if1_tdm_rx_0),
- },
- {
- .name = "HS_IF1_TDM_TX_0",
- .stream_name = "TDM-LPAIF_SDR-TX-SECONDARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF1_TDM_TX_0,
- SND_SOC_DAILINK_REG(hs_if1_tdm_tx_0),
- },
- {
- .name = "HS_IF2_TDM_RX_0",
- .stream_name = "TDM-LPAIF_SDR-RX-TERTIARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF2_TDM_RX_0,
- SND_SOC_DAILINK_REG(hs_if2_tdm_rx_0),
- },
- {
- .name = "HS_IF2_TDM_TX_0",
- .stream_name = "TDM-LPAIF_SDR-TX-TERTIARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF2_TDM_TX_0,
- SND_SOC_DAILINK_REG(hs_if2_tdm_tx_0),
- },
- {
- .name = "HS_IF3_TDM_RX_0",
- .stream_name = "TDM-LPAIF_SDR-RX-QUATERNARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF3_TDM_RX_0,
- SND_SOC_DAILINK_REG(hs_if3_tdm_rx_0),
- },
- {
- .name = "HS_IF3_TDM_TX_0",
- .stream_name = "TDM-LPAIF_SDR-TX-QUATERNARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF3_TDM_TX_0,
- SND_SOC_DAILINK_REG(hs_if3_tdm_tx_0),
- },
- {
- .name = "HS_IF4_TDM_RX_0",
- .stream_name = "TDM-LPAIF_SDR-RX-QUINARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF4_TDM_RX_0,
- SND_SOC_DAILINK_REG(hs_if4_tdm_rx_0),
- },
- {
- .name = "HS_IF4_TDM_TX_0",
- .stream_name = "TDM-LPAIF_SDR-TX-QUINARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_HSIF4_TDM_TX_0,
- SND_SOC_DAILINK_REG(hs_if4_tdm_tx_0),
- },
- {
- .name = "QUAT_TDM_RX_0_DUMMY",
- .stream_name = "TDM-LPAIF-RX-QUATERNARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_QUATERNARY_TDM_RX_DUMMY_0,
- SND_SOC_DAILINK_REG(quat_tdm_rx_0_dummy),
- },
- {
- .name = "QUAT_TDM_TX_0_DUMMY",
- .stream_name = "TDM-LPAIF-TX-QUATERNARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_QUATERNARY_TDM_TX_DUMMY_0,
- SND_SOC_DAILINK_REG(quat_tdm_tx_0_dummy),
- },
- {
- .name = "QUIN_TDM_RX_0_DUMMY",
- .stream_name = "TDM-LPAIF-RX-QUINARY",
- .dpcm_playback = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_QUINARY_TDM_RX_DUMMY_0,
- SND_SOC_DAILINK_REG(quin_tdm_rx_0_dummy),
- },
- {
- .name = "QUIN_TDM_TX_0_DUMMY",
- .stream_name = "TDM-LPAIF-TX-QUINARY",
- .dpcm_capture = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ops = &tdm_be_ops,
- .ignore_suspend = 1,
- .ignore_pmdown_time = 1,
- .id = IDX_QUINARY_TDM_TX_DUMMY_0,
- SND_SOC_DAILINK_REG(quin_tdm_tx_0_dummy),
- },
- };
- static int msm_populate_dai_link_component_of_node(
- struct snd_soc_card *card)
- {
- int i, j, index, ret = 0;
- struct device *cdev = card->dev;
- struct snd_soc_dai_link *dai_link = card->dai_link;
- struct device_node *np;
- if (!cdev) {
- pr_err("%s: Sound card device memory NULL\n", __func__);
- return -ENODEV;
- }
- for (i = 0; i < card->num_links; i++) {
- if (dai_link[i].platforms->of_node && dai_link[i].cpus->of_node)
- continue;
- /* populate platform_of_node for snd card dai links
- * Skip this part for dummy snd card
- */
- if (0) {
- if (dai_link[i].platforms->name &&
- !dai_link[i].platforms->of_node) {
- index = of_property_match_string(cdev->of_node,
- "asoc-platform-names",
- dai_link[i].platforms->name);
- if (index < 0) {
- pr_err("%s: No match found for platform name: %s\n index: %i cdev_of_node: %s\n",
- __func__,
- dai_link[i].platforms->name,
- index,
- cdev->of_node);
- ret = index;
- goto err;
- }
- np = of_parse_phandle(cdev->of_node, "asoc-platform",
- index);
- if (!np) {
- pr_err("%s: retrieving phandle for platform %s, index %d failed\n",
- __func__, dai_link[i].platforms->name,
- index);
- ret = -ENODEV;
- goto err;
- }
- dai_link[i].platforms->of_node = np;
- dai_link[i].platforms->name = NULL;
- }
- }
- /* populate cpu_of_node for snd card dai links */
- if (dai_link[i].cpus->dai_name && !dai_link[i].cpus->of_node) {
- index = of_property_match_string(cdev->of_node,
- "asoc-cpu-names",
- dai_link[i].cpus->dai_name);
- pr_err("%s: retrieving cpu_of_node for %s\n",
- __func__,
- dai_link[i].cpus->dai_name);
- if (index >= 0) {
- np = of_parse_phandle(cdev->of_node, "asoc-cpu",
- index);
- if (!np) {
- pr_err("%s: retrieving phandle for cpu dai %s failed\n",
- __func__,
- dai_link[i].cpus->dai_name);
- ret = -ENODEV;
- goto err;
- }
- dai_link[i].cpus->of_node = np;
- dai_link[i].cpus->dai_name = NULL;
- }
- }
- /* populate codec_of_node for snd card dai links */
- if (dai_link[i].num_codecs > 0) {
- for (j = 0; j < dai_link[i].num_codecs; j++) {
- if (dai_link[i].codecs[j].of_node ||
- !dai_link[i].codecs[j].name)
- continue;
- index = of_property_match_string(cdev->of_node,
- "asoc-codec-names",
- dai_link[i].codecs[j].name);
- if (index < 0)
- continue;
- np = of_parse_phandle(cdev->of_node,
- "asoc-codec",
- index);
- if (!np) {
- pr_err("%s: retrieving phandle for codec %s failed\n",
- __func__,
- dai_link[i].codecs[j].name);
- ret = -ENODEV;
- goto err;
- }
- dai_link[i].codecs[j].of_node = np;
- dai_link[i].codecs[j].name = NULL;
- }
- }
- }
- err:
- return ret;
- }
- static const struct of_device_id asoc_machine_of_match[] = {
- { .compatible = "qcom,sa8295-asoc-snd-adp-star",
- .data = "adp_star_codec"},
- { .compatible = "qcom,sa8155-asoc-snd-adp-star",
- .data = "adp_star_codec"},
- { .compatible = "qcom,sa8255-asoc-snd-adp-star",
- .data = "adp_star_codec"},
- { .compatible = "qcom,sa7255-asoc-snd-adp-star",
- .data = "adp_star_codec"},
- {},
- };
- static const struct of_device_id audio_pinctrl_dummy_match[] = {
- { .compatible = "qcom,msm-pcm-pinctrl" },
- { },
- };
- static struct snd_soc_dai_link msm_auto_dai_links[
- ARRAY_SIZE(msm_common_dai_links)];
- static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
- {
- struct snd_soc_card *card = NULL;
- struct snd_soc_dai_link *dailink;
- int total_links;
- const struct of_device_id *match;
- match = of_match_node(asoc_machine_of_match, dev->of_node);
- if (!match) {
- dev_err(dev, "%s: No DT match found for sound card\n",
- __func__);
- return NULL;
- }
- if (!strcmp(match->compatible, "qcom,sa8155-asoc-snd-adp-star"))
- card = &sa8155_snd_soc_card_auto_msm;
- else if (!strcmp(match->compatible, "qcom,sa8295-asoc-snd-adp-star"))
- card = &sa8295_snd_soc_card_auto_msm;
- else if (!strcmp(match->compatible, "qcom,sa8255-asoc-snd-adp-star"))
- card = &sa8255_snd_soc_card_auto_msm;
- else if (!strcmp(match->compatible, "qcom,sa7255-asoc-snd-adp-star"))
- card = &sa7255_snd_soc_card_auto_msm;
- total_links = ARRAY_SIZE(msm_common_dai_links);
- memcpy(msm_auto_dai_links,
- msm_common_dai_links,
- sizeof(msm_common_dai_links));
- dailink = msm_auto_dai_links;
- if (card) {
- card->dai_link = dailink;
- card->num_links = total_links;
- }
- return card;
- }
- static int msm_get_hwparams(struct platform_device *pdev)
- {
- struct snd_soc_card *card = NULL;
- struct msm_asoc_mach_data *pdata = NULL;
- u32 pcm_info = 0;
- u32 buffer_bytes_max = 0;
- u32 periods_bytes[2] = {0};
- u32 periods_count[2] = {0};
- int ret = 0;
- card = platform_get_drvdata(pdev);
- if (!card) {
- pr_err("%s: card is NULL\n",
- __func__);
- return -EINVAL;
- }
- pdata = snd_soc_card_get_drvdata(card);
- if (!pdata) {
- pr_err("%s: pdata is NULL\n",
- __func__);
- return -EINVAL;
- }
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,hw_pcm_info",
- &pcm_info);
- if (ret) {
- pr_err("%s: read pcm info failed\n",
- __func__);
- return ret;
- }
- ret = of_property_read_u32(pdev->dev.of_node,
- "qcom,hw_buffer_size_max",
- &buffer_bytes_max);
- if (ret) {
- pr_err("%s: read buffer size max failed\n",
- __func__);
- return ret;
- }
- ret = of_property_read_u32_array(pdev->dev.of_node,
- "qcom,hw_period_byte_size",
- periods_bytes, 2);
- if (ret) {
- pr_err("%s: read period byte size failed\n",
- __func__);
- return ret;
- }
- ret = of_property_read_u32_array(pdev->dev.of_node,
- "qcom,hw_period_count_size",
- periods_count, 2);
- if (ret) {
- pr_err("%s: read period count size failed\n",
- __func__);
- return ret;
- }
- pdata->hw_params.info = pcm_info;
- pdata->hw_params.buffer_bytes_max = buffer_bytes_max;
- pdata->hw_params.period_bytes_min = periods_bytes[0];
- pdata->hw_params.period_bytes_max = periods_bytes[1];
- pdata->hw_params.periods_min = periods_count[0];
- pdata->hw_params.periods_max = periods_count[1];
- return ret;
- }
- struct msm_common_pdata *msm_common_get_pdata(struct snd_soc_card *card)
- {
- struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- if (!pdata)
- return NULL;
- return pdata->common_pdata;
- }
- void msm_common_set_pdata(struct snd_soc_card *card,
- struct msm_common_pdata *common_pdata)
- {
- struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- if (!pdata)
- return;
- pdata->common_pdata = common_pdata;
- }
- /*****************************************************************************
- * pinctrl
- *****************************************************************************/
- static void msm_release_pinctrl(struct platform_device *pdev)
- {
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct msm_pinctrl_info *pinctrl_info = NULL;
- int i;
- for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) {
- pinctrl_info = &pdata->pinctrl_info[i];
- if (pinctrl_info == NULL)
- continue;
- if (pinctrl_info->pinctrl) {
- devm_pinctrl_put(pinctrl_info->pinctrl);
- pinctrl_info->pinctrl = NULL;
- }
- }
- }
- static void msm_release_mclk_pinctrl(struct platform_device *pdev)
- {
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct msm_pinctrl_info *pinctrl_info = NULL;
- int i;
- for (i = 0; i < MCLK_MAX; i++) {
- pinctrl_info = &pdata->mclk_pinctrl_info[i];
- if (pinctrl_info == NULL)
- continue;
- if (pinctrl_info->pinctrl) {
- devm_pinctrl_put(pinctrl_info->pinctrl);
- pinctrl_info->pinctrl = NULL;
- }
- }
- }
- static int msm_get_pinctrl(struct platform_device *pdev)
- {
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct msm_pinctrl_info *pinctrl_info = NULL;
- struct pinctrl *pinctrl = NULL;
- int i, j;
- struct device_node *np = NULL;
- struct platform_device *pdev_np = NULL;
- int ret = 0;
- for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) {
- np = of_parse_phandle(pdev->dev.of_node,
- tdm_gpio_phandle[i], 0);
- if (!np) {
- pr_debug("%s: device node %s is null\n",
- __func__, tdm_gpio_phandle[i]);
- continue;
- }
- pdev_np = of_find_device_by_node(np);
- if (!pdev_np) {
- pr_err("%s: platform device not found\n",
- __func__);
- continue;
- }
- pinctrl_info = &pdata->pinctrl_info[i];
- if (pinctrl_info == NULL) {
- pr_err("%s: pinctrl info is null\n",
- __func__);
- continue;
- }
- pinctrl = devm_pinctrl_get(&pdev_np->dev);
- if (IS_ERR_OR_NULL(pinctrl)) {
- pr_err("%s: fail to get pinctrl handle\n",
- __func__);
- goto err;
- }
- pinctrl_info->pinctrl = pinctrl;
- /* get all the states handles from Device Tree */
- pinctrl_info->sleep = pinctrl_lookup_state(pinctrl,
- "default");
- if (IS_ERR(pinctrl_info->sleep)) {
- pr_err("%s: could not get sleep pin state\n",
- __func__);
- goto err;
- }
- pinctrl_info->active = pinctrl_lookup_state(pinctrl,
- "active");
- if (IS_ERR(pinctrl_info->active)) {
- pr_err("%s: could not get active pin state\n",
- __func__);
- goto err;
- }
- /* Reset the TLMM pins to a sleep state */
- ret = pinctrl_select_state(pinctrl_info->pinctrl,
- pinctrl_info->sleep);
- if (ret != 0) {
- pr_err("%s: set pin state to sleep failed with %d\n",
- __func__, ret);
- ret = -EIO;
- goto err;
- }
- pinctrl_info->curr_state = STATE_SLEEP;
- }
- return 0;
- err:
- for (j = i; j >= 0; j--) {
- pinctrl_info = &pdata->pinctrl_info[j];
- if (pinctrl_info == NULL)
- continue;
- if (pinctrl_info->pinctrl) {
- devm_pinctrl_put(pinctrl_info->pinctrl);
- pinctrl_info->pinctrl = NULL;
- }
- }
- return -EINVAL;
- }
- static int msm_get_mclk_pinctrl(struct platform_device *pdev)
- {
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct msm_pinctrl_info *pinctrl_info = NULL;
- struct pinctrl *pinctrl = NULL;
- int i, j;
- struct device_node *np = NULL;
- struct platform_device *pdev_np = NULL;
- int ret = 0;
- for (i = 0; i < MCLK_MAX; i++) {
- np = of_parse_phandle(pdev->dev.of_node,
- mclk_gpio_phandle[i],
- 0);
- if (!np) {
- pr_err("%s: device node %s is null\n",
- __func__, mclk_gpio_phandle[i]);
- continue;
- }
- pdev_np = of_find_device_by_node(np);
- if (!pdev_np) {
- pr_err("%s: platform device not found\n",
- __func__);
- continue;
- }
- pinctrl_info = &pdata->mclk_pinctrl_info[i];
- if (pinctrl_info == NULL) {
- pr_err("%s: pinctrl info is null\n",
- __func__);
- continue;
- }
- pinctrl = devm_pinctrl_get(&pdev_np->dev);
- if (IS_ERR_OR_NULL(pinctrl)) {
- pr_err("%s: fail to get pinctrl handle\n",
- __func__);
- goto err;
- }
- pinctrl_info->pinctrl = pinctrl;
- /* get all the states handles from Device Tree */
- pinctrl_info->sleep = pinctrl_lookup_state(pinctrl,
- "default");
- if (IS_ERR(pinctrl_info->sleep)) {
- pr_err("%s: could not get sleep pin state\n",
- __func__);
- goto err;
- }
- pinctrl_info->active = pinctrl_lookup_state(pinctrl,
- "active");
- if (IS_ERR(pinctrl_info->active)) {
- pr_err("%s: could not get active pin state\n",
- __func__);
- goto err;
- }
- /* Reset the mclk pins to a sleep state */
- ret = pinctrl_select_state(pinctrl_info->pinctrl,
- pinctrl_info->sleep);
- if (ret != 0) {
- pr_err("%s: set pin state to sleep failed with %d\n",
- __func__, ret);
- ret = -EIO;
- goto err;
- }
- pinctrl_info->curr_state = STATE_SLEEP;
- }
- return 0;
- err:
- for (j = i; j >= 0; j--) {
- pinctrl_info = &pdata->mclk_pinctrl_info[i];
- if (pinctrl_info == NULL)
- continue;
- if (pinctrl_info->pinctrl) {
- devm_pinctrl_put(pinctrl_info->pinctrl);
- pinctrl_info->pinctrl = NULL;
- }
- }
- return -EINVAL;
- }
- static int msm_asoc_machine_probe(struct platform_device *pdev)
- {
- struct snd_soc_card *card = NULL;
- struct msm_asoc_mach_data *pdata = NULL;
- int ret = 0;
- const struct of_device_id *match = NULL;
- dev_err(&pdev->dev, "%s: audio_reach\n",
- __func__);
- match = of_match_node(asoc_machine_of_match, pdev->dev.of_node);
- if (!match) {
- dev_err(&pdev->dev, "%s: No DT match found for sound card\n",
- __func__);
- return -EINVAL;
- }
- if (!pdev->dev.of_node) {
- dev_err(&pdev->dev, "No platform supplied from device tree\n");
- return -EINVAL;
- }
- pdata = devm_kzalloc(&pdev->dev,
- sizeof(struct msm_asoc_mach_data), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
- card = populate_snd_card_dailinks(&pdev->dev);
- if (!card) {
- dev_err(&pdev->dev, "%s: Card uninitialized\n",
- __func__);
- ret = -EINVAL;
- goto err;
- }
- card->dev = &pdev->dev;
- platform_set_drvdata(pdev, card);
- snd_soc_card_set_drvdata(card, pdata);
- ret = snd_soc_of_parse_card_name(card, "qcom,model");
- if (ret) {
- dev_err(&pdev->dev, "parse card name failed, err:%d\n",
- ret);
- pr_err("%s: parse card name failed with err:%d\n",
- __func__, ret);
- goto err;
- }
- ret = msm_populate_dai_link_component_of_node(card);
- if (ret) {
- ret = -EPROBE_DEFER;
- goto err;
- }
- ret = devm_snd_soc_register_card(&pdev->dev, card);
- if (ret == -EPROBE_DEFER) {
- goto err;
- } else if (ret) {
- dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
- ret);
- pr_err("snd_soc_register_card failed (%d)\n",
- ret);
- goto err;
- }
- msm_common_snd_init(pdev, card);
- /* Parse pinctrl info from devicetree */
- ret = msm_get_pinctrl(pdev);
- if (!ret) {
- pr_err("%s: pinctrl parsing successful\n",
- __func__);
- } else {
- dev_dbg(&pdev->dev,
- "%s: pinctrl parsing failed with %d\n",
- __func__, ret);
- ret = 0;
- }
- pdata->mclk_used = false;
- if (strnstr(match->compatible, "sa8295",
- sizeof(match->compatible)) ||
- strnstr(match->compatible, "sa8255",
- sizeof(match->compatible)) ||
- strnstr(match->compatible, "sa7255",
- sizeof(match->compatible))) {
- /* get mclk pinctrl info from devicetree */
- ret = msm_get_mclk_pinctrl(pdev);
- if (!ret) {
- pr_debug("%s: pinctrl mclk parsing successful\n",
- __func__);
- pdata->mclk_used = true;
- } else {
- dev_err(&pdev->dev,
- "%s: pinctrl mclk parsing failed with %d\n",
- __func__, ret);
- ret = 0;
- }
- }
- ret = msm_get_hwparams(pdev);
- if (ret) {
- dev_err(&pdev->dev,
- "%s: hwparams get failed with %d\n",
- __func__, ret);
- goto err;
- }
- dev_info(&pdev->dev, "Sound card %s registered\n",
- card->name);
- pr_err("Sound card %s registered\n",
- card->name);
- spdev = pdev;
- #ifdef CONFIG_MSM_COUPLED_SSR
- mutex_init(&dsps_state.lock);
- ret = audio_notifier_register("auto_modem",
- AUDIO_NOTIFIER_MODEM_ROOT_DOMAIN,
- &modem_service_nb);
- if (ret < 0)
- pr_err("%s: Registration with modem PDR failed ret = %d\n",
- __func__, ret);
- #endif
- ret = msm_audio_adsp_ssr_register(&pdev->dev);
- if (ret)
- pr_err("%s: Registration with SND event FWK failed ret = %d\n",
- __func__, ret);
- snd_card_notify_user(SND_CARD_STATUS_ONLINE);
- return 0;
- err:
- msm_release_mclk_pinctrl(pdev);
- msm_release_pinctrl(pdev);
- return ret;
- }
- static int msm_asoc_machine_remove(struct platform_device *pdev)
- {
- msm_release_mclk_pinctrl(pdev);
- msm_release_pinctrl(pdev);
- snd_event_master_deregister(&pdev->dev);
- #ifdef CONFIG_MSM_COUPLED_SSR
- audio_notifier_deregister("auto_modem");
- mutex_destroy(&dsps_state.lock);
- #endif
- return 0;
- }
- static int audio_pinctrl_dummy_probe(struct platform_device *pdev)
- {
- return 0;
- }
- static int audio_pinctrl_dummy_remove(struct platform_device *pdev)
- {
- return 0;
- }
- static struct platform_driver audio_pinctrl_dummy_driver = {
- .driver = {
- .name = DRV_PINCTRL_NAME,
- .of_match_table = audio_pinctrl_dummy_match,
- .suppress_bind_attrs = true,
- },
- .probe = audio_pinctrl_dummy_probe,
- .remove = audio_pinctrl_dummy_remove,
- };
- static struct platform_driver asoc_machine_driver = {
- .driver = {
- .name = DRV_NAME,
- .pm = &snd_soc_pm_ops,
- .of_match_table = asoc_machine_of_match,
- .suppress_bind_attrs = true,
- },
- .probe = msm_asoc_machine_probe,
- .remove = msm_asoc_machine_remove,
- };
- int __init auto_spf_init(void)
- {
- snd_card_sysfs_init();
- platform_driver_register(&audio_pinctrl_dummy_driver);
- return platform_driver_register(&asoc_machine_driver);
- }
- void auto_spf_exit(void)
- {
- platform_driver_unregister(&audio_pinctrl_dummy_driver);
- platform_driver_unregister(&asoc_machine_driver);
- }
- module_init(auto_spf_init);
- module_exit(auto_spf_exit);
- MODULE_DESCRIPTION("ALSA SoC Machine Driver for SPF");
- MODULE_LICENSE("GPL");
- MODULE_ALIAS("platform:" DRV_NAME);
- MODULE_ALIAS("platform:" DRV_PINCTRL_NAME);
- MODULE_DEVICE_TABLE(of, asoc_machine_of_match);
- MODULE_DEVICE_TABLE(of, audio_pinctrl_dummy_match);
|