To enable MP3 playback, we recently completed the I2S driver on sep4020. The main experience is summarized as follows:
1. First, perform a series of initialization in the probe function.Is very important, and many
● Configure the gpio port Line for operating codec l3;
Compared with a mixer control interface, the L3 interface corresponds to the mixer structure in the driver. here we need to use three gpio port lines to control the L3. The following is the initialization code:
* (Volatile unsigned long *) (gpio_portd_dir_v) & = ~ (0xd <1); // GPB [4:1] = 00_0 output (l3clock): output (l3data): output (l3mode)
* (Volatile unsigned long *) (gpio_portd_sel_v) | = (0xd <1 );
// GPD [] 1 1010
● The Configuration Port is the sound releasing function. Because the sep4020 only supports separate sound recording and recording, it cannot be a full duplex. Therefore, the configuration here is implemented by setting the port line to a high or low position, code:
* (Volatile unsigned long *) (gpio_portg_dir_v) & = ~ (0x1 <11 );
* (Volatile unsigned long *) (gpio_portg_sel_v) | = 0x1 <11;
* (Volatile unsigned long *) (gpio_portg_data_v) | = 0x1 <11;
● Configure PWM to provide the codec clock:
* (Volatile unsigned long *) pwm4_ctrl_v = 0x00;
* (Volatile unsigned long *) pwm4_div_v = 0x4; // 88 MHz/(4*2) = 11 MHz 11 m/256fs = 42.96 K
* (Volatile unsigned long *) pwm4_period_v = 0x2; // The counting clock is the DIV division of the bus.
* (Volatile unsigned long *) pwm4_data_v = 0x1; // the cycle is two counting clocks.
* (Volatile unsigned long *) pwm_enable_v = 0x1 <3; // The high level is a counting clock.
● Initialize codec (uda1341). The actual step is to configure and control the L3 port line together with the first step. After configuring the port line, configure the parameters of codec through these ports, of course, the specific codec parameters should refer to the uda1341 manual, where uda1341_l3_address and uda1341_l3_data are separately compiled functions:
* (Volatile unsigned long *) (gpio_portd_data_v) & = ~ (L3m | l3c | l3d );
* (Volatile unsigned long *) (gpio_portd_data_v) | = (l3m | l3c); // start condition: l3m = H, l3c = H
// The following configuration may need to be modified for marked at 11-08
Uda1341_l3_address (0x14 + 2 );
Uda1341_l3_data (0x61); // 1110 DC-filtering cannot be enabled.
Uda1341_l3_address (0x14 + 2 );
Uda1341_l3_data (0x21 );
Uda1341_l3_address (0x14 + 2 );
Uda1341_l3_data (0xc1); // status 1, gain of DAC 6 dB, gain of ADC 0db, ADC non-inverting, DAC non-inverting, single speed playback, ADC-off DAC-on
Uda1341_l3_address (0x14 + 0 );
Uda1341_l3_data (0x0f); // 00 FFFF: volume control (6 bits)-14db
Uda1341_l3_address (0x14 + 0 );
Uda1341_l3_data (0x7b); //, 11: data0, Bass boost 18 ~ 24db, treble 6db
Uda1341_l3_address (0x14 + 0 );
Uda1341_l3_data (0x83 );
● The DMA configuration mainly enables the DMA channel and removes the interrupt flag. The specific DMA buffer allocation will be implemented in a dmasetup function prior to the DMA, and there is a corresponding dmaclear clearing buffer.
2. Audio-driven audio struct and mixer struct
In the audio driver, operation functions of these two structures are implemented:
Static struct file_operations sep4020_audio_fops = {
Llseek: sep4020_audio_llseek,
Write: sep4020_audio_write,
Read: sep4020_audio_read,
Poll: sep4020_audio_poll,
IOCTL: sep4020_audio_ioctl,
Open: sep4020_audio_open,
Release: sep4020_audio_release
};
Static struct file_operations sep4020_mixer_fops = {
IOCTL: sep4020_mixer_ioctl,
Open: sep4020_mixer_open,
Release: sep4020_mixer_release
};
The sep4020_audio_fops struct mainly implements I2S controller operations, including read/write, control, query (poll), open, and release. Audio is mainly used to accept upper-layer application data and transmit the data to codec for playing (PLAYING). It receives data from codec and transmits the data to upper-layer functions (recording ). In this part, the write and read functions are the most important, and IOCTL can be used by others. Therefore, our main work is to focus on the write and read functions.
The sep4020_mixer_fops mainly implements the codec parameter configuration. We can also clearly see that its operation struct only contains the control function and does not read/write. In addition, due to the versatility of codec, this part of code can basically be followed by others, such as 2410.
3. About the sep4020_audio_write function:
This is the core and difficulty of the entire driver. It involves the DMA Operation, the buffer ring idea, and the semaphore idea in Linux. I will continue tomorrow. I am tired today.