^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0 OR MIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (c) 2018 BayLibre, SAS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // Author: Jerome Brunet <jbrunet@baylibre.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <sound/soc-dai.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "axg-tdm-formatter.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define TDMIN_CTRL 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define TDMIN_CTRL_ENABLE BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define TDMIN_CTRL_I2S_MODE BIT(30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define TDMIN_CTRL_RST_OUT BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define TDMIN_CTRL_RST_IN BIT(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define TDMIN_CTRL_WS_INV BIT(25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define TDMIN_CTRL_SEL_SHIFT 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define TDMIN_CTRL_IN_BIT_SKEW_MASK GENMASK(18, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define TDMIN_CTRL_IN_BIT_SKEW(x) ((x) << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define TDMIN_CTRL_LSB_FIRST BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define TDMIN_CTRL_BITNUM_MASK GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define TDMIN_CTRL_BITNUM(x) ((x) << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define TDMIN_SWAP 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define TDMIN_MASK0 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define TDMIN_MASK1 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define TDMIN_MASK2 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define TDMIN_MASK3 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define TDMIN_STAT 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define TDMIN_MUTE_VAL 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define TDMIN_MUTE0 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define TDMIN_MUTE1 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define TDMIN_MUTE2 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define TDMIN_MUTE3 0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static const struct regmap_config axg_tdmin_regmap_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .max_register = TDMIN_MUTE3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static const char * const axg_tdmin_sel_texts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) "IN 0", "IN 1", "IN 2", "IN 3", "IN 4", "IN 5", "IN 6", "IN 7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) "IN 8", "IN 9", "IN 10", "IN 11", "IN 12", "IN 13", "IN 14", "IN 15",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* Change to special mux control to reset dapm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static SOC_ENUM_SINGLE_DECL(axg_tdmin_sel_enum, TDMIN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) TDMIN_CTRL_SEL_SHIFT, axg_tdmin_sel_texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static const struct snd_kcontrol_new axg_tdmin_in_mux =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) SOC_DAPM_ENUM("Input Source", axg_tdmin_sel_enum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static struct snd_soc_dai *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) axg_tdmin_get_be(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct snd_soc_dapm_path *p = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct snd_soc_dai *be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) snd_soc_dapm_widget_for_each_source_path(w, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (!p->connect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (p->source->id == snd_soc_dapm_dai_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return (struct snd_soc_dai *)p->source->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) be = axg_tdmin_get_be(p->source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (be)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return be;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static struct axg_tdm_stream *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) axg_tdmin_get_tdm_stream(struct snd_soc_dapm_widget *w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct snd_soc_dai *be = axg_tdmin_get_be(w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!be)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return be->capture_dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static void axg_tdmin_enable(struct regmap *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* Apply both reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) regmap_update_bits(map, TDMIN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) TDMIN_CTRL_RST_OUT | TDMIN_CTRL_RST_IN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* Clear out reset before in reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) regmap_update_bits(map, TDMIN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) TDMIN_CTRL_RST_OUT, TDMIN_CTRL_RST_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) regmap_update_bits(map, TDMIN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) TDMIN_CTRL_RST_IN, TDMIN_CTRL_RST_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* Actually enable tdmin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) regmap_update_bits(map, TDMIN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) TDMIN_CTRL_ENABLE, TDMIN_CTRL_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static void axg_tdmin_disable(struct regmap *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) regmap_update_bits(map, TDMIN_CTRL, TDMIN_CTRL_ENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int axg_tdmin_prepare(struct regmap *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) const struct axg_tdm_formatter_hw *quirks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct axg_tdm_stream *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned int val, skew = quirks->skew_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Set stream skew */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) switch (ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case SND_SOC_DAIFMT_I2S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case SND_SOC_DAIFMT_DSP_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) skew += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case SND_SOC_DAIFMT_LEFT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) case SND_SOC_DAIFMT_DSP_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) pr_err("Unsupported format: %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) val = TDMIN_CTRL_IN_BIT_SKEW(skew);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* Set stream format mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) switch (ts->iface->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) case SND_SOC_DAIFMT_I2S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) case SND_SOC_DAIFMT_LEFT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case SND_SOC_DAIFMT_RIGHT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) val |= TDMIN_CTRL_I2S_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* If the sample clock is inverted, invert it back for the formatter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (axg_tdm_lrclk_invert(ts->iface->fmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) val |= TDMIN_CTRL_WS_INV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Set the slot width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) val |= TDMIN_CTRL_BITNUM(ts->iface->slot_width - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * The following also reset LSB_FIRST which result in the formatter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * placing the first bit received at bit 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) regmap_update_bits(map, TDMIN_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) (TDMIN_CTRL_IN_BIT_SKEW_MASK | TDMIN_CTRL_WS_INV |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) TDMIN_CTRL_I2S_MODE | TDMIN_CTRL_LSB_FIRST |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) TDMIN_CTRL_BITNUM_MASK), val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* Set static swap mask configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) regmap_write(map, TDMIN_SWAP, 0x76543210);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return axg_tdm_formatter_set_channel_masks(map, ts, TDMIN_MASK0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static const struct snd_soc_dapm_widget axg_tdmin_dapm_widgets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) SND_SOC_DAPM_AIF_IN("IN 3", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) SND_SOC_DAPM_AIF_IN("IN 4", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) SND_SOC_DAPM_AIF_IN("IN 5", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) SND_SOC_DAPM_AIF_IN("IN 6", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) SND_SOC_DAPM_AIF_IN("IN 7", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) SND_SOC_DAPM_AIF_IN("IN 8", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) SND_SOC_DAPM_AIF_IN("IN 9", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) SND_SOC_DAPM_AIF_IN("IN 10", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) SND_SOC_DAPM_AIF_IN("IN 11", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) SND_SOC_DAPM_AIF_IN("IN 12", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) SND_SOC_DAPM_AIF_IN("IN 13", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) SND_SOC_DAPM_AIF_IN("IN 14", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) SND_SOC_DAPM_AIF_IN("IN 15", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &axg_tdmin_in_mux),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) SND_SOC_DAPM_PGA_E("DEC", SND_SOC_NOPM, 0, 0, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) axg_tdm_formatter_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) SND_SOC_DAPM_AIF_OUT("OUT", NULL, 0, SND_SOC_NOPM, 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static const struct snd_soc_dapm_route axg_tdmin_dapm_routes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) { "SRC SEL", "IN 0", "IN 0" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) { "SRC SEL", "IN 1", "IN 1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) { "SRC SEL", "IN 2", "IN 2" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { "SRC SEL", "IN 3", "IN 3" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) { "SRC SEL", "IN 4", "IN 4" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { "SRC SEL", "IN 5", "IN 5" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) { "SRC SEL", "IN 6", "IN 6" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) { "SRC SEL", "IN 7", "IN 7" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) { "SRC SEL", "IN 8", "IN 8" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { "SRC SEL", "IN 9", "IN 9" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) { "SRC SEL", "IN 10", "IN 10" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) { "SRC SEL", "IN 11", "IN 11" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) { "SRC SEL", "IN 12", "IN 12" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { "SRC SEL", "IN 13", "IN 13" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) { "SRC SEL", "IN 14", "IN 14" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) { "SRC SEL", "IN 15", "IN 15" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) { "DEC", NULL, "SRC SEL" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { "OUT", NULL, "DEC" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static const struct snd_soc_component_driver axg_tdmin_component_drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .dapm_widgets = axg_tdmin_dapm_widgets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .num_dapm_widgets = ARRAY_SIZE(axg_tdmin_dapm_widgets),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .dapm_routes = axg_tdmin_dapm_routes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .num_dapm_routes = ARRAY_SIZE(axg_tdmin_dapm_routes),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static const struct axg_tdm_formatter_ops axg_tdmin_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .get_stream = axg_tdmin_get_tdm_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .prepare = axg_tdmin_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .enable = axg_tdmin_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .disable = axg_tdmin_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static const struct axg_tdm_formatter_driver axg_tdmin_drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .component_drv = &axg_tdmin_component_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .regmap_cfg = &axg_tdmin_regmap_cfg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .ops = &axg_tdmin_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .quirks = &(const struct axg_tdm_formatter_hw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .skew_offset = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static const struct of_device_id axg_tdmin_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .compatible = "amlogic,axg-tdmin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .data = &axg_tdmin_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .compatible = "amlogic,g12a-tdmin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .data = &axg_tdmin_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .compatible = "amlogic,sm1-tdmin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .data = &axg_tdmin_drv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }, {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) MODULE_DEVICE_TABLE(of, axg_tdmin_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static struct platform_driver axg_tdmin_pdrv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .probe = axg_tdm_formatter_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .name = "axg-tdmin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) .of_match_table = axg_tdmin_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) module_platform_driver(axg_tdmin_pdrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) MODULE_DESCRIPTION("Amlogic AXG TDM input formatter driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) MODULE_LICENSE("GPL v2");