diff options
author | Dylan Reid <dgreid@chromium.org> | 2014-02-28 18:41:24 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-03-01 05:22:38 -0500 |
commit | 2b5fd6c2e9f2398962a932f85d951bce794f97f8 (patch) | |
tree | a9e79bcaa598ee98432ef159a075244e87b8db83 /sound/pci/hda | |
parent | 679089944317963e9abf51899b48db3b6f424489 (diff) |
ALSA: hda - Move the dsp loader to hda_controller
Moving the DSP loading functionality to hda_controller.c means that
the dsp lock doesn't need to be shared in hda_intel and
hda_controller. The forthcoming platform driver doesn't need the DSP
loading code, but sharing it doesn't hurt.
Tested on Chromebook Pixel's ca0132 that uses the DSP loader.
Signed-off-by: Dylan Reid <dgreid@chromium.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_controller.c | 149 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.h | 23 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 124 |
3 files changed, 144 insertions, 152 deletions
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index bf5e89027fc1..b637d2c46237 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c | |||
@@ -33,12 +33,25 @@ | |||
33 | #define CREATE_TRACE_POINTS | 33 | #define CREATE_TRACE_POINTS |
34 | #include "hda_intel_trace.h" | 34 | #include "hda_intel_trace.h" |
35 | 35 | ||
36 | /* DSP lock helpers */ | ||
37 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
38 | #define dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex) | ||
39 | #define dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex) | ||
40 | #define dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex) | ||
41 | #define dsp_is_locked(dev) ((dev)->locked) | ||
42 | #else | ||
43 | #define dsp_lock_init(dev) do {} while (0) | ||
44 | #define dsp_lock(dev) do {} while (0) | ||
45 | #define dsp_unlock(dev) do {} while (0) | ||
46 | #define dsp_is_locked(dev) 0 | ||
47 | #endif | ||
48 | |||
36 | /* | 49 | /* |
37 | * AZX stream operations. | 50 | * AZX stream operations. |
38 | */ | 51 | */ |
39 | 52 | ||
40 | /* start a stream */ | 53 | /* start a stream */ |
41 | void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) | 54 | static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) |
42 | { | 55 | { |
43 | /* | 56 | /* |
44 | * Before stream start, initialize parameter | 57 | * Before stream start, initialize parameter |
@@ -53,7 +66,6 @@ void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) | |||
53 | azx_sd_readb(chip, azx_dev, SD_CTL) | | 66 | azx_sd_readb(chip, azx_dev, SD_CTL) | |
54 | SD_CTL_DMA_START | SD_INT_MASK); | 67 | SD_CTL_DMA_START | SD_INT_MASK); |
55 | } | 68 | } |
56 | EXPORT_SYMBOL_GPL(azx_stream_start); | ||
57 | 69 | ||
58 | /* stop DMA */ | 70 | /* stop DMA */ |
59 | static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev) | 71 | static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev) |
@@ -75,7 +87,7 @@ void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) | |||
75 | EXPORT_SYMBOL_GPL(azx_stream_stop); | 87 | EXPORT_SYMBOL_GPL(azx_stream_stop); |
76 | 88 | ||
77 | /* reset stream */ | 89 | /* reset stream */ |
78 | void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) | 90 | static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) |
79 | { | 91 | { |
80 | unsigned char val; | 92 | unsigned char val; |
81 | int timeout; | 93 | int timeout; |
@@ -103,12 +115,11 @@ void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev) | |||
103 | /* reset first position - may not be synced with hw at this time */ | 115 | /* reset first position - may not be synced with hw at this time */ |
104 | *azx_dev->posbuf = 0; | 116 | *azx_dev->posbuf = 0; |
105 | } | 117 | } |
106 | EXPORT_SYMBOL_GPL(azx_stream_reset); | ||
107 | 118 | ||
108 | /* | 119 | /* |
109 | * set up the SD for streaming | 120 | * set up the SD for streaming |
110 | */ | 121 | */ |
111 | int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | 122 | static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) |
112 | { | 123 | { |
113 | unsigned int val; | 124 | unsigned int val; |
114 | /* make sure the run bit is zero for SD */ | 125 | /* make sure the run bit is zero for SD */ |
@@ -152,7 +163,6 @@ int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
152 | 163 | ||
153 | return 0; | 164 | return 0; |
154 | } | 165 | } |
155 | EXPORT_SYMBOL_GPL(azx_setup_controller); | ||
156 | 166 | ||
157 | /* assign a stream for the PCM */ | 167 | /* assign a stream for the PCM */ |
158 | static inline struct azx_dev * | 168 | static inline struct azx_dev * |
@@ -267,10 +277,10 @@ static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream, | |||
267 | /* | 277 | /* |
268 | * set up a BDL entry | 278 | * set up a BDL entry |
269 | */ | 279 | */ |
270 | int setup_bdle(struct azx *chip, | 280 | static int setup_bdle(struct azx *chip, |
271 | struct snd_dma_buffer *dmab, | 281 | struct snd_dma_buffer *dmab, |
272 | struct azx_dev *azx_dev, u32 **bdlp, | 282 | struct azx_dev *azx_dev, u32 **bdlp, |
273 | int ofs, int size, int with_ioc) | 283 | int ofs, int size, int with_ioc) |
274 | { | 284 | { |
275 | u32 *bdl = *bdlp; | 285 | u32 *bdl = *bdlp; |
276 | 286 | ||
@@ -306,7 +316,6 @@ int setup_bdle(struct azx *chip, | |||
306 | *bdlp = bdl; | 316 | *bdlp = bdl; |
307 | return ofs; | 317 | return ofs; |
308 | } | 318 | } |
309 | EXPORT_SYMBOL_GPL(setup_bdle); | ||
310 | 319 | ||
311 | /* | 320 | /* |
312 | * set up BDL entries | 321 | * set up BDL entries |
@@ -1014,6 +1023,124 @@ int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, | |||
1014 | } | 1023 | } |
1015 | EXPORT_SYMBOL_GPL(azx_attach_pcm_stream); | 1024 | EXPORT_SYMBOL_GPL(azx_attach_pcm_stream); |
1016 | 1025 | ||
1026 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
1027 | /* | ||
1028 | * DSP loading code (e.g. for CA0132) | ||
1029 | */ | ||
1030 | |||
1031 | /* use the first stream for loading DSP */ | ||
1032 | static struct azx_dev * | ||
1033 | azx_get_dsp_loader_dev(struct azx *chip) | ||
1034 | { | ||
1035 | return &chip->azx_dev[chip->playback_index_offset]; | ||
1036 | } | ||
1037 | |||
1038 | int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, | ||
1039 | unsigned int byte_size, | ||
1040 | struct snd_dma_buffer *bufp) | ||
1041 | { | ||
1042 | u32 *bdl; | ||
1043 | struct azx *chip = bus->private_data; | ||
1044 | struct azx_dev *azx_dev; | ||
1045 | int err; | ||
1046 | |||
1047 | azx_dev = azx_get_dsp_loader_dev(chip); | ||
1048 | |||
1049 | dsp_lock(azx_dev); | ||
1050 | spin_lock_irq(&chip->reg_lock); | ||
1051 | if (azx_dev->running || azx_dev->locked) { | ||
1052 | spin_unlock_irq(&chip->reg_lock); | ||
1053 | err = -EBUSY; | ||
1054 | goto unlock; | ||
1055 | } | ||
1056 | azx_dev->prepared = 0; | ||
1057 | chip->saved_azx_dev = *azx_dev; | ||
1058 | azx_dev->locked = 1; | ||
1059 | spin_unlock_irq(&chip->reg_lock); | ||
1060 | |||
1061 | err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV_SG, | ||
1062 | byte_size, bufp); | ||
1063 | if (err < 0) | ||
1064 | goto err_alloc; | ||
1065 | |||
1066 | azx_dev->bufsize = byte_size; | ||
1067 | azx_dev->period_bytes = byte_size; | ||
1068 | azx_dev->format_val = format; | ||
1069 | |||
1070 | azx_stream_reset(chip, azx_dev); | ||
1071 | |||
1072 | /* reset BDL address */ | ||
1073 | azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); | ||
1074 | azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); | ||
1075 | |||
1076 | azx_dev->frags = 0; | ||
1077 | bdl = (u32 *)azx_dev->bdl.area; | ||
1078 | err = setup_bdle(chip, bufp, azx_dev, &bdl, 0, byte_size, 0); | ||
1079 | if (err < 0) | ||
1080 | goto error; | ||
1081 | |||
1082 | azx_setup_controller(chip, azx_dev); | ||
1083 | dsp_unlock(azx_dev); | ||
1084 | return azx_dev->stream_tag; | ||
1085 | |||
1086 | error: | ||
1087 | chip->ops->dma_free_pages(chip, bufp); | ||
1088 | err_alloc: | ||
1089 | spin_lock_irq(&chip->reg_lock); | ||
1090 | if (azx_dev->opened) | ||
1091 | *azx_dev = chip->saved_azx_dev; | ||
1092 | azx_dev->locked = 0; | ||
1093 | spin_unlock_irq(&chip->reg_lock); | ||
1094 | unlock: | ||
1095 | dsp_unlock(azx_dev); | ||
1096 | return err; | ||
1097 | } | ||
1098 | EXPORT_SYMBOL_GPL(azx_load_dsp_prepare); | ||
1099 | |||
1100 | void azx_load_dsp_trigger(struct hda_bus *bus, bool start) | ||
1101 | { | ||
1102 | struct azx *chip = bus->private_data; | ||
1103 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); | ||
1104 | |||
1105 | if (start) | ||
1106 | azx_stream_start(chip, azx_dev); | ||
1107 | else | ||
1108 | azx_stream_stop(chip, azx_dev); | ||
1109 | azx_dev->running = start; | ||
1110 | } | ||
1111 | EXPORT_SYMBOL_GPL(azx_load_dsp_trigger); | ||
1112 | |||
1113 | void azx_load_dsp_cleanup(struct hda_bus *bus, | ||
1114 | struct snd_dma_buffer *dmab) | ||
1115 | { | ||
1116 | struct azx *chip = bus->private_data; | ||
1117 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); | ||
1118 | |||
1119 | if (!dmab->area || !azx_dev->locked) | ||
1120 | return; | ||
1121 | |||
1122 | dsp_lock(azx_dev); | ||
1123 | /* reset BDL address */ | ||
1124 | azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); | ||
1125 | azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); | ||
1126 | azx_sd_writel(chip, azx_dev, SD_CTL, 0); | ||
1127 | azx_dev->bufsize = 0; | ||
1128 | azx_dev->period_bytes = 0; | ||
1129 | azx_dev->format_val = 0; | ||
1130 | |||
1131 | chip->ops->dma_free_pages(chip, dmab); | ||
1132 | dmab->area = NULL; | ||
1133 | |||
1134 | spin_lock_irq(&chip->reg_lock); | ||
1135 | if (azx_dev->opened) | ||
1136 | *azx_dev = chip->saved_azx_dev; | ||
1137 | azx_dev->locked = 0; | ||
1138 | spin_unlock_irq(&chip->reg_lock); | ||
1139 | dsp_unlock(azx_dev); | ||
1140 | } | ||
1141 | EXPORT_SYMBOL_GPL(azx_load_dsp_cleanup); | ||
1142 | #endif /* CONFIG_SND_HDA_DSP_LOADER */ | ||
1143 | |||
1017 | int azx_alloc_stream_pages(struct azx *chip) | 1144 | int azx_alloc_stream_pages(struct azx *chip) |
1018 | { | 1145 | { |
1019 | int i, err; | 1146 | int i, err; |
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index 9ea6b44e033d..7c9c04d23f20 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h | |||
@@ -32,26 +32,15 @@ unsigned int azx_get_position(struct azx *chip, | |||
32 | bool with_check); | 32 | bool with_check); |
33 | 33 | ||
34 | /* Stream control. */ | 34 | /* Stream control. */ |
35 | void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev); | ||
36 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); | 35 | void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev); |
37 | void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev); | ||
38 | int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev); | ||
39 | int setup_bdle(struct azx *chip, | ||
40 | struct snd_dma_buffer *dmab, | ||
41 | struct azx_dev *azx_dev, u32 **bdlp, | ||
42 | int ofs, int size, int with_ioc); | ||
43 | 36 | ||
44 | /* DSP lock helpers */ | ||
45 | #ifdef CONFIG_SND_HDA_DSP_LOADER | 37 | #ifdef CONFIG_SND_HDA_DSP_LOADER |
46 | #define dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex) | 38 | int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, |
47 | #define dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex) | 39 | unsigned int byte_size, |
48 | #define dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex) | 40 | struct snd_dma_buffer *bufp); |
49 | #define dsp_is_locked(dev) ((dev)->locked) | 41 | void azx_load_dsp_trigger(struct hda_bus *bus, bool start); |
50 | #else | 42 | void azx_load_dsp_cleanup(struct hda_bus *bus, |
51 | #define dsp_lock_init(dev) do {} while (0) | 43 | struct snd_dma_buffer *dmab); |
52 | #define dsp_lock(dev) do {} while (0) | ||
53 | #define dsp_unlock(dev) do {} while (0) | ||
54 | #define dsp_is_locked(dev) 0 | ||
55 | #endif | 44 | #endif |
56 | 45 | ||
57 | /* Allocation functions. */ | 46 | /* Allocation functions. */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 4a0b228d70f7..80250b3a6fc3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -723,15 +723,6 @@ static unsigned int azx_get_response(struct hda_bus *bus, | |||
723 | static void azx_power_notify(struct hda_bus *bus, bool power_up); | 723 | static void azx_power_notify(struct hda_bus *bus, bool power_up); |
724 | #endif | 724 | #endif |
725 | 725 | ||
726 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
727 | static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, | ||
728 | unsigned int byte_size, | ||
729 | struct snd_dma_buffer *bufp); | ||
730 | static void azx_load_dsp_trigger(struct hda_bus *bus, bool start); | ||
731 | static void azx_load_dsp_cleanup(struct hda_bus *bus, | ||
732 | struct snd_dma_buffer *dmab); | ||
733 | #endif | ||
734 | |||
735 | /* enter link reset */ | 726 | /* enter link reset */ |
736 | static void azx_enter_link_reset(struct azx *chip) | 727 | static void azx_enter_link_reset(struct azx *chip) |
737 | { | 728 | { |
@@ -1354,121 +1345,6 @@ static void azx_stop_chip(struct azx *chip) | |||
1354 | chip->initialized = 0; | 1345 | chip->initialized = 0; |
1355 | } | 1346 | } |
1356 | 1347 | ||
1357 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
1358 | /* | ||
1359 | * DSP loading code (e.g. for CA0132) | ||
1360 | */ | ||
1361 | |||
1362 | /* use the first stream for loading DSP */ | ||
1363 | static struct azx_dev * | ||
1364 | azx_get_dsp_loader_dev(struct azx *chip) | ||
1365 | { | ||
1366 | return &chip->azx_dev[chip->playback_index_offset]; | ||
1367 | } | ||
1368 | |||
1369 | static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, | ||
1370 | unsigned int byte_size, | ||
1371 | struct snd_dma_buffer *bufp) | ||
1372 | { | ||
1373 | u32 *bdl; | ||
1374 | struct azx *chip = bus->private_data; | ||
1375 | struct azx_dev *azx_dev; | ||
1376 | int err; | ||
1377 | |||
1378 | azx_dev = azx_get_dsp_loader_dev(chip); | ||
1379 | |||
1380 | dsp_lock(azx_dev); | ||
1381 | spin_lock_irq(&chip->reg_lock); | ||
1382 | if (azx_dev->running || azx_dev->locked) { | ||
1383 | spin_unlock_irq(&chip->reg_lock); | ||
1384 | err = -EBUSY; | ||
1385 | goto unlock; | ||
1386 | } | ||
1387 | azx_dev->prepared = 0; | ||
1388 | chip->saved_azx_dev = *azx_dev; | ||
1389 | azx_dev->locked = 1; | ||
1390 | spin_unlock_irq(&chip->reg_lock); | ||
1391 | |||
1392 | err = chip->ops->dma_alloc_pages(chip, SNDRV_DMA_TYPE_DEV_SG, | ||
1393 | byte_size, bufp); | ||
1394 | if (err < 0) | ||
1395 | goto err_alloc; | ||
1396 | |||
1397 | azx_dev->bufsize = byte_size; | ||
1398 | azx_dev->period_bytes = byte_size; | ||
1399 | azx_dev->format_val = format; | ||
1400 | |||
1401 | azx_stream_reset(chip, azx_dev); | ||
1402 | |||
1403 | /* reset BDL address */ | ||
1404 | azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); | ||
1405 | azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); | ||
1406 | |||
1407 | azx_dev->frags = 0; | ||
1408 | bdl = (u32 *)azx_dev->bdl.area; | ||
1409 | err = setup_bdle(chip, bufp, azx_dev, &bdl, 0, byte_size, 0); | ||
1410 | if (err < 0) | ||
1411 | goto error; | ||
1412 | |||
1413 | azx_setup_controller(chip, azx_dev); | ||
1414 | dsp_unlock(azx_dev); | ||
1415 | return azx_dev->stream_tag; | ||
1416 | |||
1417 | error: | ||
1418 | chip->ops->dma_free_pages(chip, bufp); | ||
1419 | err_alloc: | ||
1420 | spin_lock_irq(&chip->reg_lock); | ||
1421 | if (azx_dev->opened) | ||
1422 | *azx_dev = chip->saved_azx_dev; | ||
1423 | azx_dev->locked = 0; | ||
1424 | spin_unlock_irq(&chip->reg_lock); | ||
1425 | unlock: | ||
1426 | dsp_unlock(azx_dev); | ||
1427 | return err; | ||
1428 | } | ||
1429 | |||
1430 | static void azx_load_dsp_trigger(struct hda_bus *bus, bool start) | ||
1431 | { | ||
1432 | struct azx *chip = bus->private_data; | ||
1433 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); | ||
1434 | |||
1435 | if (start) | ||
1436 | azx_stream_start(chip, azx_dev); | ||
1437 | else | ||
1438 | azx_stream_stop(chip, azx_dev); | ||
1439 | azx_dev->running = start; | ||
1440 | } | ||
1441 | |||
1442 | static void azx_load_dsp_cleanup(struct hda_bus *bus, | ||
1443 | struct snd_dma_buffer *dmab) | ||
1444 | { | ||
1445 | struct azx *chip = bus->private_data; | ||
1446 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); | ||
1447 | |||
1448 | if (!dmab->area || !azx_dev->locked) | ||
1449 | return; | ||
1450 | |||
1451 | dsp_lock(azx_dev); | ||
1452 | /* reset BDL address */ | ||
1453 | azx_sd_writel(chip, azx_dev, SD_BDLPL, 0); | ||
1454 | azx_sd_writel(chip, azx_dev, SD_BDLPU, 0); | ||
1455 | azx_sd_writel(chip, azx_dev, SD_CTL, 0); | ||
1456 | azx_dev->bufsize = 0; | ||
1457 | azx_dev->period_bytes = 0; | ||
1458 | azx_dev->format_val = 0; | ||
1459 | |||
1460 | chip->ops->dma_free_pages(chip, dmab); | ||
1461 | dmab->area = NULL; | ||
1462 | |||
1463 | spin_lock_irq(&chip->reg_lock); | ||
1464 | if (azx_dev->opened) | ||
1465 | *azx_dev = chip->saved_azx_dev; | ||
1466 | azx_dev->locked = 0; | ||
1467 | spin_unlock_irq(&chip->reg_lock); | ||
1468 | dsp_unlock(azx_dev); | ||
1469 | } | ||
1470 | #endif /* CONFIG_SND_HDA_DSP_LOADER */ | ||
1471 | |||
1472 | #ifdef CONFIG_PM | 1348 | #ifdef CONFIG_PM |
1473 | /* power-up/down the controller */ | 1349 | /* power-up/down the controller */ |
1474 | static void azx_power_notify(struct hda_bus *bus, bool power_up) | 1350 | static void azx_power_notify(struct hda_bus *bus, bool power_up) |