--- drivers/sound/trident.c.orig Thu Jun 6 13:07:30 2002 +++ drivers/sound/trident.c Thu Jun 6 13:59:59 2002 @@ -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 @@ -46,7 +49,7 @@ * this chip is often found in settop boxes (combined video+audio) * v0.14.9b * Switch to static inline not extern inline (gcc 3) - * v0.14.9a + * v0.14.9a * Aug 6 2001 Alan Cox * 0.14.9 crashed on rmmod due to a timer/bh left running. Simplified * the existing logic (the BH doesnt help as ac97 is lock_irqsave) @@ -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,80 @@ 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 acquirecodecaccess(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; + 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; - data = ((u32) val) << 16; + 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; + } + udelay(20); - 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 - } - inw(TRID_REG(card, address)); //wait for a read cycle } + if(!block) + { + printk("accesscodecsemaphore : try unlock \n"); + block=1; +goto unlock; + } + printk("accesscodecsemaphore :fail\n"); + return 0; +} - printk(KERN_ERR "ali: AC97 CODEC write timed out.\n"); - spin_unlock_irqrestore(&card->lock, flags); - return; +static void releasecodecaccess(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 waitforstimertick(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(" waitforstimertick :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 +2956,126 @@ mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY; if (secondary) mask |= ALI_AC97_SECONDARY; + + + + + if( !acquirecodecaccess(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)); - } - } - } - inw(TRID_REG(card, address)); //wait a read cycle + + if(!waitforstimertick(card)) + { + printk(" BIT_CLOCK is dead \n"); + goto l; } - spin_unlock_irqrestore(&card->lock, flags); + + 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)); + } + udelay(10); + } + + data = inl(TRID_REG(card, address)); + + return ((u16) (data >> 16)); + + +l: + releasecodecaccess(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(!acquirecodecaccess(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(!waitforstimertick(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: + releasecodecaccess(card); + return; +} + + + + static void ali_enable_special_channel(struct trident_state *stat) { struct trident_card *card = stat->card;