| --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c |
| +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c |
| @@ -361,6 +361,222 @@ |
| } |
| EXPORT_SYMBOL_GPL(mtk_afe_dai_resume); |
| |
| +int mtk_memif_set_enable(struct mtk_base_afe *afe, int id) |
| +{ |
| + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
| + |
| + if (memif->data->enable_shift < 0) { |
| + dev_warn(afe->dev, "%s(), error, id %d, enable_shift < 0\n", |
| + __func__, id); |
| + return 0; |
| + } |
| + return mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg, |
| + 1, 1, memif->data->enable_shift); |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_memif_set_enable); |
| + |
| +int mtk_memif_set_disable(struct mtk_base_afe *afe, int id) |
| +{ |
| + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
| + |
| + if (memif->data->enable_shift < 0) { |
| + dev_warn(afe->dev, "%s(), error, id %d, enable_shift < 0\n", |
| + __func__, id); |
| + return 0; |
| + } |
| + return mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg, |
| + 1, 0, memif->data->enable_shift); |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_memif_set_disable); |
| + |
| +int mtk_memif_set_addr(struct mtk_base_afe *afe, int id, |
| + unsigned char *dma_area, |
| + dma_addr_t dma_addr, |
| + size_t dma_bytes) |
| +{ |
| + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
| + int msb_at_bit33 = upper_32_bits(dma_addr) ? 1 : 0; |
| + unsigned int phys_buf_addr = lower_32_bits(dma_addr); |
| + unsigned int phys_buf_addr_upper_32 = upper_32_bits(dma_addr); |
| + |
| + memif->dma_area = dma_area; |
| + memif->dma_addr = dma_addr; |
| + memif->dma_bytes = dma_bytes; |
| + |
| + /* start */ |
| + mtk_regmap_write(afe->regmap, memif->data->reg_ofs_base, |
| + phys_buf_addr); |
| + /* end */ |
| + if (memif->data->reg_ofs_end) |
| + mtk_regmap_write(afe->regmap, |
| + memif->data->reg_ofs_end, |
| + phys_buf_addr + dma_bytes - 1); |
| + else |
| + mtk_regmap_write(afe->regmap, |
| + memif->data->reg_ofs_base + |
| + AFE_BASE_END_OFFSET, |
| + phys_buf_addr + dma_bytes - 1); |
| + |
| + /* set start, end, upper 32 bits */ |
| + if (memif->data->reg_ofs_base_msb) { |
| + mtk_regmap_write(afe->regmap, memif->data->reg_ofs_base_msb, |
| + phys_buf_addr_upper_32); |
| + mtk_regmap_write(afe->regmap, |
| + memif->data->reg_ofs_end_msb, |
| + phys_buf_addr_upper_32); |
| + } |
| + |
| + /* set MSB to 33-bit */ |
| + if (memif->data->msb_reg >= 0) |
| + mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg, |
| + 1, msb_at_bit33, memif->data->msb_shift); |
| + |
| + return 0; |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_memif_set_addr); |
| + |
| +int mtk_memif_set_channel(struct mtk_base_afe *afe, |
| + int id, unsigned int channel) |
| +{ |
| + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
| + unsigned int mono; |
| + |
| + if (memif->data->mono_shift < 0) |
| + return 0; |
| + |
| + if (memif->data->quad_ch_mask) { |
| + unsigned int quad_ch = (channel == 4) ? 1 : 0; |
| + |
| + mtk_regmap_update_bits(afe->regmap, memif->data->quad_ch_reg, |
| + memif->data->quad_ch_mask, |
| + quad_ch, memif->data->quad_ch_shift); |
| + } |
| + |
| + if (memif->data->mono_invert) |
| + mono = (channel == 1) ? 0 : 1; |
| + else |
| + mono = (channel == 1) ? 1 : 0; |
| + |
| + return mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg, |
| + 1, mono, memif->data->mono_shift); |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_memif_set_channel); |
| + |
| +static int mtk_memif_set_rate_fs(struct mtk_base_afe *afe, |
| + int id, int fs) |
| +{ |
| + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
| + |
| + if (memif->data->fs_shift >= 0) |
| + mtk_regmap_update_bits(afe->regmap, memif->data->fs_reg, |
| + memif->data->fs_maskbit, |
| + fs, memif->data->fs_shift); |
| + |
| + return 0; |
| +} |
| + |
| +int mtk_memif_set_rate(struct mtk_base_afe *afe, |
| + int id, unsigned int rate) |
| +{ |
| + int fs = 0; |
| + |
| + if (!afe->get_dai_fs) { |
| + dev_err(afe->dev, "%s(), error, afe->get_dai_fs == NULL\n", |
| + __func__); |
| + return -EINVAL; |
| + } |
| + |
| + fs = afe->get_dai_fs(afe, id, rate); |
| + |
| + if (fs < 0) |
| + return -EINVAL; |
| + |
| + return mtk_memif_set_rate_fs(afe, id, fs); |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_memif_set_rate); |
| + |
| +int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream, |
| + int id, unsigned int rate) |
| +{ |
| + struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| + struct snd_soc_component *component = |
| + snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); |
| + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); |
| + |
| + int fs = 0; |
| + |
| + if (!afe->memif_fs) { |
| + dev_err(afe->dev, "%s(), error, afe->memif_fs == NULL\n", |
| + __func__); |
| + return -EINVAL; |
| + } |
| + |
| + fs = afe->memif_fs(substream, rate); |
| + |
| + if (fs < 0) |
| + return -EINVAL; |
| + |
| + return mtk_memif_set_rate_fs(afe, id, fs); |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_memif_set_rate_substream); |
| + |
| +int mtk_memif_set_format(struct mtk_base_afe *afe, |
| + int id, snd_pcm_format_t format) |
| +{ |
| + struct mtk_base_afe_memif *memif = &afe->memif[id]; |
| + int hd_audio = 0; |
| + int hd_align = 0; |
| + |
| + /* set hd mode */ |
| + switch (format) { |
| + case SNDRV_PCM_FORMAT_S16_LE: |
| + case SNDRV_PCM_FORMAT_U16_LE: |
| + hd_audio = 0; |
| + break; |
| + case SNDRV_PCM_FORMAT_S32_LE: |
| + case SNDRV_PCM_FORMAT_U32_LE: |
| + hd_audio = 1; |
| + hd_align = 1; |
| + break; |
| + case SNDRV_PCM_FORMAT_S24_LE: |
| + case SNDRV_PCM_FORMAT_U24_LE: |
| + hd_audio = 1; |
| + break; |
| + default: |
| + dev_err(afe->dev, "%s() error: unsupported format %d\n", |
| + __func__, format); |
| + break; |
| + } |
| + |
| + mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg, |
| + 1, hd_audio, memif->data->hd_shift); |
| + |
| + mtk_regmap_update_bits(afe->regmap, memif->data->hd_align_reg, |
| + 1, hd_align, memif->data->hd_align_mshift); |
| + |
| + return 0; |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_memif_set_format); |
| + |
| +int mtk_memif_set_pbuf_size(struct mtk_base_afe *afe, |
| + int id, int pbuf_size) |
| +{ |
| + const struct mtk_base_memif_data *memif_data = afe->memif[id].data; |
| + |
| + if (memif_data->pbuf_mask == 0 || memif_data->minlen_mask == 0) |
| + return 0; |
| + |
| + mtk_regmap_update_bits(afe->regmap, memif_data->pbuf_reg, |
| + memif_data->pbuf_mask, |
| + pbuf_size, memif_data->pbuf_shift); |
| + |
| + mtk_regmap_update_bits(afe->regmap, memif_data->minlen_reg, |
| + memif_data->minlen_mask, |
| + pbuf_size, memif_data->minlen_shift); |
| + return 0; |
| +} |
| +EXPORT_SYMBOL_GPL(mtk_memif_set_pbuf_size); |
| + |
| MODULE_DESCRIPTION("Mediatek simple fe dai operator"); |
| MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>"); |
| MODULE_LICENSE("GPL v2"); |
| --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.h |
| +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.h |
| @@ -34,4 +34,20 @@ |
| int mtk_afe_dai_suspend(struct snd_soc_dai *dai); |
| int mtk_afe_dai_resume(struct snd_soc_dai *dai); |
| |
| +int mtk_memif_set_enable(struct mtk_base_afe *afe, int id); |
| +int mtk_memif_set_disable(struct mtk_base_afe *afe, int id); |
| +int mtk_memif_set_addr(struct mtk_base_afe *afe, int id, |
| + unsigned char *dma_area, |
| + dma_addr_t dma_addr, |
| + size_t dma_bytes); |
| +int mtk_memif_set_channel(struct mtk_base_afe *afe, |
| + int id, unsigned int channel); |
| +int mtk_memif_set_rate(struct mtk_base_afe *afe, |
| + int id, unsigned int rate); |
| +int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream, |
| + int id, unsigned int rate); |
| +int mtk_memif_set_format(struct mtk_base_afe *afe, |
| + int id, snd_pcm_format_t format); |
| +int mtk_memif_set_pbuf_size(struct mtk_base_afe *afe, |
| + int id, int pbuf_size); |
| #endif |
| --- a/sound/soc/mediatek/common/mtk-base-afe.h |
| +++ b/sound/soc/mediatek/common/mtk-base-afe.h |
| @@ -16,21 +16,38 @@ |
| const char *name; |
| int reg_ofs_base; |
| int reg_ofs_cur; |
| + int reg_ofs_end; |
| + int reg_ofs_base_msb; |
| + int reg_ofs_cur_msb; |
| + int reg_ofs_end_msb; |
| int fs_reg; |
| int fs_shift; |
| int fs_maskbit; |
| int mono_reg; |
| int mono_shift; |
| + int mono_invert; |
| + int quad_ch_reg; |
| + int quad_ch_mask; |
| + int quad_ch_shift; |
| int enable_reg; |
| int enable_shift; |
| int hd_reg; |
| - int hd_align_reg; |
| int hd_shift; |
| + int hd_align_reg; |
| int hd_align_mshift; |
| int msb_reg; |
| int msb_shift; |
| + int msb2_reg; |
| + int msb2_shift; |
| int agent_disable_reg; |
| int agent_disable_shift; |
| + /* playback memif only */ |
| + int pbuf_reg; |
| + int pbuf_mask; |
| + int pbuf_shift; |
| + int minlen_reg; |
| + int minlen_mask; |
| + int minlen_shift; |
| }; |
| |
| struct mtk_base_irq_data { |
| @@ -84,6 +101,12 @@ |
| unsigned int rate); |
| int (*irq_fs)(struct snd_pcm_substream *substream, |
| unsigned int rate); |
| + int (*get_dai_fs)(struct mtk_base_afe *afe, |
| + int dai_id, unsigned int rate); |
| + int (*get_memif_pbuf_size)(struct snd_pcm_substream *substream); |
| + |
| + int (*request_dram_resource)(struct device *dev); |
| + int (*release_dram_resource)(struct device *dev); |
| |
| void *platform_priv; |
| }; |
| @@ -95,6 +118,9 @@ |
| const struct mtk_base_memif_data *data; |
| int irq_usage; |
| int const_irq; |
| + unsigned char *dma_area; |
| + dma_addr_t dma_addr; |
| + size_t dma_bytes; |
| }; |
| |
| struct mtk_base_afe_irq { |