ASoC: fsl-ssi: introduce SoC specific data
Introduce a SoC data struct which contains the differences between the different SoCs this driver supports. This makes it easy to support more differences without having to introduce a new switch/case each time. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Markus Pargmann <mpa@pengutronix.de> Tested-By: Michael Grzeschik <mgr@pengutronix.de> Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
parent
b20e53a826
commit
fcdbadef37
@ -132,6 +132,12 @@ struct fsl_ssi_rxtx_reg_val {
|
||||
struct fsl_ssi_reg_val tx;
|
||||
};
|
||||
|
||||
struct fsl_ssi_soc_data {
|
||||
bool imx;
|
||||
bool offline_config;
|
||||
u32 sisr_write_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* fsl_ssi_private: per-SSI private data
|
||||
*
|
||||
@ -153,7 +159,6 @@ struct fsl_ssi_private {
|
||||
struct platform_device *pdev;
|
||||
unsigned int dai_fmt;
|
||||
|
||||
enum fsl_ssi_type hw_type;
|
||||
bool use_dma;
|
||||
bool baudclk_locked;
|
||||
bool use_dual_fifo;
|
||||
@ -168,36 +173,10 @@ struct fsl_ssi_private {
|
||||
struct fsl_ssi_rxtx_reg_val rxtx_reg_val;
|
||||
|
||||
struct fsl_ssi_dbg dbg_stats;
|
||||
|
||||
const struct fsl_ssi_soc_data *soc;
|
||||
};
|
||||
|
||||
static const struct of_device_id fsl_ssi_ids[] = {
|
||||
{ .compatible = "fsl,mpc8610-ssi", .data = (void *) FSL_SSI_MCP8610},
|
||||
{ .compatible = "fsl,imx51-ssi", .data = (void *) FSL_SSI_MX51},
|
||||
{ .compatible = "fsl,imx35-ssi", .data = (void *) FSL_SSI_MX35},
|
||||
{ .compatible = "fsl,imx21-ssi", .data = (void *) FSL_SSI_MX21},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
|
||||
|
||||
static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private)
|
||||
{
|
||||
return !!(ssi_private->dai_fmt & SND_SOC_DAIFMT_AC97);
|
||||
}
|
||||
|
||||
static bool fsl_ssi_on_imx(struct fsl_ssi_private *ssi_private)
|
||||
{
|
||||
switch (ssi_private->hw_type) {
|
||||
case FSL_SSI_MX21:
|
||||
case FSL_SSI_MX35:
|
||||
case FSL_SSI_MX51:
|
||||
return true;
|
||||
case FSL_SSI_MCP8610:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* imx51 and later SoCs have a slightly different IP that allows the
|
||||
* SSI configuration while the SSI unit is running.
|
||||
@ -213,18 +192,48 @@ static bool fsl_ssi_on_imx(struct fsl_ssi_private *ssi_private)
|
||||
* while the SSI unit is running (SSIEN). So we support the necessary
|
||||
* online configuration of fsl-ssi starting at imx51.
|
||||
*/
|
||||
static bool fsl_ssi_offline_config(struct fsl_ssi_private *ssi_private)
|
||||
{
|
||||
switch (ssi_private->hw_type) {
|
||||
case FSL_SSI_MCP8610:
|
||||
case FSL_SSI_MX21:
|
||||
case FSL_SSI_MX35:
|
||||
return true;
|
||||
case FSL_SSI_MX51:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = {
|
||||
.imx = false,
|
||||
.offline_config = true,
|
||||
.sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC |
|
||||
CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
|
||||
CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1,
|
||||
};
|
||||
|
||||
static struct fsl_ssi_soc_data fsl_ssi_imx21 = {
|
||||
.imx = true,
|
||||
.offline_config = true,
|
||||
.sisr_write_mask = 0,
|
||||
};
|
||||
|
||||
static struct fsl_ssi_soc_data fsl_ssi_imx35 = {
|
||||
.imx = true,
|
||||
.offline_config = true,
|
||||
.sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC |
|
||||
CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
|
||||
CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1,
|
||||
};
|
||||
|
||||
static struct fsl_ssi_soc_data fsl_ssi_imx51 = {
|
||||
.imx = true,
|
||||
.offline_config = false,
|
||||
.sisr_write_mask = CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
|
||||
CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1,
|
||||
};
|
||||
|
||||
static const struct of_device_id fsl_ssi_ids[] = {
|
||||
{ .compatible = "fsl,mpc8610-ssi", .data = &fsl_ssi_mpc8610 },
|
||||
{ .compatible = "fsl,imx51-ssi", .data = &fsl_ssi_imx51 },
|
||||
{ .compatible = "fsl,imx35-ssi", .data = &fsl_ssi_imx35 },
|
||||
{ .compatible = "fsl,imx21-ssi", .data = &fsl_ssi_imx21 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
|
||||
|
||||
static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private)
|
||||
{
|
||||
return !!(ssi_private->dai_fmt & SND_SOC_DAIFMT_AC97);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -245,25 +254,6 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
|
||||
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
|
||||
__be32 sisr;
|
||||
__be32 sisr2;
|
||||
__be32 sisr_write_mask = 0;
|
||||
|
||||
switch (ssi_private->hw_type) {
|
||||
case FSL_SSI_MX21:
|
||||
sisr_write_mask = 0;
|
||||
break;
|
||||
|
||||
case FSL_SSI_MCP8610:
|
||||
case FSL_SSI_MX35:
|
||||
sisr_write_mask = CCSR_SSI_SISR_RFRC | CCSR_SSI_SISR_TFRC |
|
||||
CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
|
||||
CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1;
|
||||
break;
|
||||
|
||||
case FSL_SSI_MX51:
|
||||
sisr_write_mask = CCSR_SSI_SISR_ROE0 | CCSR_SSI_SISR_ROE1 |
|
||||
CCSR_SSI_SISR_TUE0 | CCSR_SSI_SISR_TUE1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We got an interrupt, so read the status register to see what we
|
||||
were interrupted for. We mask it with the Interrupt Enable register
|
||||
@ -271,7 +261,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
|
||||
*/
|
||||
sisr = read_ssi(&ssi->sisr);
|
||||
|
||||
sisr2 = sisr & sisr_write_mask;
|
||||
sisr2 = sisr & ssi_private->soc->sisr_write_mask;
|
||||
/* Clear the bits that we set */
|
||||
if (sisr2)
|
||||
write_ssi(sisr2, &ssi->sisr);
|
||||
@ -359,7 +349,7 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
|
||||
* reconfiguration, so we have to enable all necessary flags at once
|
||||
* even if we do not use them later (capture and playback configuration)
|
||||
*/
|
||||
if (fsl_ssi_offline_config(ssi_private)) {
|
||||
if (ssi_private->soc->offline_config) {
|
||||
if ((enable && !nr_active_streams) ||
|
||||
(!enable && !keep_active))
|
||||
fsl_ssi_rxtx_config(ssi_private, enable);
|
||||
@ -915,7 +905,7 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
if (fsl_ssi_on_imx(ssi_private) && ssi_private->use_dma) {
|
||||
if (ssi_private->soc->imx && ssi_private->use_dma) {
|
||||
dai->playback_dma_data = &ssi_private->dma_params_tx;
|
||||
dai->capture_dma_data = &ssi_private->dma_params_rx;
|
||||
}
|
||||
@ -1141,7 +1131,6 @@ static int fsl_ssi_probe(struct platform_device *pdev)
|
||||
int ret = 0;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct of_device_id *of_id;
|
||||
enum fsl_ssi_type hw_type;
|
||||
const char *p, *sprop;
|
||||
const uint32_t *iprop;
|
||||
struct resource res;
|
||||
@ -1156,9 +1145,8 @@ static int fsl_ssi_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
|
||||
of_id = of_match_device(fsl_ssi_ids, &pdev->dev);
|
||||
if (!of_id)
|
||||
if (!of_id || !of_id->data)
|
||||
return -EINVAL;
|
||||
hw_type = (enum fsl_ssi_type) of_id->data;
|
||||
|
||||
sprop = of_get_property(np, "fsl,mode", NULL);
|
||||
if (!sprop) {
|
||||
@ -1175,9 +1163,10 @@ static int fsl_ssi_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ssi_private->soc = of_id->data;
|
||||
|
||||
ssi_private->use_dma = !of_property_read_bool(np,
|
||||
"fsl,fiq-stream-filter");
|
||||
ssi_private->hw_type = hw_type;
|
||||
|
||||
if (ac97) {
|
||||
memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_ac97_dai,
|
||||
@ -1232,7 +1221,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
|
||||
|
||||
dev_set_drvdata(&pdev->dev, ssi_private);
|
||||
|
||||
if (fsl_ssi_on_imx(ssi_private)) {
|
||||
if (ssi_private->soc->imx) {
|
||||
ret = fsl_ssi_imx_probe(pdev, ssi_private, ssi_private->ssi);
|
||||
if (ret)
|
||||
goto error_irqmap;
|
||||
@ -1299,7 +1288,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
||||
error_asoc_register:
|
||||
if (fsl_ssi_on_imx(ssi_private))
|
||||
if (ssi_private->soc->imx)
|
||||
fsl_ssi_imx_clean(pdev, ssi_private);
|
||||
|
||||
error_irqmap:
|
||||
@ -1319,7 +1308,7 @@ static int fsl_ssi_remove(struct platform_device *pdev)
|
||||
platform_device_unregister(ssi_private->pdev);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
|
||||
if (fsl_ssi_on_imx(ssi_private))
|
||||
if (ssi_private->soc->imx)
|
||||
fsl_ssi_imx_clean(pdev, ssi_private);
|
||||
|
||||
if (ssi_private->use_dma)
|
||||
|
Loading…
Reference in New Issue
Block a user