From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: Linux driver for cs4281 with TWO cs4299 codecs? Date: Wed, 22 May 2002 20:11:55 +0200 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: Mime-Version: 1.0 (generated by SEMI 1.14.3 - "Ushinoya") Content-Type: multipart/mixed; boundary="Multipart_Wed_May_22_20:11:55_2002-1" Return-path: In-Reply-To: Errors-To: alsa-devel-admin@lists.sourceforge.net List-Help: List-Post: List-Subscribe: , List-Unsubscribe: , List-Archive: To: tomasz motylewski Cc: twoller@crystal.cirrus.com, pcaudio@crystal.cirrus.com, alsa-devel@lists.sourceforge.net, peter wachtendorf List-Id: alsa-devel@alsa-project.org --Multipart_Wed_May_22_20:11:55_2002-1 Content-Type: text/plain; charset=US-ASCII Hi, At Wed, 22 May 2002 17:59:55 +0200 (CEST), tomasz motylewski wrote: > > > I hope you do not mind that I have contacted you directly. > > I would like to ask whether anyone has developed a driver for cs4281 working in > a dual codec sound card. > > We have developed such a card, and it works fine with a single cs4299 codec, > but current alsa-driver-0.9.0rc1 fails with: > > ALSA ../alsa-kernel/pci/cs4281.c:1455: DLLRDY not seen > CS4281 soundcard not found or device busy > > when we connect another codec configured as slave (no quartz signal on > secondary, but SYNC, BIT_CLK, SDATA_OUT, SDATA_IN, RESET connected). > > I have tried to increase the timeout to 1 s, but without any result. > > Any advice? ALSA driver still doesn't support secondary codec, so most likely it's a driver problem. according to the cirrus' doc, ASDI2E and TCID must be set for the secondary codec before the loop checking DLLRDY. ok, now i did a very very quick hack. could you try the attached patch? (you'll need to pass the module option snd_dual_codec=1) it doesn't change the TCID value (it was set to 1). it might be different value. tune as you like. Takashi --Multipart_Wed_May_22_20:11:55_2002-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="cs4281-dual-codec.dif" Content-Transfer-Encoding: 7bit Index: alsa-kernel/pci/cs4281.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/pci/cs4281.c,v retrieving revision 1.15 diff -u -r1.15 cs4281.c --- alsa-kernel/pci/cs4281.c 21 May 2002 09:33:23 -0000 1.15 +++ alsa-kernel/pci/cs4281.c 22 May 2002 17:57:22 -0000 @@ -50,6 +50,7 @@ static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ +static int snd_dual_codec[SNDRV_CARDS]; /* dual codec */ MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM_DESC(snd_index, "Index value for CS4281 soundcard."); @@ -60,6 +61,9 @@ MODULE_PARM(snd_enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM_DESC(snd_enable, "Enable CS4281 soundcard."); MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC); +MODULE_PARM(snd_dual_codec, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(snd_dual_codec, "Enable Dual Codec."); +MODULE_PARM_SYNTAX(snd_dual_codec, SNDRV_BOOLEAN_FALSE_DESC); /* * @@ -473,7 +477,10 @@ struct resource *ba0_res; struct resource *ba1_res; + int dual_codec; + ac97_t *ac97; + ac97_t *ac97_secondary; struct pci_dev *pci; snd_card_t *card; @@ -577,7 +584,7 @@ snd_cs4281_pokeBA0(chip, BA0_ACCAD, reg); snd_cs4281_pokeBA0(chip, BA0_ACCDA, val); snd_cs4281_pokeBA0(chip, BA0_ACCTL, BA0_ACCTL_DCV | BA0_ACCTL_VFRM | - BA0_ACCTL_ESYN); + BA0_ACCTL_ESYN | (ac97->num ? BA0_ACCTL_TC : 0)); for (count = 0; count < 2000; count++) { /* * First, we want to wait for a short time. @@ -610,7 +617,7 @@ * 6. Read ACSTS = Status Register = 464h, check VSTS bit */ - snd_cs4281_peekBA0(chip, BA0_ACSDA); + snd_cs4281_peekBA0(chip, ac97->num ? BA0_ACSDA2 : BA0_ACSDA); /* * Setup the AC97 control registers on the CS461x to send the @@ -628,7 +635,8 @@ snd_cs4281_pokeBA0(chip, BA0_ACCAD, reg); snd_cs4281_pokeBA0(chip, BA0_ACCDA, 0); snd_cs4281_pokeBA0(chip, BA0_ACCTL, BA0_ACCTL_DCV | BA0_ACCTL_CRW | - BA0_ACCTL_VFRM | BA0_ACCTL_ESYN); + BA0_ACCTL_VFRM | BA0_ACCTL_ESYN | + (ac97->num ? BA0_ACCTL_TC : 0)); /* @@ -661,7 +669,7 @@ * ACSTS = Status Register = 464h * VSTS - Valid Status */ - if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_VSTS) + if (snd_cs4281_peekBA0(chip, ac97->num ? BA0_ACSTS2 : BA0_ACSTS) & BA0_ACSTS_VSTS) goto __ok2; udelay(10); } @@ -675,7 +683,7 @@ * Read the data returned from the AC97 register. * ACSDA = Status Data Register = 474h */ - result = snd_cs4281_peekBA0(chip, BA0_ACSDA); + result = snd_cs4281_peekBA0(chip, ac97->num ? BA0_ACSDA2 : BA0_ACSDA); __end: return result; @@ -1021,7 +1029,10 @@ static void snd_cs4281_mixer_free_ac97(ac97_t *ac97) { cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return); - chip->ac97 = NULL; + if (ac97->num) + chip->ac97_secondary = NULL; + else + chip->ac97 = NULL; } static int __devinit snd_cs4281_mixer(cs4281_t * chip) @@ -1037,6 +1048,11 @@ ac97.private_free = snd_cs4281_mixer_free_ac97; if ((err = snd_ac97_mixer(card, &ac97, &chip->ac97)) < 0) return err; + if (chip->dual_codec) { + ac97.num = 1; + if ((err = snd_ac97_mixer(card, &ac97, &chip->ac97_secondary)) < 0) + return err; + } return 0; } @@ -1324,7 +1340,8 @@ static int __devinit snd_cs4281_create(snd_card_t * card, struct pci_dev *pci, - cs4281_t ** rchip) + cs4281_t ** rchip, + int dual_codec) { cs4281_t *chip; unsigned int tmp; @@ -1347,6 +1364,7 @@ chip->ba0_addr = pci_resource_start(pci, 0); chip->ba1_addr = pci_resource_start(pci, 1); pci_set_master(pci); + chip->dual_codec = dual_codec; if ((chip->ba0_res = request_mem_region(chip->ba0_addr, CS4281_BA0_SIZE, "CS4281 BA0")) == NULL) { snd_cs4281_free(chip); @@ -1426,6 +1444,9 @@ snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN); snd_cs4281_delay(50000); + if (chip->dual_codec) + snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN | BA0_SPMC_ASDI2E); + /* * Set the serial port timing configuration. */ @@ -1486,6 +1507,18 @@ return -EIO; __ok1: + if (chip->dual_codec) { + end_time = (jiffies + (3 * HZ) / 4) + 1; + do { + if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY) + goto __codec2_ok; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } while (end_time - (signed long)jiffies >= 0); + snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n"); + chip->dual_codec = 0; + __codec2_ok: ; + } /* * Assert the valid frame signal so that we can start sending commands @@ -1836,7 +1869,7 @@ if (card == NULL) return -ENOMEM; - if ((err = snd_cs4281_create(card, pci, &chip)) < 0) { + if ((err = snd_cs4281_create(card, pci, &chip, snd_dual_codec[dev])) < 0) { snd_card_free(card); return err; } --Multipart_Wed_May_22_20:11:55_2002-1-- _______________________________________________________________ Don't miss the 2002 Sprint PCS Application Developer's Conference August 25-28 in Las Vegas -- http://devcon.sprintpcs.com/adp/index.cfm