brintos

brintos / linux-shallow public Read only

0
0
Text · 6.4 KiB · ce753eb Raw
255 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2020 The Linux Foundation. All rights reserved.4 *5 * lpass-hdmi.c -- ALSA SoC HDMI-CPU DAI driver for QTi LPASS HDMI6 */7 8 9#include <linux/kernel.h>10#include <linux/module.h>11#include <sound/pcm_params.h>12#include <linux/regmap.h>13#include <sound/soc.h>14#include <sound/soc-dai.h>15#include <dt-bindings/sound/sc7180-lpass.h>16#include "lpass-lpaif-reg.h"17#include "lpass.h"18 19static int lpass_hdmi_daiops_hw_params(struct snd_pcm_substream *substream,20		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)21{22	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);23	snd_pcm_format_t format = params_format(params);24	unsigned int rate = params_rate(params);25	unsigned int channels = params_channels(params);26	unsigned int ret;27	int bitwidth;28	unsigned int word_length;29	unsigned int ch_sts_buf0;30	unsigned int ch_sts_buf1;31	unsigned int data_format;32	unsigned int sampling_freq;33	unsigned int ch = 0;34	struct lpass_dp_metadata_ctl *meta_ctl = drvdata->meta_ctl;35	struct lpass_sstream_ctl *sstream_ctl = drvdata->sstream_ctl;36 37	bitwidth = snd_pcm_format_width(format);38	if (bitwidth < 0) {39		dev_err(dai->dev, "%s invalid bit width given : %d\n",40					__func__, bitwidth);41		return bitwidth;42	}43 44	switch (bitwidth) {45	case 16:46		word_length = LPASS_DP_AUDIO_BITWIDTH16;47		break;48	case 24:49		word_length = LPASS_DP_AUDIO_BITWIDTH24;50		break;51	default:52		dev_err(dai->dev, "%s invalid bit width given : %d\n",53					__func__, bitwidth);54		return -EINVAL;55	}56 57	switch (rate) {58	case 32000:59		sampling_freq = LPASS_SAMPLING_FREQ32;60		break;61	case 44100:62		sampling_freq = LPASS_SAMPLING_FREQ44;63		break;64	case 48000:65		sampling_freq = LPASS_SAMPLING_FREQ48;66		break;67	default:68		dev_err(dai->dev, "%s invalid bit width given : %d\n",69					__func__, bitwidth);70		return -EINVAL;71	}72	data_format = LPASS_DATA_FORMAT_LINEAR;73	ch_sts_buf0 = (((data_format << LPASS_DATA_FORMAT_SHIFT) & LPASS_DATA_FORMAT_MASK)74				| ((sampling_freq << LPASS_FREQ_BIT_SHIFT) & LPASS_FREQ_BIT_MASK));75	ch_sts_buf1 = (word_length) & LPASS_WORDLENGTH_MASK;76 77	ret = regmap_field_write(drvdata->tx_ctl->soft_reset, LPASS_TX_CTL_RESET);78	if (ret)79		return ret;80 81	ret = regmap_field_write(drvdata->tx_ctl->soft_reset, LPASS_TX_CTL_CLEAR);82	if (ret)83		return ret;84 85	ret = regmap_field_write(drvdata->hdmitx_legacy_en, LPASS_HDMITX_LEGACY_DISABLE);86	if (ret)87		return ret;88 89	ret = regmap_field_write(drvdata->hdmitx_parity_calc_en, HDMITX_PARITY_CALC_EN);90	if (ret)91		return ret;92 93	ret = regmap_field_write(drvdata->vbit_ctl->replace_vbit, REPLACE_VBIT);94	if (ret)95		return ret;96 97	ret = regmap_field_write(drvdata->vbit_ctl->vbit_stream, LINEAR_PCM_DATA);98	if (ret)99		return ret;100 101	ret = regmap_field_write(drvdata->hdmitx_ch_msb[0], ch_sts_buf1);102	if (ret)103		return ret;104 105	ret = regmap_field_write(drvdata->hdmitx_ch_lsb[0], ch_sts_buf0);106	if (ret)107		return ret;108 109	ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->use_hw_chs, HW_MODE);110	if (ret)111		return ret;112 113	ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->hw_chs_sel, SW_MODE);114	if (ret)115		return ret;116 117	ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->use_hw_usr, HW_MODE);118	if (ret)119		return ret;120 121	ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->hw_usr_sel, SW_MODE);122	if (ret)123		return ret;124 125	ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_ENABLE);126	if (ret)127		return ret;128 129	ret = regmap_field_write(meta_ctl->as_sdp_cc, channels - 1);130	if (ret)131		return ret;132 133	ret = regmap_field_write(meta_ctl->as_sdp_ct, LPASS_META_DEFAULT_VAL);134	if (ret)135		return ret;136 137	ret = regmap_field_write(meta_ctl->aif_db4, LPASS_META_DEFAULT_VAL);138	if (ret)139		return ret;140 141	ret = regmap_field_write(meta_ctl->frequency, sampling_freq);142	if (ret)143		return ret;144 145	ret = regmap_field_write(meta_ctl->mst_index, LPASS_META_DEFAULT_VAL);146	if (ret)147		return ret;148 149	ret = regmap_field_write(meta_ctl->dptx_index, LPASS_META_DEFAULT_VAL);150	if (ret)151		return ret;152 153	ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_DISABLE);154	if (ret)155		return ret;156 157	ret = regmap_field_write(sstream_ctl->dma_sel, ch);158	if (ret)159		return ret;160 161	ret = regmap_field_write(sstream_ctl->auto_bbit_en, LPASS_SSTREAM_DEFAULT_ENABLE);162	if (ret)163		return ret;164 165	ret = regmap_field_write(sstream_ctl->layout, LPASS_SSTREAM_DEFAULT_DISABLE);166	if (ret)167		return ret;168 169	ret = regmap_field_write(sstream_ctl->layout_sp, LPASS_LAYOUT_SP_DEFAULT);170	if (ret)171		return ret;172 173	ret = regmap_field_write(sstream_ctl->dp_audio, LPASS_SSTREAM_DEFAULT_ENABLE);174	if (ret)175		return ret;176 177	ret = regmap_field_write(sstream_ctl->set_sp_on_en, LPASS_SSTREAM_DEFAULT_ENABLE);178	if (ret)179		return ret;180 181	ret = regmap_field_write(sstream_ctl->dp_sp_b_hw_en, LPASS_SSTREAM_DEFAULT_ENABLE);182	if (ret)183		return ret;184 185	ret = regmap_field_write(sstream_ctl->dp_staffing_en, LPASS_SSTREAM_DEFAULT_ENABLE);186 187	return ret;188}189 190static int lpass_hdmi_daiops_prepare(struct snd_pcm_substream *substream,191		struct snd_soc_dai *dai)192{193	int ret;194	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);195 196	ret = regmap_field_write(drvdata->sstream_ctl->sstream_en, LPASS_SSTREAM_ENABLE);197	if (ret)198		return ret;199 200	ret = regmap_field_write(drvdata->meta_ctl->mute, LPASS_MUTE_DISABLE);201 202	return ret;203}204 205static int lpass_hdmi_daiops_trigger(struct snd_pcm_substream *substream,206		int cmd, struct snd_soc_dai *dai)207{208	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);209	struct lpass_dp_metadata_ctl *meta_ctl = drvdata->meta_ctl;210	struct lpass_sstream_ctl *sstream_ctl = drvdata->sstream_ctl;211	int ret = -EINVAL;212 213	switch (cmd) {214	case SNDRV_PCM_TRIGGER_START:215	case SNDRV_PCM_TRIGGER_RESUME:216	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:217		ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_ENABLE);218		if (ret)219			return ret;220 221		ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_DISABLE);222		if (ret)223			return ret;224 225		break;226	case SNDRV_PCM_TRIGGER_STOP:227	case SNDRV_PCM_TRIGGER_SUSPEND:228	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:229		ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_DISABLE);230		if (ret)231			return ret;232 233		ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_ENABLE);234		if (ret)235			return ret;236 237		ret = regmap_field_write(sstream_ctl->dp_audio, 0);238		if (ret)239			return ret;240 241		break;242	}243	return ret;244}245 246const struct snd_soc_dai_ops asoc_qcom_lpass_hdmi_dai_ops = {247	.hw_params	= lpass_hdmi_daiops_hw_params,248	.prepare	= lpass_hdmi_daiops_prepare,249	.trigger	= lpass_hdmi_daiops_trigger,250};251EXPORT_SYMBOL_GPL(asoc_qcom_lpass_hdmi_dai_ops);252 253MODULE_DESCRIPTION("QTi LPASS HDMI Driver");254MODULE_LICENSE("GPL");255