i810_audio, i845 updates
PATCH 1/1 i810_audio, i845 updates
-implement a codec ID <-> IO register offset mapping -in i810_ioctl, case SNDCTL_DSP_CHANNELS: only touch bits 20:21
off GLOB_CNT (multichannel capabilities)
-AMD 8111 has 6 hw channels so I must have mmio (but I don't have
any docs to verify this)
-minor fixes
Signature · 13 lines
Juergen "George" Sawinski Max-Planck Institute for Medical Research Dept. of Biomedical Optics Jahnstr. 29 D-69120 Heidelberg Germany Phone: +49-6221-486-308 Fax: +49-6221-486-325 priv. Phone: +49-6221-418 858 Mobile: +49-171-532 5302
drivers/sound/i810_audio.c +32 -29
@@ -69,12 +69,12 @@* * ICH 4 caveats * -* The ICH4 has the feature, that the codec ID may not be congruent -* with the AC-link channel. +* The ICH4 has the feature, that the codec ID doesn't have to be +* congruent with the IO connection. * -* Right now, the codec ID is not the real codec ID but the AC-link -* channel. A ID <-> AC-link mapping has still to be implemented. -* +* Therefore, from driver version 0.23 on, there is a "codec ID" <-> +* "IO register base offset" mapping (card->ac97_id_map) field. +* * Juergen "George" Sawinski (jsaw) */
@@ -207,7 +207,7 @@ CAS = 0x34 /* Codec Write Semaphore Register */ }; -ENUM_ENGINE (MC2 ,4 );/* Mic. 2 */ +ENUM_ENGINE (MC2 ,4 );/* Mic In 2 */ ENUM_ENGINE (PI2 ,5 );/* PCM In 2 */ ENUM_ENGINE (SP ,6 );/* S/PDIF */
@@ -234,8 +234,7 @@#define INT_GPI (1<<0)#define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) - -#define DRIVER_VERSION "0.22" +#define DRIVER_VERSION "0.23"/* magic numbers to protect our data structures */ #define I810_CARD_MAGIC 0x5072696E/* "Prin" */
@@ -295,7 +294,7 @@ /*@FIXME to be verified*/ { 2, 0x0000 }, /* SI7012 */ /*@FIXME to be verified*/ { 2, 0x0000 }, /* NVIDIA_NFORCE */ /*@FIXME to be verified*/ { 2, 0x0000 }, /* AMD768 */ - /*@FIXME to be verified*/ { 2, 0x0000 }, /* AMD8111 */ + /*@FIXME to be verified*/ { 3, 0x0001 }, /* AMD8111 */ }; static struct pci_device_id i810_pci_tbl [] __initdata = {
@@ -417,6 +416,7 @@int dev_audio;/* structures for abstraction of hardware facilities, codecs, banks and channels*/ +u16 ac97_id_map[NR_AC97 ];struct ac97_codec *ac97_codec[NR_AC97 ];struct i810_state *states[NR_HW_CH ];struct i810_channel *channel;/* 1:1 to states[] but diff. lifetime */
@@ -449,6 +449,9 @@int initializing; }; +/* extract register offset from codec struct */ +#define IO_REG_OFF (codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id]) +static struct i810_card *devs =NULL ;static int i810_open_mixdev (struct inode *inode,struct file *file);
@@ -1948,13 +1955,13 @@switch ( val ) {case 2 :/* 2 channels is always supported */ -outl (i_glob_cnt &0xcfffff , +outl (i_glob_cnt &0xffcfffff , state->card->iobase +GLOB_CNT );/* Do we need to change mixer settings???? */ break ;case 4 :/* Supported on some chipsets, better check first */ if ( state->card->channels >=4 ) { -outl ((i_glob_cnt &0xcfffff ) |0x100000 , +outl ((i_glob_cnt &0xffcfffff ) |0x100000 , state->card->iobase +GLOB_CNT );/* Do we need to change mixer settings??? */ }else {
@@ -1963,7 +1970,7 @@break ;case 6 :/* Supported on some chipsets, better check first */ if ( state->card->channels >=6 ) { -outl ((i_glob_cnt &0xcfffff ) |0x200000 , +outl ((i_glob_cnt &0xffcfffff ) |0x200000 , state->card->iobase +GLOB_CNT );/* Do we need to change mixer settings??? */ }else {
@@ -2553,8 +2560,7 @@ {struct i810_card *card = dev->private_data;int count =100 ; -u16 reg_set = ((u16 ) reg) &0x7f ; - reg_set |= ((u16 ) dev->id) <<7 ; +u16 reg_set =IO_REG_OFF (dev) | (reg&0x7f );while (count-- && (readb (card->iobase_mmio +CAS ) &1 ))udelay (1 );
@@ -2574,7 +2580,7 @@ {struct i810_card *card = dev->private_data;int count =100 ; -u8 reg_set = ((dev->id)?((reg&0x7f )|0x80 ):(reg&0x7f )); +u16 reg_set =IO_REG_OFF (dev) | (reg&0x7f );while (count-- && (inb (card->iobase +CAS ) &1 ))udelay (1 );
@@ -2586,8 +2592,7 @@ {struct i810_card *card = dev->private_data;int count =100 ; -u16 reg_set = ((u16 ) reg) &0x7f ; - reg_set |= ((u16 ) dev->id) <<7 ; +u16 reg_set =IO_REG_OFF (dev) | (reg&0x7f );while (count-- && (readb (card->iobase_mmio +CAS ) &1 ))udelay (1 );
@@ -2603,7 +2608,7 @@ {struct i810_card *card = dev->private_data;int count =100 ; -u8 reg_set = ((dev->id)?((reg&0x7f )|0x80 ):(reg&0x7f )); +u16 reg_set =IO_REG_OFF (dev) | (reg&0x7f );while (count-- && (inb (card->iobase +CAS ) &1 ))udelay (1 );
@@ -2779,7 +2784,7 @@if ((card->pci_id ==PCI_DEVICE_ID_INTEL_ICH4 ) && (card->use_mmio)) { primary_codec_id = (int )readl (card->iobase_mmio +SDM ) &0x3 ; -printk (KERN_INFO "i810_audio: primary codec id %d\n" , +printk (KERN_INFO "i810_audio: Primary codec has ID %d\n" , primary_codec_id); }
@@ -2803,6 +2808,7 @@int num_ac97 =0 ;int ac97_id;int total_channels =0 ; +int nr_ac97_max = card_cap[card->pci_id_internal].nr_ac97;struct ac97_codec *codec;u16 eid;u32 reg;
@@ -2828,13 +2834,15 @@ reg =inl (card->iobase +GLOB_CNT );outl (reg &0xffcfffff , card->iobase +GLOB_CNT ); -for (num_ac97 =0 ; num_ac97 < card_cap[card->pci_id_internal].nr_ac97; num_ac97++) { +for (num_ac97 =0 ; num_ac97 <NR_AC97 ; num_ac97++) card->ac97_codec[num_ac97] =NULL ; - } -for (num_ac97 =0 ; num_ac97 < card_cap[card->pci_id_internal].nr_ac97; num_ac97++) { +/*@FIXME I don't know, if I'm playing to safe here... (jsaw) */ +if ((nr_ac97_max >2 ) && !card->use_mmio) nr_ac97_max =2 ; + +for (num_ac97 =0 ; num_ac97 < nr_ac97_max; num_ac97++) {/* codec reset */ -printk (KERN_INFO "i810_audio: resetting hw channel %d\n" , num_ac97); +printk (KERN_INFO "i810_audio: Resetting connection %d\n" , num_ac97);if (card->use_mmio)readw (card->ac97base_mmio +0x80 *num_ac97);else inw (card->ac97base +0x80 *num_ac97);
@@ -2846,7 +2854,7 @@if ((card->pci_id ==PCI_DEVICE_ID_INTEL_ICH4 ) && (card->use_mmio)) { ac97_id = (int )readl (card->iobase_mmio +SDM ) &0x3 ; -printk (KERN_INFO "i810_audio: hw channel %d, codec id %d\n" , +printk (KERN_INFO "i810_audio: Connection %d with codec id %d\n" , num_ac97, ac97_id); }else {
@@ -2869,9 +2877,8 @@/* initialize some basic codec information, other fields will be filled in ac97_probe_codec */ codec->private_data = card; - -/*@FIXME this will lead to problems!!! id=2 <-> io offset=0*/ - codec->id = num_ac97; + codec->id = ac97_id; + card->ac97_id_map[ac97_id] = num_ac97 *0x80 ;if (card->use_mmio) { codec->codec_read = i810_ac97_get_mmio;
@@ -2883,7 +2890,7 @@ }if (!i810_ac97_probe_and_powerup (card,codec)) { -printk (KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n" , num_ac97); +printk (KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n" , ac97_id);kfree (codec);break ;/* it didn't work */ }
@@ -2903,7 +2910,7 @@ codec->codec_write (codec,AC97_EXTENDED_MODEM_ID ,0L );if (codec->codec_read (codec,AC97_EXTENDED_MODEM_ID )) { -printk (KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n" , num_ac97); +printk (KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n" , ac97_id);kfree (codec);continue ; }