調試WM9714音頻通道切換

來源:互聯網
上載者:User

WM9714的耳機跟喇叭通道切換由寄存器軟體控制,跟之前電視裡面插入耳機讓功放直接拉低關掉外音的方式有點差別。通過設定WM9714的0X1C寄存器的值來切換,其中設定耳機時為0X00A0,設定喇叭時為0X1200。

      電路中有外部上拉固定EINT11為高電平,通過插入耳機將這個外中斷EINT11拉低來觸發中斷,再進行WM9714的寄存器控制。首先在WM9713.C中wm9713_soc_probe()中,添加初始化通道設定和註冊中斷。

#define HdPhone_EintPin  IRQ_EINT(11)
#define HdPhone_GpioPin   S3C64XX_GPN(11) 
#define OUTPUT_VALUE_HP      (0x00a0)
#define OUTPUT_VALUE_SPK (0x1200)

static int wm9713_soc_probe(struct platform_device *pdev)

{

     ......

     s3c_gpio_cfgpin(HdPhone_GpioPin, S3C_GPIO_SFN(2));        //配置GPIO11為外中斷
     s3c_gpio_setpull(HdPhone_GpioPin, S3C_GPIO_PULL_NONE);  //不上拉也不下拉,硬體預設拉高
     set_irq_type(HdPhone_EintPin, IRQ_TYPE_EDGE_BOTH);      //插入跟拔出耳機都會觸發中斷

     if(readl(S3C64XX_GPNDAT)&(1<<11))                                    //如果上電預設是喇叭,設定通道;否則設定耳機
    { 
            ac97_write(codec, AC97_REC_GAIN, OUTPUT_VALUE_SPK);
     }
     else
     {                                                                  
             ac97_write(codec, AC97_REC_GAIN, OUTPUT_VALUE_HP);
      }

      ret = request_irq(HdPhone_EintPin, s3c6400_9713HdSp_irq,    //給EINT11註冊中斷和中斷處理函數,參數包括中斷方式,
                     IRQF_DISABLED, "HdphonSpeak", NULL);                    //中斷名

      if(ret<0)                                                                                       //如果註冊不成功,執行GOTO
     {
             printk(KERN_ERR "request_irq(s3c6400_9713HdSp_irq) failed !!!/n");
             goto irq_err;
      }

      .........

 irq_err:
      free_irq(HdPhone_EintPin,NULL);                                                 //釋放中斷

      .........

}

中斷handler如下:

static irqreturn_t s3c6400_9713HdSp_irq(int irq, void *dev_id)
{
       struct snd_soc_codec *codec = wm9713_dai->codec;          //擷取系統的codec
       writel(readl(S3C64XX_EINT0MASK)|(1<<11),S3C64XX_EINT0MASK); //disable EINT0 Interrupt before deal it
       writel(1<<11,S3C64XX_EINT0PEND);                                    //disable Interrupt

       if(readl(S3C64XX_GPNDAT)&(1<<11))                                   //如果是喇叭,否則是耳機
       {
              ac97_write(codec, AC97_REC_GAIN, OUTPUT_VALUE_SPK);
        }
        else
        { 
               ac97_write(codec, AC97_REC_GAIN, OUTPUT_VALUE_HP);
         }

         writel(readl(S3C64XX_EINT0MASK)&(~(1<<11)),S3C64XX_EINT0MASK); //Enable Interrupt after deal it
         return IRQ_HANDLED;
}

    
以上即OK,在實際中還發現一個問題,插拔耳機切通道一直正常,但是第一次開機和僅僅用喇叭播放時喇叭不出聲,也就是說一直需要耳機觸發後喇叭跟耳機才會
出聲?通過測試波形,發現有耳機輸入波形跟切換正常;但是功放輸入會沒有波形,估計還是切換通道的問題,尋找後原因在於播放聲音時,Entered
s3c6400_ac97_hifi_prepare()中,判斷SNDRV_PCM_STREAM_PLAYBACK會將0X1C寄存器寫成0XAA,
把喇叭所需的0X1200覆蓋,屏蔽這句即可。可通過在s3c6400_ac97_trigger()中,設定列印語句:

for (temp =0x00;temp<=0x7e;temp+=0x02)
     s3c6400_ac97_read(0,temp);

將CMD=1開始播放音頻時9714的寄存器值全部讀出,作出判斷依據。

 ==================WIN CE的做法===============================================

初始化執行中:

Irq = IRQ_EINT11;                                     //中斷GPIO

DWORD  m_dwSysintrHPSense = NULL;    //耳機切換標幟
HANDLE  m_hHPSenseInterrupt = NULL;   //耳機切換中斷控制代碼

HANDLE  m_hHPSenseInterruptThread;    //耳機切換中斷線程控制代碼

if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq,
sizeof(DWORD), &m_dwSysintrHPSense, sizeof(DWORD),
NULL))                               //GPIO作中斷控制註冊
{
        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);     //初始化中斷控制代碼
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))   //綁定中斷控制代碼和標誌
{
       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);  //建立中斷線程

if (m_hHPSenseInterruptThread == NULL)   //如果沒有建立成功線程,返回。

{
       WAV_ERR((_T("[WAV:ERR] InitInterruptThread() : HP sense CreateThread() Failed /n/r")));
       return FALSE;
}

void CallInterruptThreadHPSense(HardwareContext *pHWContext)
{
       pHWContext->InterruptThreadHPSense();    //通過硬體上下文調用中斷處理函數
}

中斷處理函數:

void HardwareContext::InterruptThreadHPSense()

{

       ......

       if(!(g_pGPIOReg->GPNDAT & (1<<11)))     //如果插入耳機
       {
              WriteCodecRegister(WM9713_OUTPUT_MUX, OUTPUT_VALUE_HP);
              RETAILMSG(AC97_HP_DEBUG,(_T("[WAV:] HeadPhone OUTPUT/n/r")));
        }

        while(TRUE)
        {

               WaitForSingleObject(m_hHPSenseInterrupt, INFINITE);   //線程等待中斷髮生

               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

          }

          ......
}

關於WINCE的這種做法,還需要做個說明:針對線上程迴圈中的WaitForSingleObject,如果事件是主動設定的事件,需要
SetEvent函數來使能事件;但對於中斷這類處理,由於綁定了中斷跟事件,只要中斷被動發生,事件就變成有訊號,所以無需SetEvent函數。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.