static void SetHDMIBuffer(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { kal_uint32 volatile u4tmpMrg1; struct snd_pcm_runtime *runtime = substream->runtime; AFE_BLOCK_T *pblock = &(pMemControl->rBlock); pblock->pucPhysBufAddr = runtime->dma_addr; pblock->pucVirtBufAddr = runtime->dma_area; pblock->u4BufferSize = runtime->dma_bytes; pblock->u4SampleNumMask = 0x001f; /* 32 byte align */ pblock->u4WriteIdx = 0; pblock->u4DMAReadIdx = 0; pblock->u4DataRemained = 0; pblock->u4fsyncflag = false; pblock->uResetFlag = true; PRINTK_AUD_HDMI("%s, dma_bytes = %d, dma_area = %p, dma_addr = 0x%x\n", __func__, pblock->u4BufferSize, pblock->pucVirtBufAddr, pblock->pucPhysBufAddr); Afe_Set_Reg(AFE_HDMI_BASE, pblock->pucPhysBufAddr, 0xffffffff); Afe_Set_Reg(AFE_HDMI_END, pblock->pucPhysBufAddr + (pblock->u4BufferSize - 1), 0xffffffff); u4tmpMrg1 = Afe_Get_Reg(AFE_HDMI_BASE); u4tmpMrg1 &= 0x00ffffff; PRINTK_AUD_HDMI("SetHDMIBuffer AFE_HDMI_BASE = 0x%x\n", u4tmpMrg1); }
static int mtk_pcm_hdmi_silence(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) { PRINTK_AUD_HDMI("%s\n", __func__); /* do nothing */ return 0; }
static int mtk_asoc_pcm_hdmi_new(struct snd_soc_pcm_runtime *rtd) { int ret = 0; pruntimehdmi = rtd; PRINTK_AUD_HDMI("%s\n", __func__); return ret; }
static int mtk_hdmi_probe(struct platform_device *pdev) { PRINTK_AUD_HDMI("%s\n", __func__); pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64); if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; if (pdev->dev.of_node) dev_set_name(&pdev->dev, "%s", MT_SOC_HDMI_PCM); PRINTK_AUD_HDMI("%s: dev name %s\n", __func__, dev_name(&pdev->dev)); return snd_soc_register_platform(&pdev->dev, &mtk_hdmi_soc_platform); }
static int mtk_pcm_hdmi_hw_free(struct snd_pcm_substream *substream) { PRINTK_AUD_HDMI("mtk_pcm_hdmi_hw_free\n"); if (fake_buffer) return 0; return snd_pcm_lib_free_pages(substream); }
static snd_pcm_uframes_t mtk_pcm_hdmi_pointer(struct snd_pcm_substream *substream) { kal_int32 HW_memory_index = 0; kal_int32 HW_Cur_ReadIdx = 0; kal_uint32 Frameidx = 0; kal_int32 Afe_consumed_bytes = 0; AFE_BLOCK_T *Afe_Block = &(pMemControl->rBlock); PRINTK_AUD_HDMI("%s Afe_Block->u4DMAReadIdx = 0x%x\n", __func__, Afe_Block->u4DMAReadIdx); if (GetMemoryPathEnable(Soc_Aud_Digital_Block_MEM_HDMI) == true) { HW_Cur_ReadIdx = Afe_Get_Reg(AFE_HDMI_CUR); if (HW_Cur_ReadIdx == 0) { PRINTK_AUD_HDMI("[Auddrv] HW_Cur_ReadIdx == 0\n"); HW_Cur_ReadIdx = Afe_Block->pucPhysBufAddr; } HW_memory_index = (HW_Cur_ReadIdx - Afe_Block->pucPhysBufAddr); if (HW_memory_index >= Afe_Block->u4DMAReadIdx) Afe_consumed_bytes = HW_memory_index - Afe_Block->u4DMAReadIdx; else { Afe_consumed_bytes = Afe_Block->u4BufferSize + HW_memory_index - Afe_Block->u4DMAReadIdx; } Afe_Block->u4DataRemained -= Afe_consumed_bytes; Afe_Block->u4DMAReadIdx += Afe_consumed_bytes; Afe_Block->u4DMAReadIdx %= Afe_Block->u4BufferSize; PRINTK_AUD_HDMI ("[Auddrv] HW_Cur_ReadIdx = 0x%x, HW_memory_index = 0x%x, Afe_consumed_bytes = 0x%x\n", HW_Cur_ReadIdx, HW_memory_index, Afe_consumed_bytes); return audio_bytes_to_frame(substream, Afe_Block->u4DMAReadIdx); } Frameidx = audio_bytes_to_frame(substream, Afe_Block->u4DMAReadIdx); return Frameidx; }
static int mtk_pcm_hdmi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dma_buffer *dma_buf = &substream->dma_buffer; int ret = 0; pr_debug("mtk_pcm_hdmi_hw_params\n"); dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; dma_buf->dev.dev = substream->pcm->card->dev; dma_buf->private_data = NULL; if (fake_buffer) { PRINTK_AUD_HDMI("[mtk_pcm_hdmi_hw_params] HDMI_dma_buf->area\n"); #ifdef _NO_SRAM_USAGE_ runtime->dma_area = HDMI_dma_buf->area; runtime->dma_addr = HDMI_dma_buf->addr; /* runtime->dma_bytes = HDMI_dma_buf->bytes; */ /* runtime->buffer_size = HDMI_dma_buf->bytes; */ runtime->dma_bytes = params_buffer_bytes(hw_params); runtime->buffer_size = runtime->dma_bytes; #else runtime->dma_area = (unsigned char *)Get_Afe_SramBase_Pointer(); runtime->dma_addr = AFE_INTERNAL_SRAM_PHY_BASE; runtime->dma_bytes = params_buffer_bytes(hw_params); runtime->buffer_size = runtime->dma_bytes; #endif } else { PRINTK_AUD_HDMI("[mtk_pcm_hdmi_hw_params] snd_pcm_lib_malloc_pages\n"); ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } PRINTK_AUD_HDMI("%s, dma_bytes = %zu, dma_area = %p, dma_addr = 0x%lx\n", __func__, substream->runtime->dma_bytes, substream->runtime->dma_area, (long)substream->runtime->dma_addr); SetHDMIBuffer(substream, hw_params); return ret; }
static snd_pcm_uframes_t mtk_pcm_hdmi_pointer(struct snd_pcm_substream *substream) { kal_int32 HW_memory_index = 0; kal_int32 HW_Cur_ReadIdx = 0; AFE_BLOCK_T *Afe_Block = &(pMemControl->rBlock); PRINTK_AUD_HDMI("mtk_pcm_hdmi_pointer u4DMAReadIdx=%x\n",Afe_Block->u4DMAReadIdx); if (pMemControl->interruptTrigger == 1) { HW_Cur_ReadIdx = Afe_Get_Reg(AFE_HDMI_CUR); if (HW_Cur_ReadIdx == 0) { PRINTK_AUD_HDMI("[mtk_pcm_hdmi_pointer] HW_Cur_ReadIdx ==0 \n"); HW_Cur_ReadIdx = Afe_Block->pucPhysBufAddr; } HW_memory_index = (HW_Cur_ReadIdx - Afe_Block->pucPhysBufAddr); Previous_Hw_cur = HW_memory_index; PRINTK_AUD_HDMI("[mtk_pcm_hdmi_pointer] HW_Cur_ReadIdx =0x%x HW_memory_index = 0x%x pointer return = 0x%x \n", HW_Cur_ReadIdx, HW_memory_index,(HW_memory_index >> 2)); pMemControl->interruptTrigger = 0; return (HW_memory_index >> 2); }
static int mtk_pcm_hdmi_open(struct snd_pcm_substream *substream) { int ret = 0; struct snd_pcm_runtime *runtime = substream->runtime; pr_debug("%s\n", __func__); AudDrv_ANA_Clk_On(); AudDrv_Emi_Clk_On(); AudDrv_Clk_On(); runtime->hw = mtk_hdmi_hardware; pMemControl = Get_Mem_ControlT(Soc_Aud_Digital_Block_MEM_HDMI); memcpy((void *)(&(runtime->hw)), (void *)&mtk_hdmi_hardware, sizeof(struct snd_pcm_hardware)); ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &constraints_sample_rates); if (ret < 0) { PRINTK_AUD_HDMI("snd_pcm_hw_constraint_integer failed\n"); return ret; } /* print for hw pcm information */ pr_debug("%s, runtime->rate = %d, channels = %d, substream->pcm->device = %d\n", __func__, runtime->rate, runtime->channels, substream->pcm->device); runtime->hw.info |= SNDRV_PCM_INFO_INTERLEAVED; runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID; PRINTK_AUD_HDMI("mtk_pcm_hdmi_open return\n"); return 0; }
static int mtk_pcm_hdmi_trigger(struct snd_pcm_substream *substream, int cmd) { PRINTK_AUD_HDMI("mtk_pcm_hdmi_trigger cmd = %d\n", cmd); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: return mtk_pcm_hdmi_start(substream); case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: return mtk_pcm_hdmi_stop(substream); } return -EINVAL; }
static int mtk_afe_hdmi_probe(struct snd_soc_platform *platform) { HDMI_dma_buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); memset((void *)HDMI_dma_buf, 0, sizeof(struct snd_dma_buffer)); PRINTK_AUD_HDMI("mtk_afe_hdmi_probe dma_alloc_coherent HDMI_dma_buf->addr = 0x%lx\n", (long)HDMI_dma_buf->addr); HDMI_dma_buf->area = dma_alloc_coherent(platform->dev, HDMI_MAX_BUFFER_SIZE, &HDMI_dma_buf->addr, GFP_KERNEL); /* virtual pointer */ if (HDMI_dma_buf->area) HDMI_dma_buf->bytes = HDMI_MAX_BUFFER_SIZE; snd_soc_add_platform_controls(platform, Audio_snd_hdmi_controls, ARRAY_SIZE(Audio_snd_hdmi_controls)); return 0; }
static int __init mtk_hdmi_soc_platform_init(void) { int ret; PRINTK_AUD_HDMI("%s\n", __func__); #ifndef CONFIG_OF soc_mtkhdmi_dev = platform_device_alloc(MT_SOC_HDMI_PCM, -1); if (!soc_mtkhdmi_dev) return -ENOMEM; ret = platform_device_add(soc_mtkhdmi_dev); if (ret != 0) { platform_device_put(soc_mtkhdmi_dev); return ret; } #endif ret = platform_driver_register(&mtk_hdmi_driver); return ret; }
static int mtk_pcm_hdmi_copy(struct snd_pcm_substream *substream, int channel, snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) { AFE_BLOCK_T *Afe_Block = NULL; int copy_size = 0, Afe_WriteIdx_tmp; unsigned long flags; char *data_w_ptr = (char *)dst; count = audio_frame_to_bytes(substream, count); /* check which memif need to be write */ Afe_Block = &(pMemControl->rBlock); /* handle for buffer management */ PRINTK_AUD_HDMI ("[%s] count = %d, WriteIdx = %x, ReadIdx = %x, DataRemained = %x\n", __func__, (kal_uint32) count, Afe_Block->u4WriteIdx, Afe_Block->u4DMAReadIdx, Afe_Block->u4DataRemained); if (Afe_Block->u4BufferSize == 0) { pr_err("%s: u4BufferSize = 0, Error!!!\n", __func__); return 0; } spin_lock_irqsave(&auddrv_hdmi_lock, flags); /* free space of the buffer */ copy_size = Afe_Block->u4BufferSize - Afe_Block->u4DataRemained; spin_unlock_irqrestore(&auddrv_hdmi_lock, flags); if (count <= copy_size) { if (copy_size < 0) copy_size = 0; else copy_size = count; } if (copy_size != 0) { spin_lock_irqsave(&auddrv_hdmi_lock, flags); Afe_WriteIdx_tmp = Afe_Block->u4WriteIdx; spin_unlock_irqrestore(&auddrv_hdmi_lock, flags); if (Afe_WriteIdx_tmp + copy_size < Afe_Block->u4BufferSize) { /* copy once */ if (!access_ok(VERIFY_READ, data_w_ptr, copy_size)) { pr_warn("[%s] 0 ptr invalid data_w_ptr = %p, size = %d,", __func__, data_w_ptr, copy_size); pr_warn(" u4BufferSize = %d, u4DataRemained = %d\n", Afe_Block->u4BufferSize, Afe_Block->u4DataRemained); } else { PRINTK_AUD_HDMI2 ("[%s] memcpy Afe_Block->pucVirtBufAddr+Afe_WriteIdx=%x, data_w_ptr=%p, copy_size=%x\n", Afe_Block->pucVirtBufAddr + Afe_WriteIdx_tmp, data_w_ptr, copy_size); if (copy_from_user((Afe_Block->pucVirtBufAddr + Afe_WriteIdx_tmp), data_w_ptr, copy_size)) { pr_err("[%s] Fail copy from user\n", __func__); return -1; } } spin_lock_irqsave(&auddrv_hdmi_lock, flags); Afe_Block->u4DataRemained += copy_size; Afe_Block->u4WriteIdx = Afe_WriteIdx_tmp + copy_size; Afe_Block->u4WriteIdx %= Afe_Block->u4BufferSize; spin_unlock_irqrestore(&auddrv_hdmi_lock, flags); data_w_ptr += copy_size; count -= copy_size; PRINTK_AUD_HDMI2 ("[%s] finish 1, copy_size:%x, WriteIdx:%x, ReadIdx:%x, DataRemained:%x\n", __func__, copy_size, Afe_Block->u4WriteIdx, Afe_Block->u4DMAReadIdx, Afe_Block->u4DataRemained); } else { /* copy twice */ kal_uint32 size_1 = 0, size_2 = 0; size_1 = Afe_Block->u4BufferSize - Afe_WriteIdx_tmp; size_2 = copy_size - size_1; if (!access_ok(VERIFY_READ, data_w_ptr, size_1)) { pr_warn("[%s] 1 ptr invalid data_w_ptr = %p, size_1 = %d,", __func__, data_w_ptr, size_1); pr_warn(" u4BufferSize = %d, u4DataRemained = %d\n", Afe_Block->u4BufferSize, Afe_Block->u4DataRemained); } else { PRINTK_AUD_HDMI2 ("[%s] mcmcpy Afe_Block->pucVirtBufAddr+Afe_WriteIdx=%x, data_w_ptr=%p, size_1=%x\n", __func__, Afe_Block->pucVirtBufAddr + Afe_WriteIdx_tmp, data_w_ptr, size_1); if ((copy_from_user((Afe_Block->pucVirtBufAddr + Afe_WriteIdx_tmp), data_w_ptr, size_1))) { pr_err("[%s] Fail 1 copy from user\n", __func__); return -1; } } spin_lock_irqsave(&auddrv_hdmi_lock, flags); Afe_Block->u4DataRemained += size_1; Afe_Block->u4WriteIdx = Afe_WriteIdx_tmp + size_1; Afe_Block->u4WriteIdx %= Afe_Block->u4BufferSize; Afe_WriteIdx_tmp = Afe_Block->u4WriteIdx; spin_unlock_irqrestore(&auddrv_hdmi_lock, flags); if (!access_ok(VERIFY_READ, data_w_ptr + size_1, size_2)) { pr_warn("[%s] 2 ptr invalid data_w_ptr = %p, size_1 = %d, size_2 = %d,", __func__, data_w_ptr, size_1, size_2); pr_warn(" u4BufferSize = %d, u4DataRemained = %d\n", Afe_Block->u4BufferSize, Afe_Block->u4DataRemained); } else { PRINTK_AUD_HDMI2 ("[%s] mcmcpy Afe_Block->pucVirtBufAddr+Afe_WriteIdx=%x,\n", __func__, Afe_Block->pucVirtBufAddr + Afe_WriteIdx_tmp); PRINTK_AUD_HDMI2 (" data_w_ptr+size_1=%p, size_2=%x\n", data_w_ptr + size_1, size_2); if ((copy_from_user((Afe_Block->pucVirtBufAddr + Afe_WriteIdx_tmp), (data_w_ptr + size_1), size_2))) { pr_err("[%s] Fail 2 copy from user\n", __func__); return -1; } } spin_lock_irqsave(&auddrv_hdmi_lock, flags); Afe_Block->u4DataRemained += size_2; Afe_Block->u4WriteIdx = Afe_WriteIdx_tmp + size_2; Afe_Block->u4WriteIdx %= Afe_Block->u4BufferSize; spin_unlock_irqrestore(&auddrv_hdmi_lock, flags); count -= copy_size; data_w_ptr += copy_size; PRINTK_AUD_HDMI2 ("[%s] finish 2, copy size:%x, WriteIdx:%x, ReadIdx:%x, DataRemained:%x\n", __func__, copy_size, Afe_Block->u4WriteIdx, Afe_Block->u4DMAReadIdx, Afe_Block->u4DataRemained); } } return 0; }
static void __exit mtk_hdmi_soc_platform_exit(void) { PRINTK_AUD_HDMI("%s\n", __func__); platform_driver_unregister(&mtk_hdmi_driver); }
static int mtk_hdmi_remove(struct platform_device *pdev) { PRINTK_AUD_HDMI("%s\n", __func__); snd_soc_unregister_platform(&pdev->dev); return 0; }
static struct page *mtk_pcm_page(struct snd_pcm_substream *substream, unsigned long offset) { PRINTK_AUD_HDMI("%s\n", __func__); return virt_to_page(dummy_page[substream->stream]); /* the same page */ }