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


#define FSL_XCVR_CAPDS_SIZE	256
#define SPDIF_NUM_RATES		7

enum fsl_xcvr_pll_verison {
	PLL_MX8MP,
	PLL_MX95,
};

struct fsl_xcvr_soc_data {
	const char *fw_name;
	bool spdif_only;
	bool use_edma;
	bool use_phy;
	enum fsl_xcvr_pll_verison pll_ver;
};

struct fsl_xcvr {
	const struct fsl_xcvr_soc_data *soc_data;
	struct platform_device *pdev;
	struct regmap *regmap;
	struct regmap *regmap_phy;
	struct regmap *regmap_pll;
	struct clk *ipg_clk;
	struct clk *pll_ipg_clk;
	struct clk *phy_clk;
	struct clk *spba_clk;
	struct clk *pll8k_clk;
	struct clk *pll11k_clk;
	struct reset_control *reset;
	u8 streams;
	u32 mode;
	u32 arc_mode;
	void __iomem *ram_addr;
	struct snd_dmaengine_dai_dma_data dma_prms_rx;
	struct snd_dmaengine_dai_dma_data dma_prms_tx;
	struct snd_aes_iec958 rx_iec958;
	struct snd_aes_iec958 tx_iec958;
	u8 cap_ds[FSL_XCVR_CAPDS_SIZE];
	struct work_struct work_rst;
	spinlock_t lock; /* Protect hw_reset and trigger */
	struct snd_pcm_hw_constraint_list spdif_constr_rates;
	u32 spdif_constr_rates_list[SPDIF_NUM_RATES];
	struct work_struct work;
	struct drm_bridge *bridge;
};

static const struct fsl_xcvr_pll_conf {
	u8 mfi;   /* min=0x18, max=0x38 */
	u32 mfn;  /* signed int, 2's compl., min=0x3FFF0000, max=0x00010000 */
	u32 mfd;  /* unsigned int */
	u32 fout; /* Fout = Fref*(MFI + MFN/MFD), Fref is 24MHz */
} fsl_xcvr_pll_cfg[] = {
	{ .mfi = 54, .mfn = 1,  .mfd = 6,   .fout = 1300000000, }, /* 1.3 GHz */
	{ .mfi = 32, .mfn = 96, .mfd = 125, .fout = 786432000, },  /* 8000 Hz */
	{ .mfi = 30, .mfn = 66, .mfd = 625, .fout = 722534400, },  /* 11025 Hz */
	{ .mfi = 29, .mfn = 1,  .mfd = 6,   .fout = 700000000, },  /* 700 MHz */
};

/*
 * HDMI2.1 spec defines 6- and 12-channels layout for one bit audio
 * stream. Todo: to check how this case can be considered below
 */
static const u32 fsl_xcvr_earc_channels[] = { 1, 2, 8, 16, 32, };
static const struct snd_pcm_hw_constraint_list fsl_xcvr_earc_channels_constr = {
	.count = ARRAY_SIZE(fsl_xcvr_earc_channels),
	.list = fsl_xcvr_earc_channels,
};

static const u32 fsl_xcvr_earc_rates[] = {
	32000, 44100, 48000, 64000, 88200, 96000,
	128000, 176400, 192000, 256000, 352800, 384000,
	512000, 705600, 768000, 1024000, 1411200, 1536000,
};
static const struct snd_pcm_hw_constraint_list fsl_xcvr_earc_rates_constr = {
	.count = ARRAY_SIZE(fsl_xcvr_earc_rates),
	.list = fsl_xcvr_earc_rates,
};

static const u32 fsl_xcvr_spdif_channels[] = { 2, };
static const struct snd_pcm_hw_constraint_list fsl_xcvr_spdif_channels_constr = {
	.count = ARRAY_SIZE(fsl_xcvr_spdif_channels),
	.list = fsl_xcvr_spdif_channels,
};

static const u32 fsl_xcvr_spdif_rates[] = {
	32000, 44100, 48000, 88200, 96000, 176400, 192000,
};
static const struct snd_pcm_hw_constraint_list fsl_xcvr_spdif_rates_constr = {
	.count = ARRAY_SIZE(fsl_xcvr_spdif_rates),
	.list = fsl_xcvr_spdif_rates,
};

static int fsl_xcvr_arc_mode_put(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
	struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
	unsigned int *item = ucontrol->value.enumerated.item;

	xcvr->arc_mode = snd_soc_enum_item_to_val(e, item[0]);

	return 0;
}

static int fsl_xcvr_arc_mode_get(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
	struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);

	ucontrol->value.enumerated.item[0] = xcvr->arc_mode;

	return 0;
}

static const u32 fsl_xcvr_phy_arc_cfg[] = {
	FSL_XCVR_PHY_CTRL_ARC_MODE_SE_EN, FSL_XCVR_PHY_CTRL_ARC_MODE_CM_EN,
};

static const char * const fsl_xcvr_arc_mode[] = { "Single Ended", "Common", };
static const struct soc_enum fsl_xcvr_arc_mode_enum =
	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(fsl_xcvr_arc_mode), fsl_xcvr_arc_mode);
static struct snd_kcontrol_new fsl_xcvr_arc_mode_kctl =
	SOC_ENUM_EXT("ARC Mode", fsl_xcvr_arc_mode_enum,
		     fsl_xcvr_arc_mode_get, fsl_xcvr_arc_mode_put);

/* Capabilities data structure, bytes */
static int fsl_xcvr_type_capds_bytes_info(struct snd_kcontrol *kcontrol,
					  struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
	uinfo->count = FSL_XCVR_CAPDS_SIZE;

	return 0;
}

static int fsl_xcvr_capds_get(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
	struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);

	memcpy(ucontrol->value.bytes.data, xcvr->cap_ds, FSL_XCVR_CAPDS_SIZE);

	return 0;
}

static int fsl_xcvr_capds_put(struct snd_kcontrol *kcontrol,
			      struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
	struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);

	memcpy(xcvr->cap_ds, ucontrol->value.bytes.data, FSL_XCVR_CAPDS_SIZE);

	return 0;
}

static struct snd_kcontrol_new fsl_xcvr_earc_capds_kctl = {
	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
	.name = "Capabilities Data Structure",
	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
	.info = fsl_xcvr_type_capds_bytes_info,
	.get = fsl_xcvr_capds_get,
	.put = fsl_xcvr_capds_put,
};

static int fsl_xcvr_activate_ctl(struct snd_soc_dai *dai, const char *name,
				 bool active)
{
	struct snd_soc_card *card = dai->component->card;
	struct snd_kcontrol *kctl;
	bool enabled;

	lockdep_assert_held(&card->snd_card->controls_rwsem);

	kctl = snd_soc_card_get_kcontrol(card, name);
	if (kctl == NULL)
		return -ENOENT;

	enabled = ((kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_WRITE) != 0);
	if (active == enabled)
		return 0; /* nothing to do */

	if (active)
		kctl->vd[0].access |=  SNDRV_CTL_ELEM_ACCESS_WRITE;
	else
		kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_WRITE;

	snd_ctl_notify(card->snd_card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);

	return 1;
}

static int fsl_xcvr_mode_put(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
	struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);
	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
	unsigned int *item = ucontrol->value.enumerated.item;
	struct snd_soc_card *card = dai->component->card;
	struct snd_soc_pcm_runtime *rtd;

	xcvr->mode = snd_soc_enum_item_to_val(e, item[0]);

	fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,
			      (xcvr->mode == FSL_XCVR_MODE_ARC));
	fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,
			      (xcvr->mode == FSL_XCVR_MODE_EARC));
	/* Allow playback for SPDIF only */
	rtd = snd_soc_get_pcm_runtime(card, card->dai_link);
	rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count =
		(xcvr->mode == FSL_XCVR_MODE_SPDIF ? 1 : 0);
	return 0;
}

static int fsl_xcvr_mode_get(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
	struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);

	ucontrol->value.enumerated.item[0] = xcvr->mode;

	return 0;
}

static const char * const fsl_xcvr_mode[] = { "SPDIF", "ARC RX", "eARC", };
static const struct soc_enum fsl_xcvr_mode_enum =
	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(fsl_xcvr_mode), fsl_xcvr_mode);
static struct snd_kcontrol_new fsl_xcvr_mode_kctl =
	SOC_ENUM_EXT("XCVR Mode", fsl_xcvr_mode_enum,
		     fsl_xcvr_mode_get, fsl_xcvr_mode_put);

/** phy: true => phy, false => pll */