diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2018-02-19 16:28:11 +1100 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2020-10-31 14:16:31 +0000 |
commit | dd82f13fa1241266576b508180fcf90b8d9bda2c (patch) | |
tree | cdae2331353e4f85a296782b14001d021923ddfc | |
parent | ce9e7e712238dc69a825a49f4f226ff47fbbff69 (diff) | |
download | rockbox-dd82f13fa1241266576b508180fcf90b8d9bda2c.tar.gz rockbox-dd82f13fa1241266576b508180fcf90b8d9bda2c.zip |
nwz/alsa: various improvements
Also audiohw driver to specific device name, rewrite alsa controls code to
cache more data, thus making the code easier and use less stack. Avoid using
short/long in pcm alsa code since it's the wrong size on 64-bit (simulator
for example)
Change-Id: Ibc1ec44396e37b6cbdedbcf37300878638e5d2d3
-rw-r--r-- | firmware/drivers/audio/erosqlinux_codec.c | 2 | ||||
-rw-r--r-- | firmware/drivers/audio/fiiolinux_codec.c | 8 | ||||
-rw-r--r-- | firmware/drivers/audio/nwzlinux-codec.c | 5 | ||||
-rw-r--r-- | firmware/drivers/audio/rocker_codec.c | 2 | ||||
-rw-r--r-- | firmware/drivers/audio/xduoolinux_codec.c | 2 | ||||
-rw-r--r-- | firmware/target/hosted/alsa-controls.c | 167 | ||||
-rw-r--r-- | firmware/target/hosted/alsa-controls.h | 5 | ||||
-rw-r--r-- | firmware/target/hosted/pcm-alsa.c | 18 | ||||
-rw-r--r-- | firmware/target/hosted/pcm-alsa.h | 2 | ||||
-rw-r--r-- | firmware/target/hosted/sonynwz/debug-nwz.c | 2 |
10 files changed, 121 insertions, 92 deletions
diff --git a/firmware/drivers/audio/erosqlinux_codec.c b/firmware/drivers/audio/erosqlinux_codec.c index 3b7155faef..c288c63c4f 100644 --- a/firmware/drivers/audio/erosqlinux_codec.c +++ b/firmware/drivers/audio/erosqlinux_codec.c | |||
@@ -143,7 +143,7 @@ void erosq_set_output(int ps) | |||
143 | void audiohw_preinit(void) | 143 | void audiohw_preinit(void) |
144 | { | 144 | { |
145 | logf("hw preinit"); | 145 | logf("hw preinit"); |
146 | alsa_controls_init(); | 146 | alsa_controls_init("default"); |
147 | hw_open(); | 147 | hw_open(); |
148 | audiohw_mute(false); /* No need to stay muted */ | 148 | audiohw_mute(false); /* No need to stay muted */ |
149 | } | 149 | } |
diff --git a/firmware/drivers/audio/fiiolinux_codec.c b/firmware/drivers/audio/fiiolinux_codec.c index 8b1f14662e..b2d95c91e9 100644 --- a/firmware/drivers/audio/fiiolinux_codec.c +++ b/firmware/drivers/audio/fiiolinux_codec.c | |||
@@ -67,7 +67,7 @@ static void hw_close(void) | |||
67 | 67 | ||
68 | void audiohw_preinit(void) | 68 | void audiohw_preinit(void) |
69 | { | 69 | { |
70 | alsa_controls_init(); | 70 | alsa_controls_init("default"); |
71 | hw_open(); | 71 | hw_open(); |
72 | // NOTE: | 72 | // NOTE: |
73 | // Of the exported controls, only these do anything: | 73 | // Of the exported controls, only these do anything: |
@@ -130,7 +130,7 @@ void audiohw_set_volume(int vol_l, int vol_r) | |||
130 | if (!muted) { | 130 | if (!muted) { |
131 | alsa_controls_set_ints("DACL Playback Volume", 1, &vol_hw[0]); | 131 | alsa_controls_set_ints("DACL Playback Volume", 1, &vol_hw[0]); |
132 | alsa_controls_set_ints("DACR Playback Volume", 1, &vol_hw[1]); | 132 | alsa_controls_set_ints("DACR Playback Volume", 1, &vol_hw[1]); |
133 | pcm_alsa_set_digital_volume(vol_sw[0], vol_sw[1]); | 133 | pcm_set_mixer_volume(vol_sw[0], vol_sw[1]); |
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
@@ -147,13 +147,13 @@ void audiohw_mute(int mute) | |||
147 | { | 147 | { |
148 | alsa_controls_set_ints("DACL Playback Volume", 1, &vol0); | 148 | alsa_controls_set_ints("DACL Playback Volume", 1, &vol0); |
149 | alsa_controls_set_ints("DACR Playback Volume", 1, &vol0); | 149 | alsa_controls_set_ints("DACR Playback Volume", 1, &vol0); |
150 | pcm_alsa_set_digital_volume(0, 0); | 150 | pcm_set_mixer_volume(0, 0); |
151 | } | 151 | } |
152 | else | 152 | else |
153 | { | 153 | { |
154 | alsa_controls_set_ints("DACL Playback Volume", 1, &vol_hw[0]); | 154 | alsa_controls_set_ints("DACL Playback Volume", 1, &vol_hw[0]); |
155 | alsa_controls_set_ints("DACR Playback Volume", 1, &vol_hw[1]); | 155 | alsa_controls_set_ints("DACR Playback Volume", 1, &vol_hw[1]); |
156 | pcm_alsa_set_digital_volume(vol_sw[0], vol_sw[1]); | 156 | pcm_set_mixer_volume(vol_sw[0], vol_sw[1]); |
157 | } | 157 | } |
158 | } | 158 | } |
159 | 159 | ||
diff --git a/firmware/drivers/audio/nwzlinux-codec.c b/firmware/drivers/audio/nwzlinux-codec.c index ca5e274255..5085befb20 100644 --- a/firmware/drivers/audio/nwzlinux-codec.c +++ b/firmware/drivers/audio/nwzlinux-codec.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include "audio.h" | 26 | #include "audio.h" |
27 | #include "sound.h" | 27 | #include "sound.h" |
28 | #include "audiohw.h" | 28 | #include "audiohw.h" |
29 | #include "cscodec.h" | ||
30 | #include "nwzlinux_codec.h" | 29 | #include "nwzlinux_codec.h" |
31 | #include "stdlib.h" | 30 | #include "stdlib.h" |
32 | #include "panic.h" | 31 | #include "panic.h" |
@@ -313,7 +312,7 @@ void audiohw_set_playback_src(enum nwz_src_t src) | |||
313 | 312 | ||
314 | void audiohw_preinit(void) | 313 | void audiohw_preinit(void) |
315 | { | 314 | { |
316 | alsa_controls_init(); | 315 | alsa_controls_init("default"); |
317 | /* turn on codec */ | 316 | /* turn on codec */ |
318 | alsa_controls_set_bool("CODEC Power Switch", true); | 317 | alsa_controls_set_bool("CODEC Power Switch", true); |
319 | /* mute */ | 318 | /* mute */ |
@@ -416,7 +415,7 @@ void audiohw_set_volume(int vol_l, int vol_r) | |||
416 | printf(" set driver volume %d (%d dB)\n", drv_vol, curve->level[drv_vol] / 10); | 415 | printf(" set driver volume %d (%d dB)\n", drv_vol, curve->level[drv_vol] / 10); |
417 | nwz_set_driver_vol(drv_vol); | 416 | nwz_set_driver_vol(drv_vol); |
418 | printf(" set digital volume %d dB\n", vol / 10); | 417 | printf(" set digital volume %d dB\n", vol / 10); |
419 | pcm_alsa_set_digital_volume(vol / 10, vol / 10); | 418 | pcm_set_mixer_volume(vol / 10, vol / 10); |
420 | } | 419 | } |
421 | 420 | ||
422 | void audiohw_close(void) | 421 | void audiohw_close(void) |
diff --git a/firmware/drivers/audio/rocker_codec.c b/firmware/drivers/audio/rocker_codec.c index b4ebdd7816..20c6e1e795 100644 --- a/firmware/drivers/audio/rocker_codec.c +++ b/firmware/drivers/audio/rocker_codec.c | |||
@@ -69,7 +69,7 @@ void audiohw_mute(int mute) | |||
69 | 69 | ||
70 | void audiohw_preinit(void) | 70 | void audiohw_preinit(void) |
71 | { | 71 | { |
72 | alsa_controls_init(); | 72 | alsa_controls_init("debug"); |
73 | hw_open(); | 73 | hw_open(); |
74 | #if defined(AUDIOHW_MUTE_ON_STOP) || defined(AUDIOHW_NEEDS_INITIAL_UNMUTE) | 74 | #if defined(AUDIOHW_MUTE_ON_STOP) || defined(AUDIOHW_NEEDS_INITIAL_UNMUTE) |
75 | audiohw_mute(true); /* Start muted to avoid the POP */ | 75 | audiohw_mute(true); /* Start muted to avoid the POP */ |
diff --git a/firmware/drivers/audio/xduoolinux_codec.c b/firmware/drivers/audio/xduoolinux_codec.c index 5452a0f5c3..3ce35aa62a 100644 --- a/firmware/drivers/audio/xduoolinux_codec.c +++ b/firmware/drivers/audio/xduoolinux_codec.c | |||
@@ -166,7 +166,7 @@ void xduoo_set_output(int ps) | |||
166 | void audiohw_preinit(void) | 166 | void audiohw_preinit(void) |
167 | { | 167 | { |
168 | logf("hw preinit"); | 168 | logf("hw preinit"); |
169 | alsa_controls_init(); | 169 | alsa_controls_init("default"); |
170 | hw_open(); | 170 | hw_open(); |
171 | 171 | ||
172 | #if defined(XDUOO_X3II) | 172 | #if defined(XDUOO_X3II) |
diff --git a/firmware/target/hosted/alsa-controls.c b/firmware/target/hosted/alsa-controls.c index f4914aa216..8d8c46decd 100644 --- a/firmware/target/hosted/alsa-controls.c +++ b/firmware/target/hosted/alsa-controls.c | |||
@@ -19,33 +19,108 @@ | |||
19 | ****************************************************************************/ | 19 | ****************************************************************************/ |
20 | #include "alsa-controls.h" | 20 | #include "alsa-controls.h" |
21 | #include "panic.h" | 21 | #include "panic.h" |
22 | #include "debug.h" | ||
22 | #include <stdlib.h> | 23 | #include <stdlib.h> |
23 | 24 | ||
24 | /* alsa control handle, we keep it open at all times */ | 25 | /* alsa control handle, we keep it open at all times */ |
25 | static snd_ctl_t *alsa_ctl; | 26 | static snd_ctl_t *alsa_ctl; |
26 | /* list of all controls, we allocate and fill it once, so we can easily lookup */ | 27 | /* list of all controls, we allocate and fill it once, so we can easily lookup */ |
27 | static snd_ctl_elem_list_t *alsa_ctl_list; | 28 | static snd_ctl_elem_list_t *alsa_ctl_list; |
29 | static unsigned alsa_ctl_count; | ||
30 | /* for each control, we store some info to avoid constantly using ALSA's horrible lookup functions */ | ||
31 | static struct ctl_t | ||
32 | { | ||
33 | snd_ctl_elem_id_t *id; /* ID associated with the control */ | ||
34 | const char *name; /* name of the control */ | ||
35 | snd_ctl_elem_type_t type; /* control type (boolean, enum, ...) */ | ||
36 | unsigned count; /* dimension of the control */ | ||
37 | unsigned items; /* number of items (for enums) */ | ||
38 | const char **enum_name; /* names of the enum, indexed by ALSA index */ | ||
39 | } *alsa_ctl_info; | ||
28 | 40 | ||
29 | void alsa_controls_init(void) | 41 | #if defined(DEBUG) |
42 | static const char *alsa_ctl_type_name(snd_ctl_elem_type_t type) | ||
43 | { | ||
44 | switch(type) | ||
45 | { | ||
46 | case SND_CTL_ELEM_TYPE_BOOLEAN: return "BOOLEAN"; | ||
47 | case SND_CTL_ELEM_TYPE_INTEGER: return "INTEGER"; | ||
48 | case SND_CTL_ELEM_TYPE_ENUMERATED: return "ENUMERATED"; | ||
49 | default: return "???"; | ||
50 | } | ||
51 | } | ||
52 | #endif | ||
53 | |||
54 | void alsa_controls_init(const char *name) | ||
30 | { | 55 | { |
31 | snd_ctl_elem_info_t *info; | ||
32 | /* allocate list on heap because it is used it is used in other functions */ | 56 | /* allocate list on heap because it is used it is used in other functions */ |
33 | snd_ctl_elem_list_malloc(&alsa_ctl_list); | 57 | snd_ctl_elem_list_malloc(&alsa_ctl_list); |
34 | /* allocate info on stack so there is no need to free them */ | ||
35 | snd_ctl_elem_info_alloca(&info); | ||
36 | /* there is only one card and "default" always works */ | 58 | /* there is only one card and "default" always works */ |
37 | if(snd_ctl_open(&alsa_ctl, "default", 0) < 0) | 59 | if(snd_ctl_open(&alsa_ctl, name, 0) < 0) |
38 | panicf("Cannot open ctl\n"); | 60 | panicf("Cannot open ctl\n"); |
39 | /* ALSA is braindead: first "get" the list -> only retrieve count */ | 61 | /* ALSA is braindead: first "get" the list -> only retrieve count */ |
40 | if(snd_ctl_elem_list(alsa_ctl, alsa_ctl_list) < 0) | 62 | if(snd_ctl_elem_list(alsa_ctl, alsa_ctl_list) < 0) |
41 | panicf("Cannot get element list\n"); | 63 | panicf("Cannot get element list\n"); |
42 | /* now we can allocate the list since the know the size */ | 64 | /* now we can allocate the list since the know the size */ |
43 | int count = snd_ctl_elem_list_get_count(alsa_ctl_list); | 65 | alsa_ctl_count = snd_ctl_elem_list_get_count(alsa_ctl_list); |
44 | if(snd_ctl_elem_list_alloc_space(alsa_ctl_list, count) < 0) | 66 | if(snd_ctl_elem_list_alloc_space(alsa_ctl_list, alsa_ctl_count) < 0) |
45 | panicf("Cannot allocate space for element list\n"); | 67 | panicf("Cannot allocate space for element list\n"); |
46 | /* ... and get the list again! */ | 68 | /* ... and get the list again! */ |
47 | if(snd_ctl_elem_list(alsa_ctl, alsa_ctl_list) < 0) | 69 | if(snd_ctl_elem_list(alsa_ctl, alsa_ctl_list) < 0) |
48 | panicf("Cannot get element list\n"); | 70 | panicf("Cannot get element list\n"); |
71 | /* now cache the info */ | ||
72 | alsa_ctl_info = malloc(sizeof(struct ctl_t) * alsa_ctl_count); | ||
73 | snd_ctl_elem_info_t *info; | ||
74 | snd_ctl_elem_info_malloc(&info); | ||
75 | for(unsigned i = 0; i < alsa_ctl_count; i++) | ||
76 | { | ||
77 | /* allocate the ID and retrieve it */ | ||
78 | snd_ctl_elem_id_malloc(&alsa_ctl_info[i].id); | ||
79 | snd_ctl_elem_list_get_id(alsa_ctl_list, i, alsa_ctl_info[i].id); | ||
80 | /* NOTE: name is valid as long as the ID lives; since we keep both, no need to copy */ | ||
81 | alsa_ctl_info[i].name = snd_ctl_elem_id_get_name(alsa_ctl_info[i].id); | ||
82 | /* get info */ | ||
83 | snd_ctl_elem_info_set_id(info, alsa_ctl_info[i].id); | ||
84 | if(snd_ctl_elem_info(alsa_ctl, info) < 0) | ||
85 | panicf("Cannot get control '%s' info", alsa_ctl_info[i].name); | ||
86 | alsa_ctl_info[i].type = snd_ctl_elem_info_get_type(info); | ||
87 | alsa_ctl_info[i].count = snd_ctl_elem_info_get_count(info); | ||
88 | if(alsa_ctl_info[i].type == SND_CTL_ELEM_TYPE_ENUMERATED) | ||
89 | { | ||
90 | alsa_ctl_info[i].items = snd_ctl_elem_info_get_items(info); | ||
91 | alsa_ctl_info[i].enum_name = malloc(sizeof(char *) * alsa_ctl_info[i].items); | ||
92 | for(unsigned j = 0; j < alsa_ctl_info[i].items; j++) | ||
93 | { | ||
94 | snd_ctl_elem_info_set_item(info, j); | ||
95 | if(snd_ctl_elem_info(alsa_ctl, info) < 0) | ||
96 | panicf("Cannot get control '%s' info for item %u", alsa_ctl_info[i].name, j); | ||
97 | /* NOTE: copy string because it becomes invalid after info is freed */ | ||
98 | alsa_ctl_info[i].enum_name[j] = strdup(snd_ctl_elem_info_get_item_name(info)); | ||
99 | } | ||
100 | } | ||
101 | else | ||
102 | alsa_ctl_info[i].items = 0; | ||
103 | } | ||
104 | snd_ctl_elem_info_free(info); | ||
105 | |||
106 | DEBUGF("ALSA controls:\n"); | ||
107 | for(unsigned i = 0; i < alsa_ctl_count; i++) | ||
108 | { | ||
109 | DEBUGF("- name='%s', type=%s, count=%u\n", alsa_ctl_info[i].name, | ||
110 | alsa_ctl_type_name(alsa_ctl_info[i].type), alsa_ctl_info[i].count); | ||
111 | if(alsa_ctl_info[i].type == SND_CTL_ELEM_TYPE_ENUMERATED) | ||
112 | { | ||
113 | DEBUGF(" items:"); | ||
114 | for(unsigned j = 0; j < alsa_ctl_info[i].items; j++) | ||
115 | { | ||
116 | if(j != 0) | ||
117 | DEBUGF(","); | ||
118 | DEBUGF(" '%s'", alsa_ctl_info[i].enum_name[j]); | ||
119 | } | ||
120 | DEBUGF("\n"); | ||
121 | } | ||
122 | } | ||
123 | |||
49 | } | 124 | } |
50 | 125 | ||
51 | void alsa_controls_close(void) | 126 | void alsa_controls_close(void) |
@@ -53,56 +128,33 @@ void alsa_controls_close(void) | |||
53 | snd_ctl_close(alsa_ctl); | 128 | snd_ctl_close(alsa_ctl); |
54 | } | 129 | } |
55 | 130 | ||
56 | /* find a control element ID by name, return false of not found, the id needs | 131 | /* find a control element ID by name, return -1 of not found or index into array */ |
57 | * to be allocated */ | 132 | int alsa_controls_find(const char *name) |
58 | bool alsa_controls_find(snd_ctl_elem_id_t *id, const char *name) | ||
59 | { | 133 | { |
60 | /* ALSA identifies controls by "id"s, it almost makes sense, except ids | ||
61 | * are a horrible opaque structure */ | ||
62 | int count = snd_ctl_elem_list_get_count(alsa_ctl_list); | ||
63 | /* enumerate controls */ | 134 | /* enumerate controls */ |
64 | for(int i = 0; i < count; i++) | 135 | for(unsigned i = 0; i < alsa_ctl_count; i++) |
65 | { | 136 | if(strcmp(alsa_ctl_info[i].name, name) == 0) |
66 | snd_ctl_elem_list_get_id(alsa_ctl_list, i, id); | 137 | return i; |
67 | |||
68 | if(strcmp(snd_ctl_elem_id_get_name(id), name) == 0) | ||
69 | return true; | ||
70 | } | ||
71 | /* not found */ | 138 | /* not found */ |
72 | return false; | 139 | return -1; |
73 | } | 140 | } |
74 | 141 | ||
75 | bool alsa_has_control(const char *name) | 142 | bool alsa_has_control(const char *name) |
76 | { | 143 | { |
77 | snd_ctl_elem_id_t *id; | 144 | return alsa_controls_find(name) >= 0; |
78 | /* allocate things on stack */ | ||
79 | snd_ctl_elem_id_alloca(&id); | ||
80 | /* find control */ | ||
81 | return alsa_controls_find(id, name); | ||
82 | } | 145 | } |
83 | 146 | ||
84 | /* find a control element enum index by name, return -1 if not found */ | 147 | /* find a control element enum index by name, return -1 if not found */ |
85 | int alsa_controls_find_enum(const char *name, const char *enum_name) | 148 | int alsa_controls_find_enum(const char *name, const char *enum_name) |
86 | { | 149 | { |
87 | snd_ctl_elem_id_t *id; | ||
88 | snd_ctl_elem_info_t *info; | ||
89 | /* allocate things on stack to speedup */ | ||
90 | snd_ctl_elem_id_alloca(&id); | ||
91 | snd_ctl_elem_info_alloca(&info); | ||
92 | /* find control */ | 150 | /* find control */ |
93 | if(!alsa_controls_find(id, name)) | 151 | int idx = alsa_controls_find(name); |
152 | if(idx < 0) | ||
94 | panicf("Cannot find control '%s'", name); | 153 | panicf("Cannot find control '%s'", name); |
95 | snd_ctl_elem_info_set_id(info, id); | ||
96 | if(snd_ctl_elem_info(alsa_ctl, info) < 0) | ||
97 | panicf("Cannot get control '%s' info", name); | ||
98 | /* list items */ | 154 | /* list items */ |
99 | unsigned count = snd_ctl_elem_info_get_items(info); | 155 | for(unsigned i = 0; i < alsa_ctl_info[idx].items; i++) |
100 | for(unsigned i = 0; i < count; i++) | ||
101 | { | 156 | { |
102 | snd_ctl_elem_info_set_item(info, i); | 157 | if(strcmp(alsa_ctl_info[idx].enum_name[i], enum_name) == 0) |
103 | if(snd_ctl_elem_info(alsa_ctl, info) < 0) | ||
104 | panicf("Cannot get control '%s' info for item %u", name, i); | ||
105 | if(strcmp(snd_ctl_elem_info_get_item_name(info), enum_name) == 0) | ||
106 | return i; | 158 | return i; |
107 | } | 159 | } |
108 | return -1; | 160 | return -1; |
@@ -112,27 +164,21 @@ int alsa_controls_find_enum(const char *name, const char *enum_name) | |||
112 | void alsa_controls_get_set(bool get, const char *name, snd_ctl_elem_type_t type, | 164 | void alsa_controls_get_set(bool get, const char *name, snd_ctl_elem_type_t type, |
113 | unsigned nr_values, long *val) | 165 | unsigned nr_values, long *val) |
114 | { | 166 | { |
115 | snd_ctl_elem_id_t *id; | ||
116 | snd_ctl_elem_info_t *info; | ||
117 | snd_ctl_elem_value_t *value; | 167 | snd_ctl_elem_value_t *value; |
118 | /* allocate things on stack to speedup */ | 168 | /* allocate things on stack to speedup */ |
119 | snd_ctl_elem_id_alloca(&id); | ||
120 | snd_ctl_elem_info_alloca(&info); | ||
121 | snd_ctl_elem_value_alloca(&value); | 169 | snd_ctl_elem_value_alloca(&value); |
122 | /* find control */ | 170 | /* find control */ |
123 | if(!alsa_controls_find(id, name)) | 171 | int idx = alsa_controls_find(name); |
172 | if(idx < 0) | ||
124 | panicf("Cannot find control '%s'", name); | 173 | panicf("Cannot find control '%s'", name); |
125 | /* check the type of the control */ | 174 | /* check the type of the control */ |
126 | snd_ctl_elem_info_set_id(info, id); | 175 | if(alsa_ctl_info[idx].type != type) |
127 | if(snd_ctl_elem_info(alsa_ctl, info) < 0) | ||
128 | panicf("Cannot get control '%s' info", name); | ||
129 | if(snd_ctl_elem_info_get_type(info) != type) | ||
130 | panicf("Control '%s' has wrong type (got %d, expected %d", name, | 176 | panicf("Control '%s' has wrong type (got %d, expected %d", name, |
131 | snd_ctl_elem_info_get_type(info), type); | 177 | alsa_ctl_info[idx].type, type); |
132 | if(snd_ctl_elem_info_get_count(info) != nr_values) | 178 | if(alsa_ctl_info[idx].count != nr_values) |
133 | panicf("Control '%s' has wrong count (got %u, expected %u)", | 179 | panicf("Control '%s' has wrong count (got %u, expected %u)", |
134 | name, snd_ctl_elem_info_get_count(info), nr_values); | 180 | name, alsa_ctl_info[idx].count, nr_values); |
135 | snd_ctl_elem_value_set_id(value, id); | 181 | snd_ctl_elem_value_set_id(value, alsa_ctl_info[idx].id); |
136 | /* set value */ | 182 | /* set value */ |
137 | if(get) | 183 | if(get) |
138 | { | 184 | { |
@@ -185,19 +231,12 @@ void alsa_controls_get(const char *name, snd_ctl_elem_type_t type, | |||
185 | /* get control information */ | 231 | /* get control information */ |
186 | void alsa_controls_get_info(const char *name, int *out_count) | 232 | void alsa_controls_get_info(const char *name, int *out_count) |
187 | { | 233 | { |
188 | snd_ctl_elem_id_t *id; | ||
189 | snd_ctl_elem_info_t *info; | ||
190 | /* allocate things on stack to speedup */ | ||
191 | snd_ctl_elem_id_alloca(&id); | ||
192 | snd_ctl_elem_info_alloca(&info); | ||
193 | /* find control */ | 234 | /* find control */ |
194 | if(!alsa_controls_find(id, name)) | 235 | int idx = alsa_controls_find(name); |
236 | if(idx < 0) | ||
195 | panicf("Cannot find control '%s'", name); | 237 | panicf("Cannot find control '%s'", name); |
196 | /* get info */ | 238 | /* get info */ |
197 | snd_ctl_elem_info_set_id(info, id); | 239 | *out_count = alsa_ctl_info[idx].count; |
198 | if(snd_ctl_elem_info(alsa_ctl, info) < 0) | ||
199 | panicf("Cannot get control '%s' info", name); | ||
200 | *out_count = snd_ctl_elem_info_get_count(info); | ||
201 | } | 240 | } |
202 | 241 | ||
203 | /* helper function: set a control with a single boolean value */ | 242 | /* helper function: set a control with a single boolean value */ |
diff --git a/firmware/target/hosted/alsa-controls.h b/firmware/target/hosted/alsa-controls.h index 0505ee3dd1..af3e584cd9 100644 --- a/firmware/target/hosted/alsa-controls.h +++ b/firmware/target/hosted/alsa-controls.h | |||
@@ -27,16 +27,13 @@ | |||
27 | #include <alloca.h> | 27 | #include <alloca.h> |
28 | 28 | ||
29 | /* open alsa control interface and list all controls, keep control open */ | 29 | /* open alsa control interface and list all controls, keep control open */ |
30 | void alsa_controls_init(void); | 30 | void alsa_controls_init(const char *name); |
31 | /* close alsa controls */ | 31 | /* close alsa controls */ |
32 | void alsa_controls_close(void); | 32 | void alsa_controls_close(void); |
33 | 33 | ||
34 | /* NOTE: all the following functions panic on error. This behaviour could be changed with the | 34 | /* NOTE: all the following functions panic on error. This behaviour could be changed with the |
35 | * functions returning proper values but that would make errors happen silently */ | 35 | * functions returning proper values but that would make errors happen silently */ |
36 | 36 | ||
37 | /* find a control element ID by name, return false of not found, the id needs | ||
38 | * to be allocated */ | ||
39 | bool alsa_controls_find(snd_ctl_elem_id_t *id, const char *name); | ||
40 | /* check wether a control exists */ | 37 | /* check wether a control exists */ |
41 | bool alsa_has_control(const char *name); | 38 | bool alsa_has_control(const char *name); |
42 | /* find a control element enum index by name, return -1 if not found */ | 39 | /* find a control element enum index by name, return -1 if not found */ |
diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c index 939a0cabb5..970abc78cf 100644 --- a/firmware/target/hosted/pcm-alsa.c +++ b/firmware/target/hosted/pcm-alsa.c | |||
@@ -66,10 +66,10 @@ static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access | |||
66 | #if defined(SONY_NWZ_LINUX) || defined(HAVE_FIIO_LINUX_CODEC) | 66 | #if defined(SONY_NWZ_LINUX) || defined(HAVE_FIIO_LINUX_CODEC) |
67 | /* Sony NWZ must use 32-bit per sample */ | 67 | /* Sony NWZ must use 32-bit per sample */ |
68 | static const snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; /* sample format */ | 68 | static const snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; /* sample format */ |
69 | typedef long sample_t; | 69 | typedef int32_t sample_t; |
70 | #else | 70 | #else |
71 | static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */ | 71 | static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */ |
72 | typedef short sample_t; | 72 | typedef int16_t sample_t; |
73 | #endif | 73 | #endif |
74 | static const int channels = 2; /* count of channels */ | 74 | static const int channels = 2; /* count of channels */ |
75 | static unsigned int real_sample_rate; | 75 | static unsigned int real_sample_rate; |
@@ -260,10 +260,9 @@ error: | |||
260 | * and add 48dB to the input volume. We cannot go lower -43dB because several | 260 | * and add 48dB to the input volume. We cannot go lower -43dB because several |
261 | * values between -48dB and -43dB would require a fractional multiplier, which is | 261 | * values between -48dB and -43dB would require a fractional multiplier, which is |
262 | * stupid to implement for such very low volume. */ | 262 | * stupid to implement for such very low volume. */ |
263 | static int dig_vol_mult_l = 2 ^ 16; /* multiplicative factor to apply to each sample */ | 263 | static int dig_vol_mult_l = 2 << 16; /* multiplicative factor to apply to each sample */ |
264 | static int dig_vol_mult_r = 2 ^ 16; /* multiplicative factor to apply to each sample */ | 264 | static int dig_vol_mult_r = 2 << 16; /* multiplicative factor to apply to each sample */ |
265 | 265 | void pcm_set_mixer_volume(int vol_db_l, int vol_db_r) | |
266 | void pcm_alsa_set_digital_volume(int vol_db_l, int vol_db_r) | ||
267 | { | 266 | { |
268 | if(vol_db_l > 0 || vol_db_r > 0 || vol_db_l < -43 || vol_db_r < -43) | 267 | if(vol_db_l > 0 || vol_db_r > 0 || vol_db_l < -43 || vol_db_r < -43) |
269 | panicf("invalid pcm alsa volume"); | 268 | panicf("invalid pcm alsa volume"); |
@@ -336,7 +335,7 @@ static bool copy_frames(bool first) | |||
336 | { | 335 | { |
337 | /* We have to convert 16-bit to 32-bit, the need to multiply the | 336 | /* We have to convert 16-bit to 32-bit, the need to multiply the |
338 | * sample by some value so the sound is not too low */ | 337 | * sample by some value so the sound is not too low */ |
339 | const short *pcm_ptr = pcm_data; | 338 | const int16_t *pcm_ptr = pcm_data; |
340 | sample_t *sample_ptr = &frames[2*(period_size-frames_left)]; | 339 | sample_t *sample_ptr = &frames[2*(period_size-frames_left)]; |
341 | for (int i = 0; i < nframes; i++) | 340 | for (int i = 0; i < nframes; i++) |
342 | { | 341 | { |
@@ -757,11 +756,6 @@ void pcm_play_dma_postinit(void) | |||
757 | #endif | 756 | #endif |
758 | } | 757 | } |
759 | 758 | ||
760 | void pcm_set_mixer_volume(int volume) | ||
761 | { | ||
762 | (void)volume; | ||
763 | } | ||
764 | |||
765 | int pcm_alsa_get_rate(void) | 759 | int pcm_alsa_get_rate(void) |
766 | { | 760 | { |
767 | return real_sample_rate; | 761 | return real_sample_rate; |
diff --git a/firmware/target/hosted/pcm-alsa.h b/firmware/target/hosted/pcm-alsa.h index f10574a6da..1392593c0c 100644 --- a/firmware/target/hosted/pcm-alsa.h +++ b/firmware/target/hosted/pcm-alsa.h | |||
@@ -25,7 +25,7 @@ | |||
25 | #if defined(SONY_NWZ_LINUX) || defined(HAVE_FIIO_LINUX_CODEC) | 25 | #if defined(SONY_NWZ_LINUX) || defined(HAVE_FIIO_LINUX_CODEC) |
26 | /* Set the PCM volume in dB: each sample with have this volume applied digitally | 26 | /* Set the PCM volume in dB: each sample with have this volume applied digitally |
27 | * before being sent to ALSA. Volume must satisfy -43 <= dB <= 0 */ | 27 | * before being sent to ALSA. Volume must satisfy -43 <= dB <= 0 */ |
28 | void pcm_alsa_set_digital_volume(int vol_db_l, int vol_db_r); | 28 | void pcm_set_mixer_volume(int vol_db_l, int vol_db_r); |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | /* These two should be invoked in your audiohw_preinit() call! */ | 31 | /* These two should be invoked in your audiohw_preinit() call! */ |
diff --git a/firmware/target/hosted/sonynwz/debug-nwz.c b/firmware/target/hosted/sonynwz/debug-nwz.c index c9a430e7c2..859eddb47b 100644 --- a/firmware/target/hosted/sonynwz/debug-nwz.c +++ b/firmware/target/hosted/sonynwz/debug-nwz.c | |||
@@ -369,7 +369,7 @@ bool dbg_hw_info_audio(void) | |||
369 | { | 369 | { |
370 | case VOL: | 370 | case VOL: |
371 | vol += inc ? 1 : -1; | 371 | vol += inc ? 1 : -1; |
372 | pcm_alsa_set_digital_volume(vol, vol); | 372 | pcm_set_mixer_volume(vol, vol); |
373 | break; | 373 | break; |
374 | case ACOUSTIC: | 374 | case ACOUSTIC: |
375 | audiohw_enable_acoustic(!audiohw_acoustic_enabled()); | 375 | audiohw_enable_acoustic(!audiohw_acoustic_enabled()); |