Wei Dongshan embedded Linux video tutorial _3 combat phase of the project of writing the ALSA sound card _ Add recording function from zero (Liuzhou excellent FS2410-based development board, UDA1341 sound card)

First, the experimental environment

1.1 virtual machine environment

    a) Vmware printed books: Vmware Workstation 12.5.7

    b) Ubuntu Version: 9.10

    c) kernel version: 2.6.31.14

    d) toolchain Version: arm-linux-gcc 4.3.2

1.2 Development Board

    Liuzhou excellent FS2410 development board, UDA1341 sound card

    Kernel Version: 3.4.2

Second, modify the code

2.1 modify s3c2440_dma.c

1) static volatile struct s3c_dma_regs *dma_regs;

    Read:

    static volatile struct s3c_dma_regs *dma_regs_ch1; //for playback
     static volatile struct s3c_dma_regs *dma_regs_ch2; //for capture

    Accordingly, all functions related to the modification register DMA operation, depending on the type substream-> stream, and to select the corresponding dma_regs_chx,

2) adding preallocate_dma_buffer (), modification s3c2440_dma_new (), and for the capture substream playback substream allocated DMA buffer, respectively

3) The global variables previously defined struct s3c2440_dma_info playback_dma_info changed in s3c2440_dma_open () in

static int s3c2440_dma_open(struct snd_pcm_substream *substream)
{

    struct s3c2440_dma_info *prtd;
    ...
    prtd = kzalloc(sizeof(struct s3c2440_dma_info), GFP_KERNEL);
    runtime->private_data = prtd;
    ...
}

    Accordingly, all access playback_dma_info the modification function, access to substream-> runtime-> private_data

2.2 (which was later discovered to be added when debugging)

   Reference kernel s3c24xx-i2s.c, modified s3c2440-i2s.c:

   Add s3c2440_snd_txctrl (), s3c2440_snd_rxctrl (), and then modify s3c2440_i2s_trigger ()

static int s3c2440_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
{
    int ret = 0;
    switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
	case SNDRV_PCM_TRIGGER_RESUME:
	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
	    //s3c2440_iis_start();
	    if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		s3c2440_snd_rxctrl(1);
	    else
		s3c2440_snd_txctrl(1);
	    break;
	case SNDRV_PCM_TRIGGER_STOP:
	case SNDRV_PCM_TRIGGER_SUSPEND:
	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
	default:
            //s3c2440_iis_stop();
	    if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		s3c2440_snd_rxctrl(0);
	    else
		s3c2440_snd_txctrl(0);
	    ret = -EINVAL;
	    break;
    }

exit_err:
    return ret;
}

Third, debugging

1. Compile, install the driver, not mentioned here, see: Wei Dongshan embedded Linux video tutorial _3 combat phase of the project from the commissioning of the ALSA _ zero of writing (based Liuzhou excellent FS2410 development board, UDA1341 sound card)

2. execution aplay windows.wav, headphones are high-frequency noise!

    / # Cat / proc / interrupts visible interruption does occur DMA

    CPU0

    25: 0 s3c s3c2410-wdt

    30: 26510 s3c S3C2410 Timer Tick

    35: 2 s3c  myalsa for playback

    …

    The investigation, need to add in s3c2440_dma_hw_params () in:

    prtd->phy_addr = substream->dma_buffer.addr;

    Originally playback_dma_info.phy_addr, in s3c2440_dma_new () dma_alloc_writecombine directly as output parameters are initialized:

    playback_dma_info.virt_addr = (unsigned int)dma_alloc_writecombine(pcm->card->dev, s3c2440_dma_hardware.buffer_bytes_max,
                                                                                                                     &playback_dma_info.phy_addr, GFP_KERNEL);

    Recompile load the driver, and then perform aplay windows.wav again, the headphones finally able to hear the sound!

3. Do arecord -d 5 my1.wav, but after 5 seconds, nothing happens! After the forced ctrl-c, reported:

    Recording WAVE 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono

    ^CAborted by signal Interrupt...

    arecord: pcm_read:2031: read error: Interrupted system call

    / # Cat / proc / interrupts DMA without any interruption

4. Check Register DISRC1 (0x4B000040) with devmem2, DIDST1 (0x4B000048), IISCON (0x55000000) values:

  (Note: left double arrow is to perform arecord value before the right is executedarecord value after)

    / # devmem2 0x4B000040

      Value at address 0x4B000040 (0xb6fba040): 0x0 <==> 0x55000010

    / # devmem2 0x4B000048

    Value at address 0x4B000048 (0xb6f46048): 0x0 <==> 0x33B80000

    / # devmem2 0x55000000

    Value at address 0x55000000 (0xb6fc6000): 0x100 <==> 0x122 Bit [0] = 0 , ie interface disable IIS , the description of 1 did not write into it!

    Check-kernel sound \ soc \ samsung \ s3c24xx-i2s.c, found that in addition to operating IISCON, but also operating IISMOD, IISFCO.

    Then the reference kernel s3c24xx-i2s.c, modified s3c2440-i2s.c:

    Add s3c2440_snd_txctrl (), s3c2440_snd_rxctrl (), and then modify s3c2440_i2s_trigger ().

5. recompile load the driver, and then perform arecord -d 5 my1.wav again, the normal exit after the 5 seconds, there is no error.

    IISCON see the value of:

    / # devmem2 0x55000000

    AT address 0x55000000 Value (0xb6fbd000): 0x10B , explanation bit [0] 1 get a hold!

    / # cat /proc/interrupts

    CPU0

    25: 0 s3c s3c2410-wdt

    30: 139493 s3c S3C2410 Timer Tick

    34: 1 s3c my alsa for capture  instructions DMA interrupt occurred

    Execution aplay my1.wav, capable of playing sound! Description recording success!

6. On JZ2440, wm8976 sound test, also successful. And modify the program, just need s3c2440_dma.c and s3c2440_iis.c copy to cover past.

Annex: Source

myalsa_FS2410_can_record

myalsa_JZ2440_can_record

Fourth, references

1. Wei Dongshan embedded Linux video tutorial _3 of the project combat the ALSA sound card

2. Li Lanxi  S3C24XX DMA source code analysis framework

3. linux 3.4.2 kernel source

4. s3c2440 Data Sheet

Guess you like

Origin www.cnblogs.com/normalmanzhao2003/p/12333864.html