^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "lpass-lpaif-reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "lpass.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define DRV_NAME "lpass-platform"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct lpass_pcm_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int dma_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) int i2s_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define LPASS_PLATFORM_BUFFER_SIZE (24 * 2 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define LPASS_PLATFORM_PERIODS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static const struct snd_pcm_hardware lpass_platform_pcm_hardware = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) .info = SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) SNDRV_PCM_INFO_PAUSE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) SNDRV_PCM_INFO_RESUME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .formats = SNDRV_PCM_FMTBIT_S16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) SNDRV_PCM_FMTBIT_S24 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) SNDRV_PCM_FMTBIT_S32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .rates = SNDRV_PCM_RATE_8000_192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .rate_max = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .channels_max = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .buffer_bytes_max = LPASS_PLATFORM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .period_bytes_max = LPASS_PLATFORM_BUFFER_SIZE /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) LPASS_PLATFORM_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .period_bytes_min = LPASS_PLATFORM_BUFFER_SIZE /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) LPASS_PLATFORM_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .periods_min = LPASS_PLATFORM_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .periods_max = LPASS_PLATFORM_PERIODS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .fifo_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static int lpass_platform_alloc_dmactl_fields(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct regmap *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct lpass_data *drvdata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct lpaif_dmactl *rd_dmactl, *wr_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) drvdata->rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (drvdata->rd_dmactl == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) drvdata->wr_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (drvdata->wr_dmactl == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) rd_dmactl = drvdata->rd_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) wr_dmactl = drvdata->wr_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) rval = devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) &v->rdma_intf, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (rval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return devm_regmap_field_bulk_alloc(dev, map, &wr_dmactl->intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) &v->wrdma_intf, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static int lpass_platform_alloc_hdmidmactl_fields(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct regmap *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct lpass_data *drvdata = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct lpaif_dmactl *rd_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (rd_dmactl == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) drvdata->hdmi_rd_dmactl = rd_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->bursten,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) &v->hdmi_rdma_bursten, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int lpass_platform_pcmops_open(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int ret, dma_ch, dir = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct lpass_pcm_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned int dai_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) component->id = dai_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) data = kzalloc(sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) data->i2s_port = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) runtime->private_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (v->alloc_dma_channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dma_ch = v->alloc_dma_channel(drvdata, dir, dai_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) dma_ch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (dma_ch < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return dma_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (cpu_dai->driver->id == LPASS_DP_RX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) map = drvdata->hdmiif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) drvdata->hdmi_substream[dma_ch] = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) map = drvdata->lpaif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) drvdata->substream[dma_ch] = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) data->dma_ch = dma_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ret = regmap_write(map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) LPAIF_DMACTL_REG(v, dma_ch, dir, data->i2s_port), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) "error writing to rdmactl reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ret = snd_pcm_hw_constraint_integer(runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) SNDRV_PCM_HW_PARAM_PERIODS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dev_err(soc_runtime->dev, "setting constraints failed: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int lpass_platform_pcmops_close(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct lpass_pcm_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned int dai_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) data = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (dai_id == LPASS_DP_RX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) drvdata->hdmi_substream[data->dma_ch] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) drvdata->substream[data->dma_ch] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (v->free_dma_channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) v->free_dma_channel(drvdata, data->dma_ch, dai_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct snd_pcm_runtime *rt = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct lpass_pcm_data *pcm_data = rt->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) snd_pcm_format_t format = params_format(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) unsigned int channels = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) unsigned int regval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct lpaif_dmactl *dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int id, dir = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int bitwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) unsigned int dai_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) id = pcm_data->dma_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (dai_id == LPASS_DP_RX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) dmactl = drvdata->hdmi_rd_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) dmactl = drvdata->rd_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) dmactl = drvdata->wr_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) id = pcm_data->dma_ch - v->wrdma_channel_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) bitwidth = snd_pcm_format_width(format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (bitwidth < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) dev_err(soc_runtime->dev, "invalid bit width given: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) bitwidth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return bitwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ret = regmap_fields_write(dmactl->bursten, id, LPAIF_DMACTL_BURSTEN_INCR4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) dev_err(soc_runtime->dev, "error updating bursten field: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) ret = regmap_fields_write(dmactl->fifowm, id, LPAIF_DMACTL_FIFOWM_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) dev_err(soc_runtime->dev, "error updating fifowm field: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) switch (dai_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) case LPASS_DP_RX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ret = regmap_fields_write(dmactl->burst8, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) LPAIF_DMACTL_BURSTEN_INCR4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) dev_err(soc_runtime->dev, "error updating burst8en field: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret = regmap_fields_write(dmactl->burst16, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) LPAIF_DMACTL_BURSTEN_INCR4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) dev_err(soc_runtime->dev, "error updating burst16en field: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ret = regmap_fields_write(dmactl->dynburst, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) LPAIF_DMACTL_BURSTEN_INCR4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) dev_err(soc_runtime->dev, "error updating dynbursten field: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case MI2S_PRIMARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) case MI2S_SECONDARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) case MI2S_TERTIARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case MI2S_QUATERNARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) case MI2S_QUINARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ret = regmap_fields_write(dmactl->intf, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) LPAIF_DMACTL_AUDINTF(dma_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dev_err(soc_runtime->dev, "error updating audio interface field: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) dev_err(soc_runtime->dev, "%s: invalid interface: %d\n", __func__, dai_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) switch (bitwidth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) switch (channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) regval = LPAIF_DMACTL_WPSCNT_ONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) regval = LPAIF_DMACTL_WPSCNT_TWO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) regval = LPAIF_DMACTL_WPSCNT_THREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) regval = LPAIF_DMACTL_WPSCNT_FOUR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) bitwidth, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) switch (channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) regval = LPAIF_DMACTL_WPSCNT_ONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) regval = (dai_id == LPASS_DP_RX ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) LPAIF_DMACTL_WPSCNT_ONE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) LPAIF_DMACTL_WPSCNT_TWO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) regval = (dai_id == LPASS_DP_RX ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) LPAIF_DMACTL_WPSCNT_TWO :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) LPAIF_DMACTL_WPSCNT_FOUR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) regval = (dai_id == LPASS_DP_RX ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) LPAIF_DMACTL_WPSCNT_THREE :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) LPAIF_DMACTL_WPSCNT_SIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) regval = (dai_id == LPASS_DP_RX ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) LPAIF_DMACTL_WPSCNT_FOUR :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) LPAIF_DMACTL_WPSCNT_EIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) bitwidth, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) bitwidth, channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ret = regmap_fields_write(dmactl->wpscnt, id, regval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) dev_err(soc_runtime->dev, "error writing to dmactl reg: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static int lpass_platform_pcmops_hw_free(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct snd_pcm_runtime *rt = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct lpass_pcm_data *pcm_data = rt->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) unsigned int dai_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (dai_id == LPASS_DP_RX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) map = drvdata->hdmiif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) map = drvdata->lpaif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream, dai_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ret = regmap_write(map, reg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct snd_pcm_runtime *rt = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct lpass_pcm_data *pcm_data = rt->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct lpaif_dmactl *dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int ret, id, ch, dir = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) unsigned int dai_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) ch = pcm_data->dma_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (dai_id == LPASS_DP_RX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) dmactl = drvdata->hdmi_rd_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) map = drvdata->hdmiif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) dmactl = drvdata->rd_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) map = drvdata->lpaif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) id = pcm_data->dma_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) dmactl = drvdata->wr_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) id = pcm_data->dma_ch - v->wrdma_channel_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) map = drvdata->lpaif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ret = regmap_write(map, LPAIF_DMABASE_REG(v, ch, dir, dai_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) runtime->dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) ret = regmap_write(map, LPAIF_DMABUFF_REG(v, ch, dir, dai_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) ret = regmap_write(map, LPAIF_DMAPER_REG(v, ch, dir, dai_id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) (snd_pcm_lib_period_bytes(substream) >> 2) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) ret = regmap_fields_write(dmactl->enable, id, LPAIF_DMACTL_ENABLE_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct snd_pcm_runtime *rt = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct lpass_pcm_data *pcm_data = rt->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct lpaif_dmactl *dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) int ret, ch, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) int dir = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) unsigned int reg_irqclr = 0, val_irqclr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) unsigned int reg_irqen = 0, val_irqen = 0, val_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) unsigned int dai_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) ch = pcm_data->dma_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) id = pcm_data->dma_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (dai_id == LPASS_DP_RX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) dmactl = drvdata->hdmi_rd_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) map = drvdata->hdmiif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) dmactl = drvdata->rd_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) map = drvdata->lpaif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) dmactl = drvdata->wr_dmactl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) id = pcm_data->dma_ch - v->wrdma_channel_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) map = drvdata->lpaif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) ret = regmap_fields_write(dmactl->enable, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) LPAIF_DMACTL_ENABLE_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) "error writing to rdmactl reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) switch (dai_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case LPASS_DP_RX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) ret = regmap_fields_write(dmactl->dyncclk, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) LPAIF_DMACTL_DYNCLK_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) "error writing to rdmactl reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) reg_irqclr = LPASS_HDMITX_APP_IRQCLEAR_REG(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) val_irqclr = (LPAIF_IRQ_ALL(ch) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) LPAIF_IRQ_HDMI_METADONE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) reg_irqen = LPASS_HDMITX_APP_IRQEN_REG(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) val_mask = (LPAIF_IRQ_ALL(ch) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) LPAIF_IRQ_HDMI_METADONE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) val_irqen = (LPAIF_IRQ_ALL(ch) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) LPAIF_IRQ_HDMI_METADONE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) case MI2S_PRIMARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) case MI2S_SECONDARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) case MI2S_TERTIARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case MI2S_QUATERNARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case MI2S_QUINARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) reg_irqclr = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) val_irqclr = LPAIF_IRQ_ALL(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) val_mask = LPAIF_IRQ_ALL(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) val_irqen = LPAIF_IRQ_ALL(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ret = regmap_write(map, reg_irqclr, val_irqclr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) dev_err(soc_runtime->dev, "error writing to irqclear reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ret = regmap_update_bits(map, reg_irqen, val_mask, val_irqen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) dev_err(soc_runtime->dev, "error writing to irqen reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ret = regmap_fields_write(dmactl->enable, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) LPAIF_DMACTL_ENABLE_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) "error writing to rdmactl reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) switch (dai_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) case LPASS_DP_RX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ret = regmap_fields_write(dmactl->dyncclk, id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) LPAIF_DMACTL_DYNCLK_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) "error writing to rdmactl reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) reg_irqen = LPASS_HDMITX_APP_IRQEN_REG(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) val_mask = (LPAIF_IRQ_ALL(ch) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) LPAIF_IRQ_HDMI_METADONE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) val_irqen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) case MI2S_PRIMARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) case MI2S_SECONDARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) case MI2S_TERTIARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) case MI2S_QUATERNARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) case MI2S_QUINARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) val_mask = LPAIF_IRQ_ALL(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) val_irqen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) ret = regmap_update_bits(map, reg_irqen, val_mask, val_irqen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) "error writing to irqen reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct snd_pcm_runtime *rt = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct lpass_pcm_data *pcm_data = rt->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) unsigned int base_addr, curr_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) int ret, ch, dir = substream->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) unsigned int dai_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (dai_id == LPASS_DP_RX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) map = drvdata->hdmiif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) map = drvdata->lpaif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ch = pcm_data->dma_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) ret = regmap_read(map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) LPAIF_DMABASE_REG(v, ch, dir, dai_id), &base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) "error reading from rdmabase reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) ret = regmap_read(map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) LPAIF_DMACURR_REG(v, ch, dir, dai_id), &curr_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) "error reading from rdmacurr reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return bytes_to_frames(substream->runtime, curr_addr - base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) static int lpass_platform_pcmops_mmap(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return dma_mmap_coherent(component->dev, vma, runtime->dma_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) runtime->dma_addr, runtime->dma_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static irqreturn_t lpass_dma_interrupt_handler(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) struct lpass_data *drvdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) int chan, u32 interrupts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) irqreturn_t ret = IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) unsigned int reg = 0, val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) unsigned int dai_id = cpu_dai->driver->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) switch (dai_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) case LPASS_DP_RX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) map = drvdata->hdmiif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) reg = LPASS_HDMITX_APP_IRQCLEAR_REG(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) val = (LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) LPAIF_IRQ_HDMI_METADONE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) case MI2S_PRIMARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) case MI2S_SECONDARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) case MI2S_TERTIARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) case MI2S_QUATERNARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) case MI2S_QUINARY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) map = drvdata->lpaif_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) reg = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (interrupts & LPAIF_IRQ_PER(chan)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) rv = regmap_write(map, reg, LPAIF_IRQ_PER(chan) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) "error writing to irqclear reg: %d\n", rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) snd_pcm_period_elapsed(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ret = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (interrupts & LPAIF_IRQ_XRUN(chan)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) rv = regmap_write(map, reg, LPAIF_IRQ_XRUN(chan) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) "error writing to irqclear reg: %d\n", rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) dev_warn(soc_runtime->dev, "xrun warning\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) snd_pcm_stop_xrun(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) ret = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (interrupts & LPAIF_IRQ_ERR(chan)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) rv = regmap_write(map, reg, LPAIF_IRQ_ERR(chan) | val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) "error writing to irqclear reg: %d\n", rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) dev_err(soc_runtime->dev, "bus access error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) ret = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (interrupts & val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) rv = regmap_write(map, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) dev_err(soc_runtime->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) "error writing to irqclear reg: %d\n", rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ret = IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct lpass_data *drvdata = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) unsigned int irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) int rv, chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) rv = regmap_read(drvdata->lpaif_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) pr_err("error reading from irqstat reg: %d\n", rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* Handle per channel interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) for (chan = 0; chan < LPASS_MAX_DMA_CHANNELS; chan++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->substream[chan]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) rv = lpass_dma_interrupt_handler(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) drvdata->substream[chan],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) drvdata, chan, irqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (rv != IRQ_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) static irqreturn_t lpass_platform_hdmiif_irq(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) struct lpass_data *drvdata = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) unsigned int irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) int rv, chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) rv = regmap_read(drvdata->hdmiif_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) LPASS_HDMITX_APP_IRQSTAT_REG(v), &irqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) pr_err("error reading from irqstat reg: %d\n", rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* Handle per channel interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) for (chan = 0; chan < LPASS_MAX_HDMI_DMA_CHANNELS; chan++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (irqs & (LPAIF_IRQ_ALL(chan) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) LPAIF_IRQ_HDMI_METADONE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) && drvdata->hdmi_substream[chan]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) rv = lpass_dma_interrupt_handler(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) drvdata->hdmi_substream[chan],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) drvdata, chan, irqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (rv != IRQ_HANDLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static int lpass_platform_pcm_new(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct snd_soc_pcm_runtime *soc_runtime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) struct snd_pcm *pcm = soc_runtime->pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) struct snd_pcm_substream *psubstream, *csubstream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (psubstream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) component->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) size, &psubstream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (csubstream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) component->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) size, &csubstream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (psubstream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) snd_dma_free_pages(&psubstream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) static void lpass_platform_pcm_free(struct snd_soc_component *component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct snd_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) for_each_pcm_streams(i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) substream = pcm->streams[i].substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) snd_dma_free_pages(&substream->dma_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) substream->dma_buffer.area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) substream->dma_buffer.addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) static const struct snd_soc_component_driver lpass_component_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .name = DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .open = lpass_platform_pcmops_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) .close = lpass_platform_pcmops_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) .hw_params = lpass_platform_pcmops_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) .hw_free = lpass_platform_pcmops_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .prepare = lpass_platform_pcmops_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) .trigger = lpass_platform_pcmops_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) .pointer = lpass_platform_pcmops_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .mmap = lpass_platform_pcmops_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .pcm_construct = lpass_platform_pcm_new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) .pcm_destruct = lpass_platform_pcm_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) struct lpass_data *drvdata = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct lpass_variant *v = drvdata->variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (drvdata->lpaif_irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /* ensure audio hardware is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ret = regmap_write(drvdata->lpaif_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) dev_err(&pdev->dev, "error writing to irqen reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) "lpass-irq-lpaif", drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) dev_err(&pdev->dev, "irq request failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) ret = lpass_platform_alloc_dmactl_fields(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) drvdata->lpaif_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) "error initializing dmactl fields: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (drvdata->hdmi_port_enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) drvdata->hdmiif_irq = platform_get_irq_byname(pdev, "lpass-irq-hdmi");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (drvdata->hdmiif_irq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) ret = devm_request_irq(&pdev->dev, drvdata->hdmiif_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) lpass_platform_hdmiif_irq, 0, "lpass-irq-hdmi", drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) dev_err(&pdev->dev, "irq hdmi request failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) ret = regmap_write(drvdata->hdmiif_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) LPASS_HDMITX_APP_IRQEN_REG(v), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) dev_err(&pdev->dev, "error writing to hdmi irqen reg: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) ret = lpass_platform_alloc_hdmidmactl_fields(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) drvdata->hdmiif_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) "error initializing hdmidmactl fields: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) return devm_snd_soc_register_component(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) &lpass_component_driver, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) MODULE_DESCRIPTION("QTi LPASS Platform Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) MODULE_LICENSE("GPL v2");