summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
blob: c29c4b29303a7af54b11848d6d90866ed196f824 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2006 by Michael Sevakis
 *
 * All files in this archive are subject to the GNU General Public License.
 * See the file COPYING in the source tree root for full license agreement.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#include <stdlib.h>
#include "system.h"
#include "kernel.h"
#include "logf.h"
#include "audio.h"
#include "sound.h"
#include "file.h"
#include "mmu-imx31.h"

static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */

void fiq_handler(void) __attribute__((naked));

/* Implement separately on recording and playback - simply disable the
   specific DMA interrupt. Disable the FIQ itself only temporarily to sync
   with the DMA interrupt and restore its previous state. The pcm routines
   will call the lockout first then call into these low-level routines. */
struct dma_lock
{
    int locked;
    unsigned long state;
};

static struct dma_play_lock =
{
    .locked = 0,
    .state = 0, /* Initialize this as disabled */
};

void pcm_play_lock(void)
{
    int status = set_fiq_status(FIQ_DISABLED);
    if (++dma_play_lock.locked == 1)
        ; /* Mask the DMA interrupt */
    set_fiq_status(status);
}

void pcm_play_unlock(void)
{
    int status = set_fiq_status(FIQ_DISABLED);
    if (--dma_play_lock.locked == 0)
        ; /* Unmask the DMA interrupt if enabled */
    set_fiq_status(status);
}

static void _pcm_apply_settings(void)
{
    if (pcm_freq != pcm_curr_sampr)
    {
        pcm_curr_sampr = pcm_freq;
        /* Change hardware sample rate */
        /* */
    }
}

void pcm_apply_settings(void)
{
    /* Lockout FIQ and sync the hardware to the settings */
    int oldstatus = set_fiq_status(FIQ_DISABLED);
    _pcm_apply_settings();
    set_fiq_status(oldstatus);
}

void pcm_play_dma_init(void)
{
    pcm_set_frequency(SAMPR_44);

#if 0
    /* Do basic init enable output in pcm_postinit if popping is a
       problem at boot to enable a lenghy delay and let the boot
       process continue */
    audiohw_init();
#endif
}

void pcm_postinit(void)
{
}

/* Connect the DMA and start filling the FIFO */
static void play_start_pcm(void)
{
#if 0
    /* unmask DMA interrupt when unlocking */
    dma_play_lock.state = 0; /* Set to allow pcm_play_unlock to unmask interrupt */
#endif
}

/* Disconnect the DMA and wait for the FIFO to clear */
static void play_stop_pcm(void)
{
#if 0
    /* Keep interrupt masked when unlocking */
    dma_play_lock.state = 0; /* Set to keep pcm_play_unlock from unmasking interrupt */
#endif
}

void pcm_play_dma_start(const void *addr, size_t size)
{
    (void)addr;
    (void)size;
}

void pcm_play_dma_stop(void)
{
    play_stop_pcm();
}

void pcm_play_dma_pause(bool pause)
{
    if (pause)
    {
        play_stop_pcm();
    }
    else
    {
        play_start_pcm();
    }
}

/* Get more samples to play out - call pcm_play_dma_stop and
   pcm_play_dma_stopped_callback if the data runs out */
void fiq_handler(void)
{
#if 0
    /* Callback missing or no more DMA to do */
    pcm_play_dma_stop();
    pcm_play_dma_stopped_callback();
#endif
}

/* Set the pcm frequency hardware will use when play is next started or
   when pcm_apply_settings is called. Do not apply the setting to the
   hardware here but simply cache it. */
void pcm_set_frequency(unsigned int frequency)
{
     pcm_freq = frequency;
}

/* Return the number of bytes waiting - full L-R sample pairs only */
size_t pcm_get_bytes_waiting(void)
{
}

/* Return a pointer to the samples and the number of them in *count */
const void * pcm_play_dma_get_peak_buffer(int *count)
{
    (void)count;
}

/* Any recording functionality should be implemented similarly */