Debug wm9714 audio channel Switching

Source: Internet
Author: User

The switching between the earphone and the Horn channel of wm9714 is controlled by the register software, which is a little different from the method of inserting the earphone in the TV to let the amplifier pull down and turn off the external sound directly. You can set the value of 0x1c in wm9714, where 0x00a0 and 0x1200 in the headset.

In the circuit, the eint11 is fixed externally to a high level. The eint11 is lowered by inserting a headset to trigger the interruption, and then the wm9714 register control is implemented. First, add the initialization channel settings and registration interruption in wm9713_soc_probe () in wm9713.c.

# Define hdphone_eintpin irq_eint (11)
# Define hdphone_gpiopin initi64xx_gpn (11)
# Define output_value_hp (0x00a0)
# Define output_value_spk (0x1200)

Static int wm9713_soc_probe (struct platform_device * pdev)

{

......

Initi_gpio_cfgpin (hdphone_gpiopin, initi_gpio_sfn (2); // configure gpio11 as an external interrupt
Initi_gpio_setpull (hdphone_gpiopin, initi_gpio_pull_none); // The hardware is not pulled down by default.
Set_irq_type (hdphone_eintpin, irq_type_edge_both); // The insertion and unplugging of the headset will trigger interruption.

If (readl (89c64xx_gpndat) & (1 <11) // if the power-on is powered on, set the channel; otherwise, set the headset
{
Ac97_write (codec, ac97_rec_gain, output_value_spk );
}
Else
{
Ac97_write (codec, ac97_rec_gain, output_value_hp );
}

Ret = request_irq (hdphone_eintpin, initi6400_9713hdsp_irq, // register the interrupt and interrupt processing functions for eint11. The parameters include the interrupt mode,
Irqf_disabled, "hdphonspeak", null); // interrupt name

If (Ret <0) // if the registration fails, execute GOTO
{
Printk (kern_err "request_irq (89c6400_9713hdsp_irq) failed !!! /N ");
Goto irq_err;
}

.........

Irq_err:
Free_irq (hdphone_eintpin, null); // release interruption

.........

}

The handler is interrupted as follows:

Static irqreturn_t initi6400_9713hdsp_irq (int irq, void * dev_id)
{
Struct snd_soc_codec * codec = wm9713_dai-> codec; // obtain the codec of the system
Writel (readl (initi64xx_eint0mask) | (1 <11), initi64xx_eint0mask); // disable eint0 interrupt before deal it
Writel (1 <11, 89c64xx_eint0pend); // disable interrupt

If (readl (s3c2464xx_gpndat) & (1 <11) // if it is a speaker, otherwise it is a headset
{
Ac97_write (codec, ac97_rec_gain, output_value_spk );
}
Else
{
Ac97_write (codec, ac97_rec_gain, output_value_hp );
}

Writel (readl (89c64xx_eint0mask )&(~ (1 <11), 89c64xx_eint0mask); // enable interrupt after deal it
Return irq_handled;
}


The above is OK. In practice, we still find a problem. The plug-in and plug-in earphones have been normal, but the speaker does not sound when it is started for the first time and only played with the speaker, that is to say, it always takes the headset to trigger the Speaker and the headset
Sound? Through the test waveform, we found that there was a headset Input Waveform and the switching was normal. However, there was no waveform in the Power Amplifier input, and it was estimated that the channel was still switched. The reason was that when the sound was played, entered
When you determine sndrv_pcm_stream_playback, The 0x1c register is written as 0xaa,
Overwrite the 0x1200 value required by the speaker, and block this sentence. You can set the print statement in the initiation6400_ac97_trigger:

For (temp = 0x00; temp <= 0x7e; temp + = 0x02)
Initi6400_ac97_read (0, temp );

Read all the register values of 9714 when cmd = 1 starts playing the audio and make a judgment.

========================== Win CE practices ================================== ==================================

Initializing:

IRQ = irq_eint11; // interrupt gpio

DWORD m_dwsysintrhpsense = NULL; // headset switching flag
Handle m_hhpsenseinterrupt = NULL; // the headset switches the interrupt handle.

Handle m_hhpsenseinterruptthread; // headset switch interrupt thread handle

If (! Kerneliocontrol (ioctl_hal_request_sysintr, & IRQ,
Sizeof (DWORD), & m_dwsysintrhpsense, sizeof (DWORD ),
Null) // gpio for interrupt control registration
{
Wav_err (_ T ("[WAV: Err] initinterruptthread (): HP sense ioctl_hal_request_sysintr failed/n/R ")));
M_dwsysintrhpsense = sysintr_undefined;
Return false;
}

M_hhpsenseinterrupt = createevent (null, false, false, null); // initialize the interrupt handle
If (m_hhpsenseinterrupt = NULL)

{
Wav_err (_ T ("[WAV: Err] initinterruptthread (): HP sense createevent () failed/n/R ")));
Return (false );
}

If (! Interruptinitialize (m_dwsysintrhpsense, m_hhpsenseinterrupt, null, 0) // bind the interrupt handle and flag
{
Wav_err (_ T ("[WAV: Err] initinterruptthread (): HP sense interruptinitialize () failed/n/R ")));
Return false;
}

M_hhpsenseinterruptthread = createthread (lpsecurity_attributes) null, 0,
(Lpthread_start_routine) callinterruptthreadhpsense, this, 0, null); // create an interrupt thread

If (m_hhpsenseinterruptthread = NULL) // if no thread is created successfully, return.

{
Wav_err (_ T ("[WAV: Err] initinterruptthread (): HP sense createthread () failed/n/R ")));
Return false;
}

Void callinterruptthreadhpsense (hardwarecontext * phwcontext)
{
Phwcontext-> interruptthreadhpsense (); // call the interrupt processing function through the hardware context
}

Interrupt handling function:

Void hardwarecontext: interruptthreadhpsense ()

{

......

If (! (G_pgpioreg-> gpndat & (1 <11) // If you insert a headset
{
Writecodecregister (wm9713_output_mux, output_value_hp );
Retailmsg (ac97_hp_debug, (_ T ("[WAV:] headphone output/n/R ")));
}

While (true)
{

Waitforsingleobject (m_hhpsenseinterrupt, infinite); // The thread waits for interruption

G_pgpioreg-> eint0mask | = (0x1 <11); // mask eint9, clear interrupt pending
G_pgpioreg-> eint0pend = (0x1 <11); // clear pending eint9

If (g_pgpioreg-> gpndat & (1 <11 ))
{
Writecodecregister (wm9713_output_mux, output_value_spk );
Retailmsg (ac97_hp_debug, (_ T ("[WAV:] Speak output/n/R ")));
}
Else
{
Writecodecregister (wm9713_output_mux, output_value_hp );
Retailmsg (ac97_hp_debug, (_ T ("[WAV:] headphone output/n/R ")));
}
Interruptdone (m_dwsysintrhpsense );
G_pgpioreg-> eint0mask & = ~ (0x1 <11); // unmask eint9, enable interrupt

}

......
}

For this approach, we also need to make a NOTE: For waitforsingleobject in a thread loop, if the event is an event actively set, we need
The setevent function is used to enable events. However, when an interrupt event is bound to an interrupt event, the event becomes a signal when the interrupt occurs passively, so the setevent function is not required.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.