Path: blob/master/sound/soc/mediatek/common/mtk-afe-platform-driver.c
26450 views
// SPDX-License-Identifier: GPL-2.01/*2* mtk-afe-platform-driver.c -- Mediatek afe platform driver3*4* Copyright (c) 2016 MediaTek Inc.5* Author: Garlic Tseng <[email protected]>6*/78#include <linux/module.h>9#include <linux/dma-mapping.h>10#include <sound/soc.h>1112#include "mtk-afe-platform-driver.h"13#include "mtk-base-afe.h"1415int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe)16{17struct mtk_base_afe_dai *dai;18size_t num_dai_drivers = 0, dai_idx = 0;1920/* calcualte total dai driver size */21list_for_each_entry(dai, &afe->sub_dais, list) {22num_dai_drivers += dai->num_dai_drivers;23}2425dev_info(afe->dev, "%s(), num of dai %zd\n", __func__, num_dai_drivers);2627/* combine sub_dais */28afe->num_dai_drivers = num_dai_drivers;29afe->dai_drivers = devm_kcalloc(afe->dev,30num_dai_drivers,31sizeof(struct snd_soc_dai_driver),32GFP_KERNEL);33if (!afe->dai_drivers)34return -ENOMEM;3536list_for_each_entry(dai, &afe->sub_dais, list) {37/* dai driver */38memcpy(&afe->dai_drivers[dai_idx],39dai->dai_drivers,40dai->num_dai_drivers *41sizeof(struct snd_soc_dai_driver));42dai_idx += dai->num_dai_drivers;43}44return 0;45}46EXPORT_SYMBOL_GPL(mtk_afe_combine_sub_dai);4748int mtk_afe_add_sub_dai_control(struct snd_soc_component *component)49{50struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);51struct mtk_base_afe_dai *dai;5253list_for_each_entry(dai, &afe->sub_dais, list) {54if (dai->controls)55snd_soc_add_component_controls(component,56dai->controls,57dai->num_controls);5859if (dai->dapm_widgets)60snd_soc_dapm_new_controls(&component->dapm,61dai->dapm_widgets,62dai->num_dapm_widgets);63}64/* add routes after all widgets are added */65list_for_each_entry(dai, &afe->sub_dais, list) {66if (dai->dapm_routes)67snd_soc_dapm_add_routes(&component->dapm,68dai->dapm_routes,69dai->num_dapm_routes);70}7172snd_soc_dapm_new_widgets(component->dapm.card);7374return 0;7576}77EXPORT_SYMBOL_GPL(mtk_afe_add_sub_dai_control);7879snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,80struct snd_pcm_substream *substream)81{82struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);83struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);84struct mtk_base_afe_memif *memif = &afe->memif[snd_soc_rtd_to_cpu(rtd, 0)->id];85const struct mtk_base_memif_data *memif_data = memif->data;86struct regmap *regmap = afe->regmap;87struct device *dev = afe->dev;88int reg_ofs_base = memif_data->reg_ofs_base;89int reg_ofs_cur = memif_data->reg_ofs_cur;90unsigned int hw_ptr = 0, hw_base = 0;91int ret, pcm_ptr_bytes;9293ret = regmap_read(regmap, reg_ofs_cur, &hw_ptr);94if (ret || hw_ptr == 0) {95dev_err(dev, "%s hw_ptr err\n", __func__);96pcm_ptr_bytes = 0;97goto POINTER_RETURN_FRAMES;98}99100ret = regmap_read(regmap, reg_ofs_base, &hw_base);101if (ret || hw_base == 0) {102dev_err(dev, "%s hw_ptr err\n", __func__);103pcm_ptr_bytes = 0;104goto POINTER_RETURN_FRAMES;105}106107pcm_ptr_bytes = hw_ptr - hw_base;108109POINTER_RETURN_FRAMES:110return bytes_to_frames(substream->runtime, pcm_ptr_bytes);111}112EXPORT_SYMBOL_GPL(mtk_afe_pcm_pointer);113114int mtk_afe_pcm_new(struct snd_soc_component *component,115struct snd_soc_pcm_runtime *rtd)116{117size_t size;118struct snd_pcm *pcm = rtd->pcm;119struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);120121size = afe->mtk_afe_hardware->buffer_bytes_max;122snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, afe->dev,123afe->preallocate_buffers ? size : 0,124size);125126return 0;127}128EXPORT_SYMBOL_GPL(mtk_afe_pcm_new);129130static int mtk_afe_component_probe(struct snd_soc_component *component)131{132struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);133int ret;134135snd_soc_component_init_regmap(component, afe->regmap);136137/* If the list was never initialized there are no sub-DAIs */138if (afe->sub_dais.next && afe->sub_dais.prev) {139ret = mtk_afe_add_sub_dai_control(component);140if (ret)141return ret;142}143144return 0;145}146147const struct snd_soc_component_driver mtk_afe_pcm_platform = {148.name = AFE_PCM_NAME,149.pointer = mtk_afe_pcm_pointer,150.pcm_construct = mtk_afe_pcm_new,151.probe = mtk_afe_component_probe,152};153EXPORT_SYMBOL_GPL(mtk_afe_pcm_platform);154155MODULE_DESCRIPTION("Mediatek simple platform driver");156MODULE_AUTHOR("Garlic Tseng <[email protected]>");157MODULE_LICENSE("GPL v2");158159160161