summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2018-02-19 16:28:11 +1100
committerSolomon Peachy <pizza@shaftnet.org>2020-10-31 14:16:31 +0000
commitdd82f13fa1241266576b508180fcf90b8d9bda2c (patch)
treecdae2331353e4f85a296782b14001d021923ddfc
parentce9e7e712238dc69a825a49f4f226ff47fbbff69 (diff)
downloadrockbox-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.c2
-rw-r--r--firmware/drivers/audio/fiiolinux_codec.c8
-rw-r--r--firmware/drivers/audio/nwzlinux-codec.c5
-rw-r--r--firmware/drivers/audio/rocker_codec.c2
-rw-r--r--firmware/drivers/audio/xduoolinux_codec.c2
-rw-r--r--firmware/target/hosted/alsa-controls.c167
-rw-r--r--firmware/target/hosted/alsa-controls.h5
-rw-r--r--firmware/target/hosted/pcm-alsa.c18
-rw-r--r--firmware/target/hosted/pcm-alsa.h2
-rw-r--r--firmware/target/hosted/sonynwz/debug-nwz.c2
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)
143void audiohw_preinit(void) 143void 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
68void audiohw_preinit(void) 68void 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
314void audiohw_preinit(void) 313void 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
422void audiohw_close(void) 421void 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
70void audiohw_preinit(void) 70void 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)
166void audiohw_preinit(void) 166void 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 */
25static snd_ctl_t *alsa_ctl; 26static 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 */
27static snd_ctl_elem_list_t *alsa_ctl_list; 28static snd_ctl_elem_list_t *alsa_ctl_list;
29static unsigned alsa_ctl_count;
30/* for each control, we store some info to avoid constantly using ALSA's horrible lookup functions */
31static 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
29void alsa_controls_init(void) 41#if defined(DEBUG)
42static 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
54void 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
51void alsa_controls_close(void) 126void 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 */ 132int alsa_controls_find(const char *name)
58bool 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
75bool alsa_has_control(const char *name) 142bool 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 */
85int alsa_controls_find_enum(const char *name, const char *enum_name) 148int 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)
112void alsa_controls_get_set(bool get, const char *name, snd_ctl_elem_type_t type, 164void 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 */
186void alsa_controls_get_info(const char *name, int *out_count) 232void 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 */
30void alsa_controls_init(void); 30void alsa_controls_init(const char *name);
31/* close alsa controls */ 31/* close alsa controls */
32void alsa_controls_close(void); 32void 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 */
39bool alsa_controls_find(snd_ctl_elem_id_t *id, const char *name);
40/* check wether a control exists */ 37/* check wether a control exists */
41bool alsa_has_control(const char *name); 38bool 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 */
68static const snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; /* sample format */ 68static const snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; /* sample format */
69typedef long sample_t; 69typedef int32_t sample_t;
70#else 70#else
71static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */ 71static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */
72typedef short sample_t; 72typedef int16_t sample_t;
73#endif 73#endif
74static const int channels = 2; /* count of channels */ 74static const int channels = 2; /* count of channels */
75static unsigned int real_sample_rate; 75static 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. */
263static int dig_vol_mult_l = 2 ^ 16; /* multiplicative factor to apply to each sample */ 263static int dig_vol_mult_l = 2 << 16; /* multiplicative factor to apply to each sample */
264static int dig_vol_mult_r = 2 ^ 16; /* multiplicative factor to apply to each sample */ 264static int dig_vol_mult_r = 2 << 16; /* multiplicative factor to apply to each sample */
265 265void pcm_set_mixer_volume(int vol_db_l, int vol_db_r)
266void 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
760void pcm_set_mixer_volume(int volume)
761{
762 (void)volume;
763}
764
765int pcm_alsa_get_rate(void) 759int 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 */
28void pcm_alsa_set_digital_volume(int vol_db_l, int vol_db_r); 28void 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());