aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-11-17 10:14:33 -0500
committerJaroslav Kysela <perex@suse.cz>2006-01-03 06:27:59 -0500
commitb1e9ed26a9e472548a63a59014708fdae013b7a3 (patch)
tree69403fa8ec2c417af81098946888e2555ae5e4b9 /sound
parent09668b441dacdf4640509b640ad73e24efd5204f (diff)
[ALSA] fm801 - Add PM support
Modules: FM801 driver Add PM support to fm801 driver. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/fm801.c245
1 files changed, 158 insertions, 87 deletions
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index a57aca72e91a..6ab4aefbccf8 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -103,7 +103,11 @@ MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner.");
103#define FM801_OPL3_DATA1 0x6b /* OPL3 Bank 1 Write */ 103#define FM801_OPL3_DATA1 0x6b /* OPL3 Bank 1 Write */
104#define FM801_POWERDOWN 0x70 /* Blocks Power Down Control */ 104#define FM801_POWERDOWN 0x70 /* Blocks Power Down Control */
105 105
106#define FM801_AC97_ADDR_SHIFT 10 106/* codec access */
107#define FM801_AC97_READ (1<<7) /* read=1, write=0 */
108#define FM801_AC97_VALID (1<<8) /* port valid=1 */
109#define FM801_AC97_BUSY (1<<9) /* busy=1 */
110#define FM801_AC97_ADDR_SHIFT 10 /* codec id (2bit) */
107 111
108/* playback and record control register bits */ 112/* playback and record control register bits */
109#define FM801_BUF1_LAST (1<<1) 113#define FM801_BUF1_LAST (1<<1)
@@ -189,6 +193,10 @@ struct fm801 {
189#ifdef TEA575X_RADIO 193#ifdef TEA575X_RADIO
190 struct snd_tea575x tea; 194 struct snd_tea575x tea;
191#endif 195#endif
196
197#ifdef CONFIG_PM
198 u16 saved_regs[0x20];
199#endif
192}; 200};
193 201
194static struct pci_device_id snd_fm801_ids[] = { 202static struct pci_device_id snd_fm801_ids[] = {
@@ -231,7 +239,7 @@ static void snd_fm801_codec_write(struct snd_ac97 *ac97,
231 * Wait until the codec interface is not ready.. 239 * Wait until the codec interface is not ready..
232 */ 240 */
233 for (idx = 0; idx < 100; idx++) { 241 for (idx = 0; idx < 100; idx++) {
234 if (!(inw(FM801_REG(chip, AC97_CMD)) & (1<<9))) 242 if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY))
235 goto ok1; 243 goto ok1;
236 udelay(10); 244 udelay(10);
237 } 245 }
@@ -246,7 +254,7 @@ static void snd_fm801_codec_write(struct snd_ac97 *ac97,
246 * Wait until the write command is not completed.. 254 * Wait until the write command is not completed..
247 */ 255 */
248 for (idx = 0; idx < 1000; idx++) { 256 for (idx = 0; idx < 1000; idx++) {
249 if (!(inw(FM801_REG(chip, AC97_CMD)) & (1<<9))) 257 if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY))
250 return; 258 return;
251 udelay(10); 259 udelay(10);
252 } 260 }
@@ -262,7 +270,7 @@ static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short
262 * Wait until the codec interface is not ready.. 270 * Wait until the codec interface is not ready..
263 */ 271 */
264 for (idx = 0; idx < 100; idx++) { 272 for (idx = 0; idx < 100; idx++) {
265 if (!(inw(FM801_REG(chip, AC97_CMD)) & (1<<9))) 273 if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY))
266 goto ok1; 274 goto ok1;
267 udelay(10); 275 udelay(10);
268 } 276 }
@@ -271,9 +279,10 @@ static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short
271 279
272 ok1: 280 ok1:
273 /* read command */ 281 /* read command */
274 outw(reg | (ac97->addr << FM801_AC97_ADDR_SHIFT) | (1<<7), FM801_REG(chip, AC97_CMD)); 282 outw(reg | (ac97->addr << FM801_AC97_ADDR_SHIFT) | FM801_AC97_READ,
283 FM801_REG(chip, AC97_CMD));
275 for (idx = 0; idx < 100; idx++) { 284 for (idx = 0; idx < 100; idx++) {
276 if (!(inw(FM801_REG(chip, AC97_CMD)) & (1<<9))) 285 if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY))
277 goto ok2; 286 goto ok2;
278 udelay(10); 287 udelay(10);
279 } 288 }
@@ -282,7 +291,7 @@ static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short
282 291
283 ok2: 292 ok2:
284 for (idx = 0; idx < 1000; idx++) { 293 for (idx = 0; idx < 1000; idx++) {
285 if (inw(FM801_REG(chip, AC97_CMD)) & (1<<8)) 294 if (inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_VALID)
286 goto ok3; 295 goto ok3;
287 udelay(10); 296 udelay(10);
288 } 297 }
@@ -354,9 +363,11 @@ static int snd_fm801_playback_trigger(struct snd_pcm_substream *substream,
354 chip->ply_ctrl &= ~(FM801_START | FM801_PAUSE); 363 chip->ply_ctrl &= ~(FM801_START | FM801_PAUSE);
355 break; 364 break;
356 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 365 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
366 case SNDRV_PCM_TRIGGER_SUSPEND:
357 chip->ply_ctrl |= FM801_PAUSE; 367 chip->ply_ctrl |= FM801_PAUSE;
358 break; 368 break;
359 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 369 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
370 case SNDRV_PCM_TRIGGER_RESUME:
360 chip->ply_ctrl &= ~FM801_PAUSE; 371 chip->ply_ctrl &= ~FM801_PAUSE;
361 break; 372 break;
362 default: 373 default:
@@ -387,9 +398,11 @@ static int snd_fm801_capture_trigger(struct snd_pcm_substream *substream,
387 chip->cap_ctrl &= ~(FM801_START | FM801_PAUSE); 398 chip->cap_ctrl &= ~(FM801_START | FM801_PAUSE);
388 break; 399 break;
389 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 400 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
401 case SNDRV_PCM_TRIGGER_SUSPEND:
390 chip->cap_ctrl |= FM801_PAUSE; 402 chip->cap_ctrl |= FM801_PAUSE;
391 break; 403 break;
392 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 404 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
405 case SNDRV_PCM_TRIGGER_RESUME:
393 chip->cap_ctrl &= ~FM801_PAUSE; 406 chip->cap_ctrl &= ~FM801_PAUSE;
394 break; 407 break;
395 default: 408 default:
@@ -557,7 +570,7 @@ static struct snd_pcm_hardware snd_fm801_playback =
557{ 570{
558 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 571 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
559 SNDRV_PCM_INFO_BLOCK_TRANSFER | 572 SNDRV_PCM_INFO_BLOCK_TRANSFER |
560 SNDRV_PCM_INFO_PAUSE | 573 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
561 SNDRV_PCM_INFO_MMAP_VALID), 574 SNDRV_PCM_INFO_MMAP_VALID),
562 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, 575 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
563 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, 576 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
@@ -577,7 +590,7 @@ static struct snd_pcm_hardware snd_fm801_capture =
577{ 590{
578 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 591 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
579 SNDRV_PCM_INFO_BLOCK_TRANSFER | 592 SNDRV_PCM_INFO_BLOCK_TRANSFER |
580 SNDRV_PCM_INFO_PAUSE | 593 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
581 SNDRV_PCM_INFO_MMAP_VALID), 594 SNDRV_PCM_INFO_MMAP_VALID),
582 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, 595 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
583 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, 596 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
@@ -1218,6 +1231,85 @@ static int __devinit snd_fm801_mixer(struct fm801 *chip)
1218 * initialization routines 1231 * initialization routines
1219 */ 1232 */
1220 1233
1234static int wait_for_codec(struct fm801 *chip, unsigned int codec_id,
1235 unsigned short reg, unsigned long waits)
1236{
1237 unsigned long timeout = jiffies + waits;
1238
1239 outw(FM801_AC97_READ | (codec_id << FM801_AC97_ADDR_SHIFT) | reg,
1240 FM801_REG(chip, AC97_CMD));
1241 udelay(5);
1242 do {
1243 if ((inw(FM801_REG(chip, AC97_CMD)) & (FM801_AC97_VALID|FM801_AC97_BUSY))
1244 == FM801_AC97_VALID)
1245 return 0;
1246 schedule_timeout_uninterruptible(1);
1247 } while (time_after(timeout, jiffies));
1248 return -EIO;
1249}
1250
1251static int snd_fm801_chip_init(struct fm801 *chip, int resume)
1252{
1253 int id;
1254 unsigned short cmdw;
1255
1256 /* codec cold reset + AC'97 warm reset */
1257 outw((1<<5) | (1<<6), FM801_REG(chip, CODEC_CTRL));
1258 inw(FM801_REG(chip, CODEC_CTRL)); /* flush posting data */
1259 udelay(100);
1260 outw(0, FM801_REG(chip, CODEC_CTRL));
1261
1262 if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0) {
1263 snd_printk(KERN_ERR "Primary AC'97 codec not found\n");
1264 if (! resume)
1265 return -EIO;
1266 }
1267
1268 if (chip->multichannel) {
1269 if (chip->secondary_addr) {
1270 wait_for_codec(chip, chip->secondary_addr,
1271 AC97_VENDOR_ID1, msecs_to_jiffies(50));
1272 } else {
1273 /* my card has the secondary codec */
1274 /* at address #3, so the loop is inverted */
1275 for (id = 3; id > 0; id--) {
1276 if (! wait_for_codec(chip, id, AC97_VENDOR_ID1,
1277 msecs_to_jiffies(50))) {
1278 cmdw = inw(FM801_REG(chip, AC97_DATA));
1279 if (cmdw != 0xffff && cmdw != 0) {
1280 chip->secondary = 1;
1281 chip->secondary_addr = id;
1282 break;
1283 }
1284 }
1285 }
1286 }
1287
1288 /* the recovery phase, it seems that probing for non-existing codec might */
1289 /* cause timeout problems */
1290 wait_for_codec(chip, 0, AC97_VENDOR_ID1, msecs_to_jiffies(750));
1291 }
1292
1293 /* init volume */
1294 outw(0x0808, FM801_REG(chip, PCM_VOL));
1295 outw(0x9f1f, FM801_REG(chip, FM_VOL));
1296 outw(0x8808, FM801_REG(chip, I2S_VOL));
1297
1298 /* I2S control - I2S mode */
1299 outw(0x0003, FM801_REG(chip, I2S_MODE));
1300
1301 /* interrupt setup - unmask MPU, PLAYBACK & CAPTURE */
1302 cmdw = inw(FM801_REG(chip, IRQ_MASK));
1303 cmdw &= ~0x0083;
1304 outw(cmdw, FM801_REG(chip, IRQ_MASK));
1305
1306 /* interrupt clear */
1307 outw(FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU, FM801_REG(chip, IRQ_STATUS));
1308
1309 return 0;
1310}
1311
1312
1221static int snd_fm801_free(struct fm801 *chip) 1313static int snd_fm801_free(struct fm801 *chip)
1222{ 1314{
1223 unsigned short cmdw; 1315 unsigned short cmdw;
@@ -1255,9 +1347,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
1255 struct fm801 ** rchip) 1347 struct fm801 ** rchip)
1256{ 1348{
1257 struct fm801 *chip; 1349 struct fm801 *chip;
1258 unsigned char rev, id; 1350 unsigned char rev;
1259 unsigned short cmdw;
1260 unsigned long timeout;
1261 int err; 1351 int err;
1262 static struct snd_device_ops ops = { 1352 static struct snd_device_ops ops = {
1263 .dev_free = snd_fm801_dev_free, 1353 .dev_free = snd_fm801_dev_free,
@@ -1294,81 +1384,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
1294 if (rev >= 0xb1) /* FM801-AU */ 1384 if (rev >= 0xb1) /* FM801-AU */
1295 chip->multichannel = 1; 1385 chip->multichannel = 1;
1296 1386
1297 /* codec cold reset + AC'97 warm reset */ 1387 snd_fm801_chip_init(chip, 0);
1298 outw((1<<5)|(1<<6), FM801_REG(chip, CODEC_CTRL));
1299 inw(FM801_REG(chip, CODEC_CTRL)); /* flush posting data */
1300 udelay(100);
1301 outw(0, FM801_REG(chip, CODEC_CTRL));
1302
1303 timeout = (jiffies + (3 * HZ) / 4) + 1; /* min 750ms */
1304
1305 outw((1<<7) | (0 << FM801_AC97_ADDR_SHIFT), FM801_REG(chip, AC97_CMD));
1306 udelay(5);
1307 do {
1308 if ((inw(FM801_REG(chip, AC97_CMD)) & (3<<8)) == (1<<8))
1309 goto __ac97_secondary;
1310 schedule_timeout_uninterruptible(1);
1311 } while (time_after(timeout, jiffies));
1312 snd_printk(KERN_ERR "Primary AC'97 codec not found\n");
1313 snd_fm801_free(chip);
1314 return -EIO;
1315
1316 __ac97_secondary:
1317 if (!chip->multichannel) /* lookup is not required */
1318 goto __ac97_ok;
1319 for (id = 3; id > 0; id--) { /* my card has the secondary codec */
1320 /* at address #3, so the loop is inverted */
1321
1322 timeout = jiffies + HZ / 20;
1323
1324 outw((1<<7) | (id << FM801_AC97_ADDR_SHIFT) | AC97_VENDOR_ID1,
1325 FM801_REG(chip, AC97_CMD));
1326 udelay(5);
1327 do {
1328 if ((inw(FM801_REG(chip, AC97_CMD)) & (3<<8)) == (1<<8)) {
1329 cmdw = inw(FM801_REG(chip, AC97_DATA));
1330 if (cmdw != 0xffff && cmdw != 0) {
1331 chip->secondary = 1;
1332 chip->secondary_addr = id;
1333 goto __ac97_ok;
1334 }
1335 }
1336 schedule_timeout_uninterruptible(1);
1337 } while (time_after(timeout, jiffies));
1338 }
1339
1340 /* the recovery phase, it seems that probing for non-existing codec might */
1341 /* cause timeout problems */
1342 timeout = (jiffies + (3 * HZ) / 4) + 1; /* min 750ms */
1343
1344 outw((1<<7) | (0 << FM801_AC97_ADDR_SHIFT), FM801_REG(chip, AC97_CMD));
1345 udelay(5);
1346 do {
1347 if ((inw(FM801_REG(chip, AC97_CMD)) & (3<<8)) == (1<<8))
1348 goto __ac97_ok;
1349 schedule_timeout_uninterruptible(1);
1350 } while (time_after(timeout, jiffies));
1351 snd_printk(KERN_ERR "Primary AC'97 codec not responding\n");
1352 snd_fm801_free(chip);
1353 return -EIO;
1354
1355 __ac97_ok:
1356
1357 /* init volume */
1358 outw(0x0808, FM801_REG(chip, PCM_VOL));
1359 outw(0x9f1f, FM801_REG(chip, FM_VOL));
1360 outw(0x8808, FM801_REG(chip, I2S_VOL));
1361
1362 /* I2S control - I2S mode */
1363 outw(0x0003, FM801_REG(chip, I2S_MODE));
1364
1365 /* interrupt setup - unmask MPU, PLAYBACK & CAPTURE */
1366 cmdw = inw(FM801_REG(chip, IRQ_MASK));
1367 cmdw &= ~0x0083;
1368 outw(cmdw, FM801_REG(chip, IRQ_MASK));
1369
1370 /* interrupt clear */
1371 outw(FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU, FM801_REG(chip, IRQ_STATUS));
1372 1388
1373 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { 1389 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
1374 snd_fm801_free(chip); 1390 snd_fm801_free(chip);
@@ -1415,6 +1431,7 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
1415 snd_card_free(card); 1431 snd_card_free(card);
1416 return err; 1432 return err;
1417 } 1433 }
1434 card->private_data = chip;
1418 1435
1419 strcpy(card->driver, "FM801"); 1436 strcpy(card->driver, "FM801");
1420 strcpy(card->shortname, "ForteMedia FM801-"); 1437 strcpy(card->shortname, "ForteMedia FM801-");
@@ -1462,11 +1479,65 @@ static void __devexit snd_card_fm801_remove(struct pci_dev *pci)
1462 pci_set_drvdata(pci, NULL); 1479 pci_set_drvdata(pci, NULL);
1463} 1480}
1464 1481
1482#ifdef CONFIG_PM
1483static unsigned char saved_regs[] = {
1484 FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC,
1485 FM801_PLY_CTRL, FM801_PLY_COUNT, FM801_PLY_BUF1, FM801_PLY_BUF2,
1486 FM801_CAP_CTRL, FM801_CAP_COUNT, FM801_CAP_BUF1, FM801_CAP_BUF2,
1487 FM801_CODEC_CTRL, FM801_I2S_MODE, FM801_VOLUME, FM801_GEN_CTRL,
1488};
1489
1490static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state)
1491{
1492 struct snd_card *card = pci_get_drvdata(pci);
1493 struct fm801 *chip = card->private_data;
1494 int i;
1495
1496 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1497 snd_pcm_suspend_all(chip->pcm);
1498 snd_ac97_suspend(chip->ac97);
1499 snd_ac97_suspend(chip->ac97_sec);
1500 for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
1501 chip->saved_regs[i] = inw(chip->port + saved_regs[i]);
1502 /* FIXME: tea575x suspend */
1503
1504 pci_set_power_state(pci, PCI_D3hot);
1505 pci_disable_device(pci);
1506 pci_save_state(pci);
1507 return 0;
1508}
1509
1510static int snd_fm801_resume(struct pci_dev *pci)
1511{
1512 struct snd_card *card = pci_get_drvdata(pci);
1513 struct fm801 *chip = card->private_data;
1514 int i;
1515
1516 pci_restore_state(pci);
1517 pci_enable_device(pci);
1518 pci_set_power_state(pci, PCI_D0);
1519 pci_set_master(pci);
1520
1521 snd_fm801_chip_init(chip, 1);
1522 snd_ac97_resume(chip->ac97);
1523 snd_ac97_resume(chip->ac97_sec);
1524 for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
1525 outw(chip->saved_regs[i], chip->port + saved_regs[i]);
1526
1527 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
1528 return 0;
1529}
1530#endif
1531
1465static struct pci_driver driver = { 1532static struct pci_driver driver = {
1466 .name = "FM801", 1533 .name = "FM801",
1467 .id_table = snd_fm801_ids, 1534 .id_table = snd_fm801_ids,
1468 .probe = snd_card_fm801_probe, 1535 .probe = snd_card_fm801_probe,
1469 .remove = __devexit_p(snd_card_fm801_remove), 1536 .remove = __devexit_p(snd_card_fm801_remove),
1537#ifdef CONFIG_PM
1538 .suspend = snd_fm801_suspend,
1539 .resume = snd_fm801_resume,
1540#endif
1470}; 1541};
1471 1542
1472static int __init alsa_card_fm801_init(void) 1543static int __init alsa_card_fm801_init(void)