s3c2410-uda1341_c.txt

来自「2410uda1341的测试代码」· 文本 代码 · 共 1,285 行 · 第 1/4 页

TXT
1,285
字号

        if (file->f_mode & FMODE_READ) {
                          if (audio_rd_refcount == 1)
                                audio_clear_buf(&input_stream);
                                  audio_rd_refcount = 0;
        }

        if(file->f_mode & FMODE_WRITE) {
                          if (audio_wr_refcount == 1) {
                                    audio_sync(file);
                                    audio_clear_buf(&output_stream);
                                    audio_wr_refcount = 0;
                            }
                  }

        return 0;
}


static int smdk2410_mixer_release(struct inode *inode, struct file *file)
{
        return 0;
}


static struct file_operations smdk2410_audio_fops = {
        llseek:                smdk2410_audio_llseek,
        write:                smdk2410_audio_write,
        read:                smdk2410_audio_read,
        poll:                smdk2410_audio_poll,
        ioctl:                smdk2410_audio_ioctl,
        open:                smdk2410_audio_open,
        release:        smdk2410_audio_release
};

static struct file_operations smdk2410_mixer_fops = {
        ioctl:                smdk2410_mixer_ioctl,
        open:                smdk2410_mixer_open,
        release:        smdk2410_mixer_release
};

static void init_uda1341(void)
{
        unsigned long flags;

          uda1341_volume = 62 - ((DEF_VOLUME * 61) / 100);
        uda1341_boost = 0;
          uda_sampling = DATA2_DEEMP_NONE;
        uda_sampling &= ~(DATA2_MUTE);
       

        local_irq_save(flags);

        s3c2410_gpio_setpin(S3C2410_GPB2,1);

        s3c2410_gpio_setpin(S3C2410_GPB4,1);
        local_irq_restore(flags);
       
        uda1341_l3_address(UDA1341_REG_STATUS);
        uda1341_l3_data(0x40 | STAT0_SC_256FS | STAT0_IF_MSB|STAT0_DC_FILTER); // reset uda1341
                uda1341_l3_data(STAT1 | STAT1_ADC_ON | STAT1_DAC_ON);

                uda1341_l3_address(UDA1341_REG_DATA0);
        uda1341_l3_data(DATA0 |DATA0_VOLUME(0x0));  // maximum volume
        uda1341_l3_data(DATA1 |DATA1_BASS(uda1341_boost)| DATA1_TREBLE(0));
                uda1341_l3_data(uda_sampling); /* --;;*/
        uda1341_l3_data(EXTADDR(EXT2));
        uda1341_l3_data(EXTDATA(EXT2_MIC_GAIN(0x6)) | EXT2_MIXMODE_CH1);
       
}

static void init_s3c2410_iis_bus(void){
        writel(0, iis_base + S3C2410_IISPSR);
        writel(0, iis_base + S3C2410_IISCON);
        writel(0, iis_base + S3C2410_IISMOD);
        writel(0, iis_base + S3C2410_IISFCON);
        clk_disable(iis_clock);
}
static void init_s3c2410_iis_bus_rx(void){
        unsigned int iiscon, iismod, iisfcon;
        char *dstr;
        //Kill everything...
        writel(0, iis_base + S3C2410_IISPSR);
        writel(0, iis_base + S3C2410_IISCON);
        writel(0, iis_base + S3C2410_IISMOD);
        writel(0, iis_base + S3C2410_IISFCON);

        clk_enable(iis_clock);

        iiscon = iismod = iisfcon = 0;

        //Setup basic stuff
        iiscon |= S3C2410_IISCON_PSCEN;                                // Enable prescaler
        iiscon |= S3C2410_IISCON_IISEN;                                // Enable interface

        iismod |= IISMOD_SEL_MA;                        // Set interface to Master Mode
        iismod |= S3C2410_IISMOD_LR_LLOW;                        // Low for left channel
        iismod |= S3C2410_IISMOD_MSB;                                // IIS format
        iismod |= S3C2410_IISMOD_16BIT;                                // Serial data bit/channel is 16 bit
        iismod |= S3C2410_IISMOD_384FS;                                // Master clock freq = 384 fs
        iismod |= S3C2410_IISMOD_32FS;                                // 32 fs

        iisfcon|= S3C2410_IISFCON_RXDMA;                        //Set RX FIFO acces mode to DMA
        iisfcon|= S3C2410_IISFCON_TXDMA;                        //Set RX FIFO acces mode to DMA

        iiscon |= S3C2410_IISCON_RXDMAEN;        //Enable RX DMA service request
        iiscon |= S3C2410_IISCON_TXIDLE;        //Set TX channel idle
        iismod |= S3C2410_IISMOD_RXMODE;        //Set RX Mode
        iisfcon|= S3C2410_IISFCON_RXENABLE;        //Enable RX Fifo
        dstr="RX";
        //setup the prescaler
        audio_set_dsp_speed(audio_rate);

        //iiscon has to be set last - it enables the interface
        writel(iismod, iis_base + S3C2410_IISMOD);
        writel(iisfcon, iis_base + S3C2410_IISFCON);
        writel(iiscon, iis_base + S3C2410_IISCON);
}

static void init_s3c2410_iis_bus_tx(void)
{
        unsigned int iiscon, iismod, iisfcon;
        char *dstr;

        //Kill everything...
        writel(0, iis_base + S3C2410_IISPSR);
        writel(0, iis_base + S3C2410_IISCON);
        writel(0, iis_base + S3C2410_IISMOD);
        writel(0, iis_base + S3C2410_IISFCON);

        clk_enable(iis_clock);


        iiscon = iismod = iisfcon = 0;

        //Setup basic stuff
        iiscon |= S3C2410_IISCON_PSCEN;                                // Enable prescaler
        iiscon |= S3C2410_IISCON_IISEN;                                // Enable interface

        iismod |= IISMOD_SEL_MA;                        // Set interface to Master Mode
        iismod |= S3C2410_IISMOD_LR_LLOW;                        // Low for left channel
        iismod |= S3C2410_IISMOD_MSB;                                // MSB format
        iismod |= S3C2410_IISMOD_16BIT;                                // Serial data bit/channel is 16 bit
        iismod |= S3C2410_IISMOD_256FS;                                // Master clock freq = 384 fs
        iismod |= S3C2410_IISMOD_32FS;                                // 32 fs

        iisfcon|= S3C2410_IISFCON_RXDMA;                        //Set RX FIFO acces mode to DMA
        iisfcon|= S3C2410_IISFCON_TXDMA;                        //Set TX FIFO acces mode to DMA

        iiscon |= S3C2410_IISCON_TXDMAEN;        //Enable TX DMA service request
        iiscon |= S3C2410_IISCON_RXIDLE;        //Set RX channel idle
        iismod |= S3C2410_IISMOD_TXMODE;        //Set TX Mode
        iisfcon|= S3C2410_IISFCON_TXENABLE;        //Enable TX Fifo
        dstr="TX";

        //setup the prescaler
        audio_set_dsp_speed(audio_rate);


        //iiscon has to be set last - it enables the interface
        writel(iismod, iis_base + S3C2410_IISMOD);
        writel(iisfcon, iis_base + S3C2410_IISFCON);
        writel(iiscon, iis_base + S3C2410_IISCON);
}

static int __init audio_init_dma(audio_stream_t * s, char *desc)
{
        int ret ;
        s3c2410_dmasrc_t         source;
        int                         hwcfg;
        unsigned long                 devaddr;
        dmach_t                        channel;
        int                         dcon;
        unsigned int                flags = 0;

        if(s->dma_ch == DMA_CH2){
                channel = 2;
                source  = S3C2410_DMASRC_MEM;
                hwcfg        = 3;
                devaddr        = 0x55000010;
                dcon        = 1<<31;
                flags        = S3C2410_DMAF_AUTOSTART;

                ret = s3c2410_dma_request(s->dma_ch, &s3c2410iis_dma_out, NULL);
                s3c2410_dma_devconfig(channel, source, hwcfg, devaddr);
                s3c2410_dma_config(channel, 2, dcon);
                s3c2410_dma_set_buffdone_fn(channel, audio_dmaout_done_callback);
                s3c2410_dma_setflags(channel, flags);
                s->dma_ok = 1;
                return ret;
        }
        else if(s->dma_ch == DMA_CH1){
                ret = s3c2410_dma_request(s->dma_ch, &s3c2410iis_dma_in, NULL);
                            s3c2410_dma_set_buffdone_fn(s->dma_ch, audio_dmain_done_callback);
                return ret ;                       
        }
        else
                return 1;
}

static int audio_clear_dma(audio_stream_t * s,s3c2410_dma_client_t *client)
{
        s3c2410_dma_set_buffdone_fn(s->dma_ch, NULL);
        s3c2410_dma_free(s->dma_ch, client);
        return 0;
}

static int s3c2410iis_probe(struct device *dev) {
        struct platform_device *pdev = to_platform_device(dev);
        struct resource *res;

        unsigned long flags;
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res == NULL) {
                printk(KERN_INFO PFX "failed to get memory region resouce\n");
                return -ENOENT;
        }

        iis_base = (void *)S3C24XX_VA_IIS ;
        if (iis_base == 0) {
                printk(KERN_INFO PFX "failed to ioremap() region\n");
                return -EINVAL;
        }

        iis_clock = clk_get(dev, "iis");
        if (iis_clock == NULL) {
                printk(KERN_INFO PFX "failed to find clock source\n");
                return -ENOENT;
        }

        clk_enable(iis_clock);

        local_irq_save(flags);

        /* GPB 4: L3CLOCK, OUTPUT */
        s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
        /* GPB 3: L3DATA, OUTPUT */
        s3c2410_gpio_cfgpin(S3C2410_GPB3,S3C2410_GPB3_OUTP);
        /* GPB 2: L3MODE, OUTPUT */
        s3c2410_gpio_cfgpin(S3C2410_GPB2,S3C2410_GPB2_OUTP);
        /* GPE 3: I2SSDI */
        s3c2410_gpio_cfgpin(S3C2410_GPE3,S3C2410_GPE3_I2SSDI);       
        /* GPE 0: I2SLRCK */
        s3c2410_gpio_cfgpin(S3C2410_GPE0,S3C2410_GPE0_I2SLRCK);
        /* GPE 1: I2SSCLK */
        s3c2410_gpio_cfgpin(S3C2410_GPE1,S3C2410_GPE1_I2SSCLK);       
        /* GPE 2: CDCLK */
        s3c2410_gpio_cfgpin(S3C2410_GPE2,S3C2410_GPE2_CDCLK);               
        /* GPE 4: I2SSDO */
        s3c2410_gpio_cfgpin(S3C2410_GPE4,S3C2410_GPE4_I2SSDO);

        local_irq_restore(flags);

        init_s3c2410_iis_bus();
       
        init_uda1341();

        output_stream.dma_ch = DMA_CH2;

        if (audio_init_dma(&output_stream, "UDA1341 out")) {
                audio_clear_dma(&output_stream,&s3c2410iis_dma_out);
                printk( KERN_WARNING AUDIO_NAME_VERBOSE
                        ": unable to get DMA channels\n" );
                return -EBUSY;
        }

        input_stream.dma_ch = DMA_CH1;

           if (audio_init_dma(&input_stream, "UDA1341 in")) {
                        audio_clear_dma(&input_stream,&s3c2410iis_dma_in);
                        printk( KERN_WARNING AUDIO_NAME_VERBOSE
                        ": unable to get DMA channels\n" );
                        return -EBUSY;
                }
       
        audio_dev_dsp = register_sound_dsp(&smdk2410_audio_fops, -1);
        audio_dev_mixer = register_sound_mixer(&smdk2410_mixer_fops, -1);

        printk(AUDIO_NAME_VERBOSE " initialized\n");

        return 0;
}


static int s3c2410iis_remove(struct device *dev) {
        unregister_sound_dsp(audio_dev_dsp);
        unregister_sound_mixer(audio_dev_mixer);
        audio_clear_dma(&output_stream,&s3c2410iis_dma_out);
        audio_clear_dma(&input_stream,&s3c2410iis_dma_in); /* input */
        printk(AUDIO_NAME_VERBOSE " unloaded\n");
        return 0;
}


static struct device_driver s3c2410iis_driver = {
        .name           = "s3c2410-iis",
        .bus            = &platform_bus_type,
        .probe          = s3c2410iis_probe,
        .remove         = s3c2410iis_remove,
};

static int __init s3c2410_uda1341_init(void) {
        memzero(&input_stream, sizeof(audio_stream_t));
        memzero(&output_stream, sizeof(audio_stream_t));
        return driver_register(&s3c2410iis_driver);
}

static void __exit s3c2410_uda1341_exit(void) {
        driver_unregister(&s3c2410iis_driver);
}


module_init(s3c2410_uda1341_init);
module_exit(s3c2410_uda1341_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("superlp<xinshengtaier@eyou.com>");
MODULE_DESCRIPTION("S3C2410 uda1341 sound driver");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?