MLK-24668-1 ASoC: SOF: imx8: Add DAI clocks handling

We no longer use FSL DAI generic driver as it is not
a good direction for upstreaming. Move clock handling
to SOF imx specific driver.

Note that clocks handled are for DAIs used by i.MX8/i.MX8X boards,
that is SAI1 and ESAI0.

Reviewed-by: Paul Olaru <paul.olaru@nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
This commit is contained in:
Daniel Baluta 2020-10-05 17:40:12 +03:00
parent 271cdc141d
commit 1714fabe71

View File

@ -6,6 +6,7 @@
//
// Hardware interface for audio DSP on i.MX8
#include <linux/clk.h>
#include <linux/firmware.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
@ -39,6 +40,15 @@
#define MBOX_OFFSET 0x800000
#define MBOX_SIZE 0x1000
#define IMX8_DSP_CLK_NUM 9
static const char *imx8_dsp_clks_names[IMX8_DSP_CLK_NUM] =
{
/* ESAI0 clocks */
"esai0_core", "esai0_extal", "esai0_fsys", "esai0_spba",
/* SAI1 clocks */
"sai1_bus", "sai1_mclk0", "sai1_mclk1", "sai1_mclk2", "sai1_mclk3",
};
struct imx8_priv {
struct device *dev;
struct snd_sof_dev *sdev;
@ -56,8 +66,54 @@ struct imx8_priv {
struct device **pd_dev;
struct device_link **link;
struct clk *dsp_clks[IMX8_DSP_CLK_NUM];
};
static int imx8_init_clocks(struct snd_sof_dev *sdev)
{
int i;
struct imx8_priv *priv = (struct imx8_priv *)sdev->private;
for (i = 0; i < IMX8_DSP_CLK_NUM; i++) {
priv->dsp_clks[i] = devm_clk_get(priv->dev, imx8_dsp_clks_names[i]);
if (IS_ERR(priv->dsp_clks[i]))
priv->dsp_clks[i] = NULL;
}
return 0;
}
static int imx8_prepare_clocks(struct snd_sof_dev *sdev)
{
int i, ret;
struct imx8_priv *priv = (struct imx8_priv *)sdev->private;
for (i = 0; i < IMX8_DSP_CLK_NUM; i++) {
ret = clk_prepare_enable(priv->dsp_clks[i]);
if (ret < 0) {
dev_err(priv->dev, "Failed to enable clk %s\n",
imx8_dsp_clks_names[i]);
goto err_dsp_clks;
}
}
return 0;
err_dsp_clks:
while (--i >= 0)
clk_disable_unprepare(priv->dsp_clks[i]);
return ret;
}
static void imx8_disable_clocks(struct snd_sof_dev *sdev)
{
int i;
struct imx8_priv *priv = (struct imx8_priv *)sdev->private;
for (i = 0; i < IMX8_DSP_CLK_NUM; i++)
clk_disable_unprepare(priv->dsp_clks[i]);
}
static void imx8_get_reply(struct snd_sof_dev *sdev)
{
struct snd_sof_ipc_msg *msg = sdev->msg;
@ -331,6 +387,9 @@ static int imx8_probe(struct snd_sof_dev *sdev)
/* set default mailbox offset for FW ready message */
sdev->dsp_box.offset = MBOX_OFFSET;
imx8_init_clocks(sdev);
imx8_prepare_clocks(sdev);
return 0;
exit_pdev_unregister:
@ -384,6 +443,8 @@ int imx8_resume(struct snd_sof_dev *sdev)
struct imx8_priv *priv = (struct imx8_priv *)sdev->private;
int i;
imx8_prepare_clocks(sdev);
for (i = 0; i < DSP_MU_CHAN_NUM; i++)
imx_dsp_request_channel(priv->dsp_ipc, i);
@ -398,6 +459,8 @@ int imx8_suspend(struct snd_sof_dev *sdev)
for (i = 0; i < DSP_MU_CHAN_NUM; i++)
imx_dsp_free_channel(priv->dsp_ipc, i);
imx8_disable_clocks(sdev);
return 0;
}