15ce56583SJerome Brunet // SPDX-License-Identifier: (GPL-2.0 OR MIT)
25ce56583SJerome Brunet //
35ce56583SJerome Brunet // Copyright (c) 2018 BayLibre, SAS.
45ce56583SJerome Brunet // Author: Jerome Brunet <jbrunet@baylibre.com>
55ce56583SJerome Brunet
65ce56583SJerome Brunet #include <linux/bitfield.h>
75ce56583SJerome Brunet #include <linux/clk.h>
85ce56583SJerome Brunet #include <linux/module.h>
95ce56583SJerome Brunet #include <linux/of_platform.h>
105ce56583SJerome Brunet #include <linux/regmap.h>
115ce56583SJerome Brunet #include <sound/soc.h>
125ce56583SJerome Brunet #include <sound/soc-dai.h>
135ce56583SJerome Brunet #include <sound/pcm_params.h>
145ce56583SJerome Brunet
155ce56583SJerome Brunet #define SPDIFIN_CTRL0 0x00
165ce56583SJerome Brunet #define SPDIFIN_CTRL0_EN BIT(31)
175ce56583SJerome Brunet #define SPDIFIN_CTRL0_RST_OUT BIT(29)
185ce56583SJerome Brunet #define SPDIFIN_CTRL0_RST_IN BIT(28)
195ce56583SJerome Brunet #define SPDIFIN_CTRL0_WIDTH_SEL BIT(24)
205ce56583SJerome Brunet #define SPDIFIN_CTRL0_STATUS_CH_SHIFT 11
215ce56583SJerome Brunet #define SPDIFIN_CTRL0_STATUS_SEL GENMASK(10, 8)
225ce56583SJerome Brunet #define SPDIFIN_CTRL0_SRC_SEL GENMASK(5, 4)
235ce56583SJerome Brunet #define SPDIFIN_CTRL0_CHK_VALID BIT(3)
245ce56583SJerome Brunet #define SPDIFIN_CTRL1 0x04
255ce56583SJerome Brunet #define SPDIFIN_CTRL1_BASE_TIMER GENMASK(19, 0)
265ce56583SJerome Brunet #define SPDIFIN_CTRL1_IRQ_MASK GENMASK(27, 20)
275ce56583SJerome Brunet #define SPDIFIN_CTRL2 0x08
285ce56583SJerome Brunet #define SPDIFIN_THRES_PER_REG 3
295ce56583SJerome Brunet #define SPDIFIN_THRES_WIDTH 10
305ce56583SJerome Brunet #define SPDIFIN_CTRL3 0x0c
315ce56583SJerome Brunet #define SPDIFIN_CTRL4 0x10
325ce56583SJerome Brunet #define SPDIFIN_TIMER_PER_REG 4
335ce56583SJerome Brunet #define SPDIFIN_TIMER_WIDTH 8
345ce56583SJerome Brunet #define SPDIFIN_CTRL5 0x14
355ce56583SJerome Brunet #define SPDIFIN_CTRL6 0x18
365ce56583SJerome Brunet #define SPDIFIN_STAT0 0x1c
375ce56583SJerome Brunet #define SPDIFIN_STAT0_MODE GENMASK(30, 28)
385ce56583SJerome Brunet #define SPDIFIN_STAT0_MAXW GENMASK(17, 8)
395ce56583SJerome Brunet #define SPDIFIN_STAT0_IRQ GENMASK(7, 0)
405ce56583SJerome Brunet #define SPDIFIN_IRQ_MODE_CHANGED BIT(2)
415ce56583SJerome Brunet #define SPDIFIN_STAT1 0x20
425ce56583SJerome Brunet #define SPDIFIN_STAT2 0x24
435ce56583SJerome Brunet #define SPDIFIN_MUTE_VAL 0x28
445ce56583SJerome Brunet
455ce56583SJerome Brunet #define SPDIFIN_MODE_NUM 7
465ce56583SJerome Brunet
475ce56583SJerome Brunet struct axg_spdifin_cfg {
485ce56583SJerome Brunet const unsigned int *mode_rates;
495ce56583SJerome Brunet unsigned int ref_rate;
505ce56583SJerome Brunet };
515ce56583SJerome Brunet
525ce56583SJerome Brunet struct axg_spdifin {
535ce56583SJerome Brunet const struct axg_spdifin_cfg *conf;
545ce56583SJerome Brunet struct regmap *map;
555ce56583SJerome Brunet struct clk *refclk;
565ce56583SJerome Brunet struct clk *pclk;
575ce56583SJerome Brunet };
585ce56583SJerome Brunet
595ce56583SJerome Brunet /*
605ce56583SJerome Brunet * TODO:
615ce56583SJerome Brunet * It would have been nice to check the actual rate against the sample rate
625ce56583SJerome Brunet * requested in hw_params(). Unfortunately, I was not able to make the mode
635ce56583SJerome Brunet * detection and IRQ work reliably:
645ce56583SJerome Brunet *
655ce56583SJerome Brunet * 1. IRQs are generated on mode change only, so there is no notification
665ce56583SJerome Brunet * on transition between no signal and mode 0 (32kHz).
675ce56583SJerome Brunet * 2. Mode detection very often has glitches, and may detects the
685ce56583SJerome Brunet * lowest or the highest mode before zeroing in on the actual mode.
695ce56583SJerome Brunet *
705ce56583SJerome Brunet * This makes calling snd_pcm_stop() difficult to get right. Even notifying
715ce56583SJerome Brunet * the kcontrol would be very unreliable at this point.
725ce56583SJerome Brunet * Let's keep things simple until the magic spell that makes this work is
735ce56583SJerome Brunet * found.
745ce56583SJerome Brunet */
755ce56583SJerome Brunet
axg_spdifin_get_rate(struct axg_spdifin * priv)765ce56583SJerome Brunet static unsigned int axg_spdifin_get_rate(struct axg_spdifin *priv)
775ce56583SJerome Brunet {
785ce56583SJerome Brunet unsigned int stat, mode, rate = 0;
795ce56583SJerome Brunet
805ce56583SJerome Brunet regmap_read(priv->map, SPDIFIN_STAT0, &stat);
815ce56583SJerome Brunet mode = FIELD_GET(SPDIFIN_STAT0_MODE, stat);
825ce56583SJerome Brunet
835ce56583SJerome Brunet /*
845ce56583SJerome Brunet * If max width is zero, we are not capturing anything.
855ce56583SJerome Brunet * Also Sometimes, when the capture is on but there is no data,
865ce56583SJerome Brunet * mode is SPDIFIN_MODE_NUM, but not always ...
875ce56583SJerome Brunet */
885ce56583SJerome Brunet if (FIELD_GET(SPDIFIN_STAT0_MAXW, stat) &&
895ce56583SJerome Brunet mode < SPDIFIN_MODE_NUM)
905ce56583SJerome Brunet rate = priv->conf->mode_rates[mode];
915ce56583SJerome Brunet
925ce56583SJerome Brunet return rate;
935ce56583SJerome Brunet }
945ce56583SJerome Brunet
axg_spdifin_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)955ce56583SJerome Brunet static int axg_spdifin_prepare(struct snd_pcm_substream *substream,
965ce56583SJerome Brunet struct snd_soc_dai *dai)
975ce56583SJerome Brunet {
985ce56583SJerome Brunet struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
995ce56583SJerome Brunet
1005ce56583SJerome Brunet /* Apply both reset */
1015ce56583SJerome Brunet regmap_update_bits(priv->map, SPDIFIN_CTRL0,
1025ce56583SJerome Brunet SPDIFIN_CTRL0_RST_OUT |
1035ce56583SJerome Brunet SPDIFIN_CTRL0_RST_IN,
1045ce56583SJerome Brunet 0);
1055ce56583SJerome Brunet
1065ce56583SJerome Brunet /* Clear out reset before in reset */
1075ce56583SJerome Brunet regmap_update_bits(priv->map, SPDIFIN_CTRL0,
1085ce56583SJerome Brunet SPDIFIN_CTRL0_RST_OUT, SPDIFIN_CTRL0_RST_OUT);
1095ce56583SJerome Brunet regmap_update_bits(priv->map, SPDIFIN_CTRL0,
1105ce56583SJerome Brunet SPDIFIN_CTRL0_RST_IN, SPDIFIN_CTRL0_RST_IN);
1115ce56583SJerome Brunet
1125ce56583SJerome Brunet return 0;
1135ce56583SJerome Brunet }
1145ce56583SJerome Brunet
axg_spdifin_write_mode_param(struct regmap * map,int mode,unsigned int val,unsigned int num_per_reg,unsigned int base_reg,unsigned int width)1155ce56583SJerome Brunet static void axg_spdifin_write_mode_param(struct regmap *map, int mode,
1165ce56583SJerome Brunet unsigned int val,
1175ce56583SJerome Brunet unsigned int num_per_reg,
1185ce56583SJerome Brunet unsigned int base_reg,
1195ce56583SJerome Brunet unsigned int width)
1205ce56583SJerome Brunet {
121165be3c2SJerome Brunet uint64_t offset = mode;
122165be3c2SJerome Brunet unsigned int reg, shift, rem;
1235ce56583SJerome Brunet
1245ce56583SJerome Brunet rem = do_div(offset, num_per_reg);
1255ce56583SJerome Brunet
1265ce56583SJerome Brunet reg = offset * regmap_get_reg_stride(map) + base_reg;
1275ce56583SJerome Brunet shift = width * (num_per_reg - 1 - rem);
1285ce56583SJerome Brunet
1295ce56583SJerome Brunet regmap_update_bits(map, reg, GENMASK(width - 1, 0) << shift,
1305ce56583SJerome Brunet val << shift);
1315ce56583SJerome Brunet }
1325ce56583SJerome Brunet
axg_spdifin_write_timer(struct regmap * map,int mode,unsigned int val)1335ce56583SJerome Brunet static void axg_spdifin_write_timer(struct regmap *map, int mode,
1345ce56583SJerome Brunet unsigned int val)
1355ce56583SJerome Brunet {
1365ce56583SJerome Brunet axg_spdifin_write_mode_param(map, mode, val, SPDIFIN_TIMER_PER_REG,
1375ce56583SJerome Brunet SPDIFIN_CTRL4, SPDIFIN_TIMER_WIDTH);
1385ce56583SJerome Brunet }
1395ce56583SJerome Brunet
axg_spdifin_write_threshold(struct regmap * map,int mode,unsigned int val)1405ce56583SJerome Brunet static void axg_spdifin_write_threshold(struct regmap *map, int mode,
1415ce56583SJerome Brunet unsigned int val)
1425ce56583SJerome Brunet {
1435ce56583SJerome Brunet axg_spdifin_write_mode_param(map, mode, val, SPDIFIN_THRES_PER_REG,
1445ce56583SJerome Brunet SPDIFIN_CTRL2, SPDIFIN_THRES_WIDTH);
1455ce56583SJerome Brunet }
1465ce56583SJerome Brunet
axg_spdifin_mode_timer(struct axg_spdifin * priv,int mode,unsigned int rate)1475ce56583SJerome Brunet static unsigned int axg_spdifin_mode_timer(struct axg_spdifin *priv,
1485ce56583SJerome Brunet int mode,
1495ce56583SJerome Brunet unsigned int rate)
1505ce56583SJerome Brunet {
1515ce56583SJerome Brunet /*
1525ce56583SJerome Brunet * Number of period of the reference clock during a period of the
1535ce56583SJerome Brunet * input signal reference clock
1545ce56583SJerome Brunet */
1555ce56583SJerome Brunet return rate / (128 * priv->conf->mode_rates[mode]);
1565ce56583SJerome Brunet }
1575ce56583SJerome Brunet
axg_spdifin_sample_mode_config(struct snd_soc_dai * dai,struct axg_spdifin * priv)1585ce56583SJerome Brunet static int axg_spdifin_sample_mode_config(struct snd_soc_dai *dai,
1595ce56583SJerome Brunet struct axg_spdifin *priv)
1605ce56583SJerome Brunet {
1615ce56583SJerome Brunet unsigned int rate, t_next;
1625ce56583SJerome Brunet int ret, i = SPDIFIN_MODE_NUM - 1;
1635ce56583SJerome Brunet
1645ce56583SJerome Brunet /* Set spdif input reference clock */
1655ce56583SJerome Brunet ret = clk_set_rate(priv->refclk, priv->conf->ref_rate);
1665ce56583SJerome Brunet if (ret) {
1675ce56583SJerome Brunet dev_err(dai->dev, "reference clock rate set failed\n");
1685ce56583SJerome Brunet return ret;
1695ce56583SJerome Brunet }
1705ce56583SJerome Brunet
1715ce56583SJerome Brunet /*
1725ce56583SJerome Brunet * The rate actually set might be slightly different, get
1735ce56583SJerome Brunet * the actual rate for the following mode calculation
1745ce56583SJerome Brunet */
1755ce56583SJerome Brunet rate = clk_get_rate(priv->refclk);
1765ce56583SJerome Brunet
1775ce56583SJerome Brunet /* HW will update mode every 1ms */
1785ce56583SJerome Brunet regmap_update_bits(priv->map, SPDIFIN_CTRL1,
1795ce56583SJerome Brunet SPDIFIN_CTRL1_BASE_TIMER,
1805ce56583SJerome Brunet FIELD_PREP(SPDIFIN_CTRL1_BASE_TIMER, rate / 1000));
1815ce56583SJerome Brunet
1825ce56583SJerome Brunet /* Threshold based on the minimum width between two edges */
1835ce56583SJerome Brunet regmap_update_bits(priv->map, SPDIFIN_CTRL0,
1845ce56583SJerome Brunet SPDIFIN_CTRL0_WIDTH_SEL, SPDIFIN_CTRL0_WIDTH_SEL);
1855ce56583SJerome Brunet
1865ce56583SJerome Brunet /* Calculate the last timer which has no threshold */
1875ce56583SJerome Brunet t_next = axg_spdifin_mode_timer(priv, i, rate);
1885ce56583SJerome Brunet axg_spdifin_write_timer(priv->map, i, t_next);
1895ce56583SJerome Brunet
1905ce56583SJerome Brunet do {
1915ce56583SJerome Brunet unsigned int t;
1925ce56583SJerome Brunet
1935ce56583SJerome Brunet i -= 1;
1945ce56583SJerome Brunet
1955ce56583SJerome Brunet /* Calculate the timer */
1965ce56583SJerome Brunet t = axg_spdifin_mode_timer(priv, i, rate);
1975ce56583SJerome Brunet
1985ce56583SJerome Brunet /* Set the timer value */
1995ce56583SJerome Brunet axg_spdifin_write_timer(priv->map, i, t);
2005ce56583SJerome Brunet
2015ce56583SJerome Brunet /* Set the threshold value */
2025ce56583SJerome Brunet axg_spdifin_write_threshold(priv->map, i, t + t_next);
2035ce56583SJerome Brunet
2045ce56583SJerome Brunet /* Save the current timer for the next threshold calculation */
2055ce56583SJerome Brunet t_next = t;
2065ce56583SJerome Brunet
2075ce56583SJerome Brunet } while (i > 0);
2085ce56583SJerome Brunet
2095ce56583SJerome Brunet return 0;
2105ce56583SJerome Brunet }
2115ce56583SJerome Brunet
axg_spdifin_dai_probe(struct snd_soc_dai * dai)2125ce56583SJerome Brunet static int axg_spdifin_dai_probe(struct snd_soc_dai *dai)
2135ce56583SJerome Brunet {
2145ce56583SJerome Brunet struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
2155ce56583SJerome Brunet int ret;
2165ce56583SJerome Brunet
2175ce56583SJerome Brunet ret = clk_prepare_enable(priv->pclk);
2185ce56583SJerome Brunet if (ret) {
2195ce56583SJerome Brunet dev_err(dai->dev, "failed to enable pclk\n");
2205ce56583SJerome Brunet return ret;
2215ce56583SJerome Brunet }
2225ce56583SJerome Brunet
2235ce56583SJerome Brunet ret = axg_spdifin_sample_mode_config(dai, priv);
2245ce56583SJerome Brunet if (ret) {
2255ce56583SJerome Brunet dev_err(dai->dev, "mode configuration failed\n");
226*aedf323bSJerome Brunet goto pclk_err;
2275ce56583SJerome Brunet }
2285ce56583SJerome Brunet
229*aedf323bSJerome Brunet ret = clk_prepare_enable(priv->refclk);
230*aedf323bSJerome Brunet if (ret) {
231*aedf323bSJerome Brunet dev_err(dai->dev,
232*aedf323bSJerome Brunet "failed to enable spdifin reference clock\n");
233*aedf323bSJerome Brunet goto pclk_err;
234*aedf323bSJerome Brunet }
235*aedf323bSJerome Brunet
236*aedf323bSJerome Brunet regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN,
237*aedf323bSJerome Brunet SPDIFIN_CTRL0_EN);
238*aedf323bSJerome Brunet
2395ce56583SJerome Brunet return 0;
240*aedf323bSJerome Brunet
241*aedf323bSJerome Brunet pclk_err:
242*aedf323bSJerome Brunet clk_disable_unprepare(priv->pclk);
243*aedf323bSJerome Brunet return ret;
2445ce56583SJerome Brunet }
2455ce56583SJerome Brunet
axg_spdifin_dai_remove(struct snd_soc_dai * dai)2465ce56583SJerome Brunet static int axg_spdifin_dai_remove(struct snd_soc_dai *dai)
2475ce56583SJerome Brunet {
2485ce56583SJerome Brunet struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
2495ce56583SJerome Brunet
250*aedf323bSJerome Brunet regmap_update_bits(priv->map, SPDIFIN_CTRL0, SPDIFIN_CTRL0_EN, 0);
251*aedf323bSJerome Brunet clk_disable_unprepare(priv->refclk);
2525ce56583SJerome Brunet clk_disable_unprepare(priv->pclk);
2535ce56583SJerome Brunet return 0;
2545ce56583SJerome Brunet }
2555ce56583SJerome Brunet
2565ce56583SJerome Brunet static const struct snd_soc_dai_ops axg_spdifin_ops = {
2572d3155a9SKuninori Morimoto .probe = axg_spdifin_dai_probe,
2582d3155a9SKuninori Morimoto .remove = axg_spdifin_dai_remove,
2595ce56583SJerome Brunet .prepare = axg_spdifin_prepare,
2605ce56583SJerome Brunet };
2615ce56583SJerome Brunet
axg_spdifin_iec958_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)2625ce56583SJerome Brunet static int axg_spdifin_iec958_info(struct snd_kcontrol *kcontrol,
2635ce56583SJerome Brunet struct snd_ctl_elem_info *uinfo)
2645ce56583SJerome Brunet {
2655ce56583SJerome Brunet uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2665ce56583SJerome Brunet uinfo->count = 1;
2675ce56583SJerome Brunet
2685ce56583SJerome Brunet return 0;
2695ce56583SJerome Brunet }
2705ce56583SJerome Brunet
axg_spdifin_get_status_mask(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2715ce56583SJerome Brunet static int axg_spdifin_get_status_mask(struct snd_kcontrol *kcontrol,
2725ce56583SJerome Brunet struct snd_ctl_elem_value *ucontrol)
2735ce56583SJerome Brunet {
2745ce56583SJerome Brunet int i;
2755ce56583SJerome Brunet
2765ce56583SJerome Brunet for (i = 0; i < 24; i++)
2775ce56583SJerome Brunet ucontrol->value.iec958.status[i] = 0xff;
2785ce56583SJerome Brunet
2795ce56583SJerome Brunet return 0;
2805ce56583SJerome Brunet }
2815ce56583SJerome Brunet
axg_spdifin_get_status(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2825ce56583SJerome Brunet static int axg_spdifin_get_status(struct snd_kcontrol *kcontrol,
2835ce56583SJerome Brunet struct snd_ctl_elem_value *ucontrol)
2845ce56583SJerome Brunet {
2855ce56583SJerome Brunet struct snd_soc_component *c = snd_kcontrol_chip(kcontrol);
2865ce56583SJerome Brunet struct axg_spdifin *priv = snd_soc_component_get_drvdata(c);
2875ce56583SJerome Brunet int i, j;
2885ce56583SJerome Brunet
2895ce56583SJerome Brunet for (i = 0; i < 6; i++) {
2905ce56583SJerome Brunet unsigned int val;
2915ce56583SJerome Brunet
2925ce56583SJerome Brunet regmap_update_bits(priv->map, SPDIFIN_CTRL0,
2935ce56583SJerome Brunet SPDIFIN_CTRL0_STATUS_SEL,
2945ce56583SJerome Brunet FIELD_PREP(SPDIFIN_CTRL0_STATUS_SEL, i));
2955ce56583SJerome Brunet
2965ce56583SJerome Brunet regmap_read(priv->map, SPDIFIN_STAT1, &val);
2975ce56583SJerome Brunet
2985ce56583SJerome Brunet for (j = 0; j < 4; j++) {
2995ce56583SJerome Brunet unsigned int offset = i * 4 + j;
3005ce56583SJerome Brunet
3015ce56583SJerome Brunet ucontrol->value.iec958.status[offset] =
3025ce56583SJerome Brunet (val >> (j * 8)) & 0xff;
3035ce56583SJerome Brunet }
3045ce56583SJerome Brunet }
3055ce56583SJerome Brunet
3065ce56583SJerome Brunet return 0;
3075ce56583SJerome Brunet }
3085ce56583SJerome Brunet
3095ce56583SJerome Brunet #define AXG_SPDIFIN_IEC958_MASK \
3105ce56583SJerome Brunet { \
3115ce56583SJerome Brunet .access = SNDRV_CTL_ELEM_ACCESS_READ, \
3125ce56583SJerome Brunet .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
3135ce56583SJerome Brunet .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK), \
3145ce56583SJerome Brunet .info = axg_spdifin_iec958_info, \
3155ce56583SJerome Brunet .get = axg_spdifin_get_status_mask, \
3165ce56583SJerome Brunet }
3175ce56583SJerome Brunet
3185ce56583SJerome Brunet #define AXG_SPDIFIN_IEC958_STATUS \
3195ce56583SJerome Brunet { \
3205ce56583SJerome Brunet .access = (SNDRV_CTL_ELEM_ACCESS_READ | \
3215ce56583SJerome Brunet SNDRV_CTL_ELEM_ACCESS_VOLATILE), \
3225ce56583SJerome Brunet .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
3235ce56583SJerome Brunet .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE), \
3245ce56583SJerome Brunet .info = axg_spdifin_iec958_info, \
3255ce56583SJerome Brunet .get = axg_spdifin_get_status, \
3265ce56583SJerome Brunet }
3275ce56583SJerome Brunet
3285ce56583SJerome Brunet static const char * const spdifin_chsts_src_texts[] = {
3295ce56583SJerome Brunet "A", "B",
3305ce56583SJerome Brunet };
3315ce56583SJerome Brunet
3325ce56583SJerome Brunet static SOC_ENUM_SINGLE_DECL(axg_spdifin_chsts_src_enum, SPDIFIN_CTRL0,
3335ce56583SJerome Brunet SPDIFIN_CTRL0_STATUS_CH_SHIFT,
3345ce56583SJerome Brunet spdifin_chsts_src_texts);
3355ce56583SJerome Brunet
axg_spdifin_rate_lock_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)3365ce56583SJerome Brunet static int axg_spdifin_rate_lock_info(struct snd_kcontrol *kcontrol,
3375ce56583SJerome Brunet struct snd_ctl_elem_info *uinfo)
3385ce56583SJerome Brunet {
3395ce56583SJerome Brunet uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3405ce56583SJerome Brunet uinfo->count = 1;
3415ce56583SJerome Brunet uinfo->value.integer.min = 0;
3425ce56583SJerome Brunet uinfo->value.integer.max = 192000;
3435ce56583SJerome Brunet
3445ce56583SJerome Brunet return 0;
3455ce56583SJerome Brunet }
3465ce56583SJerome Brunet
axg_spdifin_rate_lock_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3475ce56583SJerome Brunet static int axg_spdifin_rate_lock_get(struct snd_kcontrol *kcontrol,
3485ce56583SJerome Brunet struct snd_ctl_elem_value *ucontrol)
3495ce56583SJerome Brunet {
3505ce56583SJerome Brunet struct snd_soc_component *c = snd_kcontrol_chip(kcontrol);
3515ce56583SJerome Brunet struct axg_spdifin *priv = snd_soc_component_get_drvdata(c);
3525ce56583SJerome Brunet
3535ce56583SJerome Brunet ucontrol->value.integer.value[0] = axg_spdifin_get_rate(priv);
3545ce56583SJerome Brunet
3555ce56583SJerome Brunet return 0;
3565ce56583SJerome Brunet }
3575ce56583SJerome Brunet
3585ce56583SJerome Brunet #define AXG_SPDIFIN_LOCK_RATE(xname) \
3595ce56583SJerome Brunet { \
3605ce56583SJerome Brunet .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
3615ce56583SJerome Brunet .access = (SNDRV_CTL_ELEM_ACCESS_READ | \
3625ce56583SJerome Brunet SNDRV_CTL_ELEM_ACCESS_VOLATILE), \
3635ce56583SJerome Brunet .get = axg_spdifin_rate_lock_get, \
3645ce56583SJerome Brunet .info = axg_spdifin_rate_lock_info, \
3655ce56583SJerome Brunet .name = xname, \
3665ce56583SJerome Brunet }
3675ce56583SJerome Brunet
3685ce56583SJerome Brunet static const struct snd_kcontrol_new axg_spdifin_controls[] = {
3695ce56583SJerome Brunet AXG_SPDIFIN_LOCK_RATE("Capture Rate Lock"),
3705ce56583SJerome Brunet SOC_DOUBLE("Capture Switch", SPDIFIN_CTRL0, 7, 6, 1, 1),
3715ce56583SJerome Brunet SOC_ENUM(SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Src",
3725ce56583SJerome Brunet axg_spdifin_chsts_src_enum),
3735ce56583SJerome Brunet AXG_SPDIFIN_IEC958_MASK,
3745ce56583SJerome Brunet AXG_SPDIFIN_IEC958_STATUS,
3755ce56583SJerome Brunet };
3765ce56583SJerome Brunet
3775ce56583SJerome Brunet static const struct snd_soc_component_driver axg_spdifin_component_drv = {
3785ce56583SJerome Brunet .controls = axg_spdifin_controls,
3795ce56583SJerome Brunet .num_controls = ARRAY_SIZE(axg_spdifin_controls),
380d8572da0SCharles Keepax .legacy_dai_naming = 1,
3815ce56583SJerome Brunet };
3825ce56583SJerome Brunet
3835ce56583SJerome Brunet static const struct regmap_config axg_spdifin_regmap_cfg = {
3845ce56583SJerome Brunet .reg_bits = 32,
3855ce56583SJerome Brunet .val_bits = 32,
3865ce56583SJerome Brunet .reg_stride = 4,
3875ce56583SJerome Brunet .max_register = SPDIFIN_MUTE_VAL,
3885ce56583SJerome Brunet };
3895ce56583SJerome Brunet
3905ce56583SJerome Brunet static const unsigned int axg_spdifin_mode_rates[SPDIFIN_MODE_NUM] = {
3915ce56583SJerome Brunet 32000, 44100, 48000, 88200, 96000, 176400, 192000,
3925ce56583SJerome Brunet };
3935ce56583SJerome Brunet
3945ce56583SJerome Brunet static const struct axg_spdifin_cfg axg_cfg = {
3955ce56583SJerome Brunet .mode_rates = axg_spdifin_mode_rates,
3965ce56583SJerome Brunet .ref_rate = 333333333,
3975ce56583SJerome Brunet };
3985ce56583SJerome Brunet
3995ce56583SJerome Brunet static const struct of_device_id axg_spdifin_of_match[] = {
4005ce56583SJerome Brunet {
4015ce56583SJerome Brunet .compatible = "amlogic,axg-spdifin",
4025ce56583SJerome Brunet .data = &axg_cfg,
4035ce56583SJerome Brunet }, {}
4045ce56583SJerome Brunet };
4055ce56583SJerome Brunet MODULE_DEVICE_TABLE(of, axg_spdifin_of_match);
4065ce56583SJerome Brunet
4075ce56583SJerome Brunet static struct snd_soc_dai_driver *
axg_spdifin_get_dai_drv(struct device * dev,struct axg_spdifin * priv)4085ce56583SJerome Brunet axg_spdifin_get_dai_drv(struct device *dev, struct axg_spdifin *priv)
4095ce56583SJerome Brunet {
4105ce56583SJerome Brunet struct snd_soc_dai_driver *drv;
4115ce56583SJerome Brunet int i;
4125ce56583SJerome Brunet
4135ce56583SJerome Brunet drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
4145ce56583SJerome Brunet if (!drv)
4155ce56583SJerome Brunet return ERR_PTR(-ENOMEM);
4165ce56583SJerome Brunet
4175ce56583SJerome Brunet drv->name = "SPDIF Input";
4185ce56583SJerome Brunet drv->ops = &axg_spdifin_ops;
4195ce56583SJerome Brunet drv->capture.stream_name = "Capture";
4205ce56583SJerome Brunet drv->capture.channels_min = 1;
4215ce56583SJerome Brunet drv->capture.channels_max = 2;
4225ce56583SJerome Brunet drv->capture.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
4235ce56583SJerome Brunet
4245ce56583SJerome Brunet for (i = 0; i < SPDIFIN_MODE_NUM; i++) {
4255ce56583SJerome Brunet unsigned int rb =
4265ce56583SJerome Brunet snd_pcm_rate_to_rate_bit(priv->conf->mode_rates[i]);
4275ce56583SJerome Brunet
4285ce56583SJerome Brunet if (rb == SNDRV_PCM_RATE_KNOT)
4295ce56583SJerome Brunet return ERR_PTR(-EINVAL);
4305ce56583SJerome Brunet
4315ce56583SJerome Brunet drv->capture.rates |= rb;
4325ce56583SJerome Brunet }
4335ce56583SJerome Brunet
4345ce56583SJerome Brunet return drv;
4355ce56583SJerome Brunet }
4365ce56583SJerome Brunet
axg_spdifin_probe(struct platform_device * pdev)4375ce56583SJerome Brunet static int axg_spdifin_probe(struct platform_device *pdev)
4385ce56583SJerome Brunet {
4395ce56583SJerome Brunet struct device *dev = &pdev->dev;
4405ce56583SJerome Brunet struct axg_spdifin *priv;
4415ce56583SJerome Brunet struct snd_soc_dai_driver *dai_drv;
4425ce56583SJerome Brunet void __iomem *regs;
4435ce56583SJerome Brunet
4445ce56583SJerome Brunet priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
4455ce56583SJerome Brunet if (!priv)
4465ce56583SJerome Brunet return -ENOMEM;
4475ce56583SJerome Brunet platform_set_drvdata(pdev, priv);
4485ce56583SJerome Brunet
4495ce56583SJerome Brunet priv->conf = of_device_get_match_data(dev);
4505ce56583SJerome Brunet if (!priv->conf) {
4515ce56583SJerome Brunet dev_err(dev, "failed to match device\n");
4525ce56583SJerome Brunet return -ENODEV;
4535ce56583SJerome Brunet }
4545ce56583SJerome Brunet
455d61feec0SYueHaibing regs = devm_platform_ioremap_resource(pdev, 0);
4565ce56583SJerome Brunet if (IS_ERR(regs))
4575ce56583SJerome Brunet return PTR_ERR(regs);
4585ce56583SJerome Brunet
4595ce56583SJerome Brunet priv->map = devm_regmap_init_mmio(dev, regs, &axg_spdifin_regmap_cfg);
4605ce56583SJerome Brunet if (IS_ERR(priv->map)) {
4615ce56583SJerome Brunet dev_err(dev, "failed to init regmap: %ld\n",
4625ce56583SJerome Brunet PTR_ERR(priv->map));
4635ce56583SJerome Brunet return PTR_ERR(priv->map);
4645ce56583SJerome Brunet }
4655ce56583SJerome Brunet
4665ce56583SJerome Brunet priv->pclk = devm_clk_get(dev, "pclk");
4672ff4e003SKuninori Morimoto if (IS_ERR(priv->pclk))
4682ff4e003SKuninori Morimoto return dev_err_probe(dev, PTR_ERR(priv->pclk), "failed to get pclk\n");
4695ce56583SJerome Brunet
4705ce56583SJerome Brunet priv->refclk = devm_clk_get(dev, "refclk");
4712ff4e003SKuninori Morimoto if (IS_ERR(priv->refclk))
4722ff4e003SKuninori Morimoto return dev_err_probe(dev, PTR_ERR(priv->refclk), "failed to get mclk\n");
4735ce56583SJerome Brunet
4745ce56583SJerome Brunet dai_drv = axg_spdifin_get_dai_drv(dev, priv);
4755ce56583SJerome Brunet if (IS_ERR(dai_drv)) {
4765ce56583SJerome Brunet dev_err(dev, "failed to get dai driver: %ld\n",
4775ce56583SJerome Brunet PTR_ERR(dai_drv));
4785ce56583SJerome Brunet return PTR_ERR(dai_drv);
4795ce56583SJerome Brunet }
4805ce56583SJerome Brunet
4815ce56583SJerome Brunet return devm_snd_soc_register_component(dev, &axg_spdifin_component_drv,
4825ce56583SJerome Brunet dai_drv, 1);
4835ce56583SJerome Brunet }
4845ce56583SJerome Brunet
4855ce56583SJerome Brunet static struct platform_driver axg_spdifin_pdrv = {
4865ce56583SJerome Brunet .probe = axg_spdifin_probe,
4875ce56583SJerome Brunet .driver = {
4885ce56583SJerome Brunet .name = "axg-spdifin",
4895ce56583SJerome Brunet .of_match_table = axg_spdifin_of_match,
4905ce56583SJerome Brunet },
4915ce56583SJerome Brunet };
4925ce56583SJerome Brunet module_platform_driver(axg_spdifin_pdrv);
4935ce56583SJerome Brunet
4945ce56583SJerome Brunet MODULE_DESCRIPTION("Amlogic AXG SPDIF Input driver");
4955ce56583SJerome Brunet MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
4965ce56583SJerome Brunet MODULE_LICENSE("GPL v2");
497