diff options
-rw-r--r-- | sound/pci/hda/Kconfig | 8 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 45 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 116 |
3 files changed, 163 insertions, 6 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 7105c3de1bca..ba1dbd8e00a0 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
@@ -236,4 +236,12 @@ config SND_HDA_POWER_SAVE_DEFAULT | |||
236 | The default time-out value in seconds for HD-audio automatic | 236 | The default time-out value in seconds for HD-audio automatic |
237 | power-save mode. 0 means to disable the power-save mode. | 237 | power-save mode. 0 means to disable the power-save mode. |
238 | 238 | ||
239 | config SND_HDA_DSP_LOADER | ||
240 | bool "Enable DSP firmware loader" | ||
241 | depends on FW_LOADER | ||
242 | default y | ||
243 | help | ||
244 | Say Y here to enable the DSP firmware loader, used by certain | ||
245 | codecs (e.g. CA0132) to transfer their DSP binaries to the hardware. | ||
246 | |||
239 | endif | 247 | endif |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 507fe8a917b6..c218bf41261a 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -618,6 +618,17 @@ struct hda_bus_ops { | |||
618 | /* notify power-up/down from codec to controller */ | 618 | /* notify power-up/down from codec to controller */ |
619 | void (*pm_notify)(struct hda_bus *bus, bool power_up); | 619 | void (*pm_notify)(struct hda_bus *bus, bool power_up); |
620 | #endif | 620 | #endif |
621 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
622 | /* prepare DSP transfer */ | ||
623 | int (*load_dsp_prepare)(struct hda_bus *bus, unsigned int format, | ||
624 | unsigned int byte_size, | ||
625 | struct snd_dma_buffer *bufp); | ||
626 | /* start/stop DSP transfer */ | ||
627 | void (*load_dsp_trigger)(struct hda_bus *bus, bool start); | ||
628 | /* clean up DSP transfer */ | ||
629 | void (*load_dsp_cleanup)(struct hda_bus *bus, | ||
630 | struct snd_dma_buffer *dmab); | ||
631 | #endif | ||
621 | }; | 632 | }; |
622 | 633 | ||
623 | /* template to pass to the bus constructor */ | 634 | /* template to pass to the bus constructor */ |
@@ -1129,6 +1140,40 @@ static inline void snd_hda_power_sync(struct hda_codec *codec) | |||
1129 | int snd_hda_load_patch(struct hda_bus *bus, size_t size, const void *buf); | 1140 | int snd_hda_load_patch(struct hda_bus *bus, size_t size, const void *buf); |
1130 | #endif | 1141 | #endif |
1131 | 1142 | ||
1143 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
1144 | static inline int | ||
1145 | snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, | ||
1146 | unsigned int size, | ||
1147 | struct snd_dma_buffer *bufp) | ||
1148 | { | ||
1149 | return codec->bus->ops.load_dsp_prepare(codec->bus, format, size, bufp); | ||
1150 | } | ||
1151 | static inline void | ||
1152 | snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start) | ||
1153 | { | ||
1154 | return codec->bus->ops.load_dsp_trigger(codec->bus, start); | ||
1155 | } | ||
1156 | static inline void | ||
1157 | snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec, | ||
1158 | struct snd_dma_buffer *dmab) | ||
1159 | { | ||
1160 | return codec->bus->ops.load_dsp_cleanup(codec->bus, dmab); | ||
1161 | } | ||
1162 | #else | ||
1163 | static inline int | ||
1164 | snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format, | ||
1165 | unsigned int size, | ||
1166 | struct snd_dma_buffer *bufp) | ||
1167 | { | ||
1168 | return 0; | ||
1169 | } | ||
1170 | static inline void | ||
1171 | snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start) {} | ||
1172 | static inline void | ||
1173 | snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec, | ||
1174 | struct snd_dma_buffer *dmab) {} | ||
1175 | #endif | ||
1176 | |||
1132 | /* | 1177 | /* |
1133 | * Codec modularization | 1178 | * Codec modularization |
1134 | */ | 1179 | */ |
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) |