summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/hosted/agptek/debug-agptek.c52
-rw-r--r--firmware/target/hosted/pcm-alsa.c92
-rw-r--r--firmware/target/hosted/pcm-alsa.h6
-rw-r--r--firmware/target/hosted/xduoo/debug-xduoo.c7
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
3bool 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
31static int line = 0;
32
33bool 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 */
69static char device[] = "plughw:0,0"; /* playback device */ 69static char device[] = "plughw:0,0"; /* playback device */
70static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access mode */ 70static 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 */
73static const snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; /* sample format */ 73static const snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; /* sample format */
74typedef long sample_t; 74typedef long sample_t;
@@ -77,6 +77,9 @@ static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format *
77typedef short sample_t; 77typedef short sample_t;
78#endif 78#endif
79static const int channels = 2; /* count of channels */ 79static const int channels = 2; /* count of channels */
80static unsigned int sample_rate = 0;
81static unsigned int real_sample_rate = 0;
82
80static snd_pcm_t *handle = NULL; 83static snd_pcm_t *handle = NULL;
81static snd_pcm_sframes_t buffer_size = MIX_FRAME_SAMPLES * 32; /* ~16k */ 84static snd_pcm_sframes_t buffer_size = MIX_FRAME_SAMPLES * 32; /* ~16k */
82static snd_pcm_sframes_t period_size = MIX_FRAME_SAMPLES * 4; /* ~4k */ 85static snd_pcm_sframes_t period_size = MIX_FRAME_SAMPLES * 4; /* ~4k */
@@ -93,14 +96,13 @@ static char signal_stack[SIGSTKSZ];
93static int recursion; 96static int recursion;
94#endif 97#endif
95 98
96static int set_hwparams(snd_pcm_t *handle, unsigned sample_rate) 99static 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(&params); 104 snd_pcm_hw_params_malloc(&params);
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. */
232static int dig_vol_mult = 2 ^ 16; /* multiplicative factor to apply to each sample */ 236static int dig_vol_mult_l = 2 ^ 16; /* multiplicative factor to apply to each sample */
237static int dig_vol_mult_r = 2 ^ 16; /* multiplicative factor to apply to each sample */
233 238
234void pcm_alsa_set_digital_volume(int vol_db) 239void 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)
495static 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
476static void pcm_dma_apply_settings_nolock(void) 506static 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
486void pcm_dma_apply_settings(void) 517void 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
575void pcm_set_mixer_volume(int volume) 605void pcm_set_mixer_volume(int volume)
576{ 606{
577 (void)volume; 607 (void)volume;
578} 608}
609
610int pcm_alsa_get_rate(void)
611{
612 return real_sample_rate;
613}
614
579#ifdef HAVE_RECORDING 615#ifdef HAVE_RECORDING
580void pcm_rec_lock(void) 616void 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 */
28void pcm_alsa_set_digital_volume(int vol_db); 28void pcm_alsa_set_digital_volume(int vol_db_l, int vol_db_r);
29#endif 29#endif
30 30
31int 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
3bool debug_hw_info(void)
4{
5 return false;
6}