[alsa-devel] To disable dma_area caching (twice)

MASAO TAKAHASHI masao-takahashi at kanno.co.jp
Fri May 18 07:18:57 CEST 2012


Hi everybody.
Please advice me to solve my problem.
1.  My environment
    Hardware	Alpha-project MS104-SH4AG with SH7764
    kernel		sh-linux-2.6.29
    ALSA driver sh7764-pcm.c developped 
       by  Manuel Lauss <mano at roarinelk.homelinux.net>

2. My problem
	I am using the above ALSA driver for SH7764 SSI.
	I have found the runtime->dma_area address refers DMA area
	via D-cache.
	So, playback start is too late after executing 
          snd_pcm_writei().
	Until D-cache writeback is done, sound data stays in D-cache.
	I want to read and write from/to main memory 
	without D-cache.

3. My idea to solve this problem
   3-1 change allocating type of DMA area as follows
       	snd_pcm_lib_preallocate_pages_for_all(
            pcm, SNDRV_DMA_TYPE_CONTINUOUS,
            snd_dma_continuous_data(GFP_KERNEL),
            64*1024, 64*1024);

       is changed to

        snd_pcm_lib_preallocate_pages_for_all(
            pcm, SNDRV_DMA_TYPE_DEV, <----------- here
            snd_dma_continuous_data(GFP_KERNEL),
            64*1024, 64*1024);
        to let dma_addr pointing P2SEG area without caching

    3-2 program internal DMA controller start address 
        with dma_addr
   
          ssidma_outl(sd, (virt_to_phys)(u32)runtime->dma_addr,
                       SSIRDMADR);


    3-3 add mmap_data_fault routine
         static int sh7764_mmap_data_fault(    
           structvm_area_struct*area,
           struct vm_fault *vmf)
        {
	  struct snd_pcm_substream *substream = area->vm_private_data;
	  struct snd_pcm_runtime *runtime;
	  unsigned long offset;
	  struct page * page;
	  void *vaddr;
	  size_t dma_bytes;
	
	  pr_debug("mmap_data_fault\n");
	  if (substream == NULL)
		return VM_FAULT_SIGBUS;
	  runtime = substream->runtime;
	  offset = vmf->pgoff << PAGE_SHIFT;
	  dma_bytes = PAGE_ALIGN(runtime->dma_bytes);
	  if (offset > dma_bytes - PAGE_SIZE)
		return VM_FAULT_SIGBUS;
	  if (substream->ops->page) {
		page = substream->ops->page(substream, offset);
		if (!page)
			return VM_FAULT_SIGBUS;
	  } else {
		vaddr = runtime->dma_addr + offset;
		page = virt_to_page(vaddr);
	  }
	get_page(page);
	vmf->page = page;
	pr_debug("mmap_data_fault:page = %x\n", (unsigned int)page);
	return 0;
       }
       static struct vm_operations_struct sh7764_pcm_vm_ops_data =
      {
	.open =		snd_pcm_mmap_data_open,
	.close =	snd_pcm_mmap_data_close,
	.fault =	sh7764_mmap_data_fault,
      };

  3-3 add sh7764_pcm_mmap routine
      static int sh7764_pcm_mmap(
        struct snd_pcm_substream *substream,
	struct vm_area_struct *area)
      {
	unsigned long	offset;
	unsigned long	mp;
	unsigned long	virt;
	int				map_size;
	struct page *map, *mapend, *ip;
	struct snd_pcm_runtime *runtime;
	int	ret;
      #ifdef pgprot_noncached
        area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
      #endif
	offset = area->vm_pgoff << PAGE_SHIFT;
	runtime = substream->runtime;
	map_size = runtime->dma_bytes;
	mp = virt_to_phys((unsigned long)runtime->dma_addr));
	map = virt_to_page(mp);
	mapend = virt_to_page(mp+map_size - 1);
	for (ip = map; ip <= mapend; ip++){
		SetPageReserved(ip);
	area->vm_ops = &sh7764_pcm_vm_ops_data;
	area->vm_private_data = substream;
	area->vm_flags |= VM_IO;
	ret = io_remap_pfn_range(area, area->vm_start,
               mp>>PAGE_SHIFT,
               area->vm_end - area->vm_start, 
               area->vm_page_prot);
		
	if (ret ){
	  pr_debug("sh7764-pcm.c:remap_pfn_range returned EAGAIN\n");
	  return -EAGAIN;
	}
	atomic_inc(&substream->mmap_count);
	pr_debug("mmap_count=%u\n", substream->mmap_count);
	return 0;
    }

    static struct snd_pcm_ops sh7764_ssidma_ops = {
	.open		= sh7764_ssidma_open,
	.close		= sh7764_ssidma_close,
	.ioctl		= snd_pcm_lib_ioctl,
	.hw_params	= sh7764_hw_params,
	.hw_free	= sh7764_hw_free,
	.prepare	= sh7764_prepare,
	.trigger	= sh7764_trigger,
	.pointer	= sh7764_pos,
	.mmap		= sh7764_pcm_mmap,
    };
 ------------------------------------------------------------
Sorry, so long contents.

My solution is right?
or
Is there any better solution ?

Best regards
---------- 
MASAO TAKAHASHI <masao-takahashi at kanno.co.jp>
KANNO WORKS CO., LTD. JAPAN
TEL 093-436-2330


More information about the Alsa-devel mailing list