xref: /openbmc/linux/sound/soc/meson/axg-pdm.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
12cfc123eSJerome Brunet // SPDX-License-Identifier: (GPL-2.0 OR MIT)
22cfc123eSJerome Brunet //
32cfc123eSJerome Brunet // Copyright (c) 2018 BayLibre, SAS.
42cfc123eSJerome Brunet // Author: Jerome Brunet <jbrunet@baylibre.com>
52cfc123eSJerome Brunet 
62cfc123eSJerome Brunet #include <linux/clk.h>
72cfc123eSJerome Brunet #include <linux/module.h>
82cfc123eSJerome Brunet #include <linux/of_irq.h>
92cfc123eSJerome Brunet #include <linux/of_platform.h>
102cfc123eSJerome Brunet #include <linux/regmap.h>
112cfc123eSJerome Brunet #include <sound/soc.h>
122cfc123eSJerome Brunet #include <sound/soc-dai.h>
132cfc123eSJerome Brunet #include <sound/pcm_params.h>
142cfc123eSJerome Brunet 
152cfc123eSJerome Brunet #define PDM_CTRL			0x00
162cfc123eSJerome Brunet #define  PDM_CTRL_EN			BIT(31)
172cfc123eSJerome Brunet #define  PDM_CTRL_OUT_MODE		BIT(29)
182cfc123eSJerome Brunet #define  PDM_CTRL_BYPASS_MODE		BIT(28)
192cfc123eSJerome Brunet #define  PDM_CTRL_RST_FIFO		BIT(16)
202cfc123eSJerome Brunet #define  PDM_CTRL_CHAN_RSTN_MASK	GENMASK(15, 8)
212cfc123eSJerome Brunet #define  PDM_CTRL_CHAN_RSTN(x)		((x) << 8)
222cfc123eSJerome Brunet #define  PDM_CTRL_CHAN_EN_MASK		GENMASK(7, 0)
232cfc123eSJerome Brunet #define  PDM_CTRL_CHAN_EN(x)		((x) << 0)
242cfc123eSJerome Brunet #define PDM_HCIC_CTRL1			0x04
252cfc123eSJerome Brunet #define  PDM_FILTER_EN			BIT(31)
262cfc123eSJerome Brunet #define  PDM_HCIC_CTRL1_GAIN_SFT_MASK	GENMASK(29, 24)
272cfc123eSJerome Brunet #define  PDM_HCIC_CTRL1_GAIN_SFT(x)	((x) << 24)
282cfc123eSJerome Brunet #define  PDM_HCIC_CTRL1_GAIN_MULT_MASK	GENMASK(23, 16)
292cfc123eSJerome Brunet #define  PDM_HCIC_CTRL1_GAIN_MULT(x)	((x) << 16)
302cfc123eSJerome Brunet #define  PDM_HCIC_CTRL1_DSR_MASK	GENMASK(8, 4)
312cfc123eSJerome Brunet #define  PDM_HCIC_CTRL1_DSR(x)		((x) << 4)
322cfc123eSJerome Brunet #define  PDM_HCIC_CTRL1_STAGE_NUM_MASK	GENMASK(3, 0)
332cfc123eSJerome Brunet #define  PDM_HCIC_CTRL1_STAGE_NUM(x)	((x) << 0)
342cfc123eSJerome Brunet #define PDM_HCIC_CTRL2			0x08
352cfc123eSJerome Brunet #define PDM_F1_CTRL			0x0c
362cfc123eSJerome Brunet #define  PDM_LPF_ROUND_MODE_MASK	GENMASK(17, 16)
372cfc123eSJerome Brunet #define  PDM_LPF_ROUND_MODE(x)		((x) << 16)
382cfc123eSJerome Brunet #define  PDM_LPF_DSR_MASK		GENMASK(15, 12)
392cfc123eSJerome Brunet #define  PDM_LPF_DSR(x)			((x) << 12)
402cfc123eSJerome Brunet #define  PDM_LPF_STAGE_NUM_MASK		GENMASK(8, 0)
412cfc123eSJerome Brunet #define  PDM_LPF_STAGE_NUM(x)		((x) << 0)
422cfc123eSJerome Brunet #define  PDM_LPF_MAX_STAGE		336
432cfc123eSJerome Brunet #define  PDM_LPF_NUM			3
442cfc123eSJerome Brunet #define PDM_F2_CTRL			0x10
452cfc123eSJerome Brunet #define PDM_F3_CTRL			0x14
462cfc123eSJerome Brunet #define PDM_HPF_CTRL			0x18
472cfc123eSJerome Brunet #define  PDM_HPF_SFT_STEPS_MASK		GENMASK(20, 16)
482cfc123eSJerome Brunet #define  PDM_HPF_SFT_STEPS(x)		((x) << 16)
492cfc123eSJerome Brunet #define  PDM_HPF_OUT_FACTOR_MASK	GENMASK(15, 0)
502cfc123eSJerome Brunet #define  PDM_HPF_OUT_FACTOR(x)		((x) << 0)
512cfc123eSJerome Brunet #define PDM_CHAN_CTRL			0x1c
522cfc123eSJerome Brunet #define  PDM_CHAN_CTRL_POINTER_WIDTH	8
532cfc123eSJerome Brunet #define  PDM_CHAN_CTRL_POINTER_MAX	((1 << PDM_CHAN_CTRL_POINTER_WIDTH) - 1)
542cfc123eSJerome Brunet #define  PDM_CHAN_CTRL_NUM		4
552cfc123eSJerome Brunet #define PDM_CHAN_CTRL1			0x20
562cfc123eSJerome Brunet #define PDM_COEFF_ADDR			0x24
572cfc123eSJerome Brunet #define PDM_COEFF_DATA			0x28
582cfc123eSJerome Brunet #define PDM_CLKG_CTRL			0x2c
592cfc123eSJerome Brunet #define PDM_STS				0x30
602cfc123eSJerome Brunet 
612cfc123eSJerome Brunet struct axg_pdm_lpf {
622cfc123eSJerome Brunet 	unsigned int ds;
632cfc123eSJerome Brunet 	unsigned int round_mode;
642cfc123eSJerome Brunet 	const unsigned int *tap;
652cfc123eSJerome Brunet 	unsigned int tap_num;
662cfc123eSJerome Brunet };
672cfc123eSJerome Brunet 
682cfc123eSJerome Brunet struct axg_pdm_hcic {
692cfc123eSJerome Brunet 	unsigned int shift;
702cfc123eSJerome Brunet 	unsigned int mult;
712cfc123eSJerome Brunet 	unsigned int steps;
722cfc123eSJerome Brunet 	unsigned int ds;
732cfc123eSJerome Brunet };
742cfc123eSJerome Brunet 
752cfc123eSJerome Brunet struct axg_pdm_hpf {
762cfc123eSJerome Brunet 	unsigned int out_factor;
772cfc123eSJerome Brunet 	unsigned int steps;
782cfc123eSJerome Brunet };
792cfc123eSJerome Brunet 
802cfc123eSJerome Brunet struct axg_pdm_filters {
812cfc123eSJerome Brunet 	struct axg_pdm_hcic hcic;
822cfc123eSJerome Brunet 	struct axg_pdm_hpf hpf;
832cfc123eSJerome Brunet 	struct axg_pdm_lpf lpf[PDM_LPF_NUM];
842cfc123eSJerome Brunet };
852cfc123eSJerome Brunet 
862cfc123eSJerome Brunet struct axg_pdm_cfg {
872cfc123eSJerome Brunet 	const struct axg_pdm_filters *filters;
882cfc123eSJerome Brunet 	unsigned int sys_rate;
892cfc123eSJerome Brunet };
902cfc123eSJerome Brunet 
912cfc123eSJerome Brunet struct axg_pdm {
922cfc123eSJerome Brunet 	const struct axg_pdm_cfg *cfg;
932cfc123eSJerome Brunet 	struct regmap *map;
942cfc123eSJerome Brunet 	struct clk *dclk;
952cfc123eSJerome Brunet 	struct clk *sysclk;
962cfc123eSJerome Brunet 	struct clk *pclk;
972cfc123eSJerome Brunet };
982cfc123eSJerome Brunet 
axg_pdm_enable(struct regmap * map)992cfc123eSJerome Brunet static void axg_pdm_enable(struct regmap *map)
1002cfc123eSJerome Brunet {
1012cfc123eSJerome Brunet 	/* Reset AFIFO */
1022cfc123eSJerome Brunet 	regmap_update_bits(map, PDM_CTRL, PDM_CTRL_RST_FIFO, PDM_CTRL_RST_FIFO);
1032cfc123eSJerome Brunet 	regmap_update_bits(map, PDM_CTRL, PDM_CTRL_RST_FIFO, 0);
1042cfc123eSJerome Brunet 
1052cfc123eSJerome Brunet 	/* Enable PDM */
1062cfc123eSJerome Brunet 	regmap_update_bits(map, PDM_CTRL, PDM_CTRL_EN, PDM_CTRL_EN);
1072cfc123eSJerome Brunet }
1082cfc123eSJerome Brunet 
axg_pdm_disable(struct regmap * map)1092cfc123eSJerome Brunet static void axg_pdm_disable(struct regmap *map)
1102cfc123eSJerome Brunet {
1112cfc123eSJerome Brunet 	regmap_update_bits(map, PDM_CTRL, PDM_CTRL_EN, 0);
1122cfc123eSJerome Brunet }
1132cfc123eSJerome Brunet 
axg_pdm_filters_enable(struct regmap * map,bool enable)1142cfc123eSJerome Brunet static void axg_pdm_filters_enable(struct regmap *map, bool enable)
1152cfc123eSJerome Brunet {
1162cfc123eSJerome Brunet 	unsigned int val = enable ? PDM_FILTER_EN : 0;
1172cfc123eSJerome Brunet 
1182cfc123eSJerome Brunet 	regmap_update_bits(map, PDM_HCIC_CTRL1, PDM_FILTER_EN, val);
1192cfc123eSJerome Brunet 	regmap_update_bits(map, PDM_F1_CTRL, PDM_FILTER_EN, val);
1202cfc123eSJerome Brunet 	regmap_update_bits(map, PDM_F2_CTRL, PDM_FILTER_EN, val);
1212cfc123eSJerome Brunet 	regmap_update_bits(map, PDM_F3_CTRL, PDM_FILTER_EN, val);
1222cfc123eSJerome Brunet 	regmap_update_bits(map, PDM_HPF_CTRL, PDM_FILTER_EN, val);
1232cfc123eSJerome Brunet }
1242cfc123eSJerome Brunet 
axg_pdm_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)1252cfc123eSJerome Brunet static int axg_pdm_trigger(struct snd_pcm_substream *substream, int cmd,
1262cfc123eSJerome Brunet 			   struct snd_soc_dai *dai)
1272cfc123eSJerome Brunet {
1282cfc123eSJerome Brunet 	struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai);
1292cfc123eSJerome Brunet 
1302cfc123eSJerome Brunet 	switch (cmd) {
1312cfc123eSJerome Brunet 	case SNDRV_PCM_TRIGGER_START:
1322cfc123eSJerome Brunet 	case SNDRV_PCM_TRIGGER_RESUME:
1332cfc123eSJerome Brunet 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1342cfc123eSJerome Brunet 		axg_pdm_enable(priv->map);
1352cfc123eSJerome Brunet 		return 0;
1362cfc123eSJerome Brunet 
1372cfc123eSJerome Brunet 	case SNDRV_PCM_TRIGGER_STOP:
1382cfc123eSJerome Brunet 	case SNDRV_PCM_TRIGGER_SUSPEND:
1392cfc123eSJerome Brunet 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1402cfc123eSJerome Brunet 		axg_pdm_disable(priv->map);
1412cfc123eSJerome Brunet 		return 0;
1422cfc123eSJerome Brunet 
1432cfc123eSJerome Brunet 	default:
1442cfc123eSJerome Brunet 		return -EINVAL;
1452cfc123eSJerome Brunet 	}
1462cfc123eSJerome Brunet }
1472cfc123eSJerome Brunet 
axg_pdm_get_os(struct axg_pdm * priv)1482cfc123eSJerome Brunet static unsigned int axg_pdm_get_os(struct axg_pdm *priv)
1492cfc123eSJerome Brunet {
1502cfc123eSJerome Brunet 	const struct axg_pdm_filters *filters = priv->cfg->filters;
1512cfc123eSJerome Brunet 	unsigned int os = filters->hcic.ds;
1522cfc123eSJerome Brunet 	int i;
1532cfc123eSJerome Brunet 
1542cfc123eSJerome Brunet 	/*
1552cfc123eSJerome Brunet 	 * The global oversampling factor is defined by the down sampling
1562cfc123eSJerome Brunet 	 * factor applied by each filter (HCIC and LPFs)
1572cfc123eSJerome Brunet 	 */
1582cfc123eSJerome Brunet 
1592cfc123eSJerome Brunet 	for (i = 0; i < PDM_LPF_NUM; i++)
1602cfc123eSJerome Brunet 		os *= filters->lpf[i].ds;
1612cfc123eSJerome Brunet 
1622cfc123eSJerome Brunet 	return os;
1632cfc123eSJerome Brunet }
1642cfc123eSJerome Brunet 
axg_pdm_set_sysclk(struct axg_pdm * priv,unsigned int os,unsigned int rate)1652cfc123eSJerome Brunet static int axg_pdm_set_sysclk(struct axg_pdm *priv, unsigned int os,
1662cfc123eSJerome Brunet 			      unsigned int rate)
1672cfc123eSJerome Brunet {
1682cfc123eSJerome Brunet 	unsigned int sys_rate = os * 2 * rate * PDM_CHAN_CTRL_POINTER_MAX;
1692cfc123eSJerome Brunet 
1702cfc123eSJerome Brunet 	/*
1712cfc123eSJerome Brunet 	 * Set the default system clock rate unless it is too fast for
1724306fc8fSShaomin Deng 	 * the requested sample rate. In this case, the sample pointer
1732cfc123eSJerome Brunet 	 * counter could overflow so set a lower system clock rate
1742cfc123eSJerome Brunet 	 */
1752cfc123eSJerome Brunet 	if (sys_rate < priv->cfg->sys_rate)
1762cfc123eSJerome Brunet 		return clk_set_rate(priv->sysclk, sys_rate);
1772cfc123eSJerome Brunet 
1782cfc123eSJerome Brunet 	return clk_set_rate(priv->sysclk, priv->cfg->sys_rate);
1792cfc123eSJerome Brunet }
1802cfc123eSJerome Brunet 
axg_pdm_set_sample_pointer(struct axg_pdm * priv)1812cfc123eSJerome Brunet static int axg_pdm_set_sample_pointer(struct axg_pdm *priv)
1822cfc123eSJerome Brunet {
1832cfc123eSJerome Brunet 	unsigned int spmax, sp, val;
1842cfc123eSJerome Brunet 	int i;
1852cfc123eSJerome Brunet 
1862cfc123eSJerome Brunet 	/* Max sample counter value per half period of dclk */
1872cfc123eSJerome Brunet 	spmax = DIV_ROUND_UP_ULL((u64)clk_get_rate(priv->sysclk),
1882cfc123eSJerome Brunet 				 clk_get_rate(priv->dclk) * 2);
1892cfc123eSJerome Brunet 
1902cfc123eSJerome Brunet 	/* Check if sysclk is not too fast - should not happen */
1912cfc123eSJerome Brunet 	if (WARN_ON(spmax > PDM_CHAN_CTRL_POINTER_MAX))
1922cfc123eSJerome Brunet 		return -EINVAL;
1932cfc123eSJerome Brunet 
1942cfc123eSJerome Brunet 	/* Capture the data when we are at 75% of the half period */
1952cfc123eSJerome Brunet 	sp = spmax * 3 / 4;
1962cfc123eSJerome Brunet 
1972cfc123eSJerome Brunet 	for (i = 0, val = 0; i < PDM_CHAN_CTRL_NUM; i++)
1982cfc123eSJerome Brunet 		val |= sp << (PDM_CHAN_CTRL_POINTER_WIDTH * i);
1992cfc123eSJerome Brunet 
2002cfc123eSJerome Brunet 	regmap_write(priv->map, PDM_CHAN_CTRL, val);
2012cfc123eSJerome Brunet 	regmap_write(priv->map, PDM_CHAN_CTRL1, val);
2022cfc123eSJerome Brunet 
2032cfc123eSJerome Brunet 	return 0;
2042cfc123eSJerome Brunet }
2052cfc123eSJerome Brunet 
axg_pdm_set_channel_mask(struct axg_pdm * priv,unsigned int channels)2062cfc123eSJerome Brunet static void axg_pdm_set_channel_mask(struct axg_pdm *priv,
2072cfc123eSJerome Brunet 				     unsigned int channels)
2082cfc123eSJerome Brunet {
2092cfc123eSJerome Brunet 	unsigned int mask = GENMASK(channels - 1, 0);
2102cfc123eSJerome Brunet 
2112cfc123eSJerome Brunet 	/* Put all channel in reset */
2122cfc123eSJerome Brunet 	regmap_update_bits(priv->map, PDM_CTRL,
2132cfc123eSJerome Brunet 			   PDM_CTRL_CHAN_RSTN_MASK, 0);
2142cfc123eSJerome Brunet 
2152cfc123eSJerome Brunet 	/* Take the necessary channels out of reset and enable them */
2162cfc123eSJerome Brunet 	regmap_update_bits(priv->map, PDM_CTRL,
2172cfc123eSJerome Brunet 			   PDM_CTRL_CHAN_RSTN_MASK |
2182cfc123eSJerome Brunet 			   PDM_CTRL_CHAN_EN_MASK,
2192cfc123eSJerome Brunet 			   PDM_CTRL_CHAN_RSTN(mask) |
2202cfc123eSJerome Brunet 			   PDM_CTRL_CHAN_EN(mask));
2212cfc123eSJerome Brunet }
2222cfc123eSJerome Brunet 
axg_pdm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)2232cfc123eSJerome Brunet static int axg_pdm_hw_params(struct snd_pcm_substream *substream,
2242cfc123eSJerome Brunet 			     struct snd_pcm_hw_params *params,
2252cfc123eSJerome Brunet 			     struct snd_soc_dai *dai)
2262cfc123eSJerome Brunet {
2272cfc123eSJerome Brunet 	struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai);
2282cfc123eSJerome Brunet 	unsigned int os = axg_pdm_get_os(priv);
2292cfc123eSJerome Brunet 	unsigned int rate = params_rate(params);
2302cfc123eSJerome Brunet 	unsigned int val;
2312cfc123eSJerome Brunet 	int ret;
2322cfc123eSJerome Brunet 
2332cfc123eSJerome Brunet 	switch (params_width(params)) {
2342cfc123eSJerome Brunet 	case 24:
2352cfc123eSJerome Brunet 		val = PDM_CTRL_OUT_MODE;
2362cfc123eSJerome Brunet 		break;
2372cfc123eSJerome Brunet 	case 32:
2382cfc123eSJerome Brunet 		val = 0;
2392cfc123eSJerome Brunet 		break;
2402cfc123eSJerome Brunet 	default:
2412cfc123eSJerome Brunet 		dev_err(dai->dev, "unsupported sample width\n");
2422cfc123eSJerome Brunet 		return -EINVAL;
2432cfc123eSJerome Brunet 	}
2442cfc123eSJerome Brunet 
2452cfc123eSJerome Brunet 	regmap_update_bits(priv->map, PDM_CTRL, PDM_CTRL_OUT_MODE, val);
2462cfc123eSJerome Brunet 
2472cfc123eSJerome Brunet 	ret = axg_pdm_set_sysclk(priv, os, rate);
2482cfc123eSJerome Brunet 	if (ret) {
2492cfc123eSJerome Brunet 		dev_err(dai->dev, "failed to set system clock\n");
2502cfc123eSJerome Brunet 		return ret;
2512cfc123eSJerome Brunet 	}
2522cfc123eSJerome Brunet 
2532cfc123eSJerome Brunet 	ret = clk_set_rate(priv->dclk, rate * os);
2542cfc123eSJerome Brunet 	if (ret) {
2552cfc123eSJerome Brunet 		dev_err(dai->dev, "failed to set dclk\n");
2562cfc123eSJerome Brunet 		return ret;
2572cfc123eSJerome Brunet 	}
2582cfc123eSJerome Brunet 
2592cfc123eSJerome Brunet 	ret = axg_pdm_set_sample_pointer(priv);
2602cfc123eSJerome Brunet 	if (ret) {
2612cfc123eSJerome Brunet 		dev_err(dai->dev, "invalid clock setting\n");
2622cfc123eSJerome Brunet 		return ret;
2632cfc123eSJerome Brunet 	}
2642cfc123eSJerome Brunet 
2652cfc123eSJerome Brunet 	axg_pdm_set_channel_mask(priv, params_channels(params));
2662cfc123eSJerome Brunet 
2672cfc123eSJerome Brunet 	return 0;
2682cfc123eSJerome Brunet }
2692cfc123eSJerome Brunet 
axg_pdm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)2702cfc123eSJerome Brunet static int axg_pdm_startup(struct snd_pcm_substream *substream,
2712cfc123eSJerome Brunet 			   struct snd_soc_dai *dai)
2722cfc123eSJerome Brunet {
2732cfc123eSJerome Brunet 	struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai);
2742cfc123eSJerome Brunet 	int ret;
2752cfc123eSJerome Brunet 
2762cfc123eSJerome Brunet 	ret = clk_prepare_enable(priv->dclk);
2772cfc123eSJerome Brunet 	if (ret) {
2782cfc123eSJerome Brunet 		dev_err(dai->dev, "enabling dclk failed\n");
2792cfc123eSJerome Brunet 		return ret;
2802cfc123eSJerome Brunet 	}
2812cfc123eSJerome Brunet 
2822cfc123eSJerome Brunet 	/* Enable the filters */
2832cfc123eSJerome Brunet 	axg_pdm_filters_enable(priv->map, true);
2842cfc123eSJerome Brunet 
2852cfc123eSJerome Brunet 	return ret;
2862cfc123eSJerome Brunet }
2872cfc123eSJerome Brunet 
axg_pdm_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)2882cfc123eSJerome Brunet static void axg_pdm_shutdown(struct snd_pcm_substream *substream,
2892cfc123eSJerome Brunet 			     struct snd_soc_dai *dai)
2902cfc123eSJerome Brunet {
2912cfc123eSJerome Brunet 	struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai);
2922cfc123eSJerome Brunet 
2932cfc123eSJerome Brunet 	axg_pdm_filters_enable(priv->map, false);
2942cfc123eSJerome Brunet 	clk_disable_unprepare(priv->dclk);
2952cfc123eSJerome Brunet }
2962cfc123eSJerome Brunet 
axg_pdm_set_hcic_ctrl(struct axg_pdm * priv)2972cfc123eSJerome Brunet static void axg_pdm_set_hcic_ctrl(struct axg_pdm *priv)
2982cfc123eSJerome Brunet {
2992cfc123eSJerome Brunet 	const struct axg_pdm_hcic *hcic = &priv->cfg->filters->hcic;
3002cfc123eSJerome Brunet 	unsigned int val;
3012cfc123eSJerome Brunet 
3022cfc123eSJerome Brunet 	val = PDM_HCIC_CTRL1_STAGE_NUM(hcic->steps);
3032cfc123eSJerome Brunet 	val |= PDM_HCIC_CTRL1_DSR(hcic->ds);
3042cfc123eSJerome Brunet 	val |= PDM_HCIC_CTRL1_GAIN_MULT(hcic->mult);
3052cfc123eSJerome Brunet 	val |= PDM_HCIC_CTRL1_GAIN_SFT(hcic->shift);
3062cfc123eSJerome Brunet 
3072cfc123eSJerome Brunet 	regmap_update_bits(priv->map, PDM_HCIC_CTRL1,
3082cfc123eSJerome Brunet 			   PDM_HCIC_CTRL1_STAGE_NUM_MASK |
3092cfc123eSJerome Brunet 			   PDM_HCIC_CTRL1_DSR_MASK |
3102cfc123eSJerome Brunet 			   PDM_HCIC_CTRL1_GAIN_MULT_MASK |
3112cfc123eSJerome Brunet 			   PDM_HCIC_CTRL1_GAIN_SFT_MASK,
3122cfc123eSJerome Brunet 			   val);
3132cfc123eSJerome Brunet }
3142cfc123eSJerome Brunet 
axg_pdm_set_lpf_ctrl(struct axg_pdm * priv,unsigned int index)3152cfc123eSJerome Brunet static void axg_pdm_set_lpf_ctrl(struct axg_pdm *priv, unsigned int index)
3162cfc123eSJerome Brunet {
3172cfc123eSJerome Brunet 	const struct axg_pdm_lpf *lpf = &priv->cfg->filters->lpf[index];
3182cfc123eSJerome Brunet 	unsigned int offset = index * regmap_get_reg_stride(priv->map)
3192cfc123eSJerome Brunet 		+ PDM_F1_CTRL;
3202cfc123eSJerome Brunet 	unsigned int val;
3212cfc123eSJerome Brunet 
3222cfc123eSJerome Brunet 	val = PDM_LPF_STAGE_NUM(lpf->tap_num);
3232cfc123eSJerome Brunet 	val |= PDM_LPF_DSR(lpf->ds);
3242cfc123eSJerome Brunet 	val |= PDM_LPF_ROUND_MODE(lpf->round_mode);
3252cfc123eSJerome Brunet 
3262cfc123eSJerome Brunet 	regmap_update_bits(priv->map, offset,
3272cfc123eSJerome Brunet 			   PDM_LPF_STAGE_NUM_MASK |
3282cfc123eSJerome Brunet 			   PDM_LPF_DSR_MASK |
3292cfc123eSJerome Brunet 			   PDM_LPF_ROUND_MODE_MASK,
3302cfc123eSJerome Brunet 			   val);
3312cfc123eSJerome Brunet }
3322cfc123eSJerome Brunet 
axg_pdm_set_hpf_ctrl(struct axg_pdm * priv)3332cfc123eSJerome Brunet static void axg_pdm_set_hpf_ctrl(struct axg_pdm *priv)
3342cfc123eSJerome Brunet {
3352cfc123eSJerome Brunet 	const struct axg_pdm_hpf *hpf = &priv->cfg->filters->hpf;
3362cfc123eSJerome Brunet 	unsigned int val;
3372cfc123eSJerome Brunet 
3382cfc123eSJerome Brunet 	val = PDM_HPF_OUT_FACTOR(hpf->out_factor);
3392cfc123eSJerome Brunet 	val |= PDM_HPF_SFT_STEPS(hpf->steps);
3402cfc123eSJerome Brunet 
3412cfc123eSJerome Brunet 	regmap_update_bits(priv->map, PDM_HPF_CTRL,
3422cfc123eSJerome Brunet 			   PDM_HPF_OUT_FACTOR_MASK |
3432cfc123eSJerome Brunet 			   PDM_HPF_SFT_STEPS_MASK,
3442cfc123eSJerome Brunet 			   val);
3452cfc123eSJerome Brunet }
3462cfc123eSJerome Brunet 
axg_pdm_set_lpf_filters(struct axg_pdm * priv)3472cfc123eSJerome Brunet static int axg_pdm_set_lpf_filters(struct axg_pdm *priv)
3482cfc123eSJerome Brunet {
3492cfc123eSJerome Brunet 	const struct axg_pdm_lpf *lpf = priv->cfg->filters->lpf;
3502cfc123eSJerome Brunet 	unsigned int count = 0;
3512cfc123eSJerome Brunet 	int i, j;
3522cfc123eSJerome Brunet 
3532cfc123eSJerome Brunet 	for (i = 0; i < PDM_LPF_NUM; i++)
3542cfc123eSJerome Brunet 		count += lpf[i].tap_num;
3552cfc123eSJerome Brunet 
3562cfc123eSJerome Brunet 	/* Make sure the coeffs fit in the memory */
3572cfc123eSJerome Brunet 	if (count >= PDM_LPF_MAX_STAGE)
3582cfc123eSJerome Brunet 		return -EINVAL;
3592cfc123eSJerome Brunet 
3602cfc123eSJerome Brunet 	/* Set the initial APB bus register address */
3612cfc123eSJerome Brunet 	regmap_write(priv->map, PDM_COEFF_ADDR, 0);
3622cfc123eSJerome Brunet 
3632cfc123eSJerome Brunet 	/* Set the tap filter values of all 3 filters */
3642cfc123eSJerome Brunet 	for (i = 0; i < PDM_LPF_NUM; i++) {
3652cfc123eSJerome Brunet 		axg_pdm_set_lpf_ctrl(priv, i);
3662cfc123eSJerome Brunet 
3672cfc123eSJerome Brunet 		for (j = 0; j < lpf[i].tap_num; j++)
3682cfc123eSJerome Brunet 			regmap_write(priv->map, PDM_COEFF_DATA, lpf[i].tap[j]);
3692cfc123eSJerome Brunet 	}
3702cfc123eSJerome Brunet 
3712cfc123eSJerome Brunet 	return 0;
3722cfc123eSJerome Brunet }
3732cfc123eSJerome Brunet 
axg_pdm_dai_probe(struct snd_soc_dai * dai)3742cfc123eSJerome Brunet static int axg_pdm_dai_probe(struct snd_soc_dai *dai)
3752cfc123eSJerome Brunet {
3762cfc123eSJerome Brunet 	struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai);
3772cfc123eSJerome Brunet 	int ret;
3782cfc123eSJerome Brunet 
3792cfc123eSJerome Brunet 	ret = clk_prepare_enable(priv->pclk);
3802cfc123eSJerome Brunet 	if (ret) {
3812cfc123eSJerome Brunet 		dev_err(dai->dev, "enabling pclk failed\n");
3822cfc123eSJerome Brunet 		return ret;
3832cfc123eSJerome Brunet 	}
3842cfc123eSJerome Brunet 
3852cfc123eSJerome Brunet 	/*
3862cfc123eSJerome Brunet 	 * sysclk must be set and enabled as well to access the pdm registers
3872cfc123eSJerome Brunet 	 * Accessing the register w/o it will give a bus error.
3882cfc123eSJerome Brunet 	 */
3892cfc123eSJerome Brunet 	ret = clk_set_rate(priv->sysclk, priv->cfg->sys_rate);
3902cfc123eSJerome Brunet 	if (ret) {
3912cfc123eSJerome Brunet 		dev_err(dai->dev, "setting sysclk failed\n");
3922cfc123eSJerome Brunet 		goto err_pclk;
3932cfc123eSJerome Brunet 	}
3942cfc123eSJerome Brunet 
3952cfc123eSJerome Brunet 	ret = clk_prepare_enable(priv->sysclk);
3962cfc123eSJerome Brunet 	if (ret) {
3972cfc123eSJerome Brunet 		dev_err(dai->dev, "enabling sysclk failed\n");
3982cfc123eSJerome Brunet 		goto err_pclk;
3992cfc123eSJerome Brunet 	}
4002cfc123eSJerome Brunet 
4012cfc123eSJerome Brunet 	/* Make sure the device is initially disabled */
4022cfc123eSJerome Brunet 	axg_pdm_disable(priv->map);
4032cfc123eSJerome Brunet 
4042cfc123eSJerome Brunet 	/* Make sure filter bypass is disabled */
4052cfc123eSJerome Brunet 	regmap_update_bits(priv->map, PDM_CTRL, PDM_CTRL_BYPASS_MODE, 0);
4062cfc123eSJerome Brunet 
4072cfc123eSJerome Brunet 	/* Load filter settings */
4082cfc123eSJerome Brunet 	axg_pdm_set_hcic_ctrl(priv);
4092cfc123eSJerome Brunet 	axg_pdm_set_hpf_ctrl(priv);
4102cfc123eSJerome Brunet 
4112cfc123eSJerome Brunet 	ret = axg_pdm_set_lpf_filters(priv);
4122cfc123eSJerome Brunet 	if (ret) {
4132cfc123eSJerome Brunet 		dev_err(dai->dev, "invalid filter configuration\n");
4142cfc123eSJerome Brunet 		goto err_sysclk;
4152cfc123eSJerome Brunet 	}
4162cfc123eSJerome Brunet 
4172cfc123eSJerome Brunet 	return 0;
4182cfc123eSJerome Brunet 
4192cfc123eSJerome Brunet err_sysclk:
4202cfc123eSJerome Brunet 	clk_disable_unprepare(priv->sysclk);
4212cfc123eSJerome Brunet err_pclk:
4222cfc123eSJerome Brunet 	clk_disable_unprepare(priv->pclk);
4232cfc123eSJerome Brunet 	return ret;
4242cfc123eSJerome Brunet }
4252cfc123eSJerome Brunet 
axg_pdm_dai_remove(struct snd_soc_dai * dai)4262cfc123eSJerome Brunet static int axg_pdm_dai_remove(struct snd_soc_dai *dai)
4272cfc123eSJerome Brunet {
4282cfc123eSJerome Brunet 	struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai);
4292cfc123eSJerome Brunet 
4302cfc123eSJerome Brunet 	clk_disable_unprepare(priv->sysclk);
4312cfc123eSJerome Brunet 	clk_disable_unprepare(priv->pclk);
4322cfc123eSJerome Brunet 
4332cfc123eSJerome Brunet 	return 0;
4342cfc123eSJerome Brunet }
4352cfc123eSJerome Brunet 
436*2d3155a9SKuninori Morimoto static const struct snd_soc_dai_ops axg_pdm_dai_ops = {
437*2d3155a9SKuninori Morimoto 	.probe		= axg_pdm_dai_probe,
438*2d3155a9SKuninori Morimoto 	.remove		= axg_pdm_dai_remove,
439*2d3155a9SKuninori Morimoto 	.trigger	= axg_pdm_trigger,
440*2d3155a9SKuninori Morimoto 	.hw_params	= axg_pdm_hw_params,
441*2d3155a9SKuninori Morimoto 	.startup	= axg_pdm_startup,
442*2d3155a9SKuninori Morimoto 	.shutdown	= axg_pdm_shutdown,
443*2d3155a9SKuninori Morimoto };
444*2d3155a9SKuninori Morimoto 
4452cfc123eSJerome Brunet static struct snd_soc_dai_driver axg_pdm_dai_drv = {
4462cfc123eSJerome Brunet 	.name = "PDM",
4472cfc123eSJerome Brunet 	.capture = {
4482cfc123eSJerome Brunet 		.stream_name	= "Capture",
4492cfc123eSJerome Brunet 		.channels_min	= 1,
4502cfc123eSJerome Brunet 		.channels_max	= 8,
4512cfc123eSJerome Brunet 		.rates		= SNDRV_PCM_RATE_CONTINUOUS,
4522cfc123eSJerome Brunet 		.rate_min	= 5512,
4532cfc123eSJerome Brunet 		.rate_max	= 48000,
4542cfc123eSJerome Brunet 		.formats	= (SNDRV_PCM_FMTBIT_S24_LE |
4552cfc123eSJerome Brunet 				   SNDRV_PCM_FMTBIT_S32_LE),
4562cfc123eSJerome Brunet 	},
4572cfc123eSJerome Brunet 	.ops		= &axg_pdm_dai_ops,
4582cfc123eSJerome Brunet };
4592cfc123eSJerome Brunet 
460d8572da0SCharles Keepax static const struct snd_soc_component_driver axg_pdm_component_drv = {
461d8572da0SCharles Keepax 	.legacy_dai_naming = 1,
462d8572da0SCharles Keepax };
4632cfc123eSJerome Brunet 
4642cfc123eSJerome Brunet static const struct regmap_config axg_pdm_regmap_cfg = {
4652cfc123eSJerome Brunet 	.reg_bits	= 32,
4662cfc123eSJerome Brunet 	.val_bits	= 32,
4672cfc123eSJerome Brunet 	.reg_stride	= 4,
4682cfc123eSJerome Brunet 	.max_register	= PDM_STS,
4692cfc123eSJerome Brunet };
4702cfc123eSJerome Brunet 
4712cfc123eSJerome Brunet static const unsigned int lpf1_default_tap[] = {
4722cfc123eSJerome Brunet 	0x000014, 0xffffb2, 0xfffed9, 0xfffdce, 0xfffd45,
4732cfc123eSJerome Brunet 	0xfffe32, 0x000147, 0x000645, 0x000b86, 0x000e21,
4742cfc123eSJerome Brunet 	0x000ae3, 0x000000, 0xffeece, 0xffdca8, 0xffd212,
4752cfc123eSJerome Brunet 	0xffd7d1, 0xfff2a7, 0x001f4c, 0x0050c2, 0x0072aa,
4762cfc123eSJerome Brunet 	0x006ff1, 0x003c32, 0xffdc4e, 0xff6a18, 0xff0fef,
4772cfc123eSJerome Brunet 	0xfefbaf, 0xff4c40, 0x000000, 0x00ebc8, 0x01c077,
4782cfc123eSJerome Brunet 	0x02209e, 0x01c1a4, 0x008e60, 0xfebe52, 0xfcd690,
4792cfc123eSJerome Brunet 	0xfb8fa5, 0xfba498, 0xfd9812, 0x0181ce, 0x06f5f3,
4802cfc123eSJerome Brunet 	0x0d112f, 0x12a958, 0x169686, 0x18000e, 0x169686,
4812cfc123eSJerome Brunet 	0x12a958, 0x0d112f, 0x06f5f3, 0x0181ce, 0xfd9812,
4822cfc123eSJerome Brunet 	0xfba498, 0xfb8fa5, 0xfcd690, 0xfebe52, 0x008e60,
4832cfc123eSJerome Brunet 	0x01c1a4, 0x02209e, 0x01c077, 0x00ebc8, 0x000000,
4842cfc123eSJerome Brunet 	0xff4c40, 0xfefbaf, 0xff0fef, 0xff6a18, 0xffdc4e,
4852cfc123eSJerome Brunet 	0x003c32, 0x006ff1, 0x0072aa, 0x0050c2, 0x001f4c,
4862cfc123eSJerome Brunet 	0xfff2a7, 0xffd7d1, 0xffd212, 0xffdca8, 0xffeece,
4872cfc123eSJerome Brunet 	0x000000, 0x000ae3, 0x000e21, 0x000b86, 0x000645,
4882cfc123eSJerome Brunet 	0x000147, 0xfffe32, 0xfffd45, 0xfffdce, 0xfffed9,
4892cfc123eSJerome Brunet 	0xffffb2, 0x000014,
4902cfc123eSJerome Brunet };
4912cfc123eSJerome Brunet 
4922cfc123eSJerome Brunet static const unsigned int lpf2_default_tap[] = {
4932cfc123eSJerome Brunet 	0x00050a, 0xfff004, 0x0002c1, 0x003c12, 0xffa818,
4942cfc123eSJerome Brunet 	0xffc87d, 0x010aef, 0xff5223, 0xfebd93, 0x028f41,
4952cfc123eSJerome Brunet 	0xff5c0e, 0xfc63f8, 0x055f81, 0x000000, 0xf478a0,
4962cfc123eSJerome Brunet 	0x11c5e3, 0x2ea74d, 0x11c5e3, 0xf478a0, 0x000000,
4972cfc123eSJerome Brunet 	0x055f81, 0xfc63f8, 0xff5c0e, 0x028f41, 0xfebd93,
4982cfc123eSJerome Brunet 	0xff5223, 0x010aef, 0xffc87d, 0xffa818, 0x003c12,
4992cfc123eSJerome Brunet 	0x0002c1, 0xfff004, 0x00050a,
5002cfc123eSJerome Brunet };
5012cfc123eSJerome Brunet 
5022cfc123eSJerome Brunet static const unsigned int lpf3_default_tap[] = {
5032cfc123eSJerome Brunet 	0x000000, 0x000081, 0x000000, 0xfffedb, 0x000000,
5042cfc123eSJerome Brunet 	0x00022d, 0x000000, 0xfffc46, 0x000000, 0x0005f7,
5052cfc123eSJerome Brunet 	0x000000, 0xfff6eb, 0x000000, 0x000d4e, 0x000000,
5062cfc123eSJerome Brunet 	0xffed1e, 0x000000, 0x001a1c, 0x000000, 0xffdcb0,
5072cfc123eSJerome Brunet 	0x000000, 0x002ede, 0x000000, 0xffc2d1, 0x000000,
5082cfc123eSJerome Brunet 	0x004ebe, 0x000000, 0xff9beb, 0x000000, 0x007dd7,
5092cfc123eSJerome Brunet 	0x000000, 0xff633a, 0x000000, 0x00c1d2, 0x000000,
5102cfc123eSJerome Brunet 	0xff11d5, 0x000000, 0x012368, 0x000000, 0xfe9c45,
5112cfc123eSJerome Brunet 	0x000000, 0x01b252, 0x000000, 0xfdebf6, 0x000000,
5122cfc123eSJerome Brunet 	0x0290b8, 0x000000, 0xfcca0d, 0x000000, 0x041d7c,
5132cfc123eSJerome Brunet 	0x000000, 0xfa8152, 0x000000, 0x07e9c6, 0x000000,
5142cfc123eSJerome Brunet 	0xf28fb5, 0x000000, 0x28b216, 0x3fffde, 0x28b216,
5152cfc123eSJerome Brunet 	0x000000, 0xf28fb5, 0x000000, 0x07e9c6, 0x000000,
5162cfc123eSJerome Brunet 	0xfa8152, 0x000000, 0x041d7c, 0x000000, 0xfcca0d,
5172cfc123eSJerome Brunet 	0x000000, 0x0290b8, 0x000000, 0xfdebf6, 0x000000,
5182cfc123eSJerome Brunet 	0x01b252, 0x000000, 0xfe9c45, 0x000000, 0x012368,
5192cfc123eSJerome Brunet 	0x000000, 0xff11d5, 0x000000, 0x00c1d2, 0x000000,
5202cfc123eSJerome Brunet 	0xff633a, 0x000000, 0x007dd7, 0x000000, 0xff9beb,
5212cfc123eSJerome Brunet 	0x000000, 0x004ebe, 0x000000, 0xffc2d1, 0x000000,
5222cfc123eSJerome Brunet 	0x002ede, 0x000000, 0xffdcb0, 0x000000, 0x001a1c,
5232cfc123eSJerome Brunet 	0x000000, 0xffed1e, 0x000000, 0x000d4e, 0x000000,
5242cfc123eSJerome Brunet 	0xfff6eb, 0x000000, 0x0005f7, 0x000000, 0xfffc46,
5252cfc123eSJerome Brunet 	0x000000, 0x00022d, 0x000000, 0xfffedb, 0x000000,
5262cfc123eSJerome Brunet 	0x000081, 0x000000,
5272cfc123eSJerome Brunet };
5282cfc123eSJerome Brunet 
5292cfc123eSJerome Brunet /*
5302cfc123eSJerome Brunet  * These values are sane defaults for the axg platform:
5312cfc123eSJerome Brunet  * - OS = 64
5322cfc123eSJerome Brunet  * - Latency = 38700 (?)
5332cfc123eSJerome Brunet  *
5342cfc123eSJerome Brunet  * TODO: There is a lot of different HCIC, LPFs and HPF configurations possible.
5352cfc123eSJerome Brunet  *       the configuration may depend on the dmic used by the platform, the
5362cfc123eSJerome Brunet  *       expected tradeoff between latency and quality, etc ... If/When other
5372cfc123eSJerome Brunet  *       settings are required, we should add a fw interface to this driver to
5382cfc123eSJerome Brunet  *       load new filter settings.
5392cfc123eSJerome Brunet  */
5402cfc123eSJerome Brunet static const struct axg_pdm_filters axg_default_filters = {
5412cfc123eSJerome Brunet 	.hcic = {
5422cfc123eSJerome Brunet 		.shift = 0x15,
5432cfc123eSJerome Brunet 		.mult = 0x80,
5442cfc123eSJerome Brunet 		.steps = 7,
5452cfc123eSJerome Brunet 		.ds = 8,
5462cfc123eSJerome Brunet 	},
5472cfc123eSJerome Brunet 	.hpf = {
5482cfc123eSJerome Brunet 		.out_factor = 0x8000,
5492cfc123eSJerome Brunet 		.steps = 13,
5502cfc123eSJerome Brunet 	},
5512cfc123eSJerome Brunet 	.lpf = {
5522cfc123eSJerome Brunet 		[0] = {
5532cfc123eSJerome Brunet 			.ds = 2,
5542cfc123eSJerome Brunet 			.round_mode = 1,
5552cfc123eSJerome Brunet 			.tap = lpf1_default_tap,
5562cfc123eSJerome Brunet 			.tap_num = ARRAY_SIZE(lpf1_default_tap),
5572cfc123eSJerome Brunet 		},
5582cfc123eSJerome Brunet 		[1] = {
5592cfc123eSJerome Brunet 			.ds = 2,
5602cfc123eSJerome Brunet 			.round_mode = 0,
5612cfc123eSJerome Brunet 			.tap = lpf2_default_tap,
5622cfc123eSJerome Brunet 			.tap_num = ARRAY_SIZE(lpf2_default_tap),
5632cfc123eSJerome Brunet 		},
5642cfc123eSJerome Brunet 		[2] = {
5652cfc123eSJerome Brunet 			.ds = 2,
5662cfc123eSJerome Brunet 			.round_mode = 1,
5672cfc123eSJerome Brunet 			.tap = lpf3_default_tap,
5682cfc123eSJerome Brunet 			.tap_num = ARRAY_SIZE(lpf3_default_tap)
5692cfc123eSJerome Brunet 		},
5702cfc123eSJerome Brunet 	},
5712cfc123eSJerome Brunet };
5722cfc123eSJerome Brunet 
5732cfc123eSJerome Brunet static const struct axg_pdm_cfg axg_pdm_config = {
5742cfc123eSJerome Brunet 	.filters = &axg_default_filters,
5752cfc123eSJerome Brunet 	.sys_rate = 250000000,
5762cfc123eSJerome Brunet };
5772cfc123eSJerome Brunet 
5782cfc123eSJerome Brunet static const struct of_device_id axg_pdm_of_match[] = {
5792cfc123eSJerome Brunet 	{
5802cfc123eSJerome Brunet 		.compatible = "amlogic,axg-pdm",
5812cfc123eSJerome Brunet 		.data = &axg_pdm_config,
5822cfc123eSJerome Brunet 	}, {}
5832cfc123eSJerome Brunet };
5842cfc123eSJerome Brunet MODULE_DEVICE_TABLE(of, axg_pdm_of_match);
5852cfc123eSJerome Brunet 
axg_pdm_probe(struct platform_device * pdev)5862cfc123eSJerome Brunet static int axg_pdm_probe(struct platform_device *pdev)
5872cfc123eSJerome Brunet {
5882cfc123eSJerome Brunet 	struct device *dev = &pdev->dev;
5892cfc123eSJerome Brunet 	struct axg_pdm *priv;
5902cfc123eSJerome Brunet 	void __iomem *regs;
5912cfc123eSJerome Brunet 
5922cfc123eSJerome Brunet 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
5932cfc123eSJerome Brunet 	if (!priv)
5942cfc123eSJerome Brunet 		return -ENOMEM;
5952cfc123eSJerome Brunet 	platform_set_drvdata(pdev, priv);
5962cfc123eSJerome Brunet 
5972cfc123eSJerome Brunet 	priv->cfg = of_device_get_match_data(dev);
5982cfc123eSJerome Brunet 	if (!priv->cfg) {
5992cfc123eSJerome Brunet 		dev_err(dev, "failed to match device\n");
6002cfc123eSJerome Brunet 		return -ENODEV;
6012cfc123eSJerome Brunet 	}
6022cfc123eSJerome Brunet 
6032e73d98fSYueHaibing 	regs = devm_platform_ioremap_resource(pdev, 0);
6042cfc123eSJerome Brunet 	if (IS_ERR(regs))
6052cfc123eSJerome Brunet 		return PTR_ERR(regs);
6062cfc123eSJerome Brunet 
6072cfc123eSJerome Brunet 	priv->map = devm_regmap_init_mmio(dev, regs, &axg_pdm_regmap_cfg);
6082cfc123eSJerome Brunet 	if (IS_ERR(priv->map)) {
6092cfc123eSJerome Brunet 		dev_err(dev, "failed to init regmap: %ld\n",
6102cfc123eSJerome Brunet 			PTR_ERR(priv->map));
6112cfc123eSJerome Brunet 		return PTR_ERR(priv->map);
6122cfc123eSJerome Brunet 	}
6132cfc123eSJerome Brunet 
6142cfc123eSJerome Brunet 	priv->pclk = devm_clk_get(dev, "pclk");
6152ff4e003SKuninori Morimoto 	if (IS_ERR(priv->pclk))
6162ff4e003SKuninori Morimoto 		return dev_err_probe(dev, PTR_ERR(priv->pclk), "failed to get pclk\n");
6172cfc123eSJerome Brunet 
6182cfc123eSJerome Brunet 	priv->dclk = devm_clk_get(dev, "dclk");
6192ff4e003SKuninori Morimoto 	if (IS_ERR(priv->dclk))
6202ff4e003SKuninori Morimoto 		return dev_err_probe(dev, PTR_ERR(priv->dclk), "failed to get dclk\n");
6212cfc123eSJerome Brunet 
6222cfc123eSJerome Brunet 	priv->sysclk = devm_clk_get(dev, "sysclk");
6232ff4e003SKuninori Morimoto 	if (IS_ERR(priv->sysclk))
6242ff4e003SKuninori Morimoto 		return dev_err_probe(dev, PTR_ERR(priv->sysclk), "failed to get dclk\n");
6252cfc123eSJerome Brunet 
6262cfc123eSJerome Brunet 	return devm_snd_soc_register_component(dev, &axg_pdm_component_drv,
6272cfc123eSJerome Brunet 					       &axg_pdm_dai_drv, 1);
6282cfc123eSJerome Brunet }
6292cfc123eSJerome Brunet 
6302cfc123eSJerome Brunet static struct platform_driver axg_pdm_pdrv = {
6312cfc123eSJerome Brunet 	.probe = axg_pdm_probe,
6322cfc123eSJerome Brunet 	.driver = {
6332cfc123eSJerome Brunet 		.name = "axg-pdm",
6342cfc123eSJerome Brunet 		.of_match_table = axg_pdm_of_match,
6352cfc123eSJerome Brunet 	},
6362cfc123eSJerome Brunet };
6372cfc123eSJerome Brunet module_platform_driver(axg_pdm_pdrv);
6382cfc123eSJerome Brunet 
6392cfc123eSJerome Brunet MODULE_DESCRIPTION("Amlogic AXG PDM Input driver");
6402cfc123eSJerome Brunet MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
6412cfc123eSJerome Brunet MODULE_LICENSE("GPL v2");
642