diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-09-20 23:29:13 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-11-28 02:47:03 -0500 |
commit | 1d1a4564d8e0a05d56a95df08c6c411bea704bec (patch) | |
tree | 19bfbe4c00fe3c14d3cc2696731495bb2a28c3ce /sound/pci/hda/hda_intel.c | |
parent | f4a75d2eb7b1e2206094b901be09adb31ba63681 (diff) |
ALSA: hda - Add new DSP loader callback routines
Pass DMA buffer pointers in calls to setup_bdle().
Add DSP loader callback routines to controller.
Add new DSP loader switch to Kconfig to turn off DSP firmware.
Signed-off-by: Ian Minett <ian_minett@creativelabs.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 116 |
1 files changed, 110 insertions, 6 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index cd2dbaf1be78..99e61b985d29 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1038,6 +1038,15 @@ static unsigned int azx_get_response(struct hda_bus *bus, | |||
1038 | static void azx_power_notify(struct hda_bus *bus, bool power_up); | 1038 | static void azx_power_notify(struct hda_bus *bus, bool power_up); |
1039 | #endif | 1039 | #endif |
1040 | 1040 | ||
1041 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
1042 | static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, | ||
1043 | unsigned int byte_size, | ||
1044 | struct snd_dma_buffer *bufp); | ||
1045 | static void azx_load_dsp_trigger(struct hda_bus *bus, bool start); | ||
1046 | static void azx_load_dsp_cleanup(struct hda_bus *bus, | ||
1047 | struct snd_dma_buffer *dmab); | ||
1048 | #endif | ||
1049 | |||
1041 | /* reset codec link */ | 1050 | /* reset codec link */ |
1042 | static int azx_reset(struct azx *chip, int full_reset) | 1051 | static int azx_reset(struct azx *chip, int full_reset) |
1043 | { | 1052 | { |
@@ -1359,7 +1368,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
1359 | * set up a BDL entry | 1368 | * set up a BDL entry |
1360 | */ | 1369 | */ |
1361 | static int setup_bdle(struct azx *chip, | 1370 | static int setup_bdle(struct azx *chip, |
1362 | struct snd_pcm_substream *substream, | 1371 | struct snd_dma_buffer *dmab, |
1363 | struct azx_dev *azx_dev, u32 **bdlp, | 1372 | struct azx_dev *azx_dev, u32 **bdlp, |
1364 | int ofs, int size, int with_ioc) | 1373 | int ofs, int size, int with_ioc) |
1365 | { | 1374 | { |
@@ -1372,12 +1381,12 @@ static int setup_bdle(struct azx *chip, | |||
1372 | if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) | 1381 | if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) |
1373 | return -EINVAL; | 1382 | return -EINVAL; |
1374 | 1383 | ||
1375 | addr = snd_pcm_sgbuf_get_addr(substream, ofs); | 1384 | addr = snd_sgbuf_get_addr(dmab, ofs); |
1376 | /* program the address field of the BDL entry */ | 1385 | /* program the address field of the BDL entry */ |
1377 | bdl[0] = cpu_to_le32((u32)addr); | 1386 | bdl[0] = cpu_to_le32((u32)addr); |
1378 | bdl[1] = cpu_to_le32(upper_32_bits(addr)); | 1387 | bdl[1] = cpu_to_le32(upper_32_bits(addr)); |
1379 | /* program the size field of the BDL entry */ | 1388 | /* program the size field of the BDL entry */ |
1380 | chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size); | 1389 | chunk = snd_sgbuf_get_chunk_size(dmab, ofs, size); |
1381 | /* one BDLE cannot cross 4K boundary on CTHDA chips */ | 1390 | /* one BDLE cannot cross 4K boundary on CTHDA chips */ |
1382 | if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) { | 1391 | if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) { |
1383 | u32 remain = 0x1000 - (ofs & 0xfff); | 1392 | u32 remain = 0x1000 - (ofs & 0xfff); |
@@ -1436,7 +1445,8 @@ static int azx_setup_periods(struct azx *chip, | |||
1436 | bdl_pos_adj[chip->dev_index]); | 1445 | bdl_pos_adj[chip->dev_index]); |
1437 | pos_adj = 0; | 1446 | pos_adj = 0; |
1438 | } else { | 1447 | } else { |
1439 | ofs = setup_bdle(chip, substream, azx_dev, | 1448 | ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), |
1449 | azx_dev, | ||
1440 | &bdl, ofs, pos_adj, true); | 1450 | &bdl, ofs, pos_adj, true); |
1441 | if (ofs < 0) | 1451 | if (ofs < 0) |
1442 | goto error; | 1452 | goto error; |
@@ -1445,10 +1455,12 @@ static int azx_setup_periods(struct azx *chip, | |||
1445 | pos_adj = 0; | 1455 | pos_adj = 0; |
1446 | for (i = 0; i < periods; i++) { | 1456 | for (i = 0; i < periods; i++) { |
1447 | if (i == periods - 1 && pos_adj) | 1457 | if (i == periods - 1 && pos_adj) |
1448 | ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs, | 1458 | ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), |
1459 | azx_dev, &bdl, ofs, | ||
1449 | period_bytes - pos_adj, 0); | 1460 | period_bytes - pos_adj, 0); |
1450 | else | 1461 | else |
1451 | ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs, | 1462 | ofs = setup_bdle(chip, snd_pcm_get_dma_buf(substream), |
1463 | azx_dev, &bdl, ofs, | ||
1452 | period_bytes, | 1464 | period_bytes, |
1453 | !azx_dev->no_period_wakeup); | 1465 | !azx_dev->no_period_wakeup); |
1454 | if (ofs < 0) | 1466 | if (ofs < 0) |
@@ -1610,6 +1622,11 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode | |||
1610 | bus_temp.power_save = &power_save; | 1622 | bus_temp.power_save = &power_save; |
1611 | bus_temp.ops.pm_notify = azx_power_notify; | 1623 | bus_temp.ops.pm_notify = azx_power_notify; |
1612 | #endif | 1624 | #endif |
1625 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
1626 | bus_temp.ops.load_dsp_prepare = azx_load_dsp_prepare; | ||
1627 | bus_temp.ops.load_dsp_trigger = azx_load_dsp_trigger; | ||
1628 | bus_temp.ops.load_dsp_cleanup = azx_load_dsp_cleanup; | ||
1629 | #endif | ||
1613 | 1630 | ||
1614 | err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus); | 1631 | err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus); |
1615 | if (err < 0) | 1632 | if (err < 0) |
@@ -2427,6 +2444,93 @@ static void azx_stop_chip(struct azx *chip) | |||
2427 | chip->initialized = 0; | 2444 | chip->initialized = 0; |
2428 | } | 2445 | } |
2429 | 2446 | ||
2447 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
2448 | /* | ||
2449 | * DSP loading code (e.g. for CA0132) | ||
2450 | */ | ||
2451 | |||
2452 | /* use the first stream for loading DSP */ | ||
2453 | static struct azx_dev * | ||
2454 | azx_get_dsp_loader_dev(struct azx *chip) | ||
2455 | { | ||
2456 | return &chip->azx_dev[chip->playback_index_offset]; | ||
2457 | } | ||
2458 | |||
2459 | static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, | ||
2460 | unsigned int byte_size, | ||
2461 | struct snd_dma_buffer *bufp) | ||
2462 | { | ||
2463 | u32 *bdl; | ||
2464 | struct azx *chip = bus->private_data; | ||
2465 | struct azx_dev *azx_dev; | ||
2466 | int err; | ||
2467 | |||
2468 | if (snd_hda_lock_devices(bus)) | ||
2469 | return -EBUSY; | ||
2470 | |||
2471 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, | ||
2472 | snd_dma_pci_data(chip->pci), | ||
2473 | byte_size, bufp); | ||
2474 | if (err < 0) | ||
2475 | goto error; | ||
2476 | |||
2477 | azx_dev = azx_get_dsp_loader_dev(chip); | ||
2478 | azx_dev->bufsize = byte_size; | ||
2479 | azx_dev->period_bytes = byte_size; | ||
2480 | azx_dev->format_val = format; | ||
2481 | |||
2482 | azx_stream_reset(chip, azx_dev); | ||
2483 | |||
2484 | /* reset BDL address */ | ||
2485 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | ||
2486 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | ||
2487 | |||
2488 | azx_dev->frags = 0; | ||
2489 | bdl = (u32 *)azx_dev->bdl.area; | ||
2490 | err = setup_bdle(chip, bufp, azx_dev, &bdl, 0, byte_size, 0); | ||
2491 | if (err < 0) | ||
2492 | goto error; | ||
2493 | |||
2494 | azx_setup_controller(chip, azx_dev); | ||
2495 | return azx_dev->stream_tag; | ||
2496 | |||
2497 | error: | ||
2498 | snd_hda_unlock_devices(bus); | ||
2499 | return err; | ||
2500 | } | ||
2501 | |||
2502 | static void azx_load_dsp_trigger(struct hda_bus *bus, bool start) | ||
2503 | { | ||
2504 | struct azx *chip = bus->private_data; | ||
2505 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); | ||
2506 | |||
2507 | if (start) | ||
2508 | azx_stream_start(chip, azx_dev); | ||
2509 | else | ||
2510 | azx_stream_stop(chip, azx_dev); | ||
2511 | azx_dev->running = start; | ||
2512 | } | ||
2513 | |||
2514 | static void azx_load_dsp_cleanup(struct hda_bus *bus, | ||
2515 | struct snd_dma_buffer *dmab) | ||
2516 | { | ||
2517 | struct azx *chip = bus->private_data; | ||
2518 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); | ||
2519 | |||
2520 | /* reset BDL address */ | ||
2521 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | ||
2522 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | ||
2523 | azx_sd_writel(azx_dev, SD_CTL, 0); | ||
2524 | azx_dev->bufsize = 0; | ||
2525 | azx_dev->period_bytes = 0; | ||
2526 | azx_dev->format_val = 0; | ||
2527 | |||
2528 | snd_dma_free_pages(dmab); | ||
2529 | |||
2530 | snd_hda_unlock_devices(bus); | ||
2531 | } | ||
2532 | #endif /* CONFIG_SND_HDA_DSP_LOADER */ | ||
2533 | |||
2430 | #ifdef CONFIG_PM | 2534 | #ifdef CONFIG_PM |
2431 | /* power-up/down the controller */ | 2535 | /* power-up/down the controller */ |
2432 | static void azx_power_notify(struct hda_bus *bus, bool power_up) | 2536 | static void azx_power_notify(struct hda_bus *bus, bool power_up) |