?? korg1212.c
字號:
u32 RecDataPhy; u32 PlayDataPhy; unsigned long sharedBufferPhy; u32 VolumeTablePhy; u32 RoutingTablePhy; u32 AdatTimeCodePhy; u32 __iomem * statusRegPtr; // address of the interrupt status/control register u32 __iomem * outDoorbellPtr; // address of the host->card doorbell register u32 __iomem * inDoorbellPtr; // address of the card->host doorbell register u32 __iomem * mailbox0Ptr; // address of mailbox 0 on the card u32 __iomem * mailbox1Ptr; // address of mailbox 1 on the card u32 __iomem * mailbox2Ptr; // address of mailbox 2 on the card u32 __iomem * mailbox3Ptr; // address of mailbox 3 on the card u32 __iomem * controlRegPtr; // address of the EEPROM, PCI, I/O, Init ctrl reg u16 __iomem * sensRegPtr; // address of the sensitivity setting register u32 __iomem * idRegPtr; // address of the device and vendor ID registers size_t periodsize; int channels; int currentBuffer; snd_pcm_substream_t *playback_substream; snd_pcm_substream_t *capture_substream; pid_t capture_pid; pid_t playback_pid; CardState cardState; int running; int idleMonitorOn; // indicates whether the card is in idle monitor mode. u32 cmdRetryCount; // tracks how many times we have retried sending to the card. ClockSourceIndex clkSrcRate; // sample rate and clock source ClockSourceType clkSource; // clock source int clkRate; // clock rate int volumePhase[kAudioChannels]; u16 leftADCInSens; // ADC left channel input sensitivity u16 rightADCInSens; // ADC right channel input sensitivity int opencnt; // Open/Close count int setcnt; // SetupForPlay count int playcnt; // TriggerPlay count int errorcnt; // Error Count unsigned long totalerrorcnt; // Total Error Count int dsp_is_loaded; int dsp_stop_is_processed;};MODULE_DESCRIPTION("korg1212");MODULE_LICENSE("GPL");MODULE_SUPPORTED_DEVICE("{{KORG,korg1212}}");static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */module_param_array(index, int, NULL, 0444);MODULE_PARM_DESC(index, "Index value for Korg 1212 soundcard.");module_param_array(id, charp, NULL, 0444);MODULE_PARM_DESC(id, "ID string for Korg 1212 soundcard.");module_param_array(enable, bool, NULL, 0444);MODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard.");MODULE_AUTHOR("Haroldo Gamal <gamal@alternex.com.br>");static struct pci_device_id snd_korg1212_ids[] = { { .vendor = 0x10b5, .device = 0x906d, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, { 0, },};static char* stateName[] = { "Non-existent", "Uninitialized", "DSP download in process", "DSP download complete", "Ready", "Open", "Setup for play", "Playing", "Monitor mode on", "Calibrating", "Invalid"};static char* clockSourceTypeName[] = { "ADAT", "S/PDIF", "local" };static char* clockSourceName[] = { "ADAT at 44.1 kHz", "ADAT at 48 kHz", "S/PDIF at 44.1 kHz", "S/PDIF at 48 kHz", "local clock at 44.1 kHz", "local clock at 48 kHz"};static char* channelName[] = { "ADAT-1", "ADAT-2", "ADAT-3", "ADAT-4", "ADAT-5", "ADAT-6", "ADAT-7", "ADAT-8", "Analog-L", "Analog-R", "SPDIF-L", "SPDIF-R",};static u16 ClockSourceSelector[] = {0x8000, // selects source as ADAT at 44.1 kHz 0x0000, // selects source as ADAT at 48 kHz 0x8001, // selects source as S/PDIF at 44.1 kHz 0x0001, // selects source as S/PDIF at 48 kHz 0x8002, // selects source as local clock at 44.1 kHz 0x0002 // selects source as local clock at 48 kHz };static snd_korg1212rc rc;MODULE_DEVICE_TABLE(pci, snd_korg1212_ids);typedef union swap_u32 { unsigned char c[4]; u32 i; } swap_u32;#ifdef SNDRV_BIG_ENDIANstatic u32 LowerWordSwap(u32 swappee)#elsestatic u32 UpperWordSwap(u32 swappee)#endif{ swap_u32 retVal, swapper; swapper.i = swappee; retVal.c[2] = swapper.c[3]; retVal.c[3] = swapper.c[2]; retVal.c[1] = swapper.c[1]; retVal.c[0] = swapper.c[0]; return retVal.i;}#ifdef SNDRV_BIG_ENDIANstatic u32 UpperWordSwap(u32 swappee)#elsestatic u32 LowerWordSwap(u32 swappee)#endif{ swap_u32 retVal, swapper; swapper.i = swappee; retVal.c[2] = swapper.c[2]; retVal.c[3] = swapper.c[3]; retVal.c[1] = swapper.c[0]; retVal.c[0] = swapper.c[1]; return retVal.i;}#if 0 /* not used */static u32 EndianSwap(u32 swappee){ swap_u32 retVal, swapper; swapper.i = swappee; retVal.c[0] = swapper.c[3]; retVal.c[1] = swapper.c[2]; retVal.c[2] = swapper.c[1]; retVal.c[3] = swapper.c[0]; return retVal.i;}#endif /* not used */#define SetBitInWord(theWord,bitPosition) (*theWord) |= (0x0001 << bitPosition)#define SetBitInDWord(theWord,bitPosition) (*theWord) |= (0x00000001 << bitPosition)#define ClearBitInWord(theWord,bitPosition) (*theWord) &= ~(0x0001 << bitPosition)#define ClearBitInDWord(theWord,bitPosition) (*theWord) &= ~(0x00000001 << bitPosition)static snd_korg1212rc snd_korg1212_Send1212Command(korg1212_t *korg1212, korg1212_dbcnst_t doorbellVal, u32 mailBox0Val, u32 mailBox1Val, u32 mailBox2Val, u32 mailBox3Val){ u32 retryCount; u16 mailBox3Lo; snd_korg1212rc rc = K1212_CMDRET_Success; if (!korg1212->outDoorbellPtr) {#if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: CardUninitialized\n");#endif return K1212_CMDRET_CardUninitialized; }#if K1212_DEBUG_LEVEL > 0 K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- 0x%08x 0x%08x [%s]\n", doorbellVal, mailBox0Val, stateName[korg1212->cardState]);#endif for (retryCount = 0; retryCount < MAX_COMMAND_RETRIES; retryCount++) { writel(mailBox3Val, korg1212->mailbox3Ptr); writel(mailBox2Val, korg1212->mailbox2Ptr); writel(mailBox1Val, korg1212->mailbox1Ptr); writel(mailBox0Val, korg1212->mailbox0Ptr); writel(doorbellVal, korg1212->outDoorbellPtr); // interrupt the card // -------------------------------------------------------------- // the reboot command will not give an acknowledgement. // -------------------------------------------------------------- if ( doorbellVal == K1212_DB_RebootCard || doorbellVal == K1212_DB_BootFromDSPPage4 || doorbellVal == K1212_DB_StartDSPDownload ) { rc = K1212_CMDRET_Success; break; } // -------------------------------------------------------------- // See if the card acknowledged the command. Wait a bit, then // read in the low word of mailbox3. If the MSB is set and the // low byte is equal to the doorbell value, then it ack'd. // -------------------------------------------------------------- udelay(COMMAND_ACK_DELAY); mailBox3Lo = readl(korg1212->mailbox3Ptr); if (mailBox3Lo & COMMAND_ACK_MASK) { if ((mailBox3Lo & DOORBELL_VAL_MASK) == (doorbellVal & DOORBELL_VAL_MASK)) {#if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- Success\n");#endif rc = K1212_CMDRET_Success; break; } } } korg1212->cmdRetryCount += retryCount; if (retryCount >= MAX_COMMAND_RETRIES) {#if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- NoAckFromCard\n");#endif rc = K1212_CMDRET_NoAckFromCard; } return rc;}/* spinlock already held */static void snd_korg1212_SendStop(korg1212_t *korg1212){ if (! korg1212->stop_pending_cnt) { korg1212->sharedBufferPtr->cardCommand = 0xffffffff; /* program the timer */ korg1212->stop_pending_cnt = HZ; korg1212->timer.expires = jiffies + 1; add_timer(&korg1212->timer); }}static void snd_korg1212_SendStopAndWait(korg1212_t *korg1212){ unsigned long flags; spin_lock_irqsave(&korg1212->lock, flags); korg1212->dsp_stop_is_processed = 0; snd_korg1212_SendStop(korg1212); spin_unlock_irqrestore(&korg1212->lock, flags); wait_event_timeout(korg1212->wait, korg1212->dsp_stop_is_processed, (HZ * 3) / 2);}/* timer callback for checking the ack of stop request */static void snd_korg1212_timer_func(unsigned long data){ korg1212_t *korg1212 = (korg1212_t *) data; spin_lock(&korg1212->lock); if (korg1212->sharedBufferPtr->cardCommand == 0) { /* ack'ed */ korg1212->stop_pending_cnt = 0; korg1212->dsp_stop_is_processed = 1; wake_up(&korg1212->wait);#if K1212_DEBUG_LEVEL > 1 K1212_DEBUG_PRINTK("K1212_DEBUG: Stop ack'ed [%s]\n", stateName[korg1212->cardState]);#endif } else { if (--korg1212->stop_pending_cnt > 0) { /* reprogram timer */ korg1212->timer.expires = jiffies + 1; add_timer(&korg1212->timer); } else { snd_printd("korg1212_timer_func timeout\n"); korg1212->sharedBufferPtr->cardCommand = 0; korg1212->dsp_stop_is_processed = 1; wake_up(&korg1212->wait);#if K1212_DEBUG_LEVEL > 0 K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n", stateName[korg1212->cardState]);#endif } } spin_unlock(&korg1212->lock);}static void snd_korg1212_TurnOnIdleMonitor(korg1212_t *korg1212){ unsigned long flags; udelay(INTERCOMMAND_DELAY); spin_lock_irqsave(&korg1212->lock, flags); korg1212->idleMonitorOn = 1; rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, K1212_MODE_MonitorOn, 0, 0, 0); spin_unlock_irqrestore(&korg1212->lock, flags);}static void snd_korg1212_TurnOffIdleMonitor(korg1212_t *korg1212){ if (korg1212->idleMonitorOn) { snd_korg1212_SendStopAndWait(korg1212); korg1212->idleMonitorOn = 0; }}static inline void snd_korg1212_setCardState(korg1212_t * korg1212, CardState csState){ korg1212->cardState = csState;}static int snd_korg1212_OpenCard(korg1212_t * korg1212){#if K1212_DEBUG_LEVEL > 0 K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n", stateName[korg1212->cardState], korg1212->opencnt);#endif down(&korg1212->open_mutex); if (korg1212->opencnt++ == 0) { snd_korg1212_TurnOffIdleMonitor(korg1212); snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); } up(&korg1212->open_mutex); return 1;}static int snd_korg1212_CloseCard(korg1212_t * korg1212){#if K1212_DEBUG_LEVEL > 0 K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n", stateName[korg1212->cardState], korg1212->opencnt);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -