/* The cs461x has a certain amount of cross channel interaction
so we use a single per card lock */
spinlock_t lock;
+
+ /* Keep AC97 sane */
+ spinlock_t ac97_lock;
/* mixer use count */
atomic_t mixer_use_cnt;
}
/*
- * ganularity is byte boundary, good part.
+ * granularity is byte boundary, good part.
*/
if(dmabuf->enable & DAC_RUNNING)
{
// 2. mark each physical page in range as 'reserved'.
for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
- SetPageReserved(map);
+ cs4x_mem_map_reserve(map);
CS_DBGOUT(CS_PARMS, 9, printk("cs46xx: alloc_dmabuf(): allocated %ld (order = %d) bytes at %p\n",
PAGE_SIZE << order, order, rawbuf) );
// 2. mark each physical page in range as 'reserved'.
for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++)
- SetPageReserved(map);
+ cs4x_mem_map_reserve(map);
return 0;
}
mapend = virt_to_page(dmabuf->rawbuf +
(PAGE_SIZE << dmabuf->buforder) - 1);
for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++)
- ClearPageReserved(map);
+ cs4x_mem_map_unreserve(map);
free_dmabuf(state->card, dmabuf);
}
mapend = virt_to_page(dmabuf->tmpbuff +
(PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1);
for (map = virt_to_page(dmabuf->tmpbuff); map <= mapend; map++)
- ClearPageReserved(map);
+ cs4x_mem_map_unreserve(map);
free_dmabuf2(state->card, dmabuf);
}
break;
if (signal_pending(current))
break;
- if (file->f_flags & O_NONBLOCK) {
- remove_wait_queue(&card->midi.owait, &wait);
- current->state = TASK_RUNNING;
- return -EBUSY;
- }
+ if (file->f_flags & O_NONBLOCK)
+ break;
tmo = (count * HZ) / 3100;
if (!schedule_timeout(tmo ? : 1) && tmo)
printk(KERN_DEBUG "cs46xx: midi timed out??\n");
down(&state->sem);
if (!dmabuf->ready && (ret = __prog_dmabuf(state)))
- goto out;
+ goto out2;
add_wait_queue(&state->dmabuf.wait, &wait);
while (count > 0) {
start_adc(state);
}
out:
- up(&state->sem);
remove_wait_queue(&state->dmabuf.wait, &wait);
+out2:
+ up(&state->sem);
set_current_state(TASK_RUNNING);
CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4,
printk("cs46xx: cs_read()- %d\n",ret) );
state = (struct cs_state *)card->states[1];
if(!state)
return -ENODEV;
+ if (!access_ok(VERIFY_READ, buffer, count))
+ return -EFAULT;
dmabuf = &state->dmabuf;
if (ppos != &file->f_pos)
if (!dmabuf->ready && (ret = __prog_dmabuf(state)))
goto out;
- if (!access_ok(VERIFY_READ, buffer, count))
- {
- ret = -EFAULT;
- goto out;
- }
add_wait_queue(&state->dmabuf.wait, &wait);
ret = 0;
/*
return -ENODEV;
case SNDCTL_DSP_SETDUPLEX:
- return -EINVAL;
+ return 0;
case SNDCTL_DSP_GETODELAY:
if (!(file->f_mode & FMODE_WRITE))
/* Write AC97 codec registers */
-static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg)
+static u16 _cs_ac97_get(struct ac97_codec *dev, u8 reg)
{
struct cs_card *card = dev->private_data;
int count,loopcnt;
unsigned int tmp;
+ u16 ret;
/*
* 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
* 6. Read ACSTS = Status Register = 464h, check VSTS bit
*/
-
cs461x_peekBA0(card, BA0_ACSDA);
/*
"cs46xx: cs_ac97_get() reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n",
reg, cs461x_peekBA0(card, BA0_ACSDA),
cs461x_peekBA0(card, BA0_ACCAD)));
- return(cs461x_peekBA0(card, BA0_ACSDA));
+ ret = cs461x_peekBA0(card, BA0_ACSDA);
+ return ret;
+}
+
+static u16 cs_ac97_get(struct ac97_codec *dev, u8 reg)
+{
+ u16 ret;
+ struct cs_card *card = dev->private_data;
+
+ spin_lock(&card->ac97_lock);
+ ret = _cs_ac97_get(dev, reg);
+ spin_unlock(&card->ac97_lock);
+ return ret;
}
static void cs_ac97_set(struct ac97_codec *dev, u8 reg, u16 val)
int count;
int val2 = 0;
+ spin_lock(&card->ac97_lock);
+
if(reg == AC97_CD_VOL)
{
- val2 = cs_ac97_get(dev, AC97_CD_VOL);
+ val2 = _cs_ac97_get(dev, AC97_CD_VOL);
}
+
/*
* 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
* 2. Write ACCDA = Command Data Register = 470h for data to write to AC97
"cs46xx: AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val));
}
+ spin_unlock(&card->ac97_lock);
+
/*
* Adjust power if the mixer is selected/deselected according
* to the CD.
"cs46xx: cs_ac97_init()+\n") );
for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
- if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL)
+ if ((codec = ac97_alloc_codec()) == NULL)
return -ENOMEM;
- memset(codec, 0, sizeof(struct ac97_codec));
/* initialize some basic codec information, other fields will be filled
in ac97_probe_codec */
eid = cs_ac97_get(codec, AC97_EXTENDED_ID);
- if(eid==0xFFFFFF)
+ if(eid==0xFFFF)
{
printk(KERN_WARNING "cs46xx: codec %d not present\n",num_ac97);
- kfree(codec);
+ ac97_release_codec(codec);
break;
}
if ((codec->dev_mixer = register_sound_mixer(&cs_mixer_fops, -1)) < 0) {
printk(KERN_ERR "cs46xx: couldn't register mixer!\n");
- kfree(codec);
+ ac97_release_codec(codec);
break;
}
card->ac97_codec[num_ac97] = codec;
.name = "Hercules Game Theatre XP",
.amp = amp_hercules,
},
+ {
+ .vendor = 0x1681,
+ .id = 0xa010,
+ .name = "Hercules Fortissimo II",
+ .amp = amp_none,
+ },
/* Not sure if the 570 needs the clkrun hack */
{
.vendor = PCI_VENDOR_ID_IBM,
card->irq = pci_dev->irq;
card->magic = CS_CARD_MAGIC;
spin_lock_init(&card->lock);
+ spin_lock_init(&card->ac97_lock);
pci_set_master(pci_dev);
for (j = 0; j < NR_AC97; j++)
if (card->ac97_codec[j] != NULL) {
unregister_sound_mixer(card->ac97_codec[j]->dev_mixer);
- kfree (card->ac97_codec[j]);
+ ac97_release_codec(card->ac97_codec[j]);
}
mdelay(10 * cs_laptop_wait);
continue;
for (i = 0; i < NR_AC97; i++)
if (card->ac97_codec[i] != NULL) {
unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
- kfree (card->ac97_codec[i]);
+ ac97_release_codec(card->ac97_codec[i]);
}
unregister_sound_dsp(card->dev_audio);
if(card->dev_midi)