0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/dma-mapping.h>
0011 #include <sound/soc.h>
0012
0013 #include "mtk-afe-platform-driver.h"
0014 #include "mtk-base-afe.h"
0015
0016 int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe)
0017 {
0018 struct mtk_base_afe_dai *dai;
0019 size_t num_dai_drivers = 0, dai_idx = 0;
0020
0021
0022 list_for_each_entry(dai, &afe->sub_dais, list) {
0023 num_dai_drivers += dai->num_dai_drivers;
0024 }
0025
0026 dev_info(afe->dev, "%s(), num of dai %zd\n", __func__, num_dai_drivers);
0027
0028
0029 afe->num_dai_drivers = num_dai_drivers;
0030 afe->dai_drivers = devm_kcalloc(afe->dev,
0031 num_dai_drivers,
0032 sizeof(struct snd_soc_dai_driver),
0033 GFP_KERNEL);
0034 if (!afe->dai_drivers)
0035 return -ENOMEM;
0036
0037 list_for_each_entry(dai, &afe->sub_dais, list) {
0038
0039 memcpy(&afe->dai_drivers[dai_idx],
0040 dai->dai_drivers,
0041 dai->num_dai_drivers *
0042 sizeof(struct snd_soc_dai_driver));
0043 dai_idx += dai->num_dai_drivers;
0044 }
0045 return 0;
0046 }
0047 EXPORT_SYMBOL_GPL(mtk_afe_combine_sub_dai);
0048
0049 int mtk_afe_add_sub_dai_control(struct snd_soc_component *component)
0050 {
0051 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
0052 struct mtk_base_afe_dai *dai;
0053
0054 list_for_each_entry(dai, &afe->sub_dais, list) {
0055 if (dai->controls)
0056 snd_soc_add_component_controls(component,
0057 dai->controls,
0058 dai->num_controls);
0059
0060 if (dai->dapm_widgets)
0061 snd_soc_dapm_new_controls(&component->dapm,
0062 dai->dapm_widgets,
0063 dai->num_dapm_widgets);
0064 }
0065
0066 list_for_each_entry(dai, &afe->sub_dais, list) {
0067 if (dai->dapm_routes)
0068 snd_soc_dapm_add_routes(&component->dapm,
0069 dai->dapm_routes,
0070 dai->num_dapm_routes);
0071 }
0072
0073 snd_soc_dapm_new_widgets(component->dapm.card);
0074
0075 return 0;
0076
0077 }
0078 EXPORT_SYMBOL_GPL(mtk_afe_add_sub_dai_control);
0079
0080 snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
0081 struct snd_pcm_substream *substream)
0082 {
0083 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0084 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
0085 struct mtk_base_afe_memif *memif = &afe->memif[asoc_rtd_to_cpu(rtd, 0)->id];
0086 const struct mtk_base_memif_data *memif_data = memif->data;
0087 struct regmap *regmap = afe->regmap;
0088 struct device *dev = afe->dev;
0089 int reg_ofs_base = memif_data->reg_ofs_base;
0090 int reg_ofs_cur = memif_data->reg_ofs_cur;
0091 unsigned int hw_ptr = 0, hw_base = 0;
0092 int ret, pcm_ptr_bytes;
0093
0094 ret = regmap_read(regmap, reg_ofs_cur, &hw_ptr);
0095 if (ret || hw_ptr == 0) {
0096 dev_err(dev, "%s hw_ptr err\n", __func__);
0097 pcm_ptr_bytes = 0;
0098 goto POINTER_RETURN_FRAMES;
0099 }
0100
0101 ret = regmap_read(regmap, reg_ofs_base, &hw_base);
0102 if (ret || hw_base == 0) {
0103 dev_err(dev, "%s hw_ptr err\n", __func__);
0104 pcm_ptr_bytes = 0;
0105 goto POINTER_RETURN_FRAMES;
0106 }
0107
0108 pcm_ptr_bytes = hw_ptr - hw_base;
0109
0110 POINTER_RETURN_FRAMES:
0111 return bytes_to_frames(substream->runtime, pcm_ptr_bytes);
0112 }
0113 EXPORT_SYMBOL_GPL(mtk_afe_pcm_pointer);
0114
0115 int mtk_afe_pcm_new(struct snd_soc_component *component,
0116 struct snd_soc_pcm_runtime *rtd)
0117 {
0118 size_t size;
0119 struct snd_pcm *pcm = rtd->pcm;
0120 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
0121
0122 size = afe->mtk_afe_hardware->buffer_bytes_max;
0123 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
0124 afe->dev, size, size);
0125 return 0;
0126 }
0127 EXPORT_SYMBOL_GPL(mtk_afe_pcm_new);
0128
0129 const struct snd_soc_component_driver mtk_afe_pcm_platform = {
0130 .name = AFE_PCM_NAME,
0131 .pointer = mtk_afe_pcm_pointer,
0132 .pcm_construct = mtk_afe_pcm_new,
0133 };
0134 EXPORT_SYMBOL_GPL(mtk_afe_pcm_platform);
0135
0136 MODULE_DESCRIPTION("Mediatek simple platform driver");
0137 MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>");
0138 MODULE_LICENSE("GPL v2");
0139