From: Pete Zaitcev <zaitcev@redhat.com>
To: Jeff Garzik <jgarzik@mandrakesoft.com>
Cc: Pete Zaitcev <zaitcev@redhat.com>, linux-kernel@vger.kernel.org
Subject: Re: Patch for PM in ymfpci (against 2.4.5-pre3)
Date: Fri, 25 May 2001 01:51:38 -0400 [thread overview]
Message-ID: <20010525015138.A30235@devserv.devel.redhat.com> (raw)
In-Reply-To: <20010525002936.A27051@devserv.devel.redhat.com> <3B0DE906.7AB3107C@mandrakesoft.com>
In-Reply-To: <3B0DE906.7AB3107C@mandrakesoft.com>; from jgarzik@mandrakesoft.com on Fri, May 25, 2001 at 01:09:26AM -0400
> From: Jeff Garzik <jgarzik@mandrakesoft.com>
> Looks ok, only a small nit: an include and 'pmdev' are left over from
> the older PM implementation, and can be removed.
Oops, here's a better one.
-- Pete
---------------------------------------------------------------------
PM support for suspend/resume (without pm_register, proper PCI API);
Killed some P3's;
Removed unused unit.error;
Removed access_ok;
diff -ur -X dontdiff linux-2.4.5-pre3/drivers/sound/ymfpci.c linux-2.4.5-pre3-p3/drivers/sound/ymfpci.c
--- linux-2.4.5-pre3/drivers/sound/ymfpci.c Fri May 18 14:09:46 2001
+++ linux-2.4.5-pre3-p3/drivers/sound/ymfpci.c Thu May 24 22:12:27 2001
@@ -23,10 +23,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* TODO:
- * - Use P44Slot for 44.1 playback.
+ * - Use P44Slot for 44.1 playback (beware of idle buzzing in P44Slot).
* - 96KHz playback for DVD - use pitch of 2.0.
- * - uLaw for Sun apps.
- * : Alan says firmly "no software format conversion in kernel".
* - Retain DMA buffer on close, do not wait the end of frame.
* - Cleanup
* ? underused structure members
@@ -66,14 +64,19 @@
#endif
#include "ymfpci.h"
-static int ymf_playback_trigger(ymfpci_t *codec, struct ymf_pcm *ypcm, int cmd);
+static int ymf_playback_trigger(ymfpci_t *unit, struct ymf_pcm *ypcm, int cmd);
static void ymf_capture_trigger(ymfpci_t *unit, struct ymf_pcm *ypcm, int cmd);
-static void ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice);
+static void ymfpci_voice_free(ymfpci_t *unit, ymfpci_voice_t *pvoice);
static int ymf_capture_alloc(struct ymf_unit *unit, int *pbank);
static int ymf_playback_prepare(struct ymf_state *state);
static int ymf_capture_prepare(struct ymf_state *state);
static struct ymf_state *ymf_state_alloc(ymfpci_t *unit);
+static void ymfpci_aclink_reset(struct pci_dev * pci);
+static void ymfpci_disable_dsp(ymfpci_t *unit);
+static void ymfpci_download_image(ymfpci_t *codec);
+static void ymf_memload(ymfpci_t *unit);
+
static LIST_HEAD(ymf_devs);
/*
@@ -330,7 +333,7 @@
spin_lock_irqsave(&state->unit->reg_lock, flags);
dmabuf->hwptr = dmabuf->swptr = 0;
dmabuf->total_bytes = 0;
- dmabuf->count = dmabuf->error = 0;
+ dmabuf->count = 0;
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
/* allocate DMA buffer if not allocated yet */
@@ -810,8 +813,6 @@
end >>= 1;
if (w_16)
end >>= 1;
-/* P3 */ // printk("ymf_pcm_init_voice: %d: Rate %d Format 0x%08x Delta 0x%x End 0x%x\n",
-// voice->number, rate, format, delta, end);
for (nbank = 0; nbank < 2; nbank++) {
bank = &voice->bank[nbank];
bank->format = format;
@@ -907,7 +908,7 @@
if ((err = ymfpci_pcm_voice_alloc(ypcm, state->format.voices)) < 0) {
/* Somebody started 32 mpg123's in parallel? */
- /* P3 */ printk("ymfpci%d: cannot allocate voice\n",
+ printk(KERN_INFO "ymfpci%d: cannot allocate voice\n",
state->unit->dev_audio);
return err;
}
@@ -1178,6 +1179,7 @@
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
struct ymf_dmabuf *dmabuf = &state->rpcm.dmabuf;
+ struct ymf_unit *unit = state->unit;
DECLARE_WAITQUEUE(waita, current);
ssize_t ret;
unsigned long flags;
@@ -1190,18 +1192,26 @@
return -ENXIO;
if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
return ret;
- if (!access_ok(VERIFY_WRITE, buffer, count))
- return -EFAULT;
ret = 0;
add_wait_queue(&dmabuf->wait, &waita);
while (count > 0) {
- spin_lock_irqsave(&state->unit->reg_lock, flags);
+ spin_lock_irqsave(&unit->reg_lock, flags);
+ if (unit->suspended) {
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret) ret = -EAGAIN;
+ break;
+ }
+ continue;
+ }
swptr = dmabuf->swptr;
cnt = dmabuf->dmasize - swptr;
if (dmabuf->count < cnt)
cnt = dmabuf->count;
- spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
if (cnt > count)
cnt = count;
@@ -1240,7 +1250,7 @@
}
spin_unlock_irqrestore(&state->unit->reg_lock, flags);
if (signal_pending(current)) {
- ret = ret ? ret : -ERESTARTSYS;
+ if (!ret) ret = -ERESTARTSYS;
break;
}
continue;
@@ -1253,19 +1263,24 @@
swptr = (swptr + cnt) % dmabuf->dmasize;
- spin_lock_irqsave(&state->unit->reg_lock, flags);
+ spin_lock_irqsave(&unit->reg_lock, flags);
+ if (unit->suspended) {
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
+ continue;
+ }
+
dmabuf->swptr = swptr;
dmabuf->count -= cnt;
- // spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ // spin_unlock_irqrestore(&unit->reg_lock, flags);
count -= cnt;
buffer += cnt;
ret += cnt;
- // spin_lock_irqsave(&state->unit->reg_lock, flags);
+ // spin_lock_irqsave(&unit->reg_lock, flags);
if (!state->rpcm.running) {
- ymf_capture_trigger(state->unit, &state->rpcm, 1);
+ ymf_capture_trigger(unit, &state->rpcm, 1);
}
- spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&dmabuf->wait, &waita);
@@ -1278,6 +1293,7 @@
{
struct ymf_state *state = (struct ymf_state *)file->private_data;
struct ymf_dmabuf *dmabuf = &state->wpcm.dmabuf;
+ struct ymf_unit *unit = state->unit;
DECLARE_WAITQUEUE(waita, current);
ssize_t ret;
unsigned long flags;
@@ -1294,8 +1310,6 @@
return -ENXIO;
if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
return ret;
- if (!access_ok(VERIFY_READ, buffer, count))
- return -EFAULT;
ret = 0;
/*
@@ -1310,7 +1324,17 @@
add_wait_queue(&dmabuf->wait, &waita);
while (count > 0) {
- spin_lock_irqsave(&state->unit->reg_lock, flags);
+ spin_lock_irqsave(&unit->reg_lock, flags);
+ if (unit->suspended) {
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret) ret = -EAGAIN;
+ break;
+ }
+ continue;
+ }
if (dmabuf->count < 0) {
printk(KERN_ERR
"ymf_write: count %d, was legal in cs46xx\n",
@@ -1342,7 +1366,7 @@
cnt = dmabuf->dmasize - swptr;
if (dmabuf->count + cnt > dmabuf->dmasize - redzone)
cnt = (dmabuf->dmasize - redzone) - dmabuf->count;
- spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
if (cnt > count)
cnt = count;
@@ -1353,11 +1377,11 @@
* buffer is full, start the dma machine and
* wait for data to be played
*/
- spin_lock_irqsave(&state->unit->reg_lock, flags);
+ spin_lock_irqsave(&unit->reg_lock, flags);
if (!state->wpcm.running) {
- ymf_playback_trigger(state->unit, &state->wpcm, 1);
+ ymf_playback_trigger(unit, &state->wpcm, 1);
}
- spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
if (file->f_flags & O_NONBLOCK) {
if (!ret) ret = -EAGAIN;
break;
@@ -1379,7 +1403,11 @@
swptr -= dmabuf->dmasize;
}
- spin_lock_irqsave(&state->unit->reg_lock, flags);
+ spin_lock_irqsave(&unit->reg_lock, flags);
+ if (unit->suspended) {
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
+ continue;
+ }
dmabuf->swptr = swptr;
dmabuf->count += cnt;
@@ -1393,10 +1421,10 @@
delay = state->format.rate / 20; /* 50ms */
delay <<= state->format.shift;
if (dmabuf->count >= delay && !state->wpcm.running) {
- ymf_playback_trigger(state->unit, &state->wpcm, 1);
+ ymf_playback_trigger(unit, &state->wpcm, 1);
}
- spin_unlock_irqrestore(&state->unit->reg_lock, flags);
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
count -= cnt;
buffer += cnt;
@@ -1621,7 +1649,6 @@
case SNDCTL_DSP_CHANNELS:
if (get_user(val, (int *)arg))
return -EFAULT;
- /* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_CHANNELS 0x%x\n", val); */
if (val != 0) {
if (file->f_mode & FMODE_WRITE) {
ymf_wait_dac(state);
@@ -2016,6 +2043,77 @@
};
/*
+ */
+
+static void ymf_suspend(struct pci_dev *pcidev)
+{
+ struct ymf_unit *unit = pci_get_drvdata(pcidev);
+ unsigned long flags;
+ struct ymf_dmabuf *dmabuf;
+ struct list_head *p;
+ struct ymf_state *state;
+
+ spin_lock_irqsave(&unit->reg_lock, flags);
+
+ unit->suspended = 1;
+
+ list_for_each(p, &unit->states) {
+ state = list_entry(p, struct ymf_state, chain);
+
+ dmabuf = &state->wpcm.dmabuf;
+ dmabuf->hwptr = dmabuf->swptr = 0;
+ dmabuf->total_bytes = 0;
+ dmabuf->count = 0;
+
+ dmabuf = &state->rpcm.dmabuf;
+ dmabuf->hwptr = dmabuf->swptr = 0;
+ dmabuf->total_bytes = 0;
+ dmabuf->count = 0;
+ }
+
+ ymfpci_writel(unit, YDSXGR_NATIVEDACOUTVOL, 0);
+ ymfpci_disable_dsp(unit);
+
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
+}
+
+static void ymf_resume(struct pci_dev *pcidev)
+{
+ struct ymf_unit *unit = pci_get_drvdata(pcidev);
+ unsigned long flags;
+ struct list_head *p;
+ struct ymf_state *state;
+
+ ymfpci_aclink_reset(unit->pci);
+ ymfpci_codec_ready(unit, 0, 1); /* prints diag if not ready. */
+
+#ifdef CONFIG_SOUND_YMFPCI_LEGACY
+ /* XXX At this time the legacy registers are probably deprogrammed. */
+#endif
+
+ ymfpci_download_image(unit);
+ udelay(100);
+
+ ymf_memload(unit);
+
+ spin_lock_irqsave(&unit->reg_lock, flags);
+
+ if (unit->start_count) {
+ ymfpci_writel(unit, YDSXGR_MODE, 3);
+ unit->active_bank = ymfpci_readl(unit, YDSXGR_CTRLSELECT) & 1;
+ }
+
+ unit->suspended = 0;
+ list_for_each(p, &unit->states) {
+ state = list_entry(p, struct ymf_state, chain);
+ wake_up(&state->wpcm.dmabuf.wait);
+ wake_up(&state->rpcm.dmabuf.wait);
+ }
+
+ spin_unlock_irqrestore(&unit->reg_lock, flags);
+}
+
+/*
* initialization routines
*/
@@ -2237,28 +2336,6 @@
ptr += (codec->bank_size_effect + 0x00ff) & ~0x00ff;
codec->work_base = ptr;
- ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, virt_to_bus(codec->bank_base_playback));
- ymfpci_writel(codec, YDSXGR_RECCTRLBASE, virt_to_bus(codec->bank_base_capture));
- ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, virt_to_bus(codec->bank_base_effect));
- ymfpci_writel(codec, YDSXGR_WORKBASE, virt_to_bus(codec->work_base));
- ymfpci_writel(codec, YDSXGR_WORKSIZE, codec->work_size >> 2);
-
- /* S/PDIF output initialization */
- ymfpci_writew(codec, YDSXGR_SPDIFOUTCTRL, 0);
- ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS,
- SND_PCM_AES0_CON_EMPHASIS_NONE |
- (SND_PCM_AES1_CON_ORIGINAL << 8) |
- (SND_PCM_AES1_CON_PCM_CODER << 8));
-
- /* S/PDIF input initialization */
- ymfpci_writew(codec, YDSXGR_SPDIFINCTRL, 0);
-
- /* move this volume setup to mixer */
- ymfpci_writel(codec, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff);
- ymfpci_writel(codec, YDSXGR_BUF441OUTVOL, 0);
- ymfpci_writel(codec, YDSXGR_NATIVEADCINVOL, 0x3fff3fff);
- ymfpci_writel(codec, YDSXGR_NATIVEDACINVOL, 0x3fff3fff);
-
return 0;
}
@@ -2272,6 +2349,32 @@
kfree(codec->work_ptr);
}
+static void ymf_memload(ymfpci_t *unit)
+{
+
+ ymfpci_writel(unit, YDSXGR_PLAYCTRLBASE, virt_to_bus(unit->bank_base_playback));
+ ymfpci_writel(unit, YDSXGR_RECCTRLBASE, virt_to_bus(unit->bank_base_capture));
+ ymfpci_writel(unit, YDSXGR_EFFCTRLBASE, virt_to_bus(unit->bank_base_effect));
+ ymfpci_writel(unit, YDSXGR_WORKBASE, virt_to_bus(unit->work_base));
+ ymfpci_writel(unit, YDSXGR_WORKSIZE, unit->work_size >> 2);
+
+ /* S/PDIF output initialization */
+ ymfpci_writew(unit, YDSXGR_SPDIFOUTCTRL, 0);
+ ymfpci_writew(unit, YDSXGR_SPDIFOUTSTATUS,
+ SND_PCM_AES0_CON_EMPHASIS_NONE |
+ (SND_PCM_AES1_CON_ORIGINAL << 8) |
+ (SND_PCM_AES1_CON_PCM_CODER << 8));
+
+ /* S/PDIF input initialization */
+ ymfpci_writew(unit, YDSXGR_SPDIFINCTRL, 0);
+
+ /* move this volume setup to mixer */
+ ymfpci_writel(unit, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff);
+ ymfpci_writel(unit, YDSXGR_BUF441OUTVOL, 0);
+ ymfpci_writel(unit, YDSXGR_NATIVEADCINVOL, 0x3fff3fff);
+ ymfpci_writel(unit, YDSXGR_NATIVEDACINVOL, 0x3fff3fff);
+}
+
static int ymf_ac97_init(ymfpci_t *unit, int num_ac97)
{
struct ac97_codec *codec;
@@ -2382,8 +2485,7 @@
if (ymfpci_memalloc(codec) < 0)
goto out_disable_dsp;
-
- /* ymfpci_proc_init(unit, codec); */
+ ymf_memload(codec);
if (request_irq(pcidev->irq, ymf_interrupt, SA_SHIRQ, "ymfpci", codec) != 0) {
printk(KERN_ERR "ymfpci: unable to request IRQ %d\n",
@@ -2479,6 +2581,8 @@
id_table: ymf_id_tbl,
probe: ymf_probe_one,
remove: ymf_remove_one,
+ suspend: ymf_suspend,
+ resume: ymf_resume
};
static int __init ymf_init_module(void)
diff -ur -X dontdiff linux-2.4.5-pre3/drivers/sound/ymfpci.h linux-2.4.5-pre3-p3/drivers/sound/ymfpci.h
--- linux-2.4.5-pre3/drivers/sound/ymfpci.h Fri May 18 14:09:46 2001
+++ linux-2.4.5-pre3-p3/drivers/sound/ymfpci.h Thu May 24 22:12:18 2001
@@ -257,6 +257,7 @@
ymfpci_effect_bank_t *bank_effect[YDSXG_EFFECT_VOICES][2];
int start_count;
+ int suspended;
u32 active_bank;
struct ymf_voice voices[64];
@@ -282,8 +283,6 @@
struct list_head ymf_devs;
struct list_head states; /* List of states for this unit */
- /* For the moment we do not traverse list of states so it is
- * entirely useless. Will be used (PM) or killed. XXX */
};
struct ymf_dmabuf {
@@ -300,7 +299,6 @@
int count; /* fill count */
unsigned total_bytes; /* total bytes dmaed by hardware */
- unsigned error; /* number of over/underruns */
wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */
/* redundant, but makes calculations easier */
prev parent reply other threads:[~2001-05-25 5:52 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-05-25 4:29 Patch for PM in ymfpci (against 2.4.5-pre3) Pete Zaitcev
2001-05-25 5:09 ` Jeff Garzik
2001-05-25 5:51 ` Pete Zaitcev [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20010525015138.A30235@devserv.devel.redhat.com \
--to=zaitcev@redhat.com \
--cc=jgarzik@mandrakesoft.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.