From: Ryan Underwood <nemesis-lists@icequake.net>
To: alsa-devel@lists.sourceforge.net
Subject: Re: cs4248 / thinkpad 755 / 755c , patch suggestions [PATCH]]
Date: Mon, 7 Jul 2003 15:53:57 -0500 [thread overview]
Message-ID: <20030707205357.GQ5013@dbz.icequake.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 1804 bytes --]
Hi Takashi,
On Thu, Jul 03, 2003 at 02:29:01PM +0200, Takashi Iwai wrote:
> At Wed, 2 Jul 2003 15:29:55 -0500,
> Ryan Underwood wrote:
> >
> > 1) What is ALSA's policy on module options? For example, would it be
> > okay to add an option like "thinkpad" to the ad1848 module, so that
> > inserting it with "thinkpad=1" would cause the necessary ports to be
> > prodded?
>
> this looks like a feasible solution.
>
> > 2) Since the chip's power mode can be controlled through a write to that
> > port (bit 2 on, cs4248 power on; bit 2 off, cs4248 power off), would it
> > be a good idea to add the _suspend, _resume, and _set_power_state
> > functions within a #ifdef CONFIG_PM block, like in other drivers?
>
> yep. we haven't done that just becase of lack of hardware.
> if you can write and test it, it would be greatly appreciated.
I have attached a patch against the ALSA 0.94. ad1848.c, ad1848_lib.c,
and ad1848.h have changed.
I tested the module against 2.4.21 on a Debian system, gcc 3.3 and it
works fine; simply set the proper resources and thinkpad=1 and the
thinkpad works.
One issue is to note, I don't know if this is a problem with the ad1848
driver in general or what; if I cat a 11025hz mono 8-bit file to
/dev/dsp, the sound comes out verrrrry slllloooowwwllly. But using
aplay, it works fine.
I am not sure the best way to test the power managmeent code -- it
doesn't crash the machine at least. ;)
I added a note to the ALSA wiki about this option. I tried to fix the
OSS driver too but it does some other weird things like not allowing a
IRQ > 7 to be used. (It thinks the CS4248 is an 8bit card or
something). So this will have to be an alsa-only fix for now at least.
Let me know if the patch is ok,
--
Ryan Underwood, <nemesis at icequake.net>, icq=10317253
[-- Attachment #2: cs4248_thinkpad.diff --]
[-- Type: text/plain, Size: 6433 bytes --]
diff -ur alsa-driver/alsa-kernel/include/ad1848.h alsanew/alsa-kernel/include/ad1848.h
--- alsa-driver/alsa-kernel/include/ad1848.h 2003-04-23 05:01:29.000000000 -0500
+++ alsanew/alsa-kernel/include/ad1848.h 2003-07-03 20:29:59.000000000 -0500
@@ -121,6 +121,11 @@
#define AD1848_HW_CS4248 0x0003 /* CS4248 chip */
#define AD1848_HW_CMI8330 0x0004 /* CMI8330 chip */
+/* IBM Thinkpad specific stuff */
+#define AD1848_THINKPAD_CTL_PORT1 0x15e8
+#define AD1848_THINKPAD_CTL_PORT2 0x15e9
+#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02
+
struct _snd_ad1848 {
unsigned long port; /* i/o port */
struct resource *res_port;
@@ -140,6 +145,10 @@
int mce_bit;
int calibrate_mute;
int dma_size;
+ int thinkpad_flag; /* Thinkpad CS4248 needs some extra help */
+#ifdef CONFIG_PM
+ struct pm_dev *thinkpad_pmstate;
+#endif
spinlock_t reg_lock;
struct semaphore open_mutex;
@@ -157,7 +166,7 @@
int snd_ad1848_create(snd_card_t * card,
unsigned long port,
- int irq, int dma,
+ int irq, int dma, int thinkpad,
unsigned short hardware,
ad1848_t ** chip);
diff -ur alsa-driver/alsa-kernel/isa/ad1848/ad1848.c alsanew/alsa-kernel/isa/ad1848/ad1848.c
--- alsa-driver/alsa-kernel/isa/ad1848/ad1848.c 2002-10-21 13:28:21.000000000 -0500
+++ alsanew/alsa-kernel/isa/ad1848/ad1848.c 2003-07-07 13:11:55.000000000 -0500
@@ -46,6 +46,7 @@
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
+static int thinkpad[SNDRV_CARDS]; /* Thinkpad special case */
MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(index, "Index value for AD1848 soundcard.");
@@ -65,6 +66,9 @@
MODULE_PARM(dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
MODULE_PARM_DESC(dma1, "DMA1 # for AD1848 driver.");
MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
+MODULE_PARM(thinkpad, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
+MODULE_PARM_SYNTAX(thinkpad, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
static snd_card_t *snd_ad1848_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
@@ -96,6 +100,7 @@
if ((err = snd_ad1848_create(card, port[dev],
irq[dev],
dma1[dev],
+ thinkpad[dev],
AD1848_HW_DETECT,
&chip)) < 0) {
snd_card_free(card);
@@ -116,6 +121,10 @@
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
pcm->name, chip->port, irq[dev], dma1[dev]);
+ if (thinkpad[dev]) {
+ strcat(card->longname, " [Thinkpad]");
+ }
+
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
return err;
@@ -168,7 +177,8 @@
get_id(&str,&id[nr_dev]) == 2 &&
get_option(&str,(int *)&port[nr_dev]) == 2 &&
get_option(&str,&irq[nr_dev]) == 2 &&
- get_option(&str,&dma1[nr_dev]) == 2);
+ get_option(&str,&dma1[nr_dev]) == 2 &&
+ get_option(&str,&thinkpad[nr_dev]) == 2);
nr_dev++;
return 1;
}
diff -ur alsa-driver/alsa-kernel/isa/ad1848/ad1848_lib.c alsanew/alsa-kernel/isa/ad1848/ad1848_lib.c
--- alsa-driver/alsa-kernel/isa/ad1848/ad1848_lib.c 2003-05-30 07:28:34.000000000 -0500
+++ alsanew/alsa-kernel/isa/ad1848/ad1848_lib.c 2003-07-03 20:25:21.000000000 -0500
@@ -625,6 +625,92 @@
*/
+static void snd_ad1848_thinkpad_twiddle(ad1848_t *chip, int on) {
+
+ int tmp;
+
+ if (!chip->thinkpad_flag) return;
+
+ outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
+ tmp = inb(AD1848_THINKPAD_CTL_PORT2);
+
+ switch (on) {
+ case 0: /* turn it off */
+ tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
+ default: /* turn it on */
+ tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
+ }
+
+ outb(tmp, AD1848_THINKPAD_CTL_PORT2);
+
+}
+
+#ifdef CONFIG_PM
+static void snd_ad1848_suspend(ad1848_t *chip) {
+
+ snd_card_t *card = chip->card;
+
+ if (card->power_state == SNDRV_CTL_POWER_D3hot)
+ return;
+
+ if (chip->thinkpad_flag) {
+ snd_pcm_suspend_all(chip->pcm);
+ snd_ad1848_thinkpad_twiddle(chip, 0);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ }
+
+}
+
+static void snd_ad1848_resume(ad1848_t *chip) {
+
+ snd_card_t *card = chip->card;
+
+ if (card->power_state == SNDRV_CTL_POWER_D0)
+ return;
+
+ if (chip->thinkpad_flag) {
+ snd_ad1848_thinkpad_twiddle(chip, 1);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ }
+}
+
+/* callback for control API */
+static int snd_ad1848_set_power_state(snd_card_t *card, unsigned int power_state)
+{
+ ad1848_t *chip = (ad1848_t *) card->power_state_private_data;
+ switch (power_state) {
+ case SNDRV_CTL_POWER_D0:
+ case SNDRV_CTL_POWER_D1:
+ case SNDRV_CTL_POWER_D2:
+ snd_ad1848_resume(chip);
+ break;
+ case SNDRV_CTL_POWER_D3hot:
+ case SNDRV_CTL_POWER_D3cold:
+ snd_ad1848_suspend(chip);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int snd_ad1848_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+ ad1848_t *chip = snd_magic_cast(ad1848_t, dev->data, return 0);
+
+ switch (rqst) {
+ case PM_SUSPEND:
+ snd_ad1848_suspend(chip);
+ break;
+ case PM_RESUME:
+ snd_ad1848_resume(chip);
+ break;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
static int snd_ad1848_probe(ad1848_t * chip)
{
unsigned long flags;
@@ -799,6 +885,10 @@
static int snd_ad1848_free(ad1848_t *chip)
{
+#ifdef CONFIG_PM
+ if (chip->thinkpad_flag && chip->thinkpad_pmstate)
+ pm_unregister(chip->thinkpad_pmstate);
+#endif
if (chip->res_port) {
release_resource(chip->res_port);
kfree_nocheck(chip->res_port);
@@ -832,7 +922,7 @@
int snd_ad1848_create(snd_card_t * card,
unsigned long port,
- int irq, int dma,
+ int irq, int dma, int thinkpad,
unsigned short hardware,
ad1848_t ** rchip)
{
@@ -870,6 +960,22 @@
}
chip->dma = dma;
+ if (thinkpad) {
+ chip->thinkpad_flag = 1;
+ snd_ad1848_thinkpad_twiddle(chip, 1);
+#ifdef CONFIG_PM
+ chip->thinkpad_pmstate = pm_register(PM_ISA_DEV, 0, snd_ad1848_pm_callback);
+ if (chip->thinkpad_pmstate) {
+ chip->thinkpad_pmstate->data = chip;
+ card->set_power_state = snd_ad1848_set_power_state; /* callback */
+ card->power_state_private_data = chip;
+ }
+#endif
+ }
+ else {
+ chip->thinkpad_flag = 0;
+ }
+
if (snd_ad1848_probe(chip) < 0) {
snd_ad1848_free(chip);
return -ENODEV;
next reply other threads:[~2003-07-07 20:53 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-07-07 20:53 Ryan Underwood [this message]
2003-07-08 10:50 ` cs4248 / thinkpad 755 / 755c , patch suggestions [PATCH]] Takashi Iwai
2003-07-08 13:58 ` Ryan Underwood
2003-07-08 17:27 ` Takashi Iwai
2003-07-08 17:32 ` Ryan Underwood
2003-07-08 17:37 ` Takashi Iwai
2003-07-08 19:54 ` Ryan Underwood
2003-07-09 12:39 ` Takashi Iwai
2003-07-09 16:05 ` Ryan Underwood
2003-07-09 16:28 ` Jaroslav Kysela
2003-07-09 21:04 ` Ryan Underwood
2003-07-08 17:01 ` Ryan Underwood
2003-07-08 17:21 ` Takashi Iwai
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=20030707205357.GQ5013@dbz.icequake.net \
--to=nemesis-lists@icequake.net \
--cc=alsa-devel@lists.sourceforge.net \
/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.