Загрузка данных


У меня режим spdif_only:

static int fsl_xcvr_en_aud_pll(struct fsl_xcvr *xcvr, u32 freq)
{
	struct device *dev = &xcvr->pdev->dev;
	int ret;

	freq = xcvr->soc_data->spdif_only ? freq / 5 : freq;
	clk_disable_unprepare(xcvr->phy_clk);
	fsl_asoc_reparent_pll_clocks(dev, xcvr->phy_clk,
				     xcvr->pll8k_clk, xcvr->pll11k_clk, freq);
	ret = clk_set_rate(xcvr->phy_clk, freq);
	if (ret < 0) {
		dev_err(dev, "Error while setting AUD PLL rate: %d\n", ret);
		return ret;
	}
	ret = clk_prepare_enable(xcvr->phy_clk);
	if (ret) {
		dev_err(dev, "failed to start PHY clock: %d\n", ret);
		return ret;
	}

	if (!xcvr->soc_data->use_phy)
		return 0;
	/* Release AI interface from reset */
	ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET,
			   FSL_XCVR_PHY_AI_CTRL_AI_RESETN);
	if (ret < 0) {
		dev_err(dev, "Error while setting IER0: %d\n", ret);
		return ret;
	}

	if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC mode */
		/* PHY: CTRL_SET: TX_DIFF_OE, PHY_EN */
		regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL,
				FSL_XCVR_PHY_CTRL_TSDIFF_OE |
				FSL_XCVR_PHY_CTRL_PHY_EN);
		/* PHY: CTRL2_SET: EARC_TX_MODE */
		regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL2,
				FSL_XCVR_PHY_CTRL2_EARC_TXMS);
	} else { /* SPDIF mode */
		/* PHY: CTRL_SET: TX_CLK_AUD_SS | SPDIF_EN */
		regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL,
				FSL_XCVR_PHY_CTRL_TX_CLK_AUD_SS |
				FSL_XCVR_PHY_CTRL_SPDIF_EN);
	}
	dev_info(dev, "PLL Fexp: %u\n", freq);
	return 0;
}

static int fsl_xcvr_prepare(struct snd_pcm_substream *substream,
			    struct snd_soc_dai *dai)
{
	struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);
	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
	u32 m_ctl = 0, v_ctl = 0;
	u32 r = substream->runtime->rate, ch = substream->runtime->channels;
	u32 fout = 32 * r * ch * 10;
	int ret = 0;

printk("%s(%d) mode=%d\n",__FUNCTION__,__LINE__,xcvr->mode);
	switch (xcvr->mode) {
	case FSL_XCVR_MODE_SPDIF:
		if (xcvr->soc_data->spdif_only && tx) {
			ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL,
						 FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM,
						 FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM);
			if (ret < 0) {
				dev_err(dai->dev, "Failed to set bypass fem: %d\n", ret);
				return ret;
			}
		}
		fallthrough;
	case FSL_XCVR_MODE_ARC:
		if (tx) {
			ret = fsl_xcvr_en_aud_pll(xcvr, fout);
			if (ret < 0) {
				dev_err(dai->dev, "Failed to set TX freq %u: %d\n",
					fout, ret);
				return ret;
			}

			ret = regmap_set_bits(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL,
					      FSL_XCVR_TX_DPTH_CTRL_FRM_FMT);
			if (ret < 0) {
				dev_err(dai->dev, "Failed to set TX_DPTH: %d\n", ret);
				return ret;
			}

			/**
			 * set SPDIF MODE - this flag is used to gate
			 * SPDIF output, useless for SPDIF RX
			 */
			m_ctl |= FSL_XCVR_EXT_CTRL_SPDIF_MODE;
			v_ctl |= FSL_XCVR_EXT_CTRL_SPDIF_MODE;
		} else {
			/**
			 * Clear RX FIFO, flip RX FIFO bits,
			 * disable eARC related HW mode detects
			 */
			ret = regmap_set_bits(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL,
					      FSL_XCVR_RX_DPTH_CTRL_STORE_FMT |
					      FSL_XCVR_RX_DPTH_CTRL_CLR_RX_FIFO |
					      FSL_XCVR_RX_DPTH_CTRL_COMP |
					      FSL_XCVR_RX_DPTH_CTRL_LAYB_CTRL);
			if (ret < 0) {
				dev_err(dai->dev, "Failed to set RX_DPTH: %d\n", ret);
				return ret;
			}

			ret = fsl_xcvr_en_phy_pll(xcvr, FSL_XCVR_SPDIF_RX_FREQ, tx);
			if (ret < 0) {
				dev_err(dai->dev, "Failed to set RX freq %u: %d\n",
					FSL_XCVR_SPDIF_RX_FREQ, ret);
				return ret;
			}
		}
		break;
	case FSL_XCVR_MODE_EARC:
		if (!tx) {
			/** Clear RX FIFO, flip RX FIFO bits */
			ret = regmap_set_bits(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL,
					      FSL_XCVR_RX_DPTH_CTRL_STORE_FMT |
					      FSL_XCVR_RX_DPTH_CTRL_CLR_RX_FIFO);
			if (ret < 0) {
				dev_err(dai->dev, "Failed to set RX_DPTH: %d\n", ret);
				return ret;
			}

			/** Enable eARC related HW mode detects */
			ret = regmap_clear_bits(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL,
						FSL_XCVR_RX_DPTH_CTRL_COMP |
						FSL_XCVR_RX_DPTH_CTRL_LAYB_CTRL);
			if (ret < 0) {
				dev_err(dai->dev, "Failed to clr TX_DPTH: %d\n", ret);
				return ret;
			}
		}

		/* clear CMDC RESET */
		m_ctl |= FSL_XCVR_EXT_CTRL_CMDC_RESET(tx);
		/* set TX_RX_MODE */
		m_ctl |= FSL_XCVR_EXT_CTRL_TX_RX_MODE;
		v_ctl |= (tx ? FSL_XCVR_EXT_CTRL_TX_RX_MODE : 0);
		break;
	}

printk("%s(%d) \n",__FUNCTION__,__LINE__);
	ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, m_ctl, v_ctl);
printk("%s(%d) ret=%d\n",__FUNCTION__,__LINE__,ret);
	if (ret < 0) {
		dev_err(dai->dev, "Error while setting EXT_CTRL: %d\n", ret);
		return ret;
	}

	return 0;
}