17cb37b7bSV Sujith Kumar Reddy // SPDX-License-Identifier: GPL-2.0-only 27cb37b7bSV Sujith Kumar Reddy /* 37cb37b7bSV Sujith Kumar Reddy * Copyright (c) 2020 The Linux Foundation. All rights reserved. 47cb37b7bSV Sujith Kumar Reddy * 57cb37b7bSV Sujith Kumar Reddy * lpass-hdmi.c -- ALSA SoC HDMI-CPU DAI driver for QTi LPASS HDMI 67cb37b7bSV Sujith Kumar Reddy */ 77cb37b7bSV Sujith Kumar Reddy 87cb37b7bSV Sujith Kumar Reddy 97cb37b7bSV Sujith Kumar Reddy #include <linux/kernel.h> 107cb37b7bSV Sujith Kumar Reddy #include <linux/module.h> 117cb37b7bSV Sujith Kumar Reddy #include <sound/pcm_params.h> 127cb37b7bSV Sujith Kumar Reddy #include <linux/regmap.h> 137cb37b7bSV Sujith Kumar Reddy #include <sound/soc.h> 147cb37b7bSV Sujith Kumar Reddy #include <sound/soc-dai.h> 157cb37b7bSV Sujith Kumar Reddy #include <dt-bindings/sound/sc7180-lpass.h> 167cb37b7bSV Sujith Kumar Reddy #include "lpass-lpaif-reg.h" 177cb37b7bSV Sujith Kumar Reddy #include "lpass.h" 187cb37b7bSV Sujith Kumar Reddy 197cb37b7bSV Sujith Kumar Reddy static int lpass_hdmi_daiops_hw_params(struct snd_pcm_substream *substream, 207cb37b7bSV Sujith Kumar Reddy struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 217cb37b7bSV Sujith Kumar Reddy { 227cb37b7bSV Sujith Kumar Reddy struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 237cb37b7bSV Sujith Kumar Reddy snd_pcm_format_t format = params_format(params); 247cb37b7bSV Sujith Kumar Reddy unsigned int rate = params_rate(params); 257cb37b7bSV Sujith Kumar Reddy unsigned int channels = params_channels(params); 267cb37b7bSV Sujith Kumar Reddy unsigned int ret; 27bcc96dc3SColin Ian King int bitwidth; 287cb37b7bSV Sujith Kumar Reddy unsigned int word_length; 297cb37b7bSV Sujith Kumar Reddy unsigned int ch_sts_buf0; 307cb37b7bSV Sujith Kumar Reddy unsigned int ch_sts_buf1; 317cb37b7bSV Sujith Kumar Reddy unsigned int data_format; 327cb37b7bSV Sujith Kumar Reddy unsigned int sampling_freq; 337cb37b7bSV Sujith Kumar Reddy unsigned int ch = 0; 347cb37b7bSV Sujith Kumar Reddy struct lpass_dp_metadata_ctl *meta_ctl = drvdata->meta_ctl; 357cb37b7bSV Sujith Kumar Reddy struct lpass_sstream_ctl *sstream_ctl = drvdata->sstream_ctl; 367cb37b7bSV Sujith Kumar Reddy 377cb37b7bSV Sujith Kumar Reddy bitwidth = snd_pcm_format_width(format); 387cb37b7bSV Sujith Kumar Reddy if (bitwidth < 0) { 397cb37b7bSV Sujith Kumar Reddy dev_err(dai->dev, "%s invalid bit width given : %d\n", 407cb37b7bSV Sujith Kumar Reddy __func__, bitwidth); 417cb37b7bSV Sujith Kumar Reddy return bitwidth; 427cb37b7bSV Sujith Kumar Reddy } 437cb37b7bSV Sujith Kumar Reddy 447cb37b7bSV Sujith Kumar Reddy switch (bitwidth) { 457cb37b7bSV Sujith Kumar Reddy case 16: 467cb37b7bSV Sujith Kumar Reddy word_length = LPASS_DP_AUDIO_BITWIDTH16; 477cb37b7bSV Sujith Kumar Reddy break; 487cb37b7bSV Sujith Kumar Reddy case 24: 497cb37b7bSV Sujith Kumar Reddy word_length = LPASS_DP_AUDIO_BITWIDTH24; 507cb37b7bSV Sujith Kumar Reddy break; 517cb37b7bSV Sujith Kumar Reddy default: 527cb37b7bSV Sujith Kumar Reddy dev_err(dai->dev, "%s invalid bit width given : %d\n", 537cb37b7bSV Sujith Kumar Reddy __func__, bitwidth); 547cb37b7bSV Sujith Kumar Reddy return -EINVAL; 557cb37b7bSV Sujith Kumar Reddy } 567cb37b7bSV Sujith Kumar Reddy 577cb37b7bSV Sujith Kumar Reddy switch (rate) { 587cb37b7bSV Sujith Kumar Reddy case 32000: 597cb37b7bSV Sujith Kumar Reddy sampling_freq = LPASS_SAMPLING_FREQ32; 607cb37b7bSV Sujith Kumar Reddy break; 617cb37b7bSV Sujith Kumar Reddy case 44100: 627cb37b7bSV Sujith Kumar Reddy sampling_freq = LPASS_SAMPLING_FREQ44; 637cb37b7bSV Sujith Kumar Reddy break; 647cb37b7bSV Sujith Kumar Reddy case 48000: 657cb37b7bSV Sujith Kumar Reddy sampling_freq = LPASS_SAMPLING_FREQ48; 667cb37b7bSV Sujith Kumar Reddy break; 677cb37b7bSV Sujith Kumar Reddy default: 687cb37b7bSV Sujith Kumar Reddy dev_err(dai->dev, "%s invalid bit width given : %d\n", 697cb37b7bSV Sujith Kumar Reddy __func__, bitwidth); 707cb37b7bSV Sujith Kumar Reddy return -EINVAL; 717cb37b7bSV Sujith Kumar Reddy } 727cb37b7bSV Sujith Kumar Reddy data_format = LPASS_DATA_FORMAT_LINEAR; 737cb37b7bSV Sujith Kumar Reddy ch_sts_buf0 = (((data_format << LPASS_DATA_FORMAT_SHIFT) & LPASS_DATA_FORMAT_MASK) 747cb37b7bSV Sujith Kumar Reddy | ((sampling_freq << LPASS_FREQ_BIT_SHIFT) & LPASS_FREQ_BIT_MASK)); 757cb37b7bSV Sujith Kumar Reddy ch_sts_buf1 = (word_length) & LPASS_WORDLENGTH_MASK; 767cb37b7bSV Sujith Kumar Reddy 777cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->tx_ctl->soft_reset, LPASS_TX_CTL_RESET); 787cb37b7bSV Sujith Kumar Reddy if (ret) 797cb37b7bSV Sujith Kumar Reddy return ret; 807cb37b7bSV Sujith Kumar Reddy 817cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->tx_ctl->soft_reset, LPASS_TX_CTL_CLEAR); 827cb37b7bSV Sujith Kumar Reddy if (ret) 837cb37b7bSV Sujith Kumar Reddy return ret; 847cb37b7bSV Sujith Kumar Reddy 857cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->hdmitx_legacy_en, LPASS_HDMITX_LEGACY_DISABLE); 867cb37b7bSV Sujith Kumar Reddy if (ret) 877cb37b7bSV Sujith Kumar Reddy return ret; 887cb37b7bSV Sujith Kumar Reddy 897cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->hdmitx_parity_calc_en, HDMITX_PARITY_CALC_EN); 907cb37b7bSV Sujith Kumar Reddy if (ret) 917cb37b7bSV Sujith Kumar Reddy return ret; 927cb37b7bSV Sujith Kumar Reddy 937cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->vbit_ctl->replace_vbit, REPLACE_VBIT); 947cb37b7bSV Sujith Kumar Reddy if (ret) 957cb37b7bSV Sujith Kumar Reddy return ret; 967cb37b7bSV Sujith Kumar Reddy 977cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->vbit_ctl->vbit_stream, LINEAR_PCM_DATA); 987cb37b7bSV Sujith Kumar Reddy if (ret) 997cb37b7bSV Sujith Kumar Reddy return ret; 1007cb37b7bSV Sujith Kumar Reddy 1017cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->hdmitx_ch_msb[0], ch_sts_buf1); 1027cb37b7bSV Sujith Kumar Reddy if (ret) 1037cb37b7bSV Sujith Kumar Reddy return ret; 1047cb37b7bSV Sujith Kumar Reddy 1057cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->hdmitx_ch_lsb[0], ch_sts_buf0); 1067cb37b7bSV Sujith Kumar Reddy if (ret) 1077cb37b7bSV Sujith Kumar Reddy return ret; 1087cb37b7bSV Sujith Kumar Reddy 1097cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->use_hw_chs, HW_MODE); 1107cb37b7bSV Sujith Kumar Reddy if (ret) 1117cb37b7bSV Sujith Kumar Reddy return ret; 1127cb37b7bSV Sujith Kumar Reddy 1137cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->hw_chs_sel, SW_MODE); 1147cb37b7bSV Sujith Kumar Reddy if (ret) 1157cb37b7bSV Sujith Kumar Reddy return ret; 1167cb37b7bSV Sujith Kumar Reddy 1177cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->use_hw_usr, HW_MODE); 1187cb37b7bSV Sujith Kumar Reddy if (ret) 1197cb37b7bSV Sujith Kumar Reddy return ret; 1207cb37b7bSV Sujith Kumar Reddy 1217cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->hw_usr_sel, SW_MODE); 1227cb37b7bSV Sujith Kumar Reddy if (ret) 1237cb37b7bSV Sujith Kumar Reddy return ret; 1247cb37b7bSV Sujith Kumar Reddy 1257cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_ENABLE); 1267cb37b7bSV Sujith Kumar Reddy if (ret) 1277cb37b7bSV Sujith Kumar Reddy return ret; 1287cb37b7bSV Sujith Kumar Reddy 1297cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(meta_ctl->as_sdp_cc, channels - 1); 1307cb37b7bSV Sujith Kumar Reddy if (ret) 1317cb37b7bSV Sujith Kumar Reddy return ret; 1327cb37b7bSV Sujith Kumar Reddy 1337cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(meta_ctl->as_sdp_ct, LPASS_META_DEFAULT_VAL); 1347cb37b7bSV Sujith Kumar Reddy if (ret) 1357cb37b7bSV Sujith Kumar Reddy return ret; 1367cb37b7bSV Sujith Kumar Reddy 1377cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(meta_ctl->aif_db4, LPASS_META_DEFAULT_VAL); 1387cb37b7bSV Sujith Kumar Reddy if (ret) 1397cb37b7bSV Sujith Kumar Reddy return ret; 1407cb37b7bSV Sujith Kumar Reddy 1417cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(meta_ctl->frequency, sampling_freq); 1427cb37b7bSV Sujith Kumar Reddy if (ret) 1437cb37b7bSV Sujith Kumar Reddy return ret; 1447cb37b7bSV Sujith Kumar Reddy 1457cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(meta_ctl->mst_index, LPASS_META_DEFAULT_VAL); 1467cb37b7bSV Sujith Kumar Reddy if (ret) 1477cb37b7bSV Sujith Kumar Reddy return ret; 1487cb37b7bSV Sujith Kumar Reddy 1497cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(meta_ctl->dptx_index, LPASS_META_DEFAULT_VAL); 1507cb37b7bSV Sujith Kumar Reddy if (ret) 1517cb37b7bSV Sujith Kumar Reddy return ret; 1527cb37b7bSV Sujith Kumar Reddy 1537cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_DISABLE); 1547cb37b7bSV Sujith Kumar Reddy if (ret) 1557cb37b7bSV Sujith Kumar Reddy return ret; 1567cb37b7bSV Sujith Kumar Reddy 1577cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->dma_sel, ch); 1587cb37b7bSV Sujith Kumar Reddy if (ret) 1597cb37b7bSV Sujith Kumar Reddy return ret; 1607cb37b7bSV Sujith Kumar Reddy 1617cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->auto_bbit_en, LPASS_SSTREAM_DEFAULT_ENABLE); 1627cb37b7bSV Sujith Kumar Reddy if (ret) 1637cb37b7bSV Sujith Kumar Reddy return ret; 1647cb37b7bSV Sujith Kumar Reddy 1657cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->layout, LPASS_SSTREAM_DEFAULT_DISABLE); 1667cb37b7bSV Sujith Kumar Reddy if (ret) 1677cb37b7bSV Sujith Kumar Reddy return ret; 1687cb37b7bSV Sujith Kumar Reddy 1697cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->layout_sp, LPASS_LAYOUT_SP_DEFAULT); 1707cb37b7bSV Sujith Kumar Reddy if (ret) 1717cb37b7bSV Sujith Kumar Reddy return ret; 1727cb37b7bSV Sujith Kumar Reddy 1737cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->dp_audio, LPASS_SSTREAM_DEFAULT_ENABLE); 1747cb37b7bSV Sujith Kumar Reddy if (ret) 1757cb37b7bSV Sujith Kumar Reddy return ret; 1767cb37b7bSV Sujith Kumar Reddy 1777cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->set_sp_on_en, LPASS_SSTREAM_DEFAULT_ENABLE); 1787cb37b7bSV Sujith Kumar Reddy if (ret) 1797cb37b7bSV Sujith Kumar Reddy return ret; 1807cb37b7bSV Sujith Kumar Reddy 1817cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->dp_sp_b_hw_en, LPASS_SSTREAM_DEFAULT_ENABLE); 1827cb37b7bSV Sujith Kumar Reddy if (ret) 1837cb37b7bSV Sujith Kumar Reddy return ret; 1847cb37b7bSV Sujith Kumar Reddy 1857cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->dp_staffing_en, LPASS_SSTREAM_DEFAULT_ENABLE); 1867cb37b7bSV Sujith Kumar Reddy 1877cb37b7bSV Sujith Kumar Reddy return ret; 1887cb37b7bSV Sujith Kumar Reddy } 1897cb37b7bSV Sujith Kumar Reddy 1907cb37b7bSV Sujith Kumar Reddy static int lpass_hdmi_daiops_prepare(struct snd_pcm_substream *substream, 1917cb37b7bSV Sujith Kumar Reddy struct snd_soc_dai *dai) 1927cb37b7bSV Sujith Kumar Reddy { 1937cb37b7bSV Sujith Kumar Reddy int ret; 1947cb37b7bSV Sujith Kumar Reddy struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 1957cb37b7bSV Sujith Kumar Reddy 1967cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->sstream_ctl->sstream_en, LPASS_SSTREAM_ENABLE); 1977cb37b7bSV Sujith Kumar Reddy if (ret) 1987cb37b7bSV Sujith Kumar Reddy return ret; 1997cb37b7bSV Sujith Kumar Reddy 2007cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(drvdata->meta_ctl->mute, LPASS_MUTE_DISABLE); 2017cb37b7bSV Sujith Kumar Reddy 2027cb37b7bSV Sujith Kumar Reddy return ret; 2037cb37b7bSV Sujith Kumar Reddy } 2047cb37b7bSV Sujith Kumar Reddy 2057cb37b7bSV Sujith Kumar Reddy static int lpass_hdmi_daiops_trigger(struct snd_pcm_substream *substream, 2067cb37b7bSV Sujith Kumar Reddy int cmd, struct snd_soc_dai *dai) 2077cb37b7bSV Sujith Kumar Reddy { 2087cb37b7bSV Sujith Kumar Reddy struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 2097cb37b7bSV Sujith Kumar Reddy struct lpass_dp_metadata_ctl *meta_ctl = drvdata->meta_ctl; 2107cb37b7bSV Sujith Kumar Reddy struct lpass_sstream_ctl *sstream_ctl = drvdata->sstream_ctl; 2117cb37b7bSV Sujith Kumar Reddy int ret = -EINVAL; 2127cb37b7bSV Sujith Kumar Reddy 2137cb37b7bSV Sujith Kumar Reddy switch (cmd) { 2147cb37b7bSV Sujith Kumar Reddy case SNDRV_PCM_TRIGGER_START: 2157cb37b7bSV Sujith Kumar Reddy case SNDRV_PCM_TRIGGER_RESUME: 2167cb37b7bSV Sujith Kumar Reddy case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 2177cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_ENABLE); 2187cb37b7bSV Sujith Kumar Reddy if (ret) 2197cb37b7bSV Sujith Kumar Reddy return ret; 2207cb37b7bSV Sujith Kumar Reddy 2217cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_DISABLE); 2227cb37b7bSV Sujith Kumar Reddy if (ret) 2237cb37b7bSV Sujith Kumar Reddy return ret; 2247cb37b7bSV Sujith Kumar Reddy 2257cb37b7bSV Sujith Kumar Reddy break; 2267cb37b7bSV Sujith Kumar Reddy case SNDRV_PCM_TRIGGER_STOP: 2277cb37b7bSV Sujith Kumar Reddy case SNDRV_PCM_TRIGGER_SUSPEND: 2287cb37b7bSV Sujith Kumar Reddy case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 2297cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_DISABLE); 2307cb37b7bSV Sujith Kumar Reddy if (ret) 2317cb37b7bSV Sujith Kumar Reddy return ret; 2327cb37b7bSV Sujith Kumar Reddy 2337cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_ENABLE); 2347cb37b7bSV Sujith Kumar Reddy if (ret) 2357cb37b7bSV Sujith Kumar Reddy return ret; 2367cb37b7bSV Sujith Kumar Reddy 2377cb37b7bSV Sujith Kumar Reddy ret = regmap_field_write(sstream_ctl->dp_audio, 0); 2387cb37b7bSV Sujith Kumar Reddy if (ret) 2397cb37b7bSV Sujith Kumar Reddy return ret; 2407cb37b7bSV Sujith Kumar Reddy 2417cb37b7bSV Sujith Kumar Reddy break; 2427cb37b7bSV Sujith Kumar Reddy } 2437cb37b7bSV Sujith Kumar Reddy return ret; 2447cb37b7bSV Sujith Kumar Reddy } 2457cb37b7bSV Sujith Kumar Reddy 2467cb37b7bSV Sujith Kumar Reddy const struct snd_soc_dai_ops asoc_qcom_lpass_hdmi_dai_ops = { 2477cb37b7bSV Sujith Kumar Reddy .hw_params = lpass_hdmi_daiops_hw_params, 2487cb37b7bSV Sujith Kumar Reddy .prepare = lpass_hdmi_daiops_prepare, 2497cb37b7bSV Sujith Kumar Reddy .trigger = lpass_hdmi_daiops_trigger, 2507cb37b7bSV Sujith Kumar Reddy }; 2517cb37b7bSV Sujith Kumar Reddy EXPORT_SYMBOL_GPL(asoc_qcom_lpass_hdmi_dai_ops); 2527cb37b7bSV Sujith Kumar Reddy 2537cb37b7bSV Sujith Kumar Reddy MODULE_DESCRIPTION("QTi LPASS HDMI Driver"); 254*bb339245SKrzysztof Kozlowski MODULE_LICENSE("GPL"); 255