Загрузка данных
#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 */