OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [char/] [dac0800.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*****************************************************************************/
2
 
3
/*
4
 *      dac0800.c -- driver for NETtel DMA audio
5
 *
6
 *      (C) Copyright 1999, greg Ungerer (gerg@moreton.com.au)
7
 *
8
 *      Based loosely on lcddma.c which is:
9
 *
10
 *      Copyright (C) 1999 Rob Scott (rscott@mtrob.fdns.net)
11
 */
12
 
13
/*****************************************************************************/
14
 
15
#include <linux/config.h>
16
#include <linux/types.h>
17
#include <linux/kernel.h>
18
#include <linux/fs.h>
19
#include <linux/mm.h>
20
#include <linux/wait.h>
21
#include <asm/param.h>
22
#include <asm/dma.h>
23
#include <asm/irq.h>
24
#include <asm/coldfire.h>
25
#include <asm/mcfsim.h>
26
#include <asm/mcfdma.h>
27
#include <asm/mcftimer.h>
28
 
29
/*****************************************************************************/
30
 
31
#define DAC0800_MAJOR   120
32
#define DAC0800_VEC     120
33
 
34
#define DAC0800_DMA_CHAN        1
35
#define DAC0800_DMA_DESTADDR    0x30400000
36
 
37
#define DAC0800_DMA_BUFSIZE     (16 * 1024)
38
 
39
/*****************************************************************************/
40
 
41
/*
42
 *      Double buffers for storing audio samples.
43
 */
44
unsigned char   dac0800_buf0[DAC0800_DMA_BUFSIZE];
45
unsigned char   dac0800_buf1[DAC0800_DMA_BUFSIZE];
46
unsigned int    dac0800_bufsize = DAC0800_DMA_BUFSIZE;
47
unsigned int    dac0800_buf0cnt;
48
unsigned int    dac0800_buf1cnt;
49
 
50
unsigned int    dac0800_curbuf = 0;
51
unsigned int    dac0800_bufbusy = 0;
52
 
53
#define DAC0800_BUF0            0x1
54
#define DAC0800_BUF1            0x2
55
 
56
#define DAC0800_ALLBUFS         0x3
57
 
58
struct wait_queue       *dac0800_waitchan = NULL;
59
 
60
/*****************************************************************************/
61
 
62
/*
63
 *      Set up internal timer1 for our sample rate.
64
 */
65
 
66
void dac0800_setclk(unsigned int rate)
67
{
68
        volatile unsigned short *timerp;
69
        unsigned long           flags;
70
 
71
        timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2);
72
        timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
73
 
74
        save_flags(flags); cli();
75
        timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE;
76
        timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
77
        timerp[MCFTIMER_TRR] = (unsigned short) (MCF_CLK / rate);
78
        timerp[MCFTIMER_TMR] = (0 << 8) | /* set prescaler to divide by 1 */
79
                        MCFTIMER_TMR_DISCE | MCFTIMER_TMR_DISOM |
80
                        MCFTIMER_TMR_ENORI | MCFTIMER_TMR_RESTART |
81
                        MCFTIMER_TMR_CLK1  | MCFTIMER_TMR_ENABLE;
82
        restore_flags(flags);
83
}
84
 
85
/*****************************************************************************/
86
 
87
void dac0800_startdma(unsigned char *buf, unsigned int size)
88
{
89
        /* Clear DMA interrupt */
90
        disable_dma(DAC0800_DMA_CHAN);
91
 
92
        /* Do DMA write to i/o operation */
93
        set_dma_mode(DAC0800_DMA_CHAN, DMA_MODE_WRITE);
94
        set_dma_device_addr(DAC0800_DMA_CHAN, DAC0800_DMA_DESTADDR);
95
        set_dma_addr(DAC0800_DMA_CHAN, (unsigned int) buf);
96
        set_dma_count(DAC0800_DMA_CHAN, size);
97
 
98
        /* Fire it off! */
99
        enable_dma(DAC0800_DMA_CHAN);
100
}
101
 
102
/*****************************************************************************/
103
 
104
/*
105
 *      If there is a buffer ready to go then start DMA from it.
106
 */
107
 
108
void dac0800_startbuf(void)
109
{
110
        unsigned char   *bufp;
111
        unsigned int    flag, cnt;
112
 
113
        /* If already DMAing nothing to do */
114
        if (dac0800_curbuf)
115
                return;
116
 
117
        /* Simple double buffered arrangement... */
118
        if (dac0800_bufbusy & DAC0800_BUF0) {
119
                bufp = dac0800_buf0;
120
                cnt = dac0800_buf0cnt;
121
                flag = DAC0800_BUF0;
122
        } else if (dac0800_bufbusy & DAC0800_BUF1) {
123
                bufp = dac0800_buf1;
124
                cnt = dac0800_buf1cnt;
125
                flag = DAC0800_BUF1;
126
        } else {
127
                return;
128
        }
129
 
130
        dac0800_curbuf = flag;
131
        dac0800_startdma(bufp, cnt);
132
}
133
 
134
/*****************************************************************************/
135
 
136
int dac0800_open(struct inode *inode, struct file *filp)
137
{
138
#if 0
139
        printk("%s(%d): dac0800_open()\n", __FILE__, __LINE__);
140
#endif
141
 
142
        dac0800_curbuf = 0;
143
        return(0);
144
}
145
 
146
/*****************************************************************************/
147
 
148
void dac0800_release(struct inode *inode, struct file *filp)
149
{
150
#if 0
151
        printk("%s(%d): dac0800_close()\n", __FILE__, __LINE__);
152
#endif
153
}
154
 
155
/*****************************************************************************/
156
 
157
int dac0800_write(struct inode *inode, struct file *filp, const char *buf, int count)
158
{
159
        unsigned char   *dacbufp;
160
        unsigned int    size, bufflag;
161
        unsigned long   flags;
162
 
163
#if 0
164
        printk("%s(%d): dac0800_write(buf=%x,count=%d)\n", __FILE__, __LINE__,
165
                (int) buf, count);
166
#endif
167
 
168
        size = (count > dac0800_bufsize) ? dac0800_bufsize : count;
169
 
170
        /* Check for empty DMA buffer, if not wait for one. */
171
        save_flags(flags); cli();
172
        while ((dac0800_bufbusy & DAC0800_ALLBUFS) == DAC0800_ALLBUFS) {
173
                if (current->signal & ~current->blocked) {
174
                        restore_flags(flags);
175
                        return(-ERESTARTSYS);
176
                }
177
                interruptible_sleep_on(&dac0800_waitchan);
178
        }
179
 
180
        if (dac0800_bufbusy & DAC0800_BUF0) {
181
                bufflag = DAC0800_BUF1;
182
                dacbufp = &dac0800_buf1[0];
183
                dac0800_buf1cnt = size;
184
        } else {
185
                bufflag = DAC0800_BUF0;
186
                dacbufp = &dac0800_buf0[0];
187
                dac0800_buf0cnt = size;
188
        }
189
        restore_flags(flags);
190
 
191
        /* Copy the buffer local and start DMAing it. */
192
        memcpy_fromfs(dacbufp, buf, size);
193
 
194
        save_flags(flags); cli();
195
        dac0800_bufbusy |= bufflag;
196
        dac0800_startbuf();
197
        restore_flags(flags);
198
 
199
        return(size);
200
}
201
 
202
/*****************************************************************************/
203
 
204
int dac0800_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
205
{
206
        int     rc = 0;
207
 
208
        switch (cmd) {
209
        case 1:
210
                dac0800_setclk(arg);
211
                break;
212
        default:
213
                rc = -EINVAL;
214
                break;
215
        }
216
 
217
        return(rc);
218
}
219
 
220
/*****************************************************************************/
221
 
222
void dac0800_isr(int irq, void *dev_id, struct pt_regs *regs)
223
{
224
        /* Clear DMA interrupt */
225
        disable_dma(DAC0800_DMA_CHAN);
226
 
227
        /* Mark buffer no longer in use */
228
        dac0800_bufbusy &= ~dac0800_curbuf;
229
        dac0800_curbuf = 0;
230
 
231
        /* Start of any other waiting buffers! */
232
        dac0800_startbuf();
233
 
234
        /* Wake up writers */
235
        wake_up_interruptible(&dac0800_waitchan);
236
}
237
 
238
/*****************************************************************************/
239
 
240
/*
241
 *      Exported file operations structure for driver...
242
 */
243
 
244
struct file_operations  dac0800_fops = {
245
        NULL,          /* lseek */
246
        NULL,          /* read */
247
        dac0800_write,
248
        NULL,          /* readdir */
249
        NULL,          /* poll */
250
        dac0800_ioctl,
251
        NULL,          /* mmap */
252
        dac0800_open,
253
        dac0800_release,
254
        NULL,          /* fsync */
255
        NULL,          /* fasync */
256
        NULL,          /* check_media_change */
257
        NULL           /* revalidate */
258
};
259
 
260
/*****************************************************************************/
261
 
262
void dac0800_init(void)
263
{
264
        volatile unsigned char  *mbarp, *dmap;
265
        unsigned long           imr;
266
        unsigned int            icr;
267
        int                     result;
268
 
269
        /* Register dac0800 as character device */
270
        result = register_chrdev(DAC0800_MAJOR, "dac0800", &dac0800_fops);
271
        if (result < 0) {
272
                printk(KERN_WARNING "DAC0800: can't get major %d\n",
273
                        DAC0800_MAJOR);
274
                return;
275
        }
276
 
277
        printk ("DAC0800: Copyright (C) 1999, Greg Ungerer "
278
                "(gerg@moreton.com.au)\n");
279
 
280
        /* Install ISR (interrupt service routine) */
281
        result = request_irq(DAC0800_VEC, dac0800_isr, SA_INTERRUPT,
282
                "DAC0800", NULL);
283
        if (result) {
284
                printk ("DAC0800: IRQ %d already in use\n", DAC0800_VEC);
285
                return;
286
        }
287
 
288
        /* Set interrupt vector location */
289
        dmap = (volatile unsigned char *) dma_base_addr[DAC0800_DMA_CHAN];
290
        dmap[MCFDMA_DIVR] = DAC0800_VEC;
291
 
292
        /* Set interrupt level and priority */
293
        switch (DAC0800_DMA_CHAN) {
294
        case 1:  icr = MCFSIM_DMA1ICR ; imr = MCFSIM_IMR_DMA1; break;
295
        case 2:  icr = MCFSIM_DMA2ICR ; imr = MCFSIM_IMR_DMA2; break;
296
        case 3:  icr = MCFSIM_DMA3ICR ; imr = MCFSIM_IMR_DMA3; break;
297
        default: icr = MCFSIM_DMA0ICR ; imr = MCFSIM_IMR_DMA0; break;
298
        }
299
 
300
        mbarp = (volatile unsigned char *) MCF_MBAR;
301
        mbarp[icr] = MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1;
302
        mcf_setimr(mcf_getimr() & ~imr);
303
 
304
        /* Request DMA channel */
305
        printk ("DAC0800: requesting DMA channel %d\n", DAC0800_DMA_CHAN);
306
        result = request_dma(DAC0800_DMA_CHAN, "dac0800");
307
        if (result) {
308
                printk ("DAC0800: dma channel %d already in use\n",
309
                        DAC0800_DMA_CHAN);
310
                return;
311
        }
312
 
313
        /* Program default timer rate */
314
        dac0800_setclk(8000);
315
}
316
 
317
/*****************************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.