diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/hosted/agptek/debug-agptek.c | 52 | ||||
-rw-r--r-- | firmware/target/hosted/pcm-alsa.c | 92 | ||||
-rw-r--r-- | firmware/target/hosted/pcm-alsa.h | 6 | ||||
-rw-r--r-- | firmware/target/hosted/xduoo/debug-xduoo.c | 7 |
4 files changed, 118 insertions, 39 deletions
diff --git a/firmware/target/hosted/agptek/debug-agptek.c b/firmware/target/hosted/agptek/debug-agptek.c index 33f3ac4b97..b4fcb4246b 100644 --- a/firmware/target/hosted/agptek/debug-agptek.c +++ b/firmware/target/hosted/agptek/debug-agptek.c | |||
@@ -1,6 +1,52 @@ | |||
1 | #include <stdbool.h> | 1 | /*************************************************************************** |
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2020 by Solomon Peachy | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version 2 | ||
14 | * of the License, or (at your option) any later version. | ||
15 | * | ||
16 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
17 | * KIND, either express or implied. | ||
18 | * | ||
19 | ****************************************************************************/ | ||
2 | 20 | ||
3 | bool debug_hw_info(void) | 21 | #include "config.h" |
22 | #include "font.h" | ||
23 | #include "lcd.h" | ||
24 | #include "kernel.h" | ||
25 | #include "button.h" | ||
26 | |||
27 | #ifndef BOOTLOADER | ||
28 | |||
29 | #include "pcm-alsa.h" | ||
30 | |||
31 | static int line = 0; | ||
32 | |||
33 | bool dbg_hw_info(void) | ||
4 | { | 34 | { |
5 | return false; | 35 | int btn = 0; |
36 | |||
37 | lcd_setfont(FONT_SYSFIXED); | ||
38 | |||
39 | while(btn ^ BUTTON_POWER) { | ||
40 | lcd_clear_display(); | ||
41 | line = 0; | ||
42 | |||
43 | lcd_putsf(0, line++, "pcm srate: %d", pcm_alsa_get_rate()); | ||
44 | btn = button_read_device(); | ||
45 | |||
46 | lcd_update(); | ||
47 | sleep(HZ/16); | ||
48 | } | ||
49 | return true; | ||
6 | } | 50 | } |
51 | |||
52 | #endif /* !BOOTLOADER */ | ||
diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c index 1b8e3c4477..f33b42429c 100644 --- a/firmware/target/hosted/pcm-alsa.c +++ b/firmware/target/hosted/pcm-alsa.c | |||
@@ -68,7 +68,7 @@ | |||
68 | * with multple applications running */ | 68 | * with multple applications running */ |
69 | static char device[] = "plughw:0,0"; /* playback device */ | 69 | static char device[] = "plughw:0,0"; /* playback device */ |
70 | static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access mode */ | 70 | static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access mode */ |
71 | #ifdef SONY_NWZ_LINUX | 71 | #if defined(SONY_NWZ_LINUX) || defined(HAVE_FIIO_LINUX_CODEC) |
72 | /* Sony NWZ must use 32-bit per sample */ | 72 | /* Sony NWZ must use 32-bit per sample */ |
73 | static const snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; /* sample format */ | 73 | static const snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; /* sample format */ |
74 | typedef long sample_t; | 74 | typedef long sample_t; |
@@ -77,6 +77,9 @@ static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format * | |||
77 | typedef short sample_t; | 77 | typedef short sample_t; |
78 | #endif | 78 | #endif |
79 | static const int channels = 2; /* count of channels */ | 79 | static const int channels = 2; /* count of channels */ |
80 | static unsigned int sample_rate = 0; | ||
81 | static unsigned int real_sample_rate = 0; | ||
82 | |||
80 | static snd_pcm_t *handle = NULL; | 83 | static snd_pcm_t *handle = NULL; |
81 | static snd_pcm_sframes_t buffer_size = MIX_FRAME_SAMPLES * 32; /* ~16k */ | 84 | static snd_pcm_sframes_t buffer_size = MIX_FRAME_SAMPLES * 32; /* ~16k */ |
82 | static snd_pcm_sframes_t period_size = MIX_FRAME_SAMPLES * 4; /* ~4k */ | 85 | static snd_pcm_sframes_t period_size = MIX_FRAME_SAMPLES * 4; /* ~4k */ |
@@ -93,14 +96,13 @@ static char signal_stack[SIGSTKSZ]; | |||
93 | static int recursion; | 96 | static int recursion; |
94 | #endif | 97 | #endif |
95 | 98 | ||
96 | static int set_hwparams(snd_pcm_t *handle, unsigned sample_rate) | 99 | static int set_hwparams(snd_pcm_t *handle) |
97 | { | 100 | { |
98 | unsigned int rrate; | ||
99 | int err; | 101 | int err; |
102 | unsigned int srate; | ||
100 | snd_pcm_hw_params_t *params; | 103 | snd_pcm_hw_params_t *params; |
101 | snd_pcm_hw_params_malloc(¶ms); | 104 | snd_pcm_hw_params_malloc(¶ms); |
102 | 105 | ||
103 | |||
104 | /* choose all parameters */ | 106 | /* choose all parameters */ |
105 | err = snd_pcm_hw_params_any(handle, params); | 107 | err = snd_pcm_hw_params_any(handle, params); |
106 | if (err < 0) | 108 | if (err < 0) |
@@ -130,16 +132,17 @@ static int set_hwparams(snd_pcm_t *handle, unsigned sample_rate) | |||
130 | goto error; | 132 | goto error; |
131 | } | 133 | } |
132 | /* set the stream rate */ | 134 | /* set the stream rate */ |
133 | rrate = sample_rate; | 135 | sample_rate = srate = pcm_sampr; |
134 | err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); | 136 | err = snd_pcm_hw_params_set_rate_near(handle, params, &srate, 0); |
135 | if (err < 0) | 137 | if (err < 0) |
136 | { | 138 | { |
137 | printf("Rate %iHz not available for playback: %s\n", sample_rate, snd_strerror(err)); | 139 | printf("Rate %iHz not available for playback: %s\n", sample_rate, snd_strerror(err)); |
138 | goto error; | 140 | goto error; |
139 | } | 141 | } |
140 | if (rrate != sample_rate) | 142 | real_sample_rate = srate; |
143 | if (real_sample_rate != sample_rate) | ||
141 | { | 144 | { |
142 | printf("Rate doesn't match (requested %iHz, get %iHz)\n", sample_rate, rrate); | 145 | printf("Rate doesn't match (requested %iHz, get %iHz)\n", sample_rate, real_sample_rate); |
143 | err = -EINVAL; | 146 | err = -EINVAL; |
144 | goto error; | 147 | goto error; |
145 | } | 148 | } |
@@ -159,8 +162,9 @@ static int set_hwparams(snd_pcm_t *handle, unsigned sample_rate) | |||
159 | printf("Unable to set period size %ld for playback: %s\n", period_size, snd_strerror(err)); | 162 | printf("Unable to set period size %ld for playback: %s\n", period_size, snd_strerror(err)); |
160 | goto error; | 163 | goto error; |
161 | } | 164 | } |
162 | if (!frames) | 165 | |
163 | frames = malloc(period_size * channels * sizeof(sample_t)); | 166 | free(frames); |
167 | frames = calloc(1, period_size * channels * sizeof(sample_t)); | ||
164 | 168 | ||
165 | /* write the parameters to device */ | 169 | /* write the parameters to device */ |
166 | err = snd_pcm_hw_params(handle, params); | 170 | err = snd_pcm_hw_params(handle, params); |
@@ -229,26 +233,37 @@ error: | |||
229 | * and add 48dB to the input volume. We cannot go lower -43dB because several | 233 | * and add 48dB to the input volume. We cannot go lower -43dB because several |
230 | * values between -48dB and -43dB would require a fractional multiplier, which is | 234 | * values between -48dB and -43dB would require a fractional multiplier, which is |
231 | * stupid to implement for such very low volume. */ | 235 | * stupid to implement for such very low volume. */ |
232 | static int dig_vol_mult = 2 ^ 16; /* multiplicative factor to apply to each sample */ | 236 | static int dig_vol_mult_l = 2 ^ 16; /* multiplicative factor to apply to each sample */ |
237 | static int dig_vol_mult_r = 2 ^ 16; /* multiplicative factor to apply to each sample */ | ||
233 | 238 | ||
234 | void pcm_alsa_set_digital_volume(int vol_db) | 239 | void pcm_alsa_set_digital_volume(int vol_db_l, int vol_db_r) |
235 | { | 240 | { |
236 | if(vol_db > 0 || vol_db < -43) | 241 | if(vol_db_l > 0 || vol_db_r > 0 || vol_db_l < -43 || vol_db_r < -43) |
237 | panicf("invalid pcm alsa volume"); | 242 | panicf("invalid pcm alsa volume"); |
238 | if(format != SND_PCM_FORMAT_S32_LE) | 243 | if(format != SND_PCM_FORMAT_S32_LE) |
239 | panicf("this function assumes 32-bit sample size"); | 244 | panicf("this function assumes 32-bit sample size"); |
240 | vol_db += 48; /* -42dB .. 0dB => 5dB .. 48dB */ | 245 | vol_db_l += 48; /* -42dB .. 0dB => 5dB .. 48dB */ |
246 | vol_db_r += 48; /* -42dB .. 0dB => 5dB .. 48dB */ | ||
241 | /* NOTE if vol_dB = 5 then vol_shift = 1 but r = 1 so we do vol_shift - 1 >= 0 | 247 | /* NOTE if vol_dB = 5 then vol_shift = 1 but r = 1 so we do vol_shift - 1 >= 0 |
242 | * otherwise vol_dB >= 0 implies vol_shift >= 2 so vol_shift - 2 >= 0 */ | 248 | * otherwise vol_dB >= 0 implies vol_shift >= 2 so vol_shift - 2 >= 0 */ |
243 | int vol_shift = vol_db / 3; | 249 | int vol_shift_l = vol_db_l / 3; |
244 | int r = vol_db % 3; | 250 | int vol_shift_r = vol_db_r / 3; |
245 | if(r == 0) | 251 | int r_l = vol_db_l % 3; |
246 | dig_vol_mult = 1 << vol_shift; | 252 | int r_r = vol_db_r % 3; |
247 | else if(r == 1) | 253 | if(r_l == 0) |
248 | dig_vol_mult = 1 << vol_shift | 1 << (vol_shift - 2); | 254 | dig_vol_mult_l = 1 << vol_shift_l; |
255 | else if(r_l == 1) | ||
256 | dig_vol_mult_l = 1 << vol_shift_l | 1 << (vol_shift_l - 2); | ||
257 | else | ||
258 | dig_vol_mult_l = 1 << vol_shift_l | 1 << (vol_shift_l - 1); | ||
259 | printf("l: %d dB -> factor = %d\n", vol_db_l - 48, dig_vol_mult_l); | ||
260 | if(r_r == 0) | ||
261 | dig_vol_mult_r = 1 << vol_shift_r; | ||
262 | else if(r_r == 1) | ||
263 | dig_vol_mult_r = 1 << vol_shift_r | 1 << (vol_shift_r - 2); | ||
249 | else | 264 | else |
250 | dig_vol_mult = 1 << vol_shift | 1 << (vol_shift - 1); | 265 | dig_vol_mult_r = 1 << vol_shift_r | 1 << (vol_shift_r - 1); |
251 | printf("%d dB -> factor = %d\n", vol_db - 48, dig_vol_mult); | 266 | printf("r: %d dB -> factor = %d\n", vol_db_r - 48, dig_vol_mult_r); |
252 | } | 267 | } |
253 | 268 | ||
254 | /* copy pcm samples to a spare buffer, suitable for snd_pcm_writei() */ | 269 | /* copy pcm samples to a spare buffer, suitable for snd_pcm_writei() */ |
@@ -279,8 +294,11 @@ static bool fill_frames(void) | |||
279 | * sample by some value so the sound is not too low */ | 294 | * sample by some value so the sound is not too low */ |
280 | const short *pcm_ptr = pcm_data; | 295 | const short *pcm_ptr = pcm_data; |
281 | sample_t *sample_ptr = &frames[2*(period_size-frames_left)]; | 296 | sample_t *sample_ptr = &frames[2*(period_size-frames_left)]; |
282 | for (int i = 0; i < copy_n*2; i++) | 297 | for (int i = 0; i < copy_n; i++) |
283 | *sample_ptr++ = *pcm_ptr++ * dig_vol_mult; | 298 | { |
299 | *sample_ptr++ = *pcm_ptr++ * dig_vol_mult_l; | ||
300 | *sample_ptr++ = *pcm_ptr++ * dig_vol_mult_r; | ||
301 | } | ||
284 | } | 302 | } |
285 | else | 303 | else |
286 | { | 304 | { |
@@ -378,7 +396,7 @@ static int async_rw(snd_pcm_t *handle) | |||
378 | 396 | ||
379 | /* fill buffer with silence to initiate playback without noisy click */ | 397 | /* fill buffer with silence to initiate playback without noisy click */ |
380 | sample_size = buffer_size; | 398 | sample_size = buffer_size; |
381 | samples = malloc(sample_size * channels * sizeof(sample_t)); | 399 | samples = calloc(1, sample_size * channels * sizeof(sample_t)); |
382 | 400 | ||
383 | snd_pcm_format_set_silence(format, samples, sample_size); | 401 | snd_pcm_format_set_silence(format, samples, sample_size); |
384 | err = snd_pcm_writei(handle, samples, sample_size); | 402 | err = snd_pcm_writei(handle, samples, sample_size); |
@@ -428,7 +446,7 @@ void pcm_play_dma_init(void) | |||
428 | if ((err = snd_pcm_nonblock(handle, 1))) | 446 | if ((err = snd_pcm_nonblock(handle, 1))) |
429 | panicf("Could not set non-block mode: %s\n", snd_strerror(err)); | 447 | panicf("Could not set non-block mode: %s\n", snd_strerror(err)); |
430 | 448 | ||
431 | if ((err = set_hwparams(handle, pcm_sampr)) < 0) | 449 | if ((err = set_hwparams(handle)) < 0) |
432 | { | 450 | { |
433 | panicf("Setting of hwparams failed: %s\n", snd_strerror(err)); | 451 | panicf("Setting of hwparams failed: %s\n", snd_strerror(err)); |
434 | } | 452 | } |
@@ -473,15 +491,28 @@ void pcm_play_unlock(void) | |||
473 | #endif | 491 | #endif |
474 | } | 492 | } |
475 | 493 | ||
494 | #if defined(HAVE_XDUOO_LINUX_CODEC) || defined(HAVE_FIIO_LINUX_CODEC) || defined(HAVE_ROCKER_CODEC) | ||
495 | static void pcm_dma_apply_settings_nolock(void) | ||
496 | { | ||
497 | if (sample_rate != pcm_sampr) | ||
498 | { | ||
499 | audiohw_mute(true); | ||
500 | snd_pcm_drop(handle); | ||
501 | set_hwparams(handle); | ||
502 | audiohw_mute(false); | ||
503 | } | ||
504 | } | ||
505 | #else | ||
476 | static void pcm_dma_apply_settings_nolock(void) | 506 | static void pcm_dma_apply_settings_nolock(void) |
477 | { | 507 | { |
478 | snd_pcm_drop(handle); | 508 | snd_pcm_drop(handle); |
479 | set_hwparams(handle, pcm_sampr); | 509 | set_hwparams(handle); |
480 | #if defined(HAVE_NWZ_LINUX_CODEC) | 510 | #if defined(HAVE_NWZ_LINUX_CODEC) |
481 | /* Sony NWZ linux driver uses a nonstandard mecanism to set the sampling rate */ | 511 | /* Sony NWZ linux driver uses a nonstandard mecanism to set the sampling rate */ |
482 | audiohw_set_frequency(pcm_sampr); | 512 | audiohw_set_frequency(pcm_sampr); |
483 | #endif | 513 | #endif |
484 | } | 514 | } |
515 | #endif | ||
485 | 516 | ||
486 | void pcm_dma_apply_settings(void) | 517 | void pcm_dma_apply_settings(void) |
487 | { | 518 | { |
@@ -571,11 +602,16 @@ void pcm_play_dma_postinit(void) | |||
571 | audiohw_postinit(); | 602 | audiohw_postinit(); |
572 | } | 603 | } |
573 | 604 | ||
574 | |||
575 | void pcm_set_mixer_volume(int volume) | 605 | void pcm_set_mixer_volume(int volume) |
576 | { | 606 | { |
577 | (void)volume; | 607 | (void)volume; |
578 | } | 608 | } |
609 | |||
610 | int pcm_alsa_get_rate(void) | ||
611 | { | ||
612 | return real_sample_rate; | ||
613 | } | ||
614 | |||
579 | #ifdef HAVE_RECORDING | 615 | #ifdef HAVE_RECORDING |
580 | void pcm_rec_lock(void) | 616 | void pcm_rec_lock(void) |
581 | { | 617 | { |
diff --git a/firmware/target/hosted/pcm-alsa.h b/firmware/target/hosted/pcm-alsa.h index a2514494de..b746f0d259 100644 --- a/firmware/target/hosted/pcm-alsa.h +++ b/firmware/target/hosted/pcm-alsa.h | |||
@@ -22,10 +22,12 @@ | |||
22 | 22 | ||
23 | #include <config.h> | 23 | #include <config.h> |
24 | 24 | ||
25 | #ifdef SONY_NWZ_LINUX | 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); | 28 | void pcm_alsa_set_digital_volume(int vol_db_l, int vol_db_r); |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | int pcm_alsa_get_rate(void); | ||
32 | |||
31 | #endif /* __PCM_ALSA_RB_H__ */ | 33 | #endif /* __PCM_ALSA_RB_H__ */ |
diff --git a/firmware/target/hosted/xduoo/debug-xduoo.c b/firmware/target/hosted/xduoo/debug-xduoo.c index 33f3ac4b97..9812b8f8b9 100644 --- a/firmware/target/hosted/xduoo/debug-xduoo.c +++ b/firmware/target/hosted/xduoo/debug-xduoo.c | |||
@@ -1,6 +1 @@ | |||
1 | #include <stdbool.h> | #include "../agptek/debug-agptek.c" | |
2 | |||
3 | bool debug_hw_info(void) | ||
4 | { | ||
5 | return false; | ||
6 | } | ||