mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-04-12 00:47:49 -04:00
pcm: introduce pcm_sink
move target-specific pcm operations into builtin_pcm_sink. in subsequent commits, another pcm_sink is added, and it becomes possible to switch between them. Change-Id: I8f8b9661e01d6e6472f34224ddc3760856778457
This commit is contained in:
parent
9931781185
commit
dfa33c246b
29 changed files with 846 additions and 424 deletions
|
|
@ -647,6 +647,7 @@ static const struct plugin_api rockbox_api = {
|
|||
pcm_apply_settings,
|
||||
pcm_play_lock,
|
||||
pcm_play_unlock,
|
||||
pcm_current_sink_caps,
|
||||
beep_play,
|
||||
#ifdef HAVE_RECORDING
|
||||
&rec_freq_sampr[0],
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ int plugin_open(const char *plugin, const char *parameter);
|
|||
#include "misc.h"
|
||||
#include "pathfuncs.h"
|
||||
#include "pcm_mixer.h"
|
||||
#include "pcm_sink.h"
|
||||
#include "dsp-util.h"
|
||||
#include "dsp_core.h"
|
||||
#include "dsp_proc_settings.h"
|
||||
|
|
@ -745,6 +746,7 @@ struct plugin_api {
|
|||
void (*pcm_apply_settings)(void);
|
||||
void (*pcm_play_lock)(void);
|
||||
void (*pcm_play_unlock)(void);
|
||||
const struct pcm_sink_caps* (*pcm_current_sink_caps)(void);
|
||||
void (*beep_play)(unsigned int frequency, unsigned int duration,
|
||||
unsigned int amplitude);
|
||||
#ifdef HAVE_RECORDING
|
||||
|
|
|
|||
|
|
@ -1783,6 +1783,10 @@ void pcm_play_unlock(void)
|
|||
\group sound
|
||||
\description
|
||||
|
||||
const struct pcm_sink_caps* pcm_current_sink_caps(enum pcm_sink_ids sink)
|
||||
\group sound
|
||||
\description
|
||||
|
||||
void pcm_record_data(pcm_rec_callback_type more_ready, pcm_status_callback_type status_cb, void *start, size_t size)
|
||||
\group sound
|
||||
\conditions (defined(HAVE_RECORDING))
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@
|
|||
#ifndef PCM_INTERNAL_H
|
||||
#define PCM_INTERNAL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm_sink.h"
|
||||
#include "gcc_extensions.h" /* for FORCE_INLINE */
|
||||
|
||||
#ifdef HAVE_SW_VOLUME_CONTROL
|
||||
|
|
@ -129,24 +133,12 @@ void pcm_play_stop_int(void);
|
|||
bool pcm_play_dma_complete_callback(enum pcm_dma_status status,
|
||||
const void **addr, size_t *size);
|
||||
|
||||
extern unsigned long pcm_curr_sampr;
|
||||
extern unsigned long pcm_sampr;
|
||||
extern int pcm_fsel;
|
||||
|
||||
#ifdef HAVE_PCM_DMA_ADDRESS
|
||||
void * pcm_dma_addr(void *addr);
|
||||
#endif
|
||||
|
||||
extern volatile bool pcm_playing;
|
||||
|
||||
void pcm_play_dma_lock(void);
|
||||
void pcm_play_dma_unlock(void);
|
||||
void pcm_play_dma_init(void) INIT_ATTR;
|
||||
void pcm_play_dma_postinit(void);
|
||||
void pcm_play_dma_start(const void *addr, size_t size);
|
||||
void pcm_play_dma_stop(void);
|
||||
|
||||
void pcm_dma_apply_settings(void);
|
||||
struct pcm_sink* pcm_get_current_sink(void);
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ void pcm_init(void) INIT_ATTR;
|
|||
void pcm_postinit(void);
|
||||
bool pcm_is_initialized(void);
|
||||
|
||||
enum pcm_sink_ids pcm_current_sink(void);
|
||||
const struct pcm_sink_caps* pcm_sink_caps(enum pcm_sink_ids sink);
|
||||
|
||||
/* shortcut for plugins */
|
||||
const struct pcm_sink_caps* pcm_current_sink_caps(void);
|
||||
|
||||
/* This is for playing "raw" PCM data */
|
||||
void pcm_play_data(pcm_play_callback_type get_more,
|
||||
pcm_status_callback_type status_cb,
|
||||
|
|
|
|||
57
firmware/export/pcm_sink.h
Normal file
57
firmware/export/pcm_sink.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
*
|
||||
* Copyright (C) 2025 by Sho Tanimoto
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct pcm_sink_caps {
|
||||
const unsigned long* samprs;
|
||||
uint16_t num_samprs;
|
||||
uint16_t default_freq;
|
||||
};
|
||||
|
||||
struct pcm_sink_ops {
|
||||
void (*init)(void);
|
||||
void (*postinit)(void);
|
||||
void (*set_freq)(uint16_t freq);
|
||||
void (*lock)(void);
|
||||
void (*unlock)(void);
|
||||
void (*play)(const void* addr, size_t size);
|
||||
void (*stop)(void);
|
||||
};
|
||||
|
||||
struct pcm_sink {
|
||||
/* characteristics */
|
||||
const struct pcm_sink_caps caps;
|
||||
|
||||
/* operations */
|
||||
const struct pcm_sink_ops ops;
|
||||
|
||||
/* runtime states */
|
||||
unsigned long pending_freq;
|
||||
unsigned long configured_freq;
|
||||
};
|
||||
|
||||
enum pcm_sink_ids {
|
||||
PCM_SINK_BUILTIN = 0,
|
||||
};
|
||||
|
||||
/* defined in each platform pcm source */
|
||||
extern struct pcm_sink builtin_pcm_sink;
|
||||
154
firmware/pcm.c
154
firmware/pcm.c
|
|
@ -42,21 +42,19 @@
|
|||
* Semi-private -
|
||||
* pcm_play_dma_complete_callback
|
||||
* pcm_play_dma_status_callback
|
||||
* pcm_play_dma_init
|
||||
* pcm_play_dma_postinit
|
||||
* pcm_play_dma_start
|
||||
* pcm_play_dma_stop
|
||||
* pcm_get_current_sink
|
||||
* pcm_sink.init
|
||||
* pcm_sink.postinit
|
||||
* pcm_sink.play
|
||||
* pcm_sink.stop
|
||||
* Data Read/Written within TSP -
|
||||
* pcm_sampr (R)
|
||||
* pcm_fsel (R)
|
||||
* pcm_curr_sampr (R)
|
||||
* pcm_playing (R)
|
||||
*
|
||||
* ==Playback/Recording==
|
||||
* Public -
|
||||
* pcm_dma_addr
|
||||
* Semi-private -
|
||||
* pcm_dma_apply_settings
|
||||
* pcm_sink.set_freq
|
||||
*
|
||||
* ==Recording==
|
||||
* Public -
|
||||
|
|
@ -81,6 +79,12 @@
|
|||
/* 'true' when all stages of pcm initialization have completed */
|
||||
static bool pcm_is_ready = false;
|
||||
|
||||
static struct pcm_sink* sinks[1] = {
|
||||
[PCM_SINK_BUILTIN] = &builtin_pcm_sink,
|
||||
};
|
||||
static enum pcm_sink_ids cur_sink = PCM_SINK_BUILTIN;
|
||||
static struct mutex sink_mutex; /* protects sinks and cur_sink */
|
||||
|
||||
/* The registered callback function to ask for more mp3 data */
|
||||
volatile pcm_play_callback_type
|
||||
pcm_callback_for_more SHAREDBSS_ATTR = NULL;
|
||||
|
|
@ -89,16 +93,14 @@ volatile pcm_status_callback_type
|
|||
pcm_play_status_callback SHAREDBSS_ATTR = NULL;
|
||||
/* PCM playback state */
|
||||
volatile bool pcm_playing SHAREDBSS_ATTR = false;
|
||||
/* samplerate of currently playing audio - undefined if stopped */
|
||||
unsigned long pcm_curr_sampr SHAREDBSS_ATTR = 0;
|
||||
/* samplerate waiting to be set */
|
||||
unsigned long pcm_sampr SHAREDBSS_ATTR = HW_SAMPR_DEFAULT;
|
||||
/* samplerate frequency selection index */
|
||||
int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
|
||||
|
||||
static void pcm_play_data_start_int(const void *addr, size_t size);
|
||||
void pcm_play_stop_int(void);
|
||||
|
||||
struct pcm_sink* pcm_get_current_sink(void)
|
||||
{
|
||||
return sinks[cur_sink];
|
||||
}
|
||||
|
||||
#if !defined(HAVE_SW_VOLUME_CONTROL) || defined(PCM_SW_VOLUME_UNBUFFERED)
|
||||
/** Standard hw volume/unbuffered control functions - otherwise, see
|
||||
** pcm_sw_volume.c **/
|
||||
|
|
@ -108,12 +110,12 @@ static inline void pcm_play_dma_start_int(const void *addr, size_t size)
|
|||
/* Smoothed transition might not have happened so sync now */
|
||||
pcm_sync_pcm_factors();
|
||||
#endif
|
||||
pcm_play_dma_start(addr, size);
|
||||
sinks[cur_sink]->ops.play(addr, size);
|
||||
}
|
||||
|
||||
static inline void pcm_play_dma_stop_int(void)
|
||||
{
|
||||
pcm_play_dma_stop();
|
||||
sinks[cur_sink]->ops.stop();
|
||||
}
|
||||
|
||||
bool pcm_play_dma_complete_callback(enum pcm_dma_status status,
|
||||
|
|
@ -123,8 +125,9 @@ bool pcm_play_dma_complete_callback(enum pcm_dma_status status,
|
|||
if (status < PCM_DMAST_OK)
|
||||
status = pcm_play_dma_status_callback(status);
|
||||
|
||||
if (status >= PCM_DMAST_OK && pcm_get_more_int(addr, size))
|
||||
if (status >= PCM_DMAST_OK && pcm_get_more_int(addr, size)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Error, callback missing or no more DMA to do */
|
||||
pcm_play_stop_int();
|
||||
|
|
@ -132,25 +135,6 @@ bool pcm_play_dma_complete_callback(enum pcm_dma_status status,
|
|||
}
|
||||
#endif /* !HAVE_SW_VOLUME_CONTROL || PCM_SW_VOLUME_UNBUFFERED */
|
||||
|
||||
static void pcm_play_data_start_int(const void *addr, size_t size)
|
||||
{
|
||||
ALIGN_AUDIOBUF(addr, size);
|
||||
|
||||
if ((addr && size) || pcm_get_more_int(&addr, &size))
|
||||
{
|
||||
pcm_apply_settings();
|
||||
logf(" pcm_play_dma_start_int");
|
||||
pcm_play_dma_start_int(addr, size);
|
||||
pcm_playing = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Force a stop */
|
||||
logf(" pcm_play_stop_int");
|
||||
pcm_play_stop_int();
|
||||
}
|
||||
}
|
||||
|
||||
void pcm_play_stop_int(void)
|
||||
{
|
||||
pcm_play_dma_stop_int();
|
||||
|
|
@ -223,7 +207,15 @@ void pcm_do_peak_calculation(struct pcm_peaks *peaks, bool active,
|
|||
|
||||
if (active)
|
||||
{
|
||||
int framecount = peaks->period*pcm_curr_sampr / HZ;
|
||||
struct pcm_sink* sink = sinks[cur_sink];
|
||||
if (sink->configured_freq == -1UL)
|
||||
{
|
||||
logf("not configured yet");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long sampr = sink->caps.samprs[sink->configured_freq];
|
||||
int framecount = peaks->period * sampr / HZ;
|
||||
count = MIN(framecount, count);
|
||||
|
||||
if (count > 0)
|
||||
|
|
@ -247,16 +239,29 @@ bool pcm_is_playing(void)
|
|||
* interface
|
||||
*/
|
||||
|
||||
void pcm_play_lock(void) {
|
||||
mutex_lock(&sink_mutex);
|
||||
sinks[cur_sink]->ops.lock();
|
||||
/* hold sink_mutex until pcm_play_unlock() */
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void) {
|
||||
sinks[cur_sink]->ops.unlock();
|
||||
mutex_unlock(&sink_mutex);
|
||||
}
|
||||
|
||||
/* This should only be called at startup before any audio playback or
|
||||
recording is attempted */
|
||||
void pcm_init(void)
|
||||
{
|
||||
logf("pcm_init");
|
||||
|
||||
pcm_set_frequency(HW_SAMPR_DEFAULT);
|
||||
|
||||
logf(" pcm_play_dma_init");
|
||||
pcm_play_dma_init();
|
||||
mutex_init(&sink_mutex);
|
||||
for(size_t i = 0; i < ARRAYLEN(sinks); i += 1) {
|
||||
sinks[i]->pending_freq = sinks[i]->caps.default_freq;
|
||||
sinks[i]->configured_freq = -1UL;
|
||||
sinks[i]->ops.init();
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish delayed init */
|
||||
|
|
@ -264,9 +269,9 @@ void pcm_postinit(void)
|
|||
{
|
||||
logf("pcm_postinit");
|
||||
|
||||
logf(" pcm_play_dma_postinit");
|
||||
|
||||
pcm_play_dma_postinit();
|
||||
for(size_t i = 0; i < ARRAYLEN(sinks); i += 1) {
|
||||
sinks[i]->ops.postinit();
|
||||
}
|
||||
|
||||
pcm_is_ready = true;
|
||||
}
|
||||
|
|
@ -276,6 +281,21 @@ bool pcm_is_initialized(void)
|
|||
return pcm_is_ready;
|
||||
}
|
||||
|
||||
enum pcm_sink_ids pcm_current_sink(void)
|
||||
{
|
||||
return cur_sink;
|
||||
}
|
||||
|
||||
const struct pcm_sink_caps* pcm_sink_caps(enum pcm_sink_ids sink)
|
||||
{
|
||||
return &sinks[sink]->caps;
|
||||
}
|
||||
|
||||
const struct pcm_sink_caps* pcm_current_sink_caps(void)
|
||||
{
|
||||
return pcm_sink_caps(pcm_current_sink());
|
||||
}
|
||||
|
||||
void pcm_play_data(pcm_play_callback_type get_more,
|
||||
pcm_status_callback_type status_cb,
|
||||
const void *start, size_t size)
|
||||
|
|
@ -287,8 +307,20 @@ void pcm_play_data(pcm_play_callback_type get_more,
|
|||
pcm_callback_for_more = get_more;
|
||||
pcm_play_status_callback = status_cb;
|
||||
|
||||
logf(" pcm_play_data_start_int");
|
||||
pcm_play_data_start_int(start, size);
|
||||
ALIGN_AUDIOBUF(start, size);
|
||||
if ((start && size) || pcm_get_more_int(&start, &size))
|
||||
{
|
||||
pcm_apply_settings();
|
||||
logf(" pcm_play_dma_start_int");
|
||||
pcm_play_dma_start_int(start, size);
|
||||
pcm_playing = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Force a stop */
|
||||
logf(" pcm_play_stop_int");
|
||||
pcm_play_stop_int();
|
||||
}
|
||||
|
||||
pcm_play_unlock();
|
||||
}
|
||||
|
|
@ -329,20 +361,22 @@ void pcm_set_frequency(unsigned int samplerate)
|
|||
samplerate = pcm_sampr_to_hw_sampr(samplerate, type);
|
||||
#endif /* CONFIG_SAMPR_TYPES */
|
||||
|
||||
index = round_value_to_list32(samplerate, hw_freq_sampr,
|
||||
HW_NUM_FREQ, false);
|
||||
mutex_lock(&sink_mutex);
|
||||
struct pcm_sink* sink = sinks[cur_sink];
|
||||
index = round_value_to_list32(samplerate, sink->caps.samprs, sink->caps.num_samprs, false);
|
||||
|
||||
if (samplerate != hw_freq_sampr[index])
|
||||
index = HW_FREQ_DEFAULT; /* Invalid = default */
|
||||
if (samplerate != sink->caps.samprs[index])
|
||||
index = sink->caps.default_freq; /* Invalid = default */
|
||||
|
||||
pcm_sampr = hw_freq_sampr[index];
|
||||
pcm_fsel = index;
|
||||
sink->pending_freq = index;
|
||||
mutex_unlock(&sink_mutex);
|
||||
}
|
||||
|
||||
/* return last-set frequency */
|
||||
unsigned int pcm_get_frequency(void)
|
||||
{
|
||||
return pcm_sampr;
|
||||
struct pcm_sink* sink = sinks[cur_sink];
|
||||
return sink->caps.samprs[sink->pending_freq];
|
||||
}
|
||||
|
||||
/* apply pcm settings to the hardware */
|
||||
|
|
@ -352,12 +386,14 @@ void pcm_apply_settings(void)
|
|||
|
||||
pcm_wait_for_init();
|
||||
|
||||
if (pcm_sampr != pcm_curr_sampr)
|
||||
{
|
||||
logf(" pcm_dma_apply_settings");
|
||||
pcm_dma_apply_settings();
|
||||
pcm_curr_sampr = pcm_sampr;
|
||||
mutex_lock(&sink_mutex);
|
||||
struct pcm_sink* sink = sinks[cur_sink];
|
||||
if(sink->pending_freq != sink->configured_freq) {
|
||||
logf(" sink->set_freq");
|
||||
sink->ops.set_freq(sink->pending_freq);
|
||||
sink->configured_freq = sink->pending_freq;
|
||||
}
|
||||
mutex_unlock(&sink_mutex);
|
||||
}
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ static void start_pcm(bool reframe)
|
|||
pcm_play_dma_status_callback(PCM_DMAST_STARTED);
|
||||
pcm_play_dma_status_callback(PCM_DMAST_STARTED);
|
||||
|
||||
pcm_play_dma_start(pcm_dbl_buf[1], pcm_dbl_buf_size[1]);
|
||||
pcm_get_current_sink()->ops.play(pcm_dbl_buf[1], pcm_dbl_buf_size[1]);
|
||||
}
|
||||
|
||||
void pcm_play_dma_start_int(const void *addr, size_t size)
|
||||
|
|
@ -338,7 +338,7 @@ void pcm_play_dma_start_int(const void *addr, size_t size)
|
|||
|
||||
void pcm_play_dma_stop_int(void)
|
||||
{
|
||||
pcm_play_dma_stop();
|
||||
pcm_get_current_sink()->ops.stop();
|
||||
src_buf_addr = NULL;
|
||||
src_buf_rem = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "mmu-arm.h"
|
||||
#include "cpucache-arm.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
#define MAX_TRANSFER (4*((1<<11)-1)) /* maximum data we can transfer via DMA
|
||||
* i.e. 32 bits at once (size of I2SO_DATA)
|
||||
|
|
@ -53,13 +54,13 @@ static bool volatile is_recording = false;
|
|||
#endif
|
||||
|
||||
/* Mask the DMA interrupt */
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
++locked;
|
||||
}
|
||||
|
||||
/* Unmask the DMA interrupt if enabled */
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if(--locked == 0 && is_playing)
|
||||
{
|
||||
|
|
@ -119,7 +120,7 @@ static void dma_callback(void)
|
|||
}
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
is_playing = true;
|
||||
|
||||
|
|
@ -136,7 +137,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
play_start_pcm();
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
is_playing = false;
|
||||
|
||||
|
|
@ -153,20 +154,6 @@ void pcm_play_dma_stop(void)
|
|||
play_callback_pending = false;
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
{
|
||||
bitset32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE);
|
||||
I2SOUT_CONTROL = (1<<6) | (1<<3); /* enable dma, stereo */
|
||||
|
||||
audiohw_preinit();
|
||||
pcm_dma_apply_settings();
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
|
||||
/* divider is 9 bits but the highest one (for 8kHz) fit in 8 bits */
|
||||
static const unsigned char divider[SAMPR_NUM_FREQ] = {
|
||||
[HW_FREQ_96] = ((AS3525_MCLK_FREQ/128 + SAMPR_96/2) / SAMPR_96) - 1,
|
||||
|
|
@ -183,12 +170,7 @@ static const unsigned char divider[SAMPR_NUM_FREQ] = {
|
|||
[HW_FREQ_8 ] = ((AS3525_MCLK_FREQ/128 + SAMPR_8 /2) / SAMPR_8 ) - 1,
|
||||
};
|
||||
|
||||
static inline unsigned char mclk_divider(void)
|
||||
{
|
||||
return divider[pcm_fsel];
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
bitmod32(&CGU_AUDIO,
|
||||
(0<<24) | /* I2SI_MCLK2PAD_EN = disabled */
|
||||
|
|
@ -196,11 +178,20 @@ void pcm_dma_apply_settings(void)
|
|||
(0<<14) | /* I2SI_MCLK_DIV_SEL = unused */
|
||||
(0<<12) | /* I2SI_MCLK_SEL = clk_main */
|
||||
(1<<11) | /* I2SO_MCLK_EN */
|
||||
(mclk_divider() << 2) | /* I2SO_MCLK_DIV_SEL */
|
||||
(divider[freq] << 2) | /* I2SO_MCLK_DIV_SEL */
|
||||
(AS3525_MCLK_SEL << 0), /* I2SO_MCLK_SEL */
|
||||
0x01ffffff);
|
||||
}
|
||||
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
bitset32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE);
|
||||
I2SOUT_CONTROL = (1<<6) | (1<<3); /* enable dma, stereo */
|
||||
|
||||
audiohw_preinit();
|
||||
sink_set_freq(HW_SAMPR_DEFAULT);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PCM_DMA_ADDRESS
|
||||
void * pcm_dma_addr(void *addr)
|
||||
{
|
||||
|
|
@ -210,6 +201,22 @@ void * pcm_dma_addr(void *addr)
|
|||
}
|
||||
#endif
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
** Recording DMA transfer
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include "dma-imx233.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "audioout-imx233.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
struct pcm_dma_command_t
|
||||
{
|
||||
|
|
@ -47,7 +49,7 @@ static const void *dac_buf; /* current buffer */
|
|||
static size_t dac_size; /* remaining size */
|
||||
|
||||
/* for both recording and playback: maximum transfer size, see
|
||||
* pcm_dma_apply_settings */
|
||||
* sink_set_sampr */
|
||||
static size_t dma_max_size = CACHEALIGN_UP(1600);
|
||||
|
||||
enum
|
||||
|
|
@ -110,33 +112,33 @@ void INT_DAC_ERROR(void)
|
|||
imx233_dma_clear_channel_interrupt(APB_AUDIO_DAC);
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
if(dac_locked++ == 0)
|
||||
imx233_dma_enable_channel_interrupt(APB_AUDIO_DAC, false);
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if(--dac_locked == 0)
|
||||
imx233_dma_enable_channel_interrupt(APB_AUDIO_DAC, true);
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
/* do not interrupt the current transaction because resetting the dma
|
||||
* would halt the DAC and clearing RUN causes sound havoc so simply
|
||||
* wait for the end of transfer */
|
||||
pcm_play_lock();
|
||||
sink_lock();
|
||||
dac_buf = NULL;
|
||||
dac_size = 0;
|
||||
dac_state = DAC_STOP_PENDING;
|
||||
pcm_play_unlock();
|
||||
sink_unlock();
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
pcm_play_lock();
|
||||
sink_lock();
|
||||
/* update pending buffer */
|
||||
dac_buf = addr;
|
||||
dac_size = size;
|
||||
|
|
@ -145,15 +147,10 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
play();
|
||||
else
|
||||
dac_state = DAC_PLAYING;
|
||||
pcm_play_unlock();
|
||||
sink_unlock();
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
{
|
||||
audiohw_preinit();
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
imx233_icoll_enable_interrupt(INT_SRC_DAC_DMA, true);
|
||||
|
|
@ -162,18 +159,35 @@ void pcm_play_dma_postinit(void)
|
|||
imx233_dma_enable_channel_interrupt(APB_AUDIO_DAC, true);
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
pcm_play_lock();
|
||||
sink_lock();
|
||||
/* update frequency */
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
/* compute maximum transfer size: aim at ~1/100s stop time maximum, make sure
|
||||
* the resulting value is a multiple of cache line. At sample rate F we
|
||||
* transfer two samples (2 x 2 bytes) F times per second = 4F b/s */
|
||||
dma_max_size = CACHEALIGN_UP(4 * pcm_sampr / 100);
|
||||
pcm_play_unlock();
|
||||
dma_max_size = CACHEALIGN_UP(4 * hw_freq_sampr[freq] / 100);
|
||||
sink_unlock();
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = audiohw_preinit,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Recording
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "sdma-imx31.h"
|
||||
#include "mmu-imx31.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
#define DMA_PLAY_CH_NUM 2
|
||||
#define DMA_REC_CH_NUM 1
|
||||
|
|
@ -112,12 +113,12 @@ static void play_dma_callback(void)
|
|||
}
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
++dma_play_data.locked;
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if (--dma_play_data.locked == 0 && dma_play_data.state != 0)
|
||||
{
|
||||
|
|
@ -131,12 +132,12 @@ void pcm_play_unlock(void)
|
|||
}
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
/* Init DMA channel information */
|
||||
sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd);
|
||||
|
|
@ -146,11 +147,6 @@ void pcm_play_dma_init(void)
|
|||
audiohw_init();
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
|
||||
static void play_start_pcm(void)
|
||||
{
|
||||
/* Stop transmission (if in progress) */
|
||||
|
|
@ -200,7 +196,7 @@ static void play_stop_pcm(void)
|
|||
dma_play_data.callback_pending = 0;
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
sdma_channel_stop(DMA_PLAY_CH_NUM);
|
||||
|
||||
|
|
@ -218,7 +214,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
play_start_dma(addr, size);
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
sdma_channel_stop(DMA_PLAY_CH_NUM);
|
||||
play_stop_pcm();
|
||||
|
|
@ -229,6 +225,23 @@ void * pcm_dma_addr(void *addr)
|
|||
return (void *)addr_virt_to_phys((unsigned long)addr);
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
static struct buffer_descriptor dma_rec_bd NOCACHEBSS_ATTR;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "i2s.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
struct dma_data
|
||||
{
|
||||
|
|
@ -62,7 +63,7 @@ struct dma_data dma_play_data SHAREDBSS_ATTR =
|
|||
.state = 0
|
||||
};
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
DAVC = 0x0; /* Digital Volume = max */
|
||||
#ifdef COWON_D2
|
||||
|
|
@ -89,12 +90,7 @@ void pcm_play_dma_init(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +121,7 @@ static void play_stop_pcm(void)
|
|||
dma_play_data.state = 0;
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
dma_play_data.p_r = addr;
|
||||
dma_play_data.size = size;
|
||||
|
|
@ -140,7 +136,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
play_start_pcm();
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
play_stop_pcm();
|
||||
dma_play_data.size = 0;
|
||||
|
|
@ -149,7 +145,7 @@ void pcm_play_dma_stop(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
int status = disable_fiq_save();
|
||||
|
||||
|
|
@ -161,7 +157,7 @@ void pcm_play_lock(void)
|
|||
restore_fiq(status);
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
int status = disable_fiq_save();
|
||||
|
||||
|
|
@ -173,6 +169,23 @@ void pcm_play_unlock(void)
|
|||
restore_fiq(status);
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
/* TODO: implement */
|
||||
void pcm_rec_dma_init(void)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "pcm.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
/** DMA **/
|
||||
|
||||
|
|
@ -89,10 +90,12 @@ static struct dma_data dma_play_data IBSS_ATTR =
|
|||
.state = 0
|
||||
};
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
{
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
}
|
||||
/* DMA status cannot be viewed from outside code in control because that can
|
||||
* clear the interrupt from outside the handler and prevent the handler from
|
||||
* from being called. Split up transfers to a reasonable size that is good as
|
||||
* a timer and peaking yet still keeps the FIQ count low.
|
||||
*/
|
||||
static uint16_t max_dma_chunk_size;
|
||||
|
||||
#if defined(CPU_PP502x)
|
||||
/* 16-bit, L-R packed into 32 bits with left in the least significant halfword */
|
||||
|
|
@ -102,12 +105,6 @@ void pcm_dma_apply_settings(void)
|
|||
#define DMA_PLAY_CONFIG ((DMA_REQ_IIS << DMA_CMD_REQ_ID_POS) | \
|
||||
DMA_CMD_RAM_TO_PER | DMA_CMD_SINGLE | \
|
||||
DMA_CMD_WAIT_REQ | DMA_CMD_INTR)
|
||||
/* DMA status cannot be viewed from outside code in control because that can
|
||||
* clear the interrupt from outside the handler and prevent the handler from
|
||||
* from being called. Split up transfers to a reasonable size that is good as
|
||||
* a timer and peaking yet still keeps the FIQ count low.
|
||||
*/
|
||||
#define MAX_DMA_CHUNK_SIZE (pcm_curr_sampr >> 6) /* ~1/256 seconds */
|
||||
|
||||
static inline void dma_tx_init(void)
|
||||
{
|
||||
|
|
@ -145,9 +142,9 @@ static inline unsigned long dma_tx_buf_prepare(const void *addr)
|
|||
|
||||
static inline void dma_tx_start(bool begin)
|
||||
{
|
||||
size_t size = MAX_DMA_CHUNK_SIZE;
|
||||
size_t size = max_dma_chunk_size;
|
||||
|
||||
/* Not at least MAX_DMA_CHUNK_SIZE left or there would be less
|
||||
/* Not at least max_dma_chunk_size left or there would be less
|
||||
* than a FIFO's worth of data after this transfer? */
|
||||
if (size + 16*4 > dma_play_data.size)
|
||||
size = dma_play_data.size;
|
||||
|
|
@ -430,10 +427,15 @@ void fiq_playback(void)
|
|||
#endif /* ASM / C selection */
|
||||
#endif /* CPU_PP502x */
|
||||
|
||||
static void sink_set_freq(uint16_t freq) {
|
||||
max_dma_chunk_size = hw_freq_sampr[freq] >> 6;
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
/* For the locks, FIQ must be disabled because the handler manipulates
|
||||
IISCONFIG and the operation is not atomic - dual core support
|
||||
will require other measures */
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
int status = disable_fiq_save();
|
||||
|
||||
|
|
@ -444,7 +446,7 @@ void pcm_play_lock(void)
|
|||
restore_fiq(status);
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
int status = disable_fiq_save();
|
||||
|
||||
|
|
@ -455,14 +457,14 @@ void pcm_play_unlock(void)
|
|||
restore_fiq(status);
|
||||
}
|
||||
|
||||
static void play_start_pcm(void)
|
||||
static void sink_start_pcm(void)
|
||||
{
|
||||
fiq_function = fiq_playback;
|
||||
dma_play_data.state = 1;
|
||||
dma_tx_start(true);
|
||||
}
|
||||
|
||||
static void play_stop_pcm(void)
|
||||
static void sink_stop_pcm(void)
|
||||
{
|
||||
dma_tx_stop();
|
||||
|
||||
|
|
@ -472,9 +474,11 @@ static void play_stop_pcm(void)
|
|||
dma_play_data.state = 0;
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_stop(void);
|
||||
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
pcm_play_dma_stop();
|
||||
sink_dma_stop();
|
||||
|
||||
#if NUM_CORES > 1
|
||||
/* This will become more important later - and different ! */
|
||||
|
|
@ -485,13 +489,13 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
|
||||
dma_play_data.addr = dma_tx_buf_prepare(addr);
|
||||
dma_play_data.size = size;
|
||||
play_start_pcm();
|
||||
sink_start_pcm();
|
||||
}
|
||||
|
||||
/* Stops the DMA transfer and interrupt */
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
play_stop_pcm();
|
||||
sink_stop_pcm();
|
||||
dma_play_data.addr = 0;
|
||||
dma_play_data.size = 0;
|
||||
#if NUM_CORES > 1
|
||||
|
|
@ -499,7 +503,7 @@ void pcm_play_dma_stop(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
/* Initialize default register values. */
|
||||
audiohw_init();
|
||||
|
|
@ -509,10 +513,22 @@ void pcm_play_dma_init(void)
|
|||
IISCONFIG |= IIS_TXFIFOEN;
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
** Recording DMA transfer
|
||||
|
|
|
|||
|
|
@ -28,11 +28,12 @@
|
|||
#include "audiohw.h"
|
||||
#include "sound.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
static int locked = 0;
|
||||
|
||||
/* Mask the DMA interrupt */
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
if (++locked == 1)
|
||||
{
|
||||
|
|
@ -43,7 +44,7 @@ void pcm_play_lock(void)
|
|||
}
|
||||
|
||||
/* Unmask the DMA interrupt if enabled */
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if(--locked == 0)
|
||||
{
|
||||
|
|
@ -53,7 +54,7 @@ void pcm_play_unlock(void)
|
|||
}
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
HDMA_CON0 = 0x00;
|
||||
HDMA_ISR = 0x00;
|
||||
|
|
@ -105,10 +106,10 @@ static void hdma_i2s_transfer(const void *addr, size_t size)
|
|||
(1<<0)); /* hardware trigger DMA mode */
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
/* Stop any DMA in progress */
|
||||
pcm_play_dma_stop();
|
||||
sink_dma_stop();
|
||||
|
||||
/* kick in DMA transfer */
|
||||
hdma_i2s_transfer(addr, size);
|
||||
|
|
@ -225,7 +226,7 @@ static void set_codec_freq(unsigned int freq)
|
|||
}
|
||||
#endif
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
/* unmask HDMA interrupt in INTC */
|
||||
INTC_IMR |= IRQ_ARM_HDMA;
|
||||
|
|
@ -236,18 +237,13 @@ void pcm_play_dma_init(void)
|
|||
i2s_init();
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
#ifdef CODEC_SLAVE
|
||||
set_codec_freq(pcm_fsel);
|
||||
set_codec_freq(freq);
|
||||
#endif
|
||||
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
/* audio DMA ISR called when chunk from callers buffer has been transfered */
|
||||
|
|
@ -263,6 +259,23 @@ void INT_HDMA(void)
|
|||
}
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
** Recording DMA transfer
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "sound.h"
|
||||
#include "file.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
/* PCM interrupt routine lockout */
|
||||
static struct
|
||||
|
|
@ -48,20 +49,20 @@ static struct
|
|||
void fiq_handler(void) __attribute__((interrupt ("FIQ")));
|
||||
|
||||
/* Mask the DMA interrupt */
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
if (++dma_play_lock.locked == 1)
|
||||
bitset32(&INTMSK, DMA2_MASK);
|
||||
}
|
||||
|
||||
/* Unmask the DMA interrupt if enabled */
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if (--dma_play_lock.locked == 0)
|
||||
bitclr32(&INTMSK, dma_play_lock.state);
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
/* There seem to be problems when changing the IIS interface configuration
|
||||
* when a clock is not present.
|
||||
|
|
@ -94,14 +95,9 @@ void pcm_play_dma_init(void)
|
|||
bitset32(&INTMOD, DMA2_MASK);
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
{
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
/* Connect the DMA and start filling the FIFO */
|
||||
|
|
@ -158,7 +154,7 @@ static void play_stop_pcm(void)
|
|||
IISCON &= ~(1<<0);
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
/* Enable the IIS clock */
|
||||
bitset32(&CLKCON, 1<<17);
|
||||
|
|
@ -187,7 +183,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
}
|
||||
|
||||
/* Promptly stop DMA transfers and stop IIS */
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
play_stop_pcm();
|
||||
|
||||
|
|
@ -219,3 +215,20 @@ void fiq_handler(void)
|
|||
|
||||
pcm_play_dma_status_callback(PCM_DMAST_STARTED);
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,11 +32,12 @@
|
|||
#include "dma-target.h"
|
||||
#include "mmu-arm.h"
|
||||
#include "cpucache-arm.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
/* Driver for the IIS/PCM part of the s5l8700 using DMA
|
||||
|
||||
Notes:
|
||||
- pcm_play_dma_stop is untested, not sure if implemented the right way
|
||||
- sink_dma_stop is untested, not sure if implemented the right way
|
||||
- recording is not implemented
|
||||
*/
|
||||
|
||||
|
|
@ -83,7 +84,7 @@ static const struct div_entry {
|
|||
};
|
||||
|
||||
/* Mask the DMA interrupt */
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
if (locked++ == 0) {
|
||||
INTMSK &= ~(1 << 10);
|
||||
|
|
@ -91,7 +92,7 @@ void pcm_play_lock(void)
|
|||
}
|
||||
|
||||
/* Unmask the DMA interrupt if enabled */
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if (--locked == 0) {
|
||||
INTMSK |= (1 << 10);
|
||||
|
|
@ -141,7 +142,7 @@ void INT_DMA(void)
|
|||
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void* addr, size_t size)
|
||||
static void sink_dma_start(const void* addr, size_t size)
|
||||
{
|
||||
/* DMA channel on */
|
||||
nextbuf = addr;
|
||||
|
|
@ -161,7 +162,7 @@ void pcm_play_dma_start(const void* addr, size_t size)
|
|||
(0 << 0); /* 0 = LRCK on */
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
/* DMA channel off */
|
||||
DMACOM0 = 5;
|
||||
|
|
@ -195,7 +196,7 @@ static void pcm_dma_set_freq(enum hw_freq_indexes idx)
|
|||
(div.cdiv - 1); /* MCLK_DIV_VAL */
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
/* configure IIS pins */
|
||||
#ifdef IPOD_NANO2G
|
||||
|
|
@ -252,15 +253,10 @@ void pcm_play_dma_init(void)
|
|||
audiohw_preinit();
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
|
||||
/* set the configured PCM frequency */
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
pcm_dma_set_freq(pcm_fsel);
|
||||
pcm_dma_set_freq(hw_freq_sampr[freq]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PCM_DMA_ADDRESS
|
||||
|
|
@ -272,6 +268,22 @@ void * pcm_dma_addr(void *addr)
|
|||
}
|
||||
#endif
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
** Recording DMA transfer
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "pcm_sampr.h"
|
||||
#include "pcm-target.h"
|
||||
#include "dma-s5l8702.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
/* DMA configuration */
|
||||
|
||||
|
|
@ -86,14 +87,14 @@ static int active_dblbuf;
|
|||
size_t pcm_remaining;
|
||||
|
||||
/* Mask the DMA interrupt */
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
if (locked++ == 0)
|
||||
dmac_ch_lock_int(&dma_play_ch);
|
||||
}
|
||||
|
||||
/* Unmask the DMA interrupt if enabled */
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if (--locked == 0)
|
||||
dmac_ch_unlock_int(&dma_play_ch);
|
||||
|
|
@ -141,30 +142,29 @@ static void dma_play_callback(void *cb_data)
|
|||
pcm_play_dma_status_callback(PCM_DMAST_STARTED);
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void* addr, size_t size)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
pcm_play_dma_stop();
|
||||
dmac_ch_stop(&dma_play_ch);
|
||||
I2STXCOM = 0xa;
|
||||
}
|
||||
|
||||
static void sink_dma_start(const void* addr, size_t size)
|
||||
{
|
||||
sink_dma_stop();
|
||||
|
||||
pcm_remaining = size;
|
||||
I2STXCOM = 0xe;
|
||||
dma_play_callback((void*)addr);
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
{
|
||||
dmac_ch_stop(&dma_play_ch);
|
||||
I2STXCOM = 0xa;
|
||||
}
|
||||
|
||||
/* MCLK = 12MHz (MCLKDIV2=1), [CS42L55 DS, s4.8] */
|
||||
#define MCLK_FREQ 12000000
|
||||
|
||||
/* set the configured PCM frequency */
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
static uint16_t last_clkcon3l = 0;
|
||||
uint16_t clkcon3l;
|
||||
int fsel;
|
||||
|
||||
/* For unknown reasons, s5l8702 I2S controller does not synchronize
|
||||
* with CS42L55 at 32000 Hz. To fix it, the CODEC is configured with
|
||||
|
|
@ -172,12 +172,11 @@ void pcm_dma_apply_settings(void)
|
|||
* obtaining 32 KHz in LRCK controller input and 8 MHz in SCLK input.
|
||||
* OF uses this trick.
|
||||
*/
|
||||
if (pcm_fsel == HW_FREQ_32) {
|
||||
fsel = HW_FREQ_48;
|
||||
if (freq == HW_FREQ_32) {
|
||||
freq = HW_FREQ_48;
|
||||
clkcon3l = 0x3028; /* PLL2 / 3 / 9 -> 8 MHz */
|
||||
}
|
||||
else {
|
||||
fsel = pcm_fsel;
|
||||
clkcon3l = 0; /* OSC0 -> 12 MHz */
|
||||
}
|
||||
|
||||
|
|
@ -192,12 +191,12 @@ void pcm_dma_apply_settings(void)
|
|||
}
|
||||
|
||||
/* configure I2S clock ratio */
|
||||
I2SCLKDIV = MCLK_FREQ / hw_freq_sampr[fsel];
|
||||
I2SCLKDIV = MCLK_FREQ / hw_freq_sampr[freq];
|
||||
/* select CS42L55 sample rate */
|
||||
audiohw_set_frequency(fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
PWRCON(1) &= ~(1 << 7);
|
||||
|
||||
|
|
@ -207,12 +206,7 @@ void pcm_play_dma_init(void)
|
|||
I2SCLKCON = 1;
|
||||
|
||||
audiohw_preinit();
|
||||
pcm_dma_apply_settings();
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
sink_set_freq(HW_FREQ_DEFAULT);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PCM_DMA_ADDRESS
|
||||
|
|
@ -222,6 +216,22 @@ void * pcm_dma_addr(void *addr)
|
|||
}
|
||||
#endif
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
** Recording DMA transfer
|
||||
|
|
|
|||
|
|
@ -20,37 +20,57 @@
|
|||
****************************************************************************/
|
||||
#include "pcm.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
(void)freq;
|
||||
}
|
||||
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
(void)addr;
|
||||
(void)size;
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
void pcm_rec_dma_init(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,13 +28,14 @@
|
|||
#include "dsp-target.h"
|
||||
#include "dsp/ipc.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
/* This is global to save some latency when pcm_play_dma_get_peak_buffer is
|
||||
* called.
|
||||
*/
|
||||
static const void *start;
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
/* Configure clock divider */
|
||||
tsc2100_writereg(CONTROL_PAGE2, TSPP1_ADDRESS, 0x1120);
|
||||
|
|
@ -45,7 +46,7 @@ void pcm_play_dma_postinit(void)
|
|||
audiohw_postinit();
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
IO_INTC_IRQ0 = INTR_IRQ0_IMGBUF;
|
||||
bitset16(&IO_INTC_EINT0, INTR_EINT0_IMGBUF);
|
||||
|
|
@ -67,15 +68,15 @@ void pcm_play_dma_init(void)
|
|||
dsp_wake();
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
/* Note that size is actually limited to the size of a short right now due to
|
||||
* the implementation on the DSP side (and the way that we access it)
|
||||
*/
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
unsigned long sdem_addr=(unsigned long)addr - CONFIG_SDRAM_START;
|
||||
/* Initialize codec. */
|
||||
|
|
@ -87,18 +88,18 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
dsp_wake();
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
DSP_(_dma0_stopped)=1;
|
||||
dsp_wake();
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -156,4 +157,20 @@ void DSPHINT(void)
|
|||
|
||||
DEBUGF("DSP: %s", buffer);
|
||||
}
|
||||
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "dsp/ipc.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "dma-target.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
/* This is global to save some latency when pcm_play_dma_get_peak_buffer is
|
||||
* called.
|
||||
|
|
@ -36,12 +37,7 @@
|
|||
static const void *start;
|
||||
static int dma_channel;
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
/* GIO16 is DSP/AIC3X CLK */
|
||||
IO_GIO_FSEL0 &= 0x3FFF;
|
||||
|
|
@ -74,15 +70,15 @@ void pcm_play_dma_init(void)
|
|||
dsp_wake();
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
/* Note that size is actually limited to the size of a short right now due to
|
||||
* the implementation on the DSP side (and the way that we access it)
|
||||
*/
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
unsigned long sdem_addr=(unsigned long)addr - CONFIG_SDRAM_START;
|
||||
/* Initialize codec. */
|
||||
|
|
@ -94,18 +90,18 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
dsp_wake();
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
DSP_(_dma0_stopped)=1;
|
||||
dsp_wake();
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -163,4 +159,20 @@ void DSPHINT(void)
|
|||
|
||||
DEBUGF("DSP: %s", buffer);
|
||||
}
|
||||
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "spdif.h"
|
||||
#endif
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
#define IIS_PLAY_DEFPARM ( (freq_ent[FPARM_CLOCKSEL] << 12) | \
|
||||
(IIS_PLAY & (7 << 8)) | \
|
||||
|
|
@ -142,12 +143,12 @@ static void iis_play_reset_if_playback(bool if_playback)
|
|||
/* This clears the reset bit to enable monitoring immediately if monitoring
|
||||
recording sources or always if playback is in progress - we might be
|
||||
switching samplerates on the fly */
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
int level = set_irq_level(DMA_IRQ_LEVEL);
|
||||
|
||||
/* remember table entry */
|
||||
freq_ent = pcm_freq_parms[pcm_fsel];
|
||||
freq_ent = pcm_freq_parms[freq];
|
||||
|
||||
/* Reprogramming bits 15-12 requires FIFO to be in a reset
|
||||
condition - Users Manual 17-8, Note 11 */
|
||||
|
|
@ -159,7 +160,7 @@ void pcm_dma_apply_settings(void)
|
|||
IIS_PLAY = IIS_PLAY_DEFPARM | IIS_FIFO_RESET;
|
||||
restore_irq(level);
|
||||
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM);
|
||||
|
||||
level = set_irq_level(DMA_IRQ_LEVEL);
|
||||
|
|
@ -170,11 +171,11 @@ void pcm_dma_apply_settings(void)
|
|||
PDOR3 = 0; /* Kick FIFO out of reset by writing to it */
|
||||
|
||||
restore_irq(level);
|
||||
} /* pcm_dma_apply_settings */
|
||||
} /* sink_set_sampr */
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
freq_ent = pcm_freq_parms[pcm_fsel];
|
||||
freq_ent = pcm_freq_parms[HW_FREQ_DEFAULT];
|
||||
|
||||
AUDIOGLOB = AUDIOGLOB_DEFPARM;
|
||||
DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */
|
||||
|
|
@ -195,15 +196,15 @@ void pcm_play_dma_init(void)
|
|||
|
||||
audio_input_mux(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
|
||||
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(HW_FREQ_DEFAULT);
|
||||
coldfire_set_pllcr_audio_bits(PLLCR_SET_AUDIO_BITS_DEFPARM);
|
||||
|
||||
#if defined(HAVE_SPDIF_REC) || defined(HAVE_SPDIF_OUT)
|
||||
spdif_init();
|
||||
#endif
|
||||
} /* pcm_play_dma_init */
|
||||
} /* sink_dma_init */
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
void sink_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
iis_play_reset();
|
||||
|
|
@ -223,23 +224,35 @@ static struct dma_lock dma_play_lock =
|
|||
.state = (1 << 14) /* bit 14 is DMA0 */
|
||||
};
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
if (++dma_play_lock.locked == 1)
|
||||
coldfire_imr_mod(1 << 14, 1 << 14);
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if (--dma_play_lock.locked == 0)
|
||||
coldfire_imr_mod(dma_play_lock.state, 1 << 14);
|
||||
}
|
||||
|
||||
/* Stops the DMA transfer and interrupt */
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */
|
||||
BCR0 = 0; /* No bytes remaining */
|
||||
DSR0 = 1; /* Clear interrupt, errors, stop transfer */
|
||||
|
||||
iis_play_reset_if_playback(true);
|
||||
|
||||
dma_play_lock.state = (1 << 14);
|
||||
} /* sink_dma_stop */
|
||||
|
||||
/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
/* Stop any DMA in progress */
|
||||
pcm_play_dma_stop();
|
||||
sink_dma_stop();
|
||||
|
||||
/* Set up DMA transfer */
|
||||
SAR0 = (unsigned long)addr; /* Source address */
|
||||
|
|
@ -250,19 +263,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
DMA_SSIZE(DMA_SIZE_LINE) | DMA_START;
|
||||
|
||||
dma_play_lock.state = (0 << 14);
|
||||
} /* pcm_play_dma_start */
|
||||
|
||||
/* Stops the DMA transfer and interrupt */
|
||||
void pcm_play_dma_stop(void)
|
||||
{
|
||||
and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */
|
||||
BCR0 = 0; /* No bytes remaining */
|
||||
DSR0 = 1; /* Clear interrupt, errors, stop transfer */
|
||||
|
||||
iis_play_reset_if_playback(true);
|
||||
|
||||
dma_play_lock.state = (1 << 14);
|
||||
} /* pcm_play_dma_stop */
|
||||
} /* sink_dma_start */
|
||||
|
||||
/* DMA0 Interrupt is called when the DMA has finished transfering a chunk
|
||||
from the caller's buffer */
|
||||
|
|
@ -301,6 +302,23 @@ void DMA0(void)
|
|||
/* else inished playing */
|
||||
} /* DMA0 */
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
/****************************************************************************
|
||||
** Recording DMA transfer
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "debug.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
extern JNIEnv *env_ptr;
|
||||
|
||||
|
|
@ -133,23 +135,24 @@ Java_org_rockbox_RockboxPCM_nativeWrite(JNIEnv *env, jobject this,
|
|||
return max_size - left;
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
if (++audio_locked == 1)
|
||||
lock_audio();
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if (--audio_locked == 0)
|
||||
unlock_audio();
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
(void)freq;
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
pcm_data_start = addr;
|
||||
pcm_data_size = size;
|
||||
|
|
@ -160,7 +163,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
0);
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
/* NOTE: due to how pcm_play_dma_complete_callback() works, this is
|
||||
* possibly called from nativeWrite(), i.e. another (host) thread
|
||||
|
|
@ -171,7 +174,7 @@ void pcm_play_dma_stop(void)
|
|||
stop_method);
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
/* in order to have background music playing after leaving the activity,
|
||||
* we need to allocate the PCM object from the Rockbox thread (the Activity
|
||||
|
|
@ -194,7 +197,7 @@ void pcm_play_dma_init(void)
|
|||
write_method = e->GetMethodID(env_ptr, RockboxPCM_class, "write", "([BII)I");
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -213,6 +216,23 @@ void pcm_shutdown(void)
|
|||
pthread_mutex_destroy(&audio_lock_mutex);
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_rockbox_RockboxPCM_postVolumeChangedEvent(JNIEnv *env,
|
||||
jobject this,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "pcm-internal.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm_mixer.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
#include <3ds/ndsp/ndsp.h>
|
||||
#include <3ds/ndsp/channel.h>
|
||||
|
|
@ -102,14 +103,14 @@ static inline bool is_in_audio_thread(int audio_thread_id)
|
|||
return false;
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
if (!is_in_audio_thread(_pcm_thread_id)) {
|
||||
RecursiveLock_Lock(&_pcm_lock_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if (!is_in_audio_thread(_pcm_thread_id)) {
|
||||
RecursiveLock_Unlock(&_pcm_lock_mtx);
|
||||
|
|
@ -188,13 +189,13 @@ void dsp_callback(void *const nul_) {
|
|||
LightEvent_Signal(&_dsp_callback_event);
|
||||
}
|
||||
|
||||
static void pcm_dma_apply_settings_nolock(void)
|
||||
static void sink_set_freq_nolock(uint16_t freq)
|
||||
{
|
||||
ndspChnReset(0);
|
||||
|
||||
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
|
||||
|
||||
ndspChnSetRate(0, pcm_sampr);
|
||||
ndspChnSetRate(0, hw_freq_sampr[freq]);
|
||||
ndspChnSetFormat(0, NDSP_FORMAT_STEREO_PCM16);
|
||||
/* ndspChnSetInterp(0, NDSP_INTERP_POLYPHASE); */
|
||||
/* ndspChnSetInterp(0, NDSP_INTERP_NONE); */
|
||||
|
|
@ -235,7 +236,7 @@ static void pcm_dma_apply_settings_nolock(void)
|
|||
-1, /* run on any core */ false);
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
_pcm_buffer = addr;
|
||||
_pcm_buffer_size = size;
|
||||
|
|
@ -245,7 +246,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
RecursiveLock_Unlock(&_pcm_lock_mtx);
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
RecursiveLock_Lock(&_pcm_lock_mtx);
|
||||
ndspChnSetPaused(0, true);
|
||||
|
|
@ -303,7 +304,7 @@ unsigned long spdif_measure_frequency(void)
|
|||
|
||||
#endif /* HAVE_RECORDING */
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
Result ndsp_init_res = ndspInit();
|
||||
if (R_FAILED(ndsp_init_res)) {
|
||||
|
|
@ -319,15 +320,15 @@ void pcm_play_dma_init(void)
|
|||
LightEvent_Init(&_dsp_callback_event, RESET_ONESHOT);
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
pcm_play_lock();
|
||||
pcm_dma_apply_settings_nolock();
|
||||
pcm_play_unlock();
|
||||
sink_lock();
|
||||
sink_set_freq_nolock(freq);
|
||||
sink_unlock();
|
||||
}
|
||||
|
||||
void pcm_close_device(void)
|
||||
|
|
@ -357,3 +358,20 @@ void audiohw_close(void)
|
|||
{
|
||||
pcm_close_device();
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include "panic.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
#include "sound/asound.h"
|
||||
#include "tinyalsa/asoundlib.h"
|
||||
|
|
@ -187,26 +189,26 @@ static const unsigned int DEVICE = 0;
|
|||
static struct pcm_config _config;
|
||||
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
TRACE;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
/*
|
||||
DEBUG pcm_play_dma_init: Access: 0x000009
|
||||
DEBUG pcm_play_dma_init: Format[0]: 0x000044
|
||||
DEBUG pcm_play_dma_init: Format[1]: 0x000010
|
||||
DEBUG pcm_play_dma_init: Format: S16_LE
|
||||
DEBUG pcm_play_dma_init: Format: S24_LE
|
||||
DEBUG pcm_play_dma_init: Format: S20_3LE
|
||||
DEBUG pcm_play_dma_init: Subformat: 0x000001
|
||||
DEBUG pcm_play_dma_init: Rate: min = 8000Hz, max = 192000Hz
|
||||
DEBUG pcm_play_dma_init: Channels: min = 2, max = 2
|
||||
DEBUG pcm_play_dma_init: Sample bits: min=16, max=32
|
||||
DEBUG pcm_play_dma_init: Period size: min=8, max=10922
|
||||
DEBUG pcm_play_dma_init: Period count: min=3, max=128
|
||||
DEBUG pcm_play_dma_init: 0 mixer controls.
|
||||
DEBUG sink_dma_init: Access: 0x000009
|
||||
DEBUG sink_dma_init: Format[0]: 0x000044
|
||||
DEBUG sink_dma_init: Format[1]: 0x000010
|
||||
DEBUG sink_dma_init: Format: S16_LE
|
||||
DEBUG sink_dma_init: Format: S24_LE
|
||||
DEBUG sink_dma_init: Format: S20_3LE
|
||||
DEBUG sink_dma_init: Subformat: 0x000001
|
||||
DEBUG sink_dma_init: Rate: min = 8000Hz, max = 192000Hz
|
||||
DEBUG sink_dma_init: Channels: min = 2, max = 2
|
||||
DEBUG sink_dma_init: Sample bits: min=16, max=32
|
||||
DEBUG sink_dma_init: Period size: min=8, max=10922
|
||||
DEBUG sink_dma_init: Period count: min=3, max=128
|
||||
DEBUG sink_dma_init: 0 mixer controls.
|
||||
*/
|
||||
|
||||
struct pcm_params* params = pcm_params_get(CARD, DEVICE, PCM_OUT);
|
||||
|
|
@ -310,7 +312,7 @@ void pcm_play_dma_init(void)
|
|||
pcm_thread_run relies on this size match. See pcm_mixer.h.
|
||||
*/
|
||||
_config.channels = 2;
|
||||
_config.rate = pcm_sampr;
|
||||
_config.rate = hw_freq_sampr[HW_FREQ_DEFAULT];
|
||||
_config.period_size = 256;
|
||||
_config.period_count = 4;
|
||||
_config.format = PCM_FORMAT_S16_LE;
|
||||
|
|
@ -337,7 +339,7 @@ void pcm_play_dma_init(void)
|
|||
}
|
||||
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
TRACE;
|
||||
|
||||
|
|
@ -364,7 +366,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
pthread_mutex_unlock(&_dma_suspended_mtx);
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
TRACE;
|
||||
|
||||
|
|
@ -375,11 +377,11 @@ void pcm_play_dma_stop(void)
|
|||
}
|
||||
|
||||
|
||||
/* Unessecary play locks before pcm_play_dma_postinit. */
|
||||
/* Unessecary play locks before sink_dma_postinit. */
|
||||
static int _play_lock_recursion_count = -10000;
|
||||
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
TRACE;
|
||||
|
||||
|
|
@ -387,7 +389,7 @@ void pcm_play_dma_postinit(void)
|
|||
}
|
||||
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
TRACE;
|
||||
|
||||
|
|
@ -402,7 +404,7 @@ void pcm_play_lock(void)
|
|||
}
|
||||
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
TRACE;
|
||||
|
||||
|
|
@ -418,9 +420,9 @@ void pcm_play_unlock(void)
|
|||
}
|
||||
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
unsigned int rate = pcm_get_frequency();
|
||||
unsigned int rate = hw_freq_sampr[freq];
|
||||
|
||||
DEBUGF("DEBUG %s: Current sample rate: %u, next sampe rate: %u.", __func__, _config.rate, rate);
|
||||
|
||||
|
|
@ -450,3 +452,20 @@ void pcm_close_device(void)
|
|||
pcm_close(_alsa_handle);
|
||||
_alsa_handle = NULL;
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "pcm-internal.h"
|
||||
#include "pcm_mixer.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm_sink.h"
|
||||
#include "audiohw.h"
|
||||
#include "pcm-alsa.h"
|
||||
#include "fixedpoint.h"
|
||||
|
|
@ -122,7 +123,7 @@ void pcm_alsa_set_capture_device(const char *device)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int set_hwparams(snd_pcm_t *handle)
|
||||
static int set_hwparams(snd_pcm_t *handle, unsigned long sampr)
|
||||
{
|
||||
int err;
|
||||
unsigned int srate;
|
||||
|
|
@ -136,10 +137,10 @@ static int set_hwparams(snd_pcm_t *handle)
|
|||
Note these are in FRAMES, and are sized to be about 8.5ms
|
||||
for the buffer and 2.1ms for the period
|
||||
*/
|
||||
if (pcm_sampr > SAMPR_96) {
|
||||
if (sampr > SAMPR_96) {
|
||||
buffer_size = MIX_FRAME_SAMPLES * 4 * 4;
|
||||
period_size = MIX_FRAME_SAMPLES * 4;
|
||||
} else if (pcm_sampr > SAMPR_48) {
|
||||
} else if (sampr > SAMPR_48) {
|
||||
buffer_size = MIX_FRAME_SAMPLES * 2 * 4;
|
||||
period_size = MIX_FRAME_SAMPLES * 2;
|
||||
} else {
|
||||
|
|
@ -176,17 +177,17 @@ static int set_hwparams(snd_pcm_t *handle)
|
|||
goto error;
|
||||
}
|
||||
/* set the stream rate */
|
||||
srate = pcm_sampr;
|
||||
srate = sampr;
|
||||
err = snd_pcm_hw_params_set_rate_near(handle, params, &srate, 0);
|
||||
if (err < 0)
|
||||
{
|
||||
logf("Rate %luHz not available for playback: %s", pcm_sampr, snd_strerror(err));
|
||||
logf("Rate %luHz not available for playback: %s", sampr, snd_strerror(err));
|
||||
goto error;
|
||||
}
|
||||
real_sample_rate = srate;
|
||||
if (real_sample_rate != pcm_sampr)
|
||||
if (real_sample_rate != sampr)
|
||||
{
|
||||
logf("Rate doesn't match (requested %luHz, get %dHz)", pcm_sampr, real_sample_rate);
|
||||
logf("Rate doesn't match (requested %luHz, get %dHz)", sampr, real_sample_rate);
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
|
@ -595,7 +596,7 @@ static void open_hwdev(const char *device, snd_pcm_stream_t mode)
|
|||
atexit(alsadev_cleanup);
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
logf("PCM DMA Init");
|
||||
|
||||
|
|
@ -606,48 +607,50 @@ void pcm_play_dma_init(void)
|
|||
return;
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
pthread_mutex_lock(&pcm_mtx);
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
pthread_mutex_unlock(&pcm_mtx);
|
||||
}
|
||||
|
||||
static void pcm_dma_apply_settings_nolock(void)
|
||||
static void sink_set_freq_nolock(uint16_t freq)
|
||||
{
|
||||
logf("PCM DMA Settings %d %lu", last_sample_rate, pcm_sampr);
|
||||
unsigned int sampr = hw_freq_sampr[freq];
|
||||
|
||||
if (last_sample_rate != pcm_sampr)
|
||||
logf("PCM DMA Settings %d %lu", last_sample_rate, sampr);
|
||||
|
||||
if (last_sample_rate != sampr)
|
||||
{
|
||||
last_sample_rate = pcm_sampr;
|
||||
last_sample_rate = sampr;
|
||||
|
||||
#ifdef AUDIOHW_MUTE_ON_SRATE_CHANGE
|
||||
audiohw_mute(true);
|
||||
#endif
|
||||
snd_pcm_drop(handle);
|
||||
|
||||
set_hwparams(handle); // FIXME: check return code?
|
||||
set_hwparams(handle, sampr); // FIXME: check return code?
|
||||
set_swparams(handle); // FIXME: check return code?
|
||||
|
||||
#if defined(HAVE_NWZ_LINUX_CODEC)
|
||||
/* Sony NWZ linux driver uses a nonstandard mecanism to set the sampling rate */
|
||||
audiohw_set_frequency(pcm_sampr);
|
||||
audiohw_set_frequency(sampr);
|
||||
#endif
|
||||
/* (Will be unmuted by pcm resuming) */
|
||||
}
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
pcm_play_lock();
|
||||
pcm_dma_apply_settings_nolock();
|
||||
pcm_play_unlock();
|
||||
sink_lock();
|
||||
sink_set_freq_nolock(freq);
|
||||
sink_unlock();
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
logf("PCM DMA stop (%d)", snd_pcm_state(handle));
|
||||
|
||||
|
|
@ -660,10 +663,9 @@ void pcm_play_dma_stop(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
logf("PCM DMA start (%p %d)", addr, size);
|
||||
pcm_dma_apply_settings_nolock();
|
||||
|
||||
pcm_data = addr;
|
||||
pcm_size = size;
|
||||
|
|
@ -749,7 +751,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
}
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
|
||||
|
|
@ -768,15 +770,32 @@ unsigned int pcm_alsa_get_xruns(void)
|
|||
return xruns;
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
void pcm_rec_lock(void)
|
||||
{
|
||||
pcm_play_lock();
|
||||
sink_lock();
|
||||
}
|
||||
|
||||
void pcm_rec_unlock(void)
|
||||
{
|
||||
pcm_play_unlock();
|
||||
sink_unlock();
|
||||
}
|
||||
|
||||
void pcm_rec_dma_init(void)
|
||||
|
|
@ -796,7 +815,6 @@ void pcm_rec_dma_close(void)
|
|||
void pcm_rec_dma_start(void *start, size_t size)
|
||||
{
|
||||
logf("PCM REC DMA start (%p %d)", start, size);
|
||||
pcm_dma_apply_settings_nolock();
|
||||
pcm_data_rec = start;
|
||||
pcm_size = size;
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "pcm-internal.h"
|
||||
#include "pcm_sampr.h"
|
||||
#include "pcm_mixer.h"
|
||||
#include "pcm_sink.h"
|
||||
|
||||
/*#define LOGF_ENABLE*/
|
||||
#include "logf.h"
|
||||
|
|
@ -57,6 +58,8 @@ extern const char *audiodev;
|
|||
|
||||
static int cvt_status = -1;
|
||||
|
||||
static unsigned long pcm_sampr;
|
||||
|
||||
static const void *pcm_data;
|
||||
static size_t pcm_data_size;
|
||||
static size_t pcm_sample_bytes;
|
||||
|
|
@ -80,13 +83,13 @@ static SDL_AudioCVT cvt;
|
|||
static int audio_locked = 0;
|
||||
static SDL_mutex *audio_lock;
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
if (++audio_locked == 1)
|
||||
SDL_LockMutex(audio_lock);
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
if (--audio_locked == 0)
|
||||
SDL_UnlockMutex(audio_lock);
|
||||
|
|
@ -97,8 +100,11 @@ void pcm_play_unlock(void)
|
|||
#endif
|
||||
|
||||
static void sdl_audio_callback(void *handle, Uint8 *stream, int len);
|
||||
static void pcm_dma_apply_settings_nolock(void)
|
||||
|
||||
static void sink_set_freq_nolock(uint16_t freq)
|
||||
{
|
||||
pcm_sampr = hw_freq_sampr[freq];
|
||||
|
||||
SDL_AudioSpec wanted_spec;
|
||||
wanted_spec.freq = pcm_sampr;
|
||||
wanted_spec.format = AUDIO_S16SYS;
|
||||
|
|
@ -161,14 +167,14 @@ static void pcm_dma_apply_settings_nolock(void)
|
|||
}
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
pcm_play_lock();
|
||||
pcm_dma_apply_settings_nolock();
|
||||
pcm_play_unlock();
|
||||
sink_lock();
|
||||
sink_set_freq_nolock(freq);
|
||||
sink_unlock();
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
pcm_data = addr;
|
||||
pcm_data_size = size;
|
||||
|
|
@ -180,7 +186,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
|
|||
#endif
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
#if SDL_MAJOR_VERSION > 1
|
||||
SDL_PauseAudioDevice(pcm_devid, 1);
|
||||
|
|
@ -397,7 +403,7 @@ unsigned long spdif_measure_frequency(void)
|
|||
|
||||
#endif /* HAVE_RECORDING */
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO))
|
||||
{
|
||||
|
|
@ -435,6 +441,23 @@ void pcm_play_dma_init(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,14 +26,14 @@
|
|||
#include "sound.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
#include "jz4740.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** Playback DMA transfer
|
||||
**/
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ void pcm_play_dma_postinit(void)
|
|||
__aic_flush_fifo();
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
|
|
@ -57,10 +57,10 @@ void pcm_play_dma_init(void)
|
|||
audiohw_init();
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
/* TODO */
|
||||
audiohw_set_frequency(pcm_sampr);
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
static const void* playback_address;
|
||||
|
|
@ -135,21 +135,7 @@ void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void)
|
|||
}
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
pcm_play_dma_stop();
|
||||
|
||||
dma_enable();
|
||||
|
||||
set_dma(addr, size);
|
||||
|
||||
__aic_enable_transmit_dma();
|
||||
__aic_enable_replay();
|
||||
|
||||
REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN;
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
int flags = disable_irq_save();
|
||||
|
||||
|
|
@ -163,8 +149,22 @@ void pcm_play_dma_stop(void)
|
|||
restore_irq(flags);
|
||||
}
|
||||
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
sink_dma_stop();
|
||||
|
||||
dma_enable();
|
||||
|
||||
set_dma(addr, size);
|
||||
|
||||
__aic_enable_transmit_dma();
|
||||
__aic_enable_replay();
|
||||
|
||||
REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN;
|
||||
}
|
||||
|
||||
static unsigned int play_lock = 0;
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
int flags = disable_irq_save();
|
||||
|
||||
|
|
@ -174,7 +174,7 @@ void pcm_play_lock(void)
|
|||
restore_irq(flags);
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
int flags = disable_irq_save();
|
||||
|
||||
|
|
@ -189,6 +189,23 @@ void audiohw_close(void)
|
|||
/* TODO: prevent pop */
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
/* TODO */
|
||||
void pcm_rec_dma_init(void)
|
||||
|
|
|
|||
|
|
@ -26,13 +26,14 @@
|
|||
#include "sound.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
#include "cpu.h"
|
||||
|
||||
/****************************************************************************
|
||||
** Playback DMA transfer
|
||||
**/
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_dma_postinit(void)
|
||||
{
|
||||
audiohw_postinit();
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ void pcm_play_dma_postinit(void)
|
|||
__aic_flush_tfifo();
|
||||
}
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
system_enable_irq(DMA_IRQ(DMA_AIC_TX_CHANNEL));
|
||||
|
||||
|
|
@ -48,9 +49,9 @@ void pcm_play_dma_init(void)
|
|||
audiohw_init();
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
static const void* playback_address;
|
||||
|
|
@ -126,20 +127,7 @@ void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void)
|
|||
}
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
pcm_play_dma_stop();
|
||||
|
||||
__dmac_channel_enable_clk(DMA_AIC_TX_CHANNEL);
|
||||
|
||||
set_dma(addr, size);
|
||||
|
||||
__aic_enable_replay();
|
||||
|
||||
__dmac_channel_enable_irq(DMA_AIC_TX_CHANNEL);
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
int flags = disable_irq_save();
|
||||
|
||||
|
|
@ -152,8 +140,21 @@ void pcm_play_dma_stop(void)
|
|||
restore_irq(flags);
|
||||
}
|
||||
|
||||
static void sink_dma_start(const void *addr, size_t size)
|
||||
{
|
||||
sink_dma_stop();
|
||||
|
||||
__dmac_channel_enable_clk(DMA_AIC_TX_CHANNEL);
|
||||
|
||||
set_dma(addr, size);
|
||||
|
||||
__aic_enable_replay();
|
||||
|
||||
__dmac_channel_enable_irq(DMA_AIC_TX_CHANNEL);
|
||||
}
|
||||
|
||||
static unsigned int play_lock = 0;
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
int flags = disable_irq_save();
|
||||
|
||||
|
|
@ -163,7 +164,7 @@ void pcm_play_lock(void)
|
|||
restore_irq(flags);
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
int flags = disable_irq_save();
|
||||
|
||||
|
|
@ -172,3 +173,20 @@ void pcm_play_unlock(void)
|
|||
|
||||
restore_irq(flags);
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = sink_dma_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "audiohw.h"
|
||||
#include "pcm.h"
|
||||
#include "pcm-internal.h"
|
||||
#include "pcm_sink.h"
|
||||
#include "panic.h"
|
||||
#include "dma-x1000.h"
|
||||
#include "irq-x1000.h"
|
||||
|
|
@ -53,7 +54,7 @@ static dma_desc rec_dma_desc;
|
|||
static void pcm_rec_dma_int_cb(int event);
|
||||
#endif
|
||||
|
||||
void pcm_play_dma_init(void)
|
||||
static void sink_dma_init(void)
|
||||
{
|
||||
/* Ungate clock */
|
||||
jz_writef(CPM_CLKGR, AIC(0));
|
||||
|
|
@ -99,14 +100,9 @@ void pcm_play_dma_init(void)
|
|||
system_enable_irq(IRQ_AIC);
|
||||
}
|
||||
|
||||
void pcm_play_dma_postinit(void)
|
||||
static void sink_set_freq(uint16_t freq)
|
||||
{
|
||||
audiohw_postinit();
|
||||
}
|
||||
|
||||
void pcm_dma_apply_settings(void)
|
||||
{
|
||||
audiohw_set_frequency(pcm_fsel);
|
||||
audiohw_set_frequency(freq);
|
||||
}
|
||||
|
||||
static void play_dma_start(const void* addr, size_t size)
|
||||
|
|
@ -157,7 +153,7 @@ static void pcm_play_dma_int_cb(int event)
|
|||
}
|
||||
}
|
||||
|
||||
void pcm_play_dma_start(const void* addr, size_t size)
|
||||
static void sink_dma_start(const void* addr, size_t size)
|
||||
{
|
||||
play_dma_pending_event = DMA_EVENT_NONE;
|
||||
aic_state |= AIC_STATE_PLAYING;
|
||||
|
|
@ -166,7 +162,7 @@ void pcm_play_dma_start(const void* addr, size_t size)
|
|||
jz_writef(AIC_CCR, TDMS(1), ETUR(1), ERPL(1));
|
||||
}
|
||||
|
||||
void pcm_play_dma_stop(void)
|
||||
static void sink_dma_stop(void)
|
||||
{
|
||||
/* disable DMA and underrun interrupts */
|
||||
jz_writef(AIC_CCR, TDMS(0), ETUR(0));
|
||||
|
|
@ -180,7 +176,7 @@ void pcm_play_dma_stop(void)
|
|||
if (jz_readf(AIC_I2SCR, STPBK) == 0) {
|
||||
while(jz_readf(AIC_SR, TFL) != 0);
|
||||
} else {
|
||||
panicf("pcm_play_dma_stop: No bit clock running!");
|
||||
panicf("sink_dma_stop: No bit clock running!");
|
||||
}
|
||||
|
||||
/* disable playback */
|
||||
|
|
@ -190,14 +186,14 @@ void pcm_play_dma_stop(void)
|
|||
aic_state &= ~AIC_STATE_PLAYING;
|
||||
}
|
||||
|
||||
void pcm_play_lock(void)
|
||||
static void sink_lock(void)
|
||||
{
|
||||
int irq = disable_irq_save();
|
||||
++play_lock;
|
||||
restore_irq(irq);
|
||||
}
|
||||
|
||||
void pcm_play_unlock(void)
|
||||
static void sink_unlock(void)
|
||||
{
|
||||
int irq = disable_irq_save();
|
||||
if(--play_lock == 0 && (aic_state & AIC_STATE_PLAYING)) {
|
||||
|
|
@ -208,6 +204,23 @@ void pcm_play_unlock(void)
|
|||
restore_irq(irq);
|
||||
}
|
||||
|
||||
struct pcm_sink builtin_pcm_sink = {
|
||||
.caps = {
|
||||
.samprs = hw_freq_sampr,
|
||||
.num_samprs = HW_NUM_FREQ,
|
||||
.default_freq = HW_FREQ_DEFAULT,
|
||||
},
|
||||
.ops = {
|
||||
.init = sink_dma_init,
|
||||
.postinit = audiohw_postinit,
|
||||
.set_freq = sink_set_freq,
|
||||
.lock = sink_lock,
|
||||
.unlock = sink_unlock,
|
||||
.play = sink_dma_start,
|
||||
.stop = sink_dma_stop,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef HAVE_RECORDING
|
||||
/*
|
||||
* Recording
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue