#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/delay.h> #include <linux/poll.h> #include <linux/interrupt.h> #include <linux/sound.h> #include <linux/soundcard.h> #include <linux/clk.h> #include <linux/platform_device.h> #include <linux/pm.h> #include <linux/wait.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/hardware.h> #include <asm/semaphore.h> #include <asm/dma.h> #include <asm/arch/dma.h> #include <asm/arch/regs-gpio.h> #include <asm/plat-s3c24xx/clock.h> #include <asm/arch/regs-clock.h> #include <linux/dma-mapping.h> #include <asm/arch/hardware.h> #include <asm/arch/map.h> #include <asm/arch/regs-iis.h> #include <asm/plat-s3c24xx/devs.h> #define PFX "s3c2410-uda1341-superlp: " #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1) #define MAX_DMA_CHANNELS 0 #define L3MODE S3C2410_GPB2 #define L3MODE_OUTP S3C2410_GPB2_OUTP #define L3CLOCK S3C2410_GPB4 #define L3CLOCK_OUTP S3C2410_GPB4_OUTP #define L3DATA S3C2410_GPB3 #define L3DATA_OUTP S3C2410_GPB3_OUTP /* The S3C2410 has four internal DMA channels. */ #define MAX_S3C2410_DMA_CHANNELS S3C2410_DMA_CHANNELS #define DMA_CH1 DMACH_I2S_IN #define DMA_CH2 DMACH_I2S_OUT #define DMA_BUF_WR 1 #define DMA_BUF_RD 0 #define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg)) /************************* add by lfc **************************/ #define UData(Data) (Data) /* * MACRO: Fld * * Purpose * The macro "Fld" encodes a bit field, given its size and its shift value * with respect to bit 0. * * Note * A more intuitive way to encode bit fields would have been to use their * mask. However, extracting size and shift value information from a bit * field's mask is cumbersome and might break the assembler (255-character * line-size limit). * * Input * Size Size of the bit field, in number of bits. * Shft Shift value of the bit field with respect to bit 0. * * Output * Fld Encoded bit field. */ #define Fld(Size, Shft) (((Size) << 16) + (Shft)) /* * MACROS: FSize, FShft, FMsk, FAlnMsk, F1stBit * * Purpose * The macros "FSize", "FShft", "FMsk", "FAlnMsk", and "F1stBit" return * the size, shift value, mask, aligned mask, and first bit of a * bit field. * * Input * Field Encoded bit field (using the macro "Fld"). * * Output * FSize Size of the bit field, in number of bits. * FShft Shift value of the bit field with respect to bit 0. * FMsk Mask for the bit field. * FAlnMsk Mask for the bit field, aligned on bit 0. * F1stBit First bit of the bit field. */ #define FSize(Field) ((Field) >> 16) #define FShft(Field) ((Field) & 0x0000FFFF) /* * MACRO: FInsrt * * Purpose * The macro "FInsrt" inserts a value into a bit field by shifting the * former appropriately. * * Input * Value Bit-field value. * Field Encoded bit field (using the macro "Fld"). * * Output * FInsrt Bit-field value positioned appropriately. */ #define FInsrt(Value, Field) (UData (Value) << FShft (Field)) #define fIISPSR_A Fld(5, 5) /* Prescaler Control A */ #define IISPSR_A(x) FInsrt((x), fIISPSR_A) #define fIISPSR_B Fld(5, 0) /* Prescaler Control B */ #define IISPSR_B(x) FInsrt((x), fIISPSR_B) /**************************** end add **************************/ static struct clk *iis_clock; static void __iomem *iis_base; static struct s3c2410_dma_client s3c2410iis_dma_out= { .name = "I2SSDO", }; static struct s3c2410_dma_client s3c2410iis_dma_in = { .name = "I2SSDI", }; //#define DEBUG #ifdef DEBUG #define DPRINTK printk #else #define DPRINTK( x... ) #endif static void init_s3c2410_iis_bus_rx(void); static void init_s3c2410_iis_bus_tx(void); #define DEF_VOLUME 80 /* UDA1341 Register bits */ #define UDA1341_ADDR 0x14 #define UDA1341_REG_DATA0 (UDA1341_ADDR + 0) #define UDA1341_REG_STATUS (UDA1341_ADDR + 2) /* status control */ #define STAT0 (0x00) #define STAT0_RST (1 << 6) #define STAT0_SC_MASK (3 << 4) #define STAT0_SC_512FS (0 << 4) #define STAT0_SC_384FS (1 << 4) #define STAT0_SC_256FS (2 << 4) #define STAT0_IF_MASK (7 << 1) #define STAT0_IF_I2S (0 << 1) #define STAT0_IF_LSB16 (1 << 1) #define STAT0_IF_LSB18 (2 << 1) #define STAT0_IF_LSB20 (3 << 1) #define STAT0_IF_MSB (4 << 1) #define STAT0_IF_LSB16MSB (5 << 1) #define STAT0_IF_LSB18MSB (6 << 1) #define STAT0_IF_LSB20MSB (7 << 1) #define STAT0_DC_FILTER (1 << 0) #define STAT0_DC_NO_FILTER (0 << 0) #define STAT1 (0x80) #define STAT1_DAC_GAIN (1 << 6) /* gain of DAC */ #define STAT1_ADC_GAIN (1 << 5) /* gain of ADC */ #define STAT1_ADC_POL (1 << 4) /* polarity of ADC */ #define STAT1_DAC_POL (1 << 3) /* polarity of DAC */ #define STAT1_DBL_SPD (1 << 2) /* double speed playback */ #define STAT1_ADC_ON (1 << 1) /* ADC powered */ #define STAT1_DAC_ON (1 << 0) /* DAC powered */ /* data0 direct control */ #define DATA0 (0x00) #define DATA0_VOLUME_MASK (0x3f) #define DATA0_VOLUME(x) (x) #define DATA1 (0x40) #define DATA1_BASS(x) ((x) << 2) #define DATA1_BASS_MASK (15 << 2) #define DATA1_TREBLE(x) ((x)) #define DATA1_TREBLE_MASK (3) #define DATA2 (0x80) #define DATA2_PEAKAFTER (0x1 << 5) #define DATA2_DEEMP_NONE (0x0 << 3) #define DATA2_DEEMP_32KHz (0x1 << 3) #define DATA2_DEEMP_44KHz (0x2 << 3) #define DATA2_DEEMP_48KHz (0x3 << 3) #define DATA2_MUTE (0x1 << 2) #define DATA2_FILTER_FLAT (0x0 << 0) #define DATA2_FILTER_MIN (0x1 << 0) #define DATA2_FILTER_MAX (0x3 << 0) /* data0 extend control */ #define EXTADDR(n) (0xc0 | (n)) #define EXTDATA(d) (0xe0 | (d)) #define EXT0 0 #define EXT0_CH1_GAIN(x) (x) #define EXT1 1 #define EXT1_CH2_GAIN(x) (x) #define EXT2 2 #define EXT2_MIC_GAIN_MASK (7 << 2) #define EXT2_MIC_GAIN(x) ((x) << 2) #define EXT2_MIXMODE_DOUBLEDIFF (0) #define EXT2_MIXMODE_CH1 (1) #define EXT2_MIXMODE_CH2 (2) #define EXT2_MIXMODE_MIX (3) #define EXT4 4 #define EXT4_AGC_ENABLE (1 << 4) #define EXT4_INPUT_GAIN_MASK (3) #define EXT4_INPUT_GAIN(x) ((x) & 3) #define EXT5 5 #define EXT5_INPUT_GAIN(x) ((x) >> 2) #define EXT6 6 #define EXT6_AGC_CONSTANT_MASK (7 << 2) #define EXT6_AGC_CONSTANT(x) ((x) << 2) #define EXT6_AGC_LEVEL_MASK (3) #define EXT6_AGC_LEVEL(x) (x) #define AUDIO_NAME "UDA1341" #define AUDIO_NAME_VERBOSE "UDA1341 audio driver" #define AUDIO_FMT_MASK (AFMT_S16_LE) #define AUDIO_FMT_DEFAULT (AFMT_S16_LE) #define AUDIO_CHANNELS_DEFAULT 2 #define AUDIO_RATE_DEFAULT 44100 #define AUDIO_NBFRAGS_DEFAULT 8 #define AUDIO_FRAGSIZE_DEFAULT 8192 #define S_CLOCK_FREQ 384 #define PCM_ABS(a) (a < 0 ? -a : a) typedef struct { int size; /* buffer size */ char *start; /* point to actual buffer */ dma_addr_t dma_addr; /* physical buffer address */ struct semaphore sem; /* down before touching the buffer */ atomic_t count; wait_queue_head_t wait; int master; /* owner for buffer allocation, contain size when true */ } audio_buf_t; typedef struct { audio_buf_t *buffers; /* pointer to audio buffer structures */ audio_buf_t *buf; /* current buffer used by read/write */ u_int buf_idx; /* index for the pointer above */ u_int fragsize; /* fragment i.e. buffer size */ u_int nbfrags; /* nbr of fragments */ dmach_t dma_ch; /* DMA channel (channel2 for audio) */ u_int dma_ok; } audio_stream_t; /* * 驱动对于内存是这样使用的: * 把buffers所指向的内存分成nbfragsxfragsize的空间(每一块的大小为fragsize,供分成nbfrags块) * buf指向当前所使用的内存块,buf_idx只是内存块序号 */ static audio_stream_t output_stream; static audio_stream_t input_stream; /* input */ #define NEXT_BUF(_s_,_b_) { / (_s_)->_b_##_idx++; / (_s_)->_b_##_idx %= (_s_)->nbfrags; / (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_idx; } static u_int audio_rate; static int audio_channels; static int audio_fmt; static u_int audio_fragsize; static u_int audio_nbfrags; static int audio_rd_refcount; static int audio_wr_refcount; #define audio_active (audio_rd_refcount | audio_wr_refcount) static int audio_dev_dsp; static int audio_dev_mixer; static int audio_mix_modcnt; static int uda1341_volume; //static u8 uda_sampling; static int uda1341_boost; static int uda1341_treble; static int mixer_igain=0x4; /* -6db*/ static void uda1341_l3_address(u8 data) { int i; un