@@ -36,6 +36,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.14.10 + * June 6 2002 Lei Hu + * rewrite the part to read/write registers of audio codec for Ali5451 * v0.14.9d * October 8 2001 Arnaldo Carvalho de Melo * use set_current_state, properly release resources on failure in @@ -180,7 +183,7 @@ #include -#define DRIVER_VERSION "0.14.9d" +#define DRIVER_VERSION "0.14.10" /* magic numbers to protect our data structures */ #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ @@ -2868,62 +2871,78 @@ return ((u16) (data >> 16)); } -/* Write AC97 codec registers for ALi*/ -static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val) +/* rewrite ac97 read and write mixer register by hulei for ALI*/ +static int ali_acquire_codec_access(struct trident_card * card ) { - unsigned int address, mask; - unsigned int wCount1 = 0xffff; - unsigned int wCount2= 0xffff; - unsigned long chk1, chk2; - unsigned long flags; - u32 data; - - data = ((u32) val) << 16; + u16 wsemamask = 0x6000; /* bit 14..13 */ + u16 wsemabits; + u16 wcontrol ; + int block = 0; + int ncount = 25; + while ( 1 ) + { + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + wsemabits = (wcontrol) & wsemamask; - if(!card) - BUG(); - - address = ALI_AC97_WRITE; - mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY; - if (secondary) - mask |= ALI_AC97_SECONDARY; - if (card->revision == ALI_5451_V02) - mask |= ALI_AC97_WRITE_MIXER_REGISTER; - - spin_lock_irqsave(&card->lock, flags); - while (wCount1--) { - if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_WRITE) == 0) { - data |= (mask | (reg & AC97_REG_ADDR)); - - chk1 = inl(TRID_REG(card, ALI_STIMER)); - chk2 = inl(TRID_REG(card, ALI_STIMER)); - while (wCount2-- && (chk1 == chk2)) - chk2 = inl(TRID_REG(card, ALI_STIMER)); - if (wCount2 == 0) { - spin_unlock_irqrestore(&card->lock, flags); - return; - } - outl(data, TRID_REG(card, address)); //write! - spin_unlock_irqrestore(&card->lock, flags); - return; //success + if (wsemabits == 0x4000) + return 1; /* 0x4000 is audio ,then success */ + if (ncount-- < 0) + break; + if (wsemabits == 0) { +unlock: + outl(((u32)(wcontrol & 0x1eff)|0x00004000), TRID_REG(card, ALI_AC97_WRITE)); + continue; } - inw(TRID_REG(card, address)); //wait for a read cycle + udelay(20); + + } + if (!block) { + printk("ali_acquire_codec_access : try unlock \n"); + block = 1; + goto unlock; } + printk("ali_acquire_codec_access :fail\n"); + return 0; +} - printk(KERN_ERR "ali: AC97 CODEC write timed out.\n"); - spin_unlock_irqrestore(&card->lock, flags); - return; +static void ali_release_codec_access(struct trident_card * card ) +{ + unsigned long wcontrol; + wcontrol = inl(TRID_REG(card, ALI_AC97_WRITE)); + outl((wcontrol & 0xffff1eff),TRID_REG(card, ALI_AC97_WRITE)); +} + +static int ali_waitfor_stimertick(struct trident_card * card ) +{ + unsigned long chk1, chk2; + unsigned int wcount = 0xffff; + chk1 = inl(TRID_REG(card, ALI_STIMER)); + + while(1) + { + chk2 = inl(TRID_REG(card, ALI_STIMER)); + if((wcount > 0)&& chk1 != chk2) + return 1; + if(wcount <= 0) + break; + udelay(50); + + } + printk(" ali_waitfor_stimertick :BIT_CLK is dead \n"); + return 0; } + + + /* Read AC97 codec registers for ALi*/ static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg) { unsigned int address, mask; - unsigned int wCount1 = 0xffff; - unsigned int wCount2= 0xffff; - unsigned long chk1, chk2; - unsigned long flags; + unsigned int ncount; + unsigned long aud_reg; u32 data; + u16 wcontrol; if(!card) BUG(); @@ -2935,37 +2954,120 @@ mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY; if (secondary) mask |= ALI_AC97_SECONDARY; + + + + if( !ali_acquire_codec_access(card)) { + printk(" access codec fail \n"); + + } + + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + wcontrol &= 0xfe00; + wcontrol |= (0x8000 | reg); + outw(wcontrol,TRID_REG(card, ALI_AC97_WRITE)); + + + - spin_lock_irqsave(&card->lock, flags); data = (mask | (reg & AC97_REG_ADDR)); - while (wCount1--) { - if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) { - chk1 = inl(TRID_REG(card, ALI_STIMER)); - chk2 = inl(TRID_REG(card, ALI_STIMER)); - while (wCount2-- && (chk1 == chk2)) - chk2 = inl(TRID_REG(card, ALI_STIMER)); - if (wCount2 == 0) { - printk(KERN_ERR "ali: AC97 CODEC read timed out.\n"); - spin_unlock_irqrestore(&card->lock, flags); - return 0; - } - outl(data, TRID_REG(card, address)); //read! - wCount2 = 0xffff; - while (wCount2--) { - if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) { - data = inl(TRID_REG(card, address)); - spin_unlock_irqrestore(&card->lock, flags); - return ((u16) (data >> 16)); - } - } + + if(!ali_waitfor_stimertick(card)) + { + printk(" BIT_CLOCK is dead \n"); + goto l; + } + + udelay(20); + ncount = 10; + + while(1) + { + if ((inw(TRID_REG(card,ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ) != 0) + break; + if (ncount <= 0) + break; + + if (ncount-- == 1) { + printk("ali_ac97_read :try clear busy flag\n"); + aud_reg = inl(TRID_REG(card, ALI_AC97_WRITE)); + outl((aud_reg & 0xffff7fff), TRID_REG(card, ALI_AC97_WRITE)); } - inw(TRID_REG(card, address)); //wait a read cycle + udelay(10); } - spin_unlock_irqrestore(&card->lock, flags); + + data = inl(TRID_REG(card, address)); + + return ((u16) (data >> 16)); + + +l: + ali_release_codec_access(card); printk(KERN_ERR "ali: AC97 CODEC read timed out.\n"); return 0; } + +/* Write AC97 codec registers for hulei*/ +static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val) +{ + unsigned int address, mask; + unsigned int ncount; + u32 data; + u16 wcontrol; + + data = ((u32) val) << 16; + + if(!card) + BUG(); + + address = ALI_AC97_WRITE; + mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY; + if (secondary) + mask |= ALI_AC97_SECONDARY; + if (card->revision == ALI_5451_V02) + mask |= ALI_AC97_WRITE_MIXER_REGISTER; + + + + if(!ali_acquire_codec_access(card)) + printk("access codec fail \n"); + + + + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + wcontrol &= 0xff00; + wcontrol |= (0x8100|reg);/* bit 8=1: (ali1535 )reserved /ali1535+ write */ + outl(( data |wcontrol), TRID_REG(card,ALI_AC97_WRITE )); + + if(!ali_waitfor_stimertick(card)) { + printk(" BIT_CLOCK is dead \n"); + goto l1; + } + + ncount = 10; + while(1) + { + + wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE)); + if (!wcontrol & 0x8000) + break; + if (ncount <= 0) + break; + if (ncount-- == 1) { + printk(" ali_ac97_set :try clear busy flag!!\n"); + outw(wcontrol & 0x7fff, TRID_REG(card, ALI_AC97_WRITE)); + } + udelay(10); + } + +l1: + ali_release_codec_access(card); + return; +} + + + static void ali_enable_special_channel(struct trident_state *stat) { struct trident_card *card = stat->card;