Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * mtk-afe-platform-driver.c  --  Mediatek afe platform driver
0004  *
0005  * Copyright (c) 2016 MediaTek Inc.
0006  * Author: Garlic Tseng <garlic.tseng@mediatek.com>
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     /* calcualte total dai driver size */
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     /* combine sub_dais */
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         /* dai driver */
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     /* add routes after all widgets are added */
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