📄 cs4281m.c
字号:
return -EIO; // If no valid data, exit initialization. } // (12), Start digital data transfer of audio data to the codec. writel(ACOSV_SLV3 | ACOSV_SLV4, card->pBA0 + BA0_ACOSV); // (468h) //************************************** // Unmute the Master and Alternate // (headphone) volumes. Set to max. //************************************** cs4281_write_ac97(card, BA0_AC97_HEADPHONE_VOLUME, 0); cs4281_write_ac97(card, BA0_AC97_MASTER_VOLUME, 0); //****************************************** // Power on the DAC(AddDACUser()from main()) //****************************************** cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfdff); // Wait until we sample a DAC ready state. for (temp2 = 0; temp2 < 32; temp2++) { // Let's wait a mil to let things settle. delayus(card,1000); // Read the current state of the power control reg. cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); // If the DAC ready state bit is set, stop waiting. if (temp1 & 0x2) break; } //****************************************** // Power on the ADC(AddADCUser()from main()) //****************************************** cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfeff); // Wait until we sample ADC ready state. for (temp2 = 0; temp2 < 32; temp2++) { // Let's wait a mil to let things settle. delayus(card,1000); // Read the current state of the power control reg. cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); // If the ADC ready state bit is set, stop waiting. if (temp1 & 0x1) break; } // Set up 4281 Register contents that // don't change for boot duration. // For playback, we map AC97 slot 3 and 4(Left // & Right PCM playback) to DMA Channel 0. // Set the fifo to be 15 bytes at offset zero. ac97_slotid = 0x01000f00; // FCR0.RS[4:0]=1(=>slot4, right PCM playback). // FCR0.LS[4:0]=0(=>slot3, left PCM playback). // FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0. writel(ac97_slotid, card->pBA0 + BA0_FCR0); // (180h) writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR0); // Turn on FIFO Enable. // For capture, we map AC97 slot 10 and 11(Left // and Right PCM Record) to DMA Channel 1. // Set the fifo to be 15 bytes at offset sixteen. ac97_slotid = 0x0B0A0f10; // FCR1.RS[4:0]=11(=>slot11, right PCM record). // FCR1.LS[4:0]=10(=>slot10, left PCM record). // FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16. writel(ac97_slotid | FCRn_PSH, card->pBA0 + BA0_FCR1); // (184h) writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR1); // Turn on FIFO Enable. // Map the Playback SRC to the same AC97 slots(3 & 4-- // --Playback left & right)as DMA channel 0. // Map the record SRC to the same AC97 slots(10 & 11-- // -- Record left & right) as DMA channel 1. ac97_slotid = 0x0b0a0100; // SCRSA.PRSS[4:0]=1(=>slot4, right PCM playback). // SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback). // SCRSA.CRSS[4:0]=11(=>slot11, right PCM record) // SCRSA.CLSS[4:0]=10(=>slot10, left PCM record). writel(ac97_slotid, card->pBA0 + BA0_SRCSA); // (75ch) // Set 'Half Terminal Count Interrupt Enable' and 'Terminal // Count Interrupt Enable' in DMA Control Registers 0 & 1. // Set 'MSK' flag to 1 to keep the DMA engines paused. temp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK); // (00030001h) writel(temp1, card->pBA0 + BA0_DCR0); // (154h writel(temp1, card->pBA0 + BA0_DCR1); // (15ch) // Set 'Auto-Initialize Control' to 'enabled'; For playback, // set 'Transfer Type Control'(TR[1:0]) to 'read transfer', // for record, set Transfer Type Control to 'write transfer'. // All other bits set to zero; Some will be changed @ transfer start. temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); // (20000018h) writel(temp1, card->pBA0 + BA0_DMR0); // (150h) temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE); // (20000014h) writel(temp1, card->pBA0 + BA0_DMR1); // (158h) // Enable DMA interrupts generally, and // DMA0 & DMA1 interrupts specifically. temp1 = readl(card->pBA0 + BA0_HIMR) & 0xfffbfcff; writel(temp1, card->pBA0 + BA0_HIMR); CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs4281_hw_init()- 0\n")); return 0;}#ifndef NOT_CS4281_PMstatic void printpm(struct cs4281_state *s){ CS_DBGOUT(CS_PM, 9, printk("pm struct:\n")); CS_DBGOUT(CS_PM, 9, printk("flags:0x%x u32CLKCR1_SAVE: 0%x u32SSPMValue: 0x%x\n", (unsigned)s->pm.flags,s->pm.u32CLKCR1_SAVE,s->pm.u32SSPMValue)); CS_DBGOUT(CS_PM, 9, printk("u32PPLVCvalue: 0x%x u32PPRVCvalue: 0x%x\n", s->pm.u32PPLVCvalue,s->pm.u32PPRVCvalue)); CS_DBGOUT(CS_PM, 9, printk("u32FMLVCvalue: 0x%x u32FMRVCvalue: 0x%x\n", s->pm.u32FMLVCvalue,s->pm.u32FMRVCvalue)); CS_DBGOUT(CS_PM, 9, printk("u32GPIORvalue: 0x%x u32JSCTLvalue: 0x%x\n", s->pm.u32GPIORvalue,s->pm.u32JSCTLvalue)); CS_DBGOUT(CS_PM, 9, printk("u32SSCR: 0x%x u32SRCSA: 0x%x\n", s->pm.u32SSCR,s->pm.u32SRCSA)); CS_DBGOUT(CS_PM, 9, printk("u32DacASR: 0x%x u32AdcASR: 0x%x\n", s->pm.u32DacASR,s->pm.u32AdcASR)); CS_DBGOUT(CS_PM, 9, printk("u32DacSR: 0x%x u32AdcSR: 0x%x\n", s->pm.u32DacSR,s->pm.u32AdcSR)); CS_DBGOUT(CS_PM, 9, printk("u32MIDCR_Save: 0x%x\n", s->pm.u32MIDCR_Save));}static void printpipe(struct cs4281_pipeline *pl){ CS_DBGOUT(CS_PM, 9, printk("pm struct:\n")); CS_DBGOUT(CS_PM, 9, printk("flags:0x%x number: 0%x\n", (unsigned)pl->flags,pl->number)); CS_DBGOUT(CS_PM, 9, printk("u32DBAnValue: 0%x u32DBCnValue: 0x%x\n", pl->u32DBAnValue,pl->u32DBCnValue)); CS_DBGOUT(CS_PM, 9, printk("u32DMRnValue: 0x%x u32DCRnValue: 0x%x\n", pl->u32DMRnValue,pl->u32DCRnValue)); CS_DBGOUT(CS_PM, 9, printk("u32DBAnAddress: 0x%x u32DBCnAddress: 0x%x\n", pl->u32DBAnAddress,pl->u32DBCnAddress)); CS_DBGOUT(CS_PM, 9, printk("u32DCAnAddress: 0x%x u32DCCnAddress: 0x%x\n", pl->u32DCCnAddress,pl->u32DCCnAddress)); CS_DBGOUT(CS_PM, 9, printk("u32DMRnAddress: 0x%x u32DCRnAddress: 0x%x\n", pl->u32DMRnAddress,pl->u32DCRnAddress)); CS_DBGOUT(CS_PM, 9, printk("u32HDSRnAddress: 0x%x u32DBAn_Save: 0x%x\n", pl->u32HDSRnAddress,pl->u32DBAn_Save)); CS_DBGOUT(CS_PM, 9, printk("u32DBCn_Save: 0x%x u32DMRn_Save: 0x%x\n", pl->u32DBCn_Save,pl->u32DMRn_Save)); CS_DBGOUT(CS_PM, 9, printk("u32DCRn_Save: 0x%x u32DCCn_Save: 0x%x\n", pl->u32DCRn_Save,pl->u32DCCn_Save)); CS_DBGOUT(CS_PM, 9, printk("u32DCAn_Save: 0x%x\n", pl->u32DCAn_Save)); CS_DBGOUT(CS_PM, 9, printk("u32FCRn_Save: 0x%x u32FSICn_Save: 0x%x\n", pl->u32FCRn_Save,pl->u32FSICn_Save)); CS_DBGOUT(CS_PM, 9, printk("u32FCRnValue: 0x%x u32FSICnValue: 0x%x\n", pl->u32FCRnValue,pl->u32FSICnValue)); CS_DBGOUT(CS_PM, 9, printk("u32FCRnAddress: 0x%x u32FSICnAddress: 0x%x\n", pl->u32FCRnAddress,pl->u32FSICnAddress)); CS_DBGOUT(CS_PM, 9, printk("u32FPDRnValue: 0x%x u32FPDRnAddress: 0x%x\n", pl->u32FPDRnValue,pl->u32FPDRnAddress));}static void printpipelines(struct cs4281_state *s){ int i; for(i=0;i<CS4281_NUMBER_OF_PIPELINES;i++) { if(s->pl[i].flags & CS4281_PIPELINE_VALID) { printpipe(&s->pl[i]); } }}/****************************************************************************** Suspend - save the ac97 regs, mute the outputs and power down the part. *****************************************************************************/static void cs4281_ac97_suspend(struct cs4281_state *s){ int Count,i; CS_DBGOUT(CS_PM, 9, printk("cs4281: cs4281_ac97_suspend()+\n"));/** change the state, save the current hwptr, then stop the dac/adc*/ s->pm.flags &= ~CS4281_PM_IDLE; s->pm.flags |= CS4281_PM_SUSPENDING; s->pm.u32hwptr_playback = readl(s->pBA0 + BA0_DCA0); s->pm.u32hwptr_capture = readl(s->pBA0 + BA0_DCA1); stop_dac(s); stop_adc(s); for(Count = 0x2, i=0; (Count <= CS4281_AC97_HIGHESTREGTORESTORE) && (i < CS4281_AC97_NUMBER_RESTORE_REGS); Count += 2, i++) { cs4281_read_ac97(s, BA0_AC97_RESET + Count, &s->pm.ac97[i]); }/** Save the ac97 volume registers as well as the current powerdown state.* Now, mute the all the outputs (master, headphone, and mono), as well* as the PCM volume, in preparation for powering down the entire part.*/ cs4281_read_ac97(s, BA0_AC97_MASTER_VOLUME, &s->pm.u32AC97_master_volume); cs4281_read_ac97(s, BA0_AC97_HEADPHONE_VOLUME, &s->pm.u32AC97_headphone_volume); cs4281_read_ac97(s, BA0_AC97_MASTER_VOLUME_MONO, &s->pm.u32AC97_master_volume_mono); cs4281_read_ac97(s, BA0_AC97_PCM_OUT_VOLUME, &s->pm.u32AC97_pcm_out_volume); cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME, 0x8000); cs4281_write_ac97(s, BA0_AC97_HEADPHONE_VOLUME, 0x8000); cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME_MONO, 0x8000); cs4281_write_ac97(s, BA0_AC97_PCM_OUT_VOLUME, 0x8000); cs4281_read_ac97(s, BA0_AC97_POWERDOWN, &s->pm.u32AC97_powerdown); cs4281_read_ac97(s, BA0_AC97_GENERAL_PURPOSE, &s->pm.u32AC97_general_purpose);/** And power down everything on the AC97 codec.*/ cs4281_write_ac97(s, BA0_AC97_POWERDOWN, 0xff00); CS_DBGOUT(CS_PM, 9, printk("cs4281: cs4281_ac97_suspend()-\n"));}/****************************************************************************** Resume - power up the part and restore its registers.. *****************************************************************************/static void cs4281_ac97_resume(struct cs4281_state *s){ int Count,i; CS_DBGOUT(CS_PM, 9, printk("cs4281: cs4281_ac97_resume()+\n"));/* do not save the power state registers at this time // // If we saved away the power control registers, write them into the // shadows so those saved values get restored instead of the current // shadowed value. // if( bPowerStateSaved ) { PokeShadow( 0x26, ulSaveReg0x26 ); bPowerStateSaved = FALSE; }*///// First, we restore the state of the general purpose register. This// contains the mic select (mic1 or mic2) and if we restore this after// we restore the mic volume/boost state and mic2 was selected at// suspend time, we will end up with a brief period of time where mic1// is selected with the volume/boost settings for mic2, causing// acoustic feedback. So we restore the general purpose register// first, thereby getting the correct mic selected before we restore// the mic volume/boost.// cs4281_write_ac97(s, BA0_AC97_GENERAL_PURPOSE, s->pm.u32AC97_general_purpose);//// Now, while the outputs are still muted, restore the state of power// on the AC97 part.// cs4281_write_ac97(s, BA0_AC97_POWERDOWN, s->pm.u32AC97_powerdown);/** Restore just the first set of registers, from register number* 0x02 to the register number that ulHighestRegToRestore specifies.*/ for( Count = 0x2, i=0; (Count <= CS4281_AC97_HIGHESTREGTORESTORE) && (i < CS4281_AC97_NUMBER_RESTORE_REGS); Count += 2, i++) { cs4281_write_ac97(s, BA0_AC97_RESET + Count, s->pm.ac97[i]); } CS_DBGOUT(CS_PM, 9, printk("cs4281: cs4281_ac97_resume()-\n"));}/* do not save the power state registers at this time****************************************************************************** SavePowerState - Save the power registers away. *****************************************************************************void HWAC97codec::SavePowerState(void){ ENTRY(TM_OBJECTCALLS, "HWAC97codec::SavePowerState()\r\n"); ulSaveReg0x26 = PeekShadow(0x26); // // Note that we have saved registers that need to be restored during a // resume instead of ulAC97Regs[]. // bPowerStateSaved = TRUE;} // SavePowerState*/static void cs4281_SuspendFIFO(struct cs4281_state *s, struct cs4281_pipeline *pl){ /* * We need to save the contents of the BASIC FIFO Registers. */ pl->u32FCRn_Save = readl(s->pBA0 + pl->u32FCRnAddress); pl->u32FSICn_Save = readl(s->pBA0 + pl->u32FSICnAddress);}static void cs4281_ResumeFIFO(struct cs4281_state *s, struct cs4281_pipeline *pl){ /* * We need to restore the contents of the BASIC FIFO Registers. */ writel(pl->u32FCRn_Save,s->pBA0 + pl->u32FCRnAddress); writel(pl->u32FSICn_Save,s->pBA0 + pl->u32FSICnAddress);}static void cs4281_SuspendDMAengine(struct cs4281_state *s, struct cs4281_pipeline *pl){ // // We need to save the contents of the BASIC DMA Registers. // pl->u32DBAn_Save = readl(s->pBA0 + pl->u32DBAnAddress); pl->u32DBCn_Save = readl(s->pBA0 + pl->u32DBCnAddress); pl->u32DMRn_Save = readl(s->pBA0 + pl->u32DMRnAddress); pl->u32DCRn_Save = readl(s->pBA0 + pl->u32DCRnAddress); pl->u32DCCn_Save = readl(s->pBA0 + pl->u32DCCnAddress); pl->u32DCAn_Save = readl(s->pBA0 + pl->u32DCAnAddress);}static void cs4281_ResumeDMAengine(struct cs4281_state *s, struct cs4281_pipeline *pl){ // // We need to save the contents of the BASIC DMA Registers. // writel( pl->u32DBAn_Save, s->pBA0 + pl->u32DBAnAddress); writel( pl->u32DBCn_Save, s->pBA0 + pl->u32DBCnAddress); writel( pl->u32DMRn_Save, s->pBA0 + pl->u32DMRnAddress); writel( pl->u32DCRn_Save, s->pBA0 + pl->u32DCRnAddress); writel( pl->u32DCCn_Save, s->pBA0 + pl->u32DCCnAddress); writel( pl->u32DCAn_Save, s->pBA0 + pl->u32DCAnAddress);}static int cs4281_suspend(struct cs4281_state *s){ int i; u32 u32CLKCR1; struct cs4281_pm *pm = &s->pm; CS_DBGOUT(CS_PM | CS_FUNCTION, 9, printk("cs4281: cs4281_suspend()+ flags=%d\n", (unsigned)s->pm.flags));/** check the current state, only suspend if IDLE*/ if(!(s->pm.flags & CS4281_PM_IDLE)) { CS_DBGOUT(CS_PM | CS_ERROR, 2, printk("cs4281: cs4281_suspend() unable to suspend, not IDLE\n")); return 1; } s->pm.flags &= ~CS4281_PM_IDLE; s->pm.flags |= CS4281_PM_SUSPENDING;//// Gershwin CLKRUN - Set CKRA// u32CLKCR1 = readl(s->pBA0 + BA0_CLKCR1); pm->u32CLKCR1_SAVE = u32CLKCR1; if(!(u32CLKCR1 & 0x00010000 ) ) writel(u32CLKCR1 | 0x00010000, s->pBA0 + BA0_CLKCR1);//// First, turn on the clocks (yikes) to the devices, so that they will// respond when we try to save their state.// if(!(u32CLKCR1 & CLKCR1_SWCE)) { writel(u32CLKCR1 | CLKCR1_SWCE , s->pBA0 + BA0_CLKCR1); } // // Save the power state // pm->u32SSPMValue = readl(s->pBA0 + BA0_SSPM); // // Disable interrupts. // writel(HICR_CHGM, s->pBA0 + BA0_HICR); // // Save the PCM Playback Left and Right Volume Control. // pm->u32PPLVCvalue = readl(s->pBA0 + BA0_PPLVC); pm->u32PPRVCvalue = readl(s->pBA0 + BA0_PPRVC); // // Save the FM Synthesis Left and Right Volume Control. // pm->u32FMLVCvalue = readl(s->pBA0 + BA0_FMLVC); pm->u32FMRVCvalue = readl(s->pBA0 + BA0_FMRVC); // // Save the GPIOR value. // pm->u32GPIORvalue = readl(s->pBA0 + BA0_GPIOR); // // Save the JSCTL value. // pm->u32JSCTLvalue = readl(s->pBA0 + BA0_GPIOR); // // Save Sound System Control Register // pm->u32SSCR = readl(s->pBA0 + BA0_SSCR); // // Save SRC Slot Assinment register // pm->u32SRCSA = readl(s->pBA0 + BA0_SRCSA); // // Save sample rate
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -