]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
ASoC: qcom: lpass: Use regmap_field for i2sctl and dmactl registers
authorRohit kumar <rohitkr@codeaurora.org>
Fri, 14 Aug 2020 10:53:01 +0000 (16:23 +0530)
committerMark Brown <broonie@kernel.org>
Mon, 17 Aug 2020 13:39:29 +0000 (14:39 +0100)
I2SCTL and DMACTL registers has different bits alignment for newer
LPASS variants of SC7180 soc. Use REG_FIELD_ID() to define the
reg_fields in platform specific file and removed shifts and mask
macros for such registers from header file.

Signed-off-by: Rohit kumar <rohitkr@codeaurora.org>
Link: https://lore.kernel.org/r/1597402388-14112-6-git-send-email-rohitkr@codeaurora.org
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/qcom/lpass-apq8016.c
sound/soc/qcom/lpass-cpu.c
sound/soc/qcom/lpass-ipq806x.c
sound/soc/qcom/lpass-lpaif-reg.h
sound/soc/qcom/lpass-platform.c
sound/soc/qcom/lpass.h

index fe4c25847022d9e924a722006042d3f374415421..dd9e3dd014f65d47767aee9956152a0423cbe63e 100644 (file)
@@ -240,6 +240,30 @@ static struct lpass_variant apq8016_data = {
        .wrdma_reg_stride       = 0x1000,
        .wrdma_channel_start    = 5,
        .wrdma_channels         = 2,
+       .loopback               = REG_FIELD_ID(0x1000, 15, 15, 4, 0x1000),
+       .spken                  = REG_FIELD_ID(0x1000, 14, 14, 4, 0x1000),
+       .spkmode                = REG_FIELD_ID(0x1000, 10, 13, 4, 0x1000),
+       .spkmono                = REG_FIELD_ID(0x1000, 9, 9, 4, 0x1000),
+       .micen                  = REG_FIELD_ID(0x1000, 8, 8, 4, 0x1000),
+       .micmode                = REG_FIELD_ID(0x1000, 4, 7, 4, 0x1000),
+       .micmono                = REG_FIELD_ID(0x1000, 3, 3, 4, 0x1000),
+       .wssrc                  = REG_FIELD_ID(0x1000, 2, 2, 4, 0x1000),
+       .bitwidth               = REG_FIELD_ID(0x1000, 0, 0, 4, 0x1000),
+
+       .rdma_dyncclk           = REG_FIELD_ID(0x8400, 12, 12, 2, 0x1000),
+       .rdma_bursten           = REG_FIELD_ID(0x8400, 11, 11, 2, 0x1000),
+       .rdma_wpscnt            = REG_FIELD_ID(0x8400, 8, 10, 2, 0x1000),
+       .rdma_intf              = REG_FIELD_ID(0x8400, 4, 7, 2, 0x1000),
+       .rdma_fifowm            = REG_FIELD_ID(0x8400, 1, 3, 2, 0x1000),
+       .rdma_enable            = REG_FIELD_ID(0x8400, 0, 0, 2, 0x1000),
+
+       .wrdma_dyncclk          = REG_FIELD_ID(0xB000, 12, 12, 2, 0x1000),
+       .wrdma_bursten          = REG_FIELD_ID(0xB000, 11, 11, 2, 0x1000),
+       .wrdma_wpscnt           = REG_FIELD_ID(0xB000, 8, 10, 2, 0x1000),
+       .wrdma_intf             = REG_FIELD_ID(0xB000, 4, 7, 2, 0x1000),
+       .wrdma_fifowm           = REG_FIELD_ID(0xB000, 1, 3, 2, 0x1000),
+       .wrdma_enable           = REG_FIELD_ID(0xB000, 0, 0, 2, 0x1000),
+
        .clk_name               = (const char*[]) {
                                   "pcnoc-mport-clk",
                                   "pcnoc-sway-clk",
index f0c7e93063b5937fde26c6f0e15f9e17c57ed825..6b86f16b6ee5742d1ece5549d17f170b084bafc3 100644 (file)
 #define LPASS_CPU_I2S_SD0_1_2_MASK     GENMASK(2, 0)
 #define LPASS_CPU_I2S_SD0_1_2_3_MASK   GENMASK(3, 0)
 
+static int lpass_cpu_init_i2sctl_bitfields(struct device *dev,
+                       struct lpaif_i2sctl *i2sctl, struct regmap *map)
+{
+       struct lpass_data *drvdata = dev_get_drvdata(dev);
+       struct lpass_variant *v = drvdata->variant;
+
+       i2sctl->loopback = devm_regmap_field_alloc(dev, map, v->loopback);
+       i2sctl->spken = devm_regmap_field_alloc(dev, map, v->spken);
+       i2sctl->spkmode = devm_regmap_field_alloc(dev, map, v->spkmode);
+       i2sctl->spkmono = devm_regmap_field_alloc(dev, map, v->spkmono);
+       i2sctl->micen = devm_regmap_field_alloc(dev, map, v->micen);
+       i2sctl->micmode = devm_regmap_field_alloc(dev, map, v->micmode);
+       i2sctl->micmono = devm_regmap_field_alloc(dev, map, v->micmono);
+       i2sctl->wssrc = devm_regmap_field_alloc(dev, map, v->wssrc);
+       i2sctl->bitwidth = devm_regmap_field_alloc(dev, map, v->bitwidth);
+
+       if (IS_ERR(i2sctl->loopback) || IS_ERR(i2sctl->spken) ||
+           IS_ERR(i2sctl->spkmode) || IS_ERR(i2sctl->spkmono) ||
+           IS_ERR(i2sctl->micen) || IS_ERR(i2sctl->micmode) ||
+           IS_ERR(i2sctl->micmono) || IS_ERR(i2sctl->wssrc) ||
+           IS_ERR(i2sctl->bitwidth))
+               return -EINVAL;
+
+       return 0;
+}
+
 static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id,
                unsigned int freq, int dir)
 {
@@ -79,6 +105,8 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
                struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
        struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+       struct lpaif_i2sctl *i2sctl = drvdata->i2sctl;
+       unsigned int id = dai->driver->id;
        snd_pcm_format_t format = params_format(params);
        unsigned int channels = params_channels(params);
        unsigned int rate = params_rate(params);
@@ -92,28 +120,45 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
                return bitwidth;
        }
 
-       regval = LPAIF_I2SCTL_LOOPBACK_DISABLE |
-                       LPAIF_I2SCTL_WSSRC_INTERNAL;
+       ret = regmap_fields_write(i2sctl->loopback, id,
+                                LPAIF_I2SCTL_LOOPBACK_DISABLE);
+       if (ret) {
+               dev_err(dai->dev, "error updating loopback field: %d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_fields_write(i2sctl->wssrc, id,
+                                LPAIF_I2SCTL_WSSRC_INTERNAL);
+       if (ret) {
+               dev_err(dai->dev, "error updating wssrc field: %d\n", ret);
+               return ret;
+       }
 
        switch (bitwidth) {
        case 16:
-               regval |= LPAIF_I2SCTL_BITWIDTH_16;
+               regval = LPAIF_I2SCTL_BITWIDTH_16;
                break;
        case 24:
-               regval |= LPAIF_I2SCTL_BITWIDTH_24;
+               regval = LPAIF_I2SCTL_BITWIDTH_24;
                break;
        case 32:
-               regval |= LPAIF_I2SCTL_BITWIDTH_32;
+               regval = LPAIF_I2SCTL_BITWIDTH_32;
                break;
        default:
                dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth);
                return -EINVAL;
        }
 
+       ret = regmap_fields_write(i2sctl->bitwidth, id, regval);
+       if (ret) {
+               dev_err(dai->dev, "error updating bitwidth field: %d\n", ret);
+               return ret;
+       }
+
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               mode = drvdata->mi2s_playback_sd_mode[dai->driver->id];
+               mode = drvdata->mi2s_playback_sd_mode[id];
        else
-               mode = drvdata->mi2s_capture_sd_mode[dai->driver->id];
+               mode = drvdata->mi2s_capture_sd_mode[id];
 
        if (!mode) {
                dev_err(dai->dev, "no line is assigned\n");
@@ -175,30 +220,42 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream,
        }
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               regval |= LPAIF_I2SCTL_SPKMODE(mode);
-
+               ret = regmap_fields_write(i2sctl->spkmode, id,
+                                        LPAIF_I2SCTL_SPKMODE(mode));
+               if (ret) {
+                       dev_err(dai->dev, "error writing to i2sctl spkr mode: %d\n",
+                               ret);
+                       return ret;
+               }
                if (channels >= 2)
-                       regval |= LPAIF_I2SCTL_SPKMONO_STEREO;
+                       ret = regmap_fields_write(i2sctl->spkmono, id,
+                                                LPAIF_I2SCTL_SPKMONO_STEREO);
                else
-                       regval |= LPAIF_I2SCTL_SPKMONO_MONO;
+                       ret = regmap_fields_write(i2sctl->spkmono, id,
+                                                LPAIF_I2SCTL_SPKMONO_MONO);
        } else {
-               regval |= LPAIF_I2SCTL_MICMODE(mode);
-
+               ret = regmap_fields_write(i2sctl->micmode, id,
+                                        LPAIF_I2SCTL_MICMODE(mode));
+               if (ret) {
+                       dev_err(dai->dev, "error writing to i2sctl mic mode: %d\n",
+                               ret);
+                       return ret;
+               }
                if (channels >= 2)
-                       regval |= LPAIF_I2SCTL_MICMONO_STEREO;
+                       ret = regmap_fields_write(i2sctl->micmono, id,
+                                                LPAIF_I2SCTL_MICMONO_STEREO);
                else
-                       regval |= LPAIF_I2SCTL_MICMONO_MONO;
+                       ret = regmap_fields_write(i2sctl->micmono, id,
+                                                LPAIF_I2SCTL_MICMONO_MONO);
        }
 
-       ret = regmap_write(drvdata->lpaif_map,
-                          LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
-                          regval);
        if (ret) {
-               dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret);
+               dev_err(dai->dev, "error writing to i2sctl channels mode: %d\n",
+                       ret);
                return ret;
        }
 
-       ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id],
+       ret = clk_set_rate(drvdata->mi2s_bit_clk[id],
                           rate * bitwidth * 2);
        if (ret) {
                dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n",
@@ -228,22 +285,20 @@ static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
        struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+       struct lpaif_i2sctl *i2sctl = drvdata->i2sctl;
+       unsigned int id = dai->driver->id;
        int ret;
-       unsigned int val, mask;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               val = LPAIF_I2SCTL_SPKEN_ENABLE;
-               mask = LPAIF_I2SCTL_SPKEN_MASK;
-       } else  {
-               val = LPAIF_I2SCTL_MICEN_ENABLE;
-               mask = LPAIF_I2SCTL_MICEN_MASK;
+               ret = regmap_fields_write(i2sctl->spken, id,
+                                        LPAIF_I2SCTL_SPKEN_ENABLE);
+       } else {
+               ret = regmap_fields_write(i2sctl->micen, id,
+                                        LPAIF_I2SCTL_MICEN_ENABLE);
        }
 
-       ret = regmap_update_bits(drvdata->lpaif_map,
-                       LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id),
-                       mask, val);
        if (ret)
-               dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret);
+               dev_err(dai->dev, "error writing to i2sctl enable: %d\n", ret);
 
        return ret;
 }
@@ -252,25 +307,21 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
                int cmd, struct snd_soc_dai *dai)
 {
        struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+       struct lpaif_i2sctl *i2sctl = drvdata->i2sctl;
+       unsigned int id = dai->driver->id;
        int ret = -EINVAL;
-       unsigned int val, mask;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       val = LPAIF_I2SCTL_SPKEN_ENABLE;
-                       mask = LPAIF_I2SCTL_SPKEN_MASK;
+                       ret = regmap_fields_write(i2sctl->spken, id,
+                                                LPAIF_I2SCTL_SPKEN_ENABLE);
                } else  {
-                       val = LPAIF_I2SCTL_MICEN_ENABLE;
-                       mask = LPAIF_I2SCTL_MICEN_MASK;
+                       ret = regmap_fields_write(i2sctl->micen, id,
+                                                LPAIF_I2SCTL_MICEN_ENABLE);
                }
-
-               ret = regmap_update_bits(drvdata->lpaif_map,
-                               LPAIF_I2SCTL_REG(drvdata->variant,
-                                               dai->driver->id),
-                               mask, val);
                if (ret)
                        dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
                                ret);
@@ -279,17 +330,12 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       val = LPAIF_I2SCTL_SPKEN_DISABLE;
-                       mask = LPAIF_I2SCTL_SPKEN_MASK;
+                       ret = regmap_fields_write(i2sctl->spken, id,
+                                                LPAIF_I2SCTL_SPKEN_DISABLE);
                } else  {
-                       val = LPAIF_I2SCTL_MICEN_DISABLE;
-                       mask = LPAIF_I2SCTL_MICEN_MASK;
+                       ret = regmap_fields_write(i2sctl->micen, id,
+                                                LPAIF_I2SCTL_MICEN_DISABLE);
                }
-
-               ret = regmap_update_bits(drvdata->lpaif_map,
-                               LPAIF_I2SCTL_REG(drvdata->variant,
-                                               dai->driver->id),
-                               mask, val);
                if (ret)
                        dev_err(dai->dev, "error writing to i2sctl reg: %d\n",
                                ret);
@@ -599,6 +645,18 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
                }
        }
 
+       /* Allocation for i2sctl regmap fields */
+       drvdata->i2sctl = devm_kzalloc(&pdev->dev, sizeof(struct lpaif_i2sctl),
+                                       GFP_KERNEL);
+
+       /* Initialize bitfields for dai I2SCTL register */
+       ret = lpass_cpu_init_i2sctl_bitfields(dev, drvdata->i2sctl,
+                                               drvdata->lpaif_map);
+       if (ret) {
+               dev_err(dev, "error init i2sctl field: %d\n", ret);
+               return ret;
+       }
+
        ret = devm_snd_soc_register_component(dev,
                                              &lpass_cpu_comp_driver,
                                              variant->dai_driver,
index b7c05863d6124beb74d2c2d2e6e3030a816159ee..72f09b3a4f6bd1a604e514afd58cb361bec106a3 100644 (file)
@@ -123,6 +123,30 @@ static struct lpass_variant ipq806x_data = {
        .wrdma_reg_stride       = 0x1000,
        .wrdma_channel_start    = 5,
        .wrdma_channels         = 4,
+       .loopback               = REG_FIELD_ID(0x0010, 15, 15, 5, 0x4),
+       .spken                  = REG_FIELD_ID(0x0010, 14, 14, 5, 0x4),
+       .spkmode                = REG_FIELD_ID(0x0010, 10, 13, 5, 0x4),
+       .spkmono                = REG_FIELD_ID(0x0010, 9, 9, 5, 0x4),
+       .micen                  = REG_FIELD_ID(0x0010, 8, 8, 5, 0x4),
+       .micmode                = REG_FIELD_ID(0x0010, 4, 7, 5, 0x4),
+       .micmono                = REG_FIELD_ID(0x0010, 3, 3, 5, 0x4),
+       .wssrc                  = REG_FIELD_ID(0x0010, 2, 2, 5, 0x4),
+       .bitwidth               = REG_FIELD_ID(0x0010, 0, 0, 5, 0x4),
+
+       .rdma_dyncclk           = REG_FIELD_ID(0x6000, 12, 12, 4, 0x1000),
+       .rdma_bursten           = REG_FIELD_ID(0x6000, 11, 11, 4, 0x1000),
+       .rdma_wpscnt            = REG_FIELD_ID(0x6000, 8, 10, 4, 0x1000),
+       .rdma_intf              = REG_FIELD_ID(0x6000, 4, 7, 4, 0x1000),
+       .rdma_fifowm            = REG_FIELD_ID(0x6000, 1, 3, 4, 0x1000),
+       .rdma_enable            = REG_FIELD_ID(0x6000, 0, 0, 4, 0x1000),
+
+       .wrdma_dyncclk          = REG_FIELD_ID(0xB000, 12, 12, 4, 0x1000),
+       .wrdma_bursten          = REG_FIELD_ID(0xB000, 11, 11, 4, 0x1000),
+       .wrdma_wpscnt           = REG_FIELD_ID(0xB000, 8, 10, 4, 0x1000),
+       .wrdma_intf             = REG_FIELD_ID(0xB000, 4, 7, 4, 0x1000),
+       .wrdma_fifowm           = REG_FIELD_ID(0xB000, 1, 3, 4, 0x1000),
+       .wrdma_enable           = REG_FIELD_ID(0xB000, 0, 0, 4, 0x1000),
+
        .dai_driver             = &ipq806x_lpass_cpu_dai_driver,
        .num_dai                = 1,
        .dai_osr_clk_names      = (const char *[]) {
index 72a3e2f69572b991b52b051f2cdb778f310d508e..5258e60d364607c794ffb18c8aaf45b24ce15c05 100644 (file)
        (v->i2sctrl_reg_base + (addr) + v->i2sctrl_reg_stride * (port))
 
 #define LPAIF_I2SCTL_REG(v, port)      LPAIF_I2SCTL_REG_ADDR(v, 0x0, (port))
-#define LPAIF_I2SCTL_LOOPBACK_MASK     0x8000
-#define LPAIF_I2SCTL_LOOPBACK_SHIFT    15
-#define LPAIF_I2SCTL_LOOPBACK_DISABLE  (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
-#define LPAIF_I2SCTL_LOOPBACK_ENABLE   (1 << LPAIF_I2SCTL_LOOPBACK_SHIFT)
 
-#define LPAIF_I2SCTL_SPKEN_MASK                0x4000
-#define LPAIF_I2SCTL_SPKEN_SHIFT       14
-#define LPAIF_I2SCTL_SPKEN_DISABLE     (0 << LPAIF_I2SCTL_SPKEN_SHIFT)
-#define LPAIF_I2SCTL_SPKEN_ENABLE      (1 << LPAIF_I2SCTL_SPKEN_SHIFT)
+#define LPAIF_I2SCTL_LOOPBACK_DISABLE  0
+#define LPAIF_I2SCTL_LOOPBACK_ENABLE   1
+
+#define LPAIF_I2SCTL_SPKEN_DISABLE     0
+#define LPAIF_I2SCTL_SPKEN_ENABLE      1
 
 #define LPAIF_I2SCTL_MODE_NONE         0
 #define LPAIF_I2SCTL_MODE_SD0          1
 #define LPAIF_I2SCTL_MODE_QUAD23       6
 #define LPAIF_I2SCTL_MODE_6CH          7
 #define LPAIF_I2SCTL_MODE_8CH          8
+#define LPAIF_I2SCTL_MODE_10CH         9
+#define LPAIF_I2SCTL_MODE_12CH         10
+#define LPAIF_I2SCTL_MODE_14CH         11
+#define LPAIF_I2SCTL_MODE_16CH         12
+#define LPAIF_I2SCTL_MODE_SD4          13
+#define LPAIF_I2SCTL_MODE_SD5          14
+#define LPAIF_I2SCTL_MODE_SD6          15
+#define LPAIF_I2SCTL_MODE_SD7          16
+#define LPAIF_I2SCTL_MODE_QUAD45       17
+#define LPAIF_I2SCTL_MODE_QUAD47       18
+#define LPAIF_I2SCTL_MODE_8CH_2                19
 
-#define LPAIF_I2SCTL_SPKMODE_MASK      0x3C00
-#define LPAIF_I2SCTL_SPKMODE_SHIFT     10
-#define LPAIF_I2SCTL_SPKMODE(mode)     ((mode) << LPAIF_I2SCTL_SPKMODE_SHIFT)
+#define LPAIF_I2SCTL_SPKMODE(mode)     mode
 
-#define LPAIF_I2SCTL_SPKMONO_MASK      0x0200
-#define LPAIF_I2SCTL_SPKMONO_SHIFT     9
-#define LPAIF_I2SCTL_SPKMONO_STEREO    (0 << LPAIF_I2SCTL_SPKMONO_SHIFT)
-#define LPAIF_I2SCTL_SPKMONO_MONO      (1 << LPAIF_I2SCTL_SPKMONO_SHIFT)
+#define LPAIF_I2SCTL_SPKMONO_STEREO    0
+#define LPAIF_I2SCTL_SPKMONO_MONO      1
 
-#define LPAIF_I2SCTL_MICEN_MASK                GENMASK(8, 8)
-#define LPAIF_I2SCTL_MICEN_SHIFT       8
-#define LPAIF_I2SCTL_MICEN_DISABLE     (0 << LPAIF_I2SCTL_MICEN_SHIFT)
-#define LPAIF_I2SCTL_MICEN_ENABLE      (1 << LPAIF_I2SCTL_MICEN_SHIFT)
+#define LPAIF_I2SCTL_MICEN_DISABLE     0
+#define LPAIF_I2SCTL_MICEN_ENABLE      1
 
-#define LPAIF_I2SCTL_MICMODE_MASK      GENMASK(7, 4)
-#define LPAIF_I2SCTL_MICMODE_SHIFT     4
-#define LPAIF_I2SCTL_MICMODE(mode)     ((mode) << LPAIF_I2SCTL_MICMODE_SHIFT)
+#define LPAIF_I2SCTL_MICMODE(mode)     mode
 
-#define LPAIF_I2SCTL_MIMONO_MASK       GENMASK(3, 3)
-#define LPAIF_I2SCTL_MICMONO_SHIFT     3
-#define LPAIF_I2SCTL_MICMONO_STEREO    (0 << LPAIF_I2SCTL_MICMONO_SHIFT)
-#define LPAIF_I2SCTL_MICMONO_MONO      (1 << LPAIF_I2SCTL_MICMONO_SHIFT)
+#define LPAIF_I2SCTL_MICMONO_STEREO    0
+#define LPAIF_I2SCTL_MICMONO_MONO      1
 
-#define LPAIF_I2SCTL_WSSRC_MASK                0x0004
-#define LPAIF_I2SCTL_WSSRC_SHIFT       2
-#define LPAIF_I2SCTL_WSSRC_INTERNAL    (0 << LPAIF_I2SCTL_WSSRC_SHIFT)
-#define LPAIF_I2SCTL_WSSRC_EXTERNAL    (1 << LPAIF_I2SCTL_WSSRC_SHIFT)
+#define LPAIF_I2SCTL_WSSRC_INTERNAL    0
+#define LPAIF_I2SCTL_WSSRC_EXTERNAL    1
 
-#define LPAIF_I2SCTL_BITWIDTH_MASK     0x0003
-#define LPAIF_I2SCTL_BITWIDTH_SHIFT    0
-#define LPAIF_I2SCTL_BITWIDTH_16       (0 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
-#define LPAIF_I2SCTL_BITWIDTH_24       (1 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
-#define LPAIF_I2SCTL_BITWIDTH_32       (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT)
+#define LPAIF_I2SCTL_BITWIDTH_16       0
+#define LPAIF_I2SCTL_BITWIDTH_24       1
+#define LPAIF_I2SCTL_BITWIDTH_32       2
 
 /* LPAIF IRQ */
 #define LPAIF_IRQ_REG_ADDR(v, addr, port) \
 #define        LPAIF_DMAPER_REG(v, chan, dir) __LPAIF_DMA_REG(v, chan, dir, PER)
 #define        LPAIF_DMAPERCNT_REG(v, chan, dir) __LPAIF_DMA_REG(v, chan, dir, PERCNT)
 
-#define LPAIF_DMACTL_BURSTEN_MASK      0x800
-#define LPAIF_DMACTL_BURSTEN_SHIFT     11
-#define LPAIF_DMACTL_BURSTEN_SINGLE    (0 << LPAIF_DMACTL_BURSTEN_SHIFT)
-#define LPAIF_DMACTL_BURSTEN_INCR4     (1 << LPAIF_DMACTL_BURSTEN_SHIFT)
-
-#define LPAIF_DMACTL_WPSCNT_MASK       0x700
-#define LPAIF_DMACTL_WPSCNT_SHIFT      8
-#define LPAIF_DMACTL_WPSCNT_ONE        (0 << LPAIF_DMACTL_WPSCNT_SHIFT)
-#define LPAIF_DMACTL_WPSCNT_TWO        (1 << LPAIF_DMACTL_WPSCNT_SHIFT)
-#define LPAIF_DMACTL_WPSCNT_THREE      (2 << LPAIF_DMACTL_WPSCNT_SHIFT)
-#define LPAIF_DMACTL_WPSCNT_FOUR       (3 << LPAIF_DMACTL_WPSCNT_SHIFT)
-#define LPAIF_DMACTL_WPSCNT_SIX        (5 << LPAIF_DMACTL_WPSCNT_SHIFT)
-#define LPAIF_DMACTL_WPSCNT_EIGHT      (7 << LPAIF_DMACTL_WPSCNT_SHIFT)
-
-#define LPAIF_DMACTL_AUDINTF_MASK      0x0F0
-#define LPAIF_DMACTL_AUDINTF_SHIFT     4
-#define LPAIF_DMACTL_AUDINTF(id)       (id << LPAIF_DMACTL_AUDINTF_SHIFT)
-
-#define LPAIF_DMACTL_FIFOWM_MASK       0x00E
-#define LPAIF_DMACTL_FIFOWM_SHIFT      1
-#define LPAIF_DMACTL_FIFOWM_1          (0 << LPAIF_DMACTL_FIFOWM_SHIFT)
-#define LPAIF_DMACTL_FIFOWM_2          (1 << LPAIF_DMACTL_FIFOWM_SHIFT)
-#define LPAIF_DMACTL_FIFOWM_3          (2 << LPAIF_DMACTL_FIFOWM_SHIFT)
-#define LPAIF_DMACTL_FIFOWM_4          (3 << LPAIF_DMACTL_FIFOWM_SHIFT)
-#define LPAIF_DMACTL_FIFOWM_5          (4 << LPAIF_DMACTL_FIFOWM_SHIFT)
-#define LPAIF_DMACTL_FIFOWM_6          (5 << LPAIF_DMACTL_FIFOWM_SHIFT)
-#define LPAIF_DMACTL_FIFOWM_7          (6 << LPAIF_DMACTL_FIFOWM_SHIFT)
-#define LPAIF_DMACTL_FIFOWM_8          (7 << LPAIF_DMACTL_FIFOWM_SHIFT)
-
-#define LPAIF_DMACTL_ENABLE_MASK       0x1
-#define LPAIF_DMACTL_ENABLE_SHIFT      0
-#define LPAIF_DMACTL_ENABLE_OFF        (0 << LPAIF_DMACTL_ENABLE_SHIFT)
-#define LPAIF_DMACTL_ENABLE_ON         (1 << LPAIF_DMACTL_ENABLE_SHIFT)
-
-#define LPAIF_DMACTL_DYNCLK_MASK       BIT(12)
-#define LPAIF_DMACTL_DYNCLK_SHIFT      12
-#define LPAIF_DMACTL_DYNCLK_OFF        (0 << LPAIF_DMACTL_DYNCLK_SHIFT)
-#define LPAIF_DMACTL_DYNCLK_ON         (1 << LPAIF_DMACTL_DYNCLK_SHIFT)
+#define LPAIF_DMACTL_BURSTEN_SINGLE    0
+#define LPAIF_DMACTL_BURSTEN_INCR4     1
+
+#define LPAIF_DMACTL_WPSCNT_ONE                0
+#define LPAIF_DMACTL_WPSCNT_TWO                1
+#define LPAIF_DMACTL_WPSCNT_THREE      2
+#define LPAIF_DMACTL_WPSCNT_FOUR       3
+#define LPAIF_DMACTL_WPSCNT_SIX                5
+#define LPAIF_DMACTL_WPSCNT_EIGHT      7
+#define LPAIF_DMACTL_WPSCNT_TEN                9
+#define LPAIF_DMACTL_WPSCNT_TWELVE     11
+#define LPAIF_DMACTL_WPSCNT_FOURTEEN   13
+#define LPAIF_DMACTL_WPSCNT_SIXTEEN    15
+
+#define LPAIF_DMACTL_AUDINTF(id)       id
+
+#define LPAIF_DMACTL_FIFOWM_1          0
+#define LPAIF_DMACTL_FIFOWM_2          1
+#define LPAIF_DMACTL_FIFOWM_3          2
+#define LPAIF_DMACTL_FIFOWM_4          3
+#define LPAIF_DMACTL_FIFOWM_5          4
+#define LPAIF_DMACTL_FIFOWM_6          5
+#define LPAIF_DMACTL_FIFOWM_7          6
+#define LPAIF_DMACTL_FIFOWM_8          7
+#define LPAIF_DMACTL_FIFOWM_9          8
+#define LPAIF_DMACTL_FIFOWM_10         9
+#define LPAIF_DMACTL_FIFOWM_11         10
+#define LPAIF_DMACTL_FIFOWM_12         11
+#define LPAIF_DMACTL_FIFOWM_13         12
+#define LPAIF_DMACTL_FIFOWM_14         13
+#define LPAIF_DMACTL_FIFOWM_15         14
+#define LPAIF_DMACTL_FIFOWM_16         15
+#define LPAIF_DMACTL_FIFOWM_17         16
+#define LPAIF_DMACTL_FIFOWM_18         17
+#define LPAIF_DMACTL_FIFOWM_19         18
+#define LPAIF_DMACTL_FIFOWM_20         19
+#define LPAIF_DMACTL_FIFOWM_21         20
+#define LPAIF_DMACTL_FIFOWM_22         21
+#define LPAIF_DMACTL_FIFOWM_23         22
+#define LPAIF_DMACTL_FIFOWM_24         23
+#define LPAIF_DMACTL_FIFOWM_25         24
+#define LPAIF_DMACTL_FIFOWM_26         25
+#define LPAIF_DMACTL_FIFOWM_27         26
+#define LPAIF_DMACTL_FIFOWM_28         27
+#define LPAIF_DMACTL_FIFOWM_29         28
+#define LPAIF_DMACTL_FIFOWM_30         29
+#define LPAIF_DMACTL_FIFOWM_31         30
+#define LPAIF_DMACTL_FIFOWM_32         31
+
+#define LPAIF_DMACTL_ENABLE_OFF                0
+#define LPAIF_DMACTL_ENABLE_ON         1
+
+#define LPAIF_DMACTL_DYNCLK_OFF                0
+#define LPAIF_DMACTL_DYNCLK_ON         1
+
 #endif /* __LPASS_LPAIF_REG_H__ */
index 315feda414d9052540a5e2c4a9d6b7a2278a31ce..35aead1bfdf86f9ab1caf6b526b8da602fc875a9 100644 (file)
@@ -50,6 +50,53 @@ static const struct snd_pcm_hardware lpass_platform_pcm_hardware = {
        .fifo_size              =       0,
 };
 
+static int lpass_platform_alloc_dmactl_fields(struct device *dev,
+                                        struct regmap *map)
+{
+       struct lpass_data *drvdata = dev_get_drvdata(dev);
+       struct lpass_variant *v = drvdata->variant;
+       struct lpaif_dmactl *rd_dmactl, *wr_dmactl;
+
+       drvdata->rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
+                                         GFP_KERNEL);
+       if (drvdata->rd_dmactl == NULL)
+               return -ENOMEM;
+
+       drvdata->wr_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
+                                         GFP_KERNEL);
+       if (drvdata->wr_dmactl == NULL)
+               return -ENOMEM;
+
+       rd_dmactl = drvdata->rd_dmactl;
+       wr_dmactl = drvdata->wr_dmactl;
+
+       rd_dmactl->bursten = devm_regmap_field_alloc(dev, map, v->rdma_bursten);
+       rd_dmactl->wpscnt = devm_regmap_field_alloc(dev, map, v->rdma_wpscnt);
+       rd_dmactl->fifowm = devm_regmap_field_alloc(dev, map, v->rdma_fifowm);
+       rd_dmactl->intf = devm_regmap_field_alloc(dev, map, v->rdma_intf);
+       rd_dmactl->enable = devm_regmap_field_alloc(dev, map, v->rdma_enable);
+       rd_dmactl->dyncclk = devm_regmap_field_alloc(dev, map, v->rdma_dyncclk);
+
+       if (IS_ERR(rd_dmactl->bursten) || IS_ERR(rd_dmactl->wpscnt) ||
+           IS_ERR(rd_dmactl->fifowm) || IS_ERR(rd_dmactl->intf) ||
+           IS_ERR(rd_dmactl->enable) || IS_ERR(rd_dmactl->dyncclk))
+               return -EINVAL;
+
+       wr_dmactl->bursten = devm_regmap_field_alloc(dev, map, v->wrdma_bursten);
+       wr_dmactl->wpscnt = devm_regmap_field_alloc(dev, map, v->wrdma_wpscnt);
+       wr_dmactl->fifowm = devm_regmap_field_alloc(dev, map, v->wrdma_fifowm);
+       wr_dmactl->intf = devm_regmap_field_alloc(dev, map, v->wrdma_intf);
+       wr_dmactl->enable = devm_regmap_field_alloc(dev, map, v->wrdma_enable);
+       wr_dmactl->dyncclk = devm_regmap_field_alloc(dev, map, v->wrdma_dyncclk);
+
+       if (IS_ERR(wr_dmactl->bursten) || IS_ERR(wr_dmactl->wpscnt) ||
+           IS_ERR(wr_dmactl->fifowm) || IS_ERR(wr_dmactl->intf) ||
+           IS_ERR(wr_dmactl->enable) || IS_ERR(wr_dmactl->dyncclk))
+               return -EINVAL;
+
+       return 0;
+}
+
 static int lpass_platform_pcmops_open(struct snd_soc_component *component,
                                      struct snd_pcm_substream *substream)
 {
@@ -134,11 +181,18 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
        snd_pcm_format_t format = params_format(params);
        unsigned int channels = params_channels(params);
        unsigned int regval;
-       int ch, dir = substream->stream;
+       struct lpaif_dmactl *dmactl;
+       int id, dir = substream->stream;
        int bitwidth;
        int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start;
 
-       ch = pcm_data->dma_ch;
+       if (dir ==  SNDRV_PCM_STREAM_PLAYBACK) {
+               dmactl = drvdata->rd_dmactl;
+               id = pcm_data->dma_ch;
+       } else {
+               dmactl = drvdata->wr_dmactl;
+               id = pcm_data->dma_ch - v->wrdma_channel_start;
+       }
 
        bitwidth = snd_pcm_format_width(format);
        if (bitwidth < 0) {
@@ -147,25 +201,39 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
                return bitwidth;
        }
 
-       regval = LPAIF_DMACTL_BURSTEN_INCR4 |
-                       LPAIF_DMACTL_AUDINTF(dma_port) |
-                       LPAIF_DMACTL_FIFOWM_8;
+       ret = regmap_fields_write(dmactl->bursten, id, LPAIF_DMACTL_BURSTEN_INCR4);
+       if (ret) {
+               dev_err(soc_runtime->dev, "error updating bursten field: %d\n", ret);
+               return ret;
+       }
+
+       regmap_fields_write(dmactl->fifowm, id, LPAIF_DMACTL_FIFOWM_8);
+       if (ret) {
+               dev_err(soc_runtime->dev, "error updating fifowm field: %d\n", ret);
+               return ret;
+       }
+
+       regmap_fields_write(dmactl->intf, id, LPAIF_DMACTL_AUDINTF(dma_port));
+       if (ret) {
+               dev_err(soc_runtime->dev, "error updating audintf field: %d\n", ret);
+               return ret;
+       }
 
        switch (bitwidth) {
        case 16:
                switch (channels) {
                case 1:
                case 2:
-                       regval |= LPAIF_DMACTL_WPSCNT_ONE;
+                       regval = LPAIF_DMACTL_WPSCNT_ONE;
                        break;
                case 4:
-                       regval |= LPAIF_DMACTL_WPSCNT_TWO;
+                       regval = LPAIF_DMACTL_WPSCNT_TWO;
                        break;
                case 6:
-                       regval |= LPAIF_DMACTL_WPSCNT_THREE;
+                       regval = LPAIF_DMACTL_WPSCNT_THREE;
                        break;
                case 8:
-                       regval |= LPAIF_DMACTL_WPSCNT_FOUR;
+                       regval = LPAIF_DMACTL_WPSCNT_FOUR;
                        break;
                default:
                        dev_err(soc_runtime->dev,
@@ -178,19 +246,19 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
        case 32:
                switch (channels) {
                case 1:
-                       regval |= LPAIF_DMACTL_WPSCNT_ONE;
+                       regval = LPAIF_DMACTL_WPSCNT_ONE;
                        break;
                case 2:
-                       regval |= LPAIF_DMACTL_WPSCNT_TWO;
+                       regval = LPAIF_DMACTL_WPSCNT_TWO;
                        break;
                case 4:
-                       regval |= LPAIF_DMACTL_WPSCNT_FOUR;
+                       regval = LPAIF_DMACTL_WPSCNT_FOUR;
                        break;
                case 6:
-                       regval |= LPAIF_DMACTL_WPSCNT_SIX;
+                       regval = LPAIF_DMACTL_WPSCNT_SIX;
                        break;
                case 8:
-                       regval |= LPAIF_DMACTL_WPSCNT_EIGHT;
+                       regval = LPAIF_DMACTL_WPSCNT_EIGHT;
                        break;
                default:
                        dev_err(soc_runtime->dev,
@@ -205,10 +273,9 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
                return -EINVAL;
        }
 
-       ret = regmap_write(drvdata->lpaif_map,
-                       LPAIF_DMACTL_REG(v, ch, dir), regval);
+       ret = regmap_fields_write(dmactl->wpscnt, id, regval);
        if (ret) {
-               dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
+               dev_err(soc_runtime->dev, "error writing to dmactl reg: %d\n",
                        ret);
                return ret;
        }
@@ -245,9 +312,17 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
        struct snd_pcm_runtime *rt = substream->runtime;
        struct lpass_pcm_data *pcm_data = rt->private_data;
        struct lpass_variant *v = drvdata->variant;
-       int ret, ch, dir = substream->stream;
+       struct lpaif_dmactl *dmactl;
+       int ret, id, ch, dir = substream->stream;
 
        ch = pcm_data->dma_ch;
+       if (dir ==  SNDRV_PCM_STREAM_PLAYBACK) {
+               dmactl = drvdata->rd_dmactl;
+               id = pcm_data->dma_ch;
+       } else {
+               dmactl = drvdata->wr_dmactl;
+               id = pcm_data->dma_ch - v->wrdma_channel_start;
+       }
 
        ret = regmap_write(drvdata->lpaif_map,
                        LPAIF_DMABASE_REG(v, ch, dir),
@@ -276,9 +351,7 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
                return ret;
        }
 
-       ret = regmap_update_bits(drvdata->lpaif_map,
-                       LPAIF_DMACTL_REG(v, ch, dir),
-                       LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON);
+       ret = regmap_fields_write(dmactl->enable, id, LPAIF_DMACTL_ENABLE_ON);
        if (ret) {
                dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
                        ret);
@@ -297,9 +370,18 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
        struct snd_pcm_runtime *rt = substream->runtime;
        struct lpass_pcm_data *pcm_data = rt->private_data;
        struct lpass_variant *v = drvdata->variant;
-       int ret, ch, dir = substream->stream;
+       struct lpaif_dmactl *dmactl;
+       int ret, ch, id;
+       int dir = substream->stream;
 
        ch = pcm_data->dma_ch;
+       if (dir ==  SNDRV_PCM_STREAM_PLAYBACK) {
+               dmactl = drvdata->rd_dmactl;
+               id = pcm_data->dma_ch;
+       } else {
+               dmactl = drvdata->wr_dmactl;
+               id = pcm_data->dma_ch - v->wrdma_channel_start;
+       }
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -325,10 +407,8 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
                        return ret;
                }
 
-               ret = regmap_update_bits(drvdata->lpaif_map,
-                               LPAIF_DMACTL_REG(v, ch, dir),
-                               LPAIF_DMACTL_ENABLE_MASK,
-                               LPAIF_DMACTL_ENABLE_ON);
+               ret = regmap_fields_write(dmactl->enable, id,
+                                        LPAIF_DMACTL_ENABLE_ON);
                if (ret) {
                        dev_err(soc_runtime->dev,
                                "error writing to rdmactl reg: %d\n", ret);
@@ -338,10 +418,8 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               ret = regmap_update_bits(drvdata->lpaif_map,
-                               LPAIF_DMACTL_REG(v, ch, dir),
-                               LPAIF_DMACTL_ENABLE_MASK,
-                               LPAIF_DMACTL_ENABLE_OFF);
+               ret = regmap_fields_write(dmactl->enable, id,
+                                        LPAIF_DMACTL_ENABLE_OFF);
                if (ret) {
                        dev_err(soc_runtime->dev,
                                "error writing to rdmactl reg: %d\n", ret);
@@ -580,6 +658,13 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
                return ret;
        }
 
+       ret = lpass_platform_alloc_dmactl_fields(&pdev->dev,
+                                                drvdata->lpaif_map);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       "error initializing dmactl fields: %d\n", ret);
+               return ret;
+       }
 
        return devm_snd_soc_register_component(&pdev->dev,
                        &lpass_component_driver, NULL, 0);
index 450020e5f3029b81a8f3eb8635a493f71e19f376..51c9991a0edf4b1af68647683695d563c7456774 100644 (file)
 #define LPASS_MAX_MI2S_PORTS                   (8)
 #define LPASS_MAX_DMA_CHANNELS                 (8)
 
+struct lpaif_i2sctl {
+       struct regmap_field *loopback;
+       struct regmap_field *spken;
+       struct regmap_field *spkmode;
+       struct regmap_field *spkmono;
+       struct regmap_field *micen;
+       struct regmap_field *micmode;
+       struct regmap_field *micmono;
+       struct regmap_field *wssrc;
+       struct regmap_field *bitwidth;
+};
+
+
+struct lpaif_dmactl {
+       struct regmap_field *bursten;
+       struct regmap_field *wpscnt;
+       struct regmap_field *intf;
+       struct regmap_field *fifowm;
+       struct regmap_field *enable;
+       struct regmap_field *dyncclk;
+};
+
 /* Both the CPU DAI and platform drivers will access this data */
 struct lpass_data {
 
@@ -55,6 +77,10 @@ struct lpass_data {
        struct clk_bulk_data *clks;
        int num_clks;
 
+       /* Regmap fields of I2SCTL & DMACTL registers bitfields */
+       struct lpaif_i2sctl *i2sctl;
+       struct lpaif_dmactl *rd_dmactl;
+       struct lpaif_dmactl *wr_dmactl;
 };
 
 /* Vairant data per each SOC */
@@ -72,6 +98,33 @@ struct lpass_variant {
        u32     wrdma_reg_stride;
        u32     wrdma_channels;
 
+       /* I2SCTL Register fields */
+       struct reg_field loopback;
+       struct reg_field spken;
+       struct reg_field spkmode;
+       struct reg_field spkmono;
+       struct reg_field micen;
+       struct reg_field micmode;
+       struct reg_field micmono;
+       struct reg_field wssrc;
+       struct reg_field bitwidth;
+
+       /* RD_DMA Register fields */
+       struct reg_field rdma_bursten;
+       struct reg_field rdma_wpscnt;
+       struct reg_field rdma_intf;
+       struct reg_field rdma_fifowm;
+       struct reg_field rdma_enable;
+       struct reg_field rdma_dyncclk;
+
+       /* WR_DMA Register fields */
+       struct reg_field wrdma_bursten;
+       struct reg_field wrdma_wpscnt;
+       struct reg_field wrdma_intf;
+       struct reg_field wrdma_fifowm;
+       struct reg_field wrdma_enable;
+       struct reg_field wrdma_dyncclk;
+
        /**
         * on SOCs like APQ8016 the channel control bits start
         * at different offset to ipq806x