]> Pileus Git - ~andy/linux/blobdiff - sound/isa/wss/wss_lib.c
Merge branch 'master' into next
[~andy/linux] / sound / isa / wss / wss_lib.c
index f2df77bd1308ca96d6bcf8d9f2769737e6d18908..3d6c5f2838af41156d7cd8d07f480e58f7dd6e04 100644 (file)
@@ -282,7 +282,7 @@ static void snd_wss_debug(struct snd_wss *chip)
        printk(KERN_DEBUG
                "CS4231 REGS:      INDEX = 0x%02x  "
                "                 STATUS = 0x%02x\n",
-                                       wss_inb(chip, CS4231P(REGSEL),
+                                       wss_inb(chip, CS4231P(REGSEL)),
                                        wss_inb(chip, CS4231P(STATUS)));
        printk(KERN_DEBUG
                "  0x00: left input      = 0x%02x  "
@@ -574,7 +574,7 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
 {
        unsigned long flags;
 
-       mute = mute ? 1 : 0;
+       mute = mute ? 0x80 : 0;
        spin_lock_irqsave(&chip->reg_lock, flags);
        if (chip->calibrate_mute == mute) {
                spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -589,34 +589,34 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
                             chip->image[CS4231_LOOPBACK]);
        }
        snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT,
-                    mute ? 0x80 : chip->image[CS4231_AUX1_LEFT_INPUT]);
+                    mute | chip->image[CS4231_AUX1_LEFT_INPUT]);
        snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT,
-                    mute ? 0x80 : chip->image[CS4231_AUX1_RIGHT_INPUT]);
+                    mute | chip->image[CS4231_AUX1_RIGHT_INPUT]);
        snd_wss_dout(chip, CS4231_AUX2_LEFT_INPUT,
-                    mute ? 0x80 : chip->image[CS4231_AUX2_LEFT_INPUT]);
+                    mute | chip->image[CS4231_AUX2_LEFT_INPUT]);
        snd_wss_dout(chip, CS4231_AUX2_RIGHT_INPUT,
-                    mute ? 0x80 : chip->image[CS4231_AUX2_RIGHT_INPUT]);
+                    mute | chip->image[CS4231_AUX2_RIGHT_INPUT]);
        snd_wss_dout(chip, CS4231_LEFT_OUTPUT,
-                    mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]);
+                    mute | chip->image[CS4231_LEFT_OUTPUT]);
        snd_wss_dout(chip, CS4231_RIGHT_OUTPUT,
-                    mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]);
+                    mute | chip->image[CS4231_RIGHT_OUTPUT]);
        if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
                snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
-                            mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);
+                            mute | chip->image[CS4231_LEFT_LINE_IN]);
                snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
-                            mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);
+                            mute | chip->image[CS4231_RIGHT_LINE_IN]);
                snd_wss_dout(chip, CS4231_MONO_CTRL,
                             mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
        }
        if (chip->hardware == WSS_HW_INTERWAVE) {
                snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT,
-                            mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]);
+                            mute | chip->image[CS4231_LEFT_MIC_INPUT]);
                snd_wss_dout(chip, CS4231_RIGHT_MIC_INPUT,
-                            mute ? 0x80 : chip->image[CS4231_RIGHT_MIC_INPUT]);
+                            mute | chip->image[CS4231_RIGHT_MIC_INPUT]);
                snd_wss_dout(chip, CS4231_LINE_LEFT_OUTPUT,
-                       mute ? 0x80 : chip->image[CS4231_LINE_LEFT_OUTPUT]);
+                            mute | chip->image[CS4231_LINE_LEFT_OUTPUT]);
                snd_wss_dout(chip, CS4231_LINE_RIGHT_OUTPUT,
-                       mute ? 0x80 : chip->image[CS4231_LINE_RIGHT_OUTPUT]);
+                            mute | chip->image[CS4231_LINE_RIGHT_OUTPUT]);
        }
        chip->calibrate_mute = mute;
        spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1147,77 +1147,84 @@ static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *subst
 
 static int snd_ad1848_probe(struct snd_wss *chip)
 {
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        unsigned long flags;
-       int i, id, rev, ad1847;
+       unsigned char r;
+       unsigned short hardware = 0;
+       int err = 0;
+       int i;
 
-       id = 0;
-       ad1847 = 0;
-       for (i = 0; i < 1000; i++) {
-               mb();
-               if (inb(chip->port + CS4231P(REGSEL)) & CS4231_INIT)
-                       msleep(1);
-               else {
-                       spin_lock_irqsave(&chip->reg_lock, flags);
-                       snd_wss_out(chip, CS4231_MISC_INFO, 0x00);
-                       snd_wss_out(chip, CS4231_LEFT_INPUT, 0xaa);
-                       snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x45);
-                       rev = snd_wss_in(chip, CS4231_RIGHT_INPUT);
-                       if (rev == 0x65) {
-                               spin_unlock_irqrestore(&chip->reg_lock, flags);
-                               id = 1;
-                               ad1847 = 1;
-                               break;
-                       }
-                       if (snd_wss_in(chip, CS4231_LEFT_INPUT) == 0xaa &&
-                           rev == 0x45) {
-                               spin_unlock_irqrestore(&chip->reg_lock, flags);
-                               id = 1;
-                               break;
-                       }
-                       spin_unlock_irqrestore(&chip->reg_lock, flags);
-               }
+       while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
+               if (time_after(jiffies, timeout))
+                       return -ENODEV;
+               cond_resched();
        }
-       if (id != 1)
-               return -ENODEV; /* no valid device found */
-       id = 0;
-       if (chip->hardware == WSS_HW_DETECT)
-               id = ad1847 ? WSS_HW_AD1847 : WSS_HW_AD1848;
-
        spin_lock_irqsave(&chip->reg_lock, flags);
-       inb(chip->port + CS4231P(STATUS));      /* clear any pendings IRQ */
-       outb(0, chip->port + CS4231P(STATUS));
-       mb();
-       if (id == WSS_HW_AD1848) {
-               /* check if there are more than 16 registers */
-               rev = snd_wss_in(chip, CS4231_MISC_INFO);
-               snd_wss_out(chip, CS4231_MISC_INFO, 0x40);
-               for (i = 0; i < 16; ++i) {
-                       if (snd_wss_in(chip, i) != snd_wss_in(chip, i + 16)) {
-                               id = WSS_HW_CMI8330;
-                               break;
-                       }
+
+       /* set CS423x MODE 1 */
+       snd_wss_dout(chip, CS4231_MISC_INFO, 0);
+
+       snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0x45); /* 0x55 & ~0x10 */
+       r = snd_wss_in(chip, CS4231_RIGHT_INPUT);
+       if (r != 0x45) {
+               /* RMGE always high on AD1847 */
+               if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) {
+                       err = -ENODEV;
+                       goto out;
+               }
+               hardware = WSS_HW_AD1847;
+       } else {
+               snd_wss_dout(chip, CS4231_LEFT_INPUT,  0xaa);
+               r = snd_wss_in(chip, CS4231_LEFT_INPUT);
+               /* L/RMGE always low on AT2320 */
+               if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) {
+                       err = -ENODEV;
+                       goto out;
                }
-               snd_wss_out(chip, CS4231_MISC_INFO, 0x00);
-               if (id != WSS_HW_CMI8330 && (rev & 0x80))
-                       id = WSS_HW_CS4248;
-               if (id == WSS_HW_CMI8330 && (rev & 0x0f) != 0x0a)
-                       id = 0;
        }
-       if (id == WSS_HW_CMI8330) {
-               /* verify it is not CS4231 by changing the version register */
-               /* on CMI8330 it is volume control register and can be set 0 */
-               snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
-               snd_wss_dout(chip, CS4231_VERSION, 0x00);
-               rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
-               if (rev)
-                       id = 0;
-               snd_wss_out(chip, CS4231_MISC_INFO, 0);
+
+       /* clear pending IRQ */
+       wss_inb(chip, CS4231P(STATUS));
+       wss_outb(chip, CS4231P(STATUS), 0);
+       mb();
+
+       if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT)
+               goto out;
+
+       if (hardware) {
+               chip->hardware = hardware;
+               goto out;
        }
-       if (id)
-               chip->hardware = id;
 
+       r = snd_wss_in(chip, CS4231_MISC_INFO);
+
+       /* set CS423x MODE 2 */
+       snd_wss_dout(chip, CS4231_MISC_INFO, CS4231_MODE2);
+       for (i = 0; i < 16; i++) {
+               if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) {
+                       /* we have more than 16 registers: check ID */
+                       if ((r & 0xf) != 0xa)
+                               goto out_mode;
+                       /*
+                        * on CMI8330, CS4231_VERSION is volume control and
+                        * can be set to 0
+                        */
+                       snd_wss_dout(chip, CS4231_VERSION, 0);
+                       r = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
+                       if (!r)
+                               chip->hardware = WSS_HW_CMI8330;
+                       goto out_mode;
+               }
+       }
+       if (r & 0x80)
+               chip->hardware = WSS_HW_CS4248;
+       else
+               chip->hardware = WSS_HW_AD1848;
+out_mode:
+       snd_wss_dout(chip, CS4231_MISC_INFO, 0);
+out:
        spin_unlock_irqrestore(&chip->reg_lock, flags);
-       return 0;               /* all things are ok.. */
+       return err;
 }
 
 static int snd_wss_probe(struct snd_wss *chip)
@@ -1866,10 +1873,6 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
        if (err < 0)
                return err;
 
-       spin_lock_init(&chip->reg_lock);
-       mutex_init(&chip->mce_mutex);
-       mutex_init(&chip->open_mutex);
-
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
 
@@ -1943,7 +1946,8 @@ static int snd_wss_info_mux(struct snd_kcontrol *kcontrol,
        char **ptexts = texts;
        struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
 
-       snd_assert(chip->card != NULL, return -EINVAL);
+       if (snd_BUG_ON(!chip->card))
+               return -EINVAL;
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 2;
        uinfo->value.enumerated.items = 4;
@@ -2259,7 +2263,8 @@ int snd_wss_mixer(struct snd_wss *chip)
        unsigned int idx;
        int err;
 
-       snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
+       if (snd_BUG_ON(!chip || !chip->pcm))
+               return -EINVAL;
 
        card = chip->card;