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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [pci/] [mixart/] [mixart_core.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * Driver for Digigram miXart soundcards
3
 *
4
 * low level interface with interrupt handling and mail box implementation
5
 *
6
 * Copyright (c) 2003 by Digigram <alsa@digigram.com>
7
 *
8
 *   This program is free software; you can redistribute it and/or modify
9
 *   it under the terms of the GNU General Public License as published by
10
 *   the Free Software Foundation; either version 2 of the License, or
11
 *   (at your option) any later version.
12
 *
13
 *   This program is distributed in the hope that it will be useful,
14
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *   GNU General Public License for more details.
17
 *
18
 *   You should have received a copy of the GNU General Public License
19
 *   along with this program; if not, write to the Free Software
20
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21
 */
22
 
23
#include <sound/driver.h>
24
#include <linux/interrupt.h>
25
#include <linux/mutex.h>
26
 
27
#include <asm/io.h>
28
#include <sound/core.h>
29
#include "mixart.h"
30
#include "mixart_hwdep.h"
31
#include "mixart_core.h"
32
 
33
 
34
#define MSG_TIMEOUT_JIFFIES         (400 * HZ) / 1000 /* 400 ms */
35
 
36
#define MSG_DESCRIPTOR_SIZE         0x24
37
#define MSG_HEADER_SIZE             (MSG_DESCRIPTOR_SIZE + 4)
38
 
39
#define MSG_DEFAULT_SIZE            512
40
 
41
#define MSG_TYPE_MASK               0x00000003    /* mask for following types */
42
#define MSG_TYPE_NOTIFY             0             /* embedded -> driver (only notification, do not get_msg() !) */
43
#define MSG_TYPE_COMMAND            1             /* driver <-> embedded (a command has no answer) */
44
#define MSG_TYPE_REQUEST            2             /* driver -> embedded (request will get an answer back) */
45
#define MSG_TYPE_ANSWER             3             /* embedded -> driver */
46
#define MSG_CANCEL_NOTIFY_MASK      0x80000000    /* this bit is set for a notification that has been canceled */
47
 
48
 
49
static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame)
50
{
51
        /* read the message frame fifo */
52
        u32 headptr, tailptr;
53
 
54
        tailptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL));
55
        headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_POST_HEAD));
56
 
57
        if (tailptr == headptr)
58
                return 0; /* no message posted */
59
 
60
        snd_assert( tailptr >= MSG_OUTBOUND_POST_STACK, return 0); /* error */
61
        snd_assert( tailptr < (MSG_OUTBOUND_POST_STACK+MSG_BOUND_STACK_SIZE), return 0); /* error */
62
 
63
        *msg_frame = readl_be(MIXART_MEM(mgr, tailptr));
64
 
65
        /* increment the tail index */
66
        tailptr += 4;
67
        if( tailptr >= (MSG_OUTBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) )
68
                tailptr = MSG_OUTBOUND_POST_STACK;
69
        writel_be(tailptr, MIXART_MEM(mgr, MSG_OUTBOUND_POST_TAIL));
70
 
71
        return 1;
72
}
73
 
74
static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
75
                   u32 msg_frame_address )
76
{
77
        unsigned long flags;
78
        u32  headptr;
79
        u32  size;
80
        int  err;
81
#ifndef __BIG_ENDIAN
82
        unsigned int i;
83
#endif
84
 
85
        spin_lock_irqsave(&mgr->msg_lock, flags);
86
        err = 0;
87
 
88
        /* copy message descriptor from miXart to driver */
89
        size                =  readl_be(MIXART_MEM(mgr, msg_frame_address));       /* size of descriptor + response */
90
        resp->message_id    =  readl_be(MIXART_MEM(mgr, msg_frame_address + 4));   /* dwMessageID */
91
        resp->uid.object_id =  readl_be(MIXART_MEM(mgr, msg_frame_address + 8));   /* uidDest */
92
        resp->uid.desc      =  readl_be(MIXART_MEM(mgr, msg_frame_address + 12));  /* */
93
 
94
        if( (size < MSG_DESCRIPTOR_SIZE) || (resp->size < (size - MSG_DESCRIPTOR_SIZE))) {
95
                err = -EINVAL;
96
                snd_printk(KERN_ERR "problem with response size = %d\n", size);
97
                goto _clean_exit;
98
        }
99
        size -= MSG_DESCRIPTOR_SIZE;
100
 
101
        memcpy_fromio(resp->data, MIXART_MEM(mgr, msg_frame_address + MSG_HEADER_SIZE ), size);
102
        resp->size = size;
103
 
104
        /* swap if necessary */
105
#ifndef __BIG_ENDIAN
106
        size /= 4; /* u32 size */
107
        for(i=0; i < size; i++) {
108
                ((u32*)resp->data)[i] = be32_to_cpu(((u32*)resp->data)[i]);
109
        }
110
#endif
111
 
112
        /*
113
         * free message frame address
114
         */
115
        headptr = readl_be(MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
116
 
117
        if( (headptr < MSG_OUTBOUND_FREE_STACK) || ( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) {
118
                err = -EINVAL;
119
                goto _clean_exit;
120
        }
121
 
122
        /* give address back to outbound fifo */
123
        writel_be(msg_frame_address, MIXART_MEM(mgr, headptr));
124
 
125
        /* increment the outbound free head */
126
        headptr += 4;
127
        if( headptr >= (MSG_OUTBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) )
128
                headptr = MSG_OUTBOUND_FREE_STACK;
129
 
130
        writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD));
131
 
132
 _clean_exit:
133
        spin_unlock_irqrestore(&mgr->msg_lock, flags);
134
 
135
        return err;
136
}
137
 
138
 
139
/*
140
 * send a message to miXart. return: the msg_frame used for this message
141
 */
142
/* call with mgr->msg_lock held! */
143
static int send_msg( struct mixart_mgr *mgr,
144
                     struct mixart_msg *msg,
145
                     int max_answersize,
146
                     int mark_pending,
147
                     u32 *msg_event)
148
{
149
        u32 headptr, tailptr;
150
        u32 msg_frame_address;
151
        int err, i;
152
 
153
        snd_assert(msg->size % 4 == 0, return -EINVAL);
154
 
155
        err = 0;
156
 
157
        /* get message frame address */
158
        tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
159
        headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD));
160
 
161
        if (tailptr == headptr) {
162
                snd_printk(KERN_ERR "error: no message frame available\n");
163
                return -EBUSY;
164
        }
165
 
166
        if( (tailptr < MSG_INBOUND_FREE_STACK) || (tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE))) {
167
                return -EINVAL;
168
        }
169
 
170
        msg_frame_address = readl_be(MIXART_MEM(mgr, tailptr));
171
        writel(0, MIXART_MEM(mgr, tailptr)); /* set address to zero on this fifo position */
172
 
173
        /* increment the inbound free tail */
174
        tailptr += 4;
175
        if( tailptr >= (MSG_INBOUND_FREE_STACK+MSG_BOUND_STACK_SIZE) )
176
                tailptr = MSG_INBOUND_FREE_STACK;
177
 
178
        writel_be(tailptr, MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
179
 
180
        /* TODO : use memcpy_toio() with intermediate buffer to copy the message */
181
 
182
        /* copy message descriptor to card memory */
183
        writel_be( msg->size + MSG_DESCRIPTOR_SIZE,      MIXART_MEM(mgr, msg_frame_address) );      /* size of descriptor + request */
184
        writel_be( msg->message_id ,                     MIXART_MEM(mgr, msg_frame_address + 4) );  /* dwMessageID */
185
        writel_be( msg->uid.object_id,                   MIXART_MEM(mgr, msg_frame_address + 8) );  /* uidDest */
186
        writel_be( msg->uid.desc,                        MIXART_MEM(mgr, msg_frame_address + 12) ); /* */
187
        writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 16) ); /* SizeHeader */
188
        writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 20) ); /* OffsetDLL_T16 */
189
        writel_be( msg->size,                            MIXART_MEM(mgr, msg_frame_address + 24) ); /* SizeDLL_T16 */
190
        writel_be( MSG_DESCRIPTOR_SIZE,                  MIXART_MEM(mgr, msg_frame_address + 28) ); /* OffsetDLL_DRV */
191
        writel_be( 0,                                    MIXART_MEM(mgr, msg_frame_address + 32) ); /* SizeDLL_DRV */
192
        writel_be( MSG_DESCRIPTOR_SIZE + max_answersize, MIXART_MEM(mgr, msg_frame_address + 36) ); /* dwExpectedAnswerSize */
193
 
194
        /* copy message data to card memory */
195
        for( i=0; i < msg->size; i+=4 ) {
196
                writel_be( *(u32*)(msg->data + i), MIXART_MEM(mgr, MSG_HEADER_SIZE + msg_frame_address + i)  );
197
        }
198
 
199
        if( mark_pending ) {
200
                if( *msg_event ) {
201
                        /* the pending event is the notification we wait for ! */
202
                        mgr->pending_event = *msg_event;
203
                }
204
                else {
205
                        /* the pending event is the answer we wait for (same address than the request)! */
206
                        mgr->pending_event = msg_frame_address;
207
 
208
                        /* copy address back to caller */
209
                        *msg_event = msg_frame_address;
210
                }
211
        }
212
 
213
        /* mark the frame as a request (will have an answer) */
214
        msg_frame_address |= MSG_TYPE_REQUEST;
215
 
216
        /* post the frame */
217
        headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
218
 
219
        if( (headptr < MSG_INBOUND_POST_STACK) || (headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE))) {
220
                return -EINVAL;
221
        }
222
 
223
        writel_be(msg_frame_address, MIXART_MEM(mgr, headptr));
224
 
225
        /* increment the inbound post head */
226
        headptr += 4;
227
        if( headptr >= (MSG_INBOUND_POST_STACK+MSG_BOUND_STACK_SIZE) )
228
                headptr = MSG_INBOUND_POST_STACK;
229
 
230
        writel_be(headptr, MIXART_MEM(mgr, MSG_INBOUND_POST_HEAD));
231
 
232
        return 0;
233
}
234
 
235
 
236
int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int max_resp_size, void *resp_data)
237
{
238
        struct mixart_msg resp;
239
        u32 msg_frame = 0; /* set to 0, so it's no notification to wait for, but the answer */
240
        int err;
241
        wait_queue_t wait;
242
        long timeout;
243
 
244
        mutex_lock(&mgr->msg_mutex);
245
 
246
        init_waitqueue_entry(&wait, current);
247
 
248
        spin_lock_irq(&mgr->msg_lock);
249
        /* send the message */
250
        err = send_msg(mgr, request, max_resp_size, 1, &msg_frame);  /* send and mark the answer pending */
251
        if (err) {
252
                spin_unlock_irq(&mgr->msg_lock);
253
                mutex_unlock(&mgr->msg_mutex);
254
                return err;
255
        }
256
 
257
        set_current_state(TASK_UNINTERRUPTIBLE);
258
        add_wait_queue(&mgr->msg_sleep, &wait);
259
        spin_unlock_irq(&mgr->msg_lock);
260
        timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
261
        remove_wait_queue(&mgr->msg_sleep, &wait);
262
 
263
        if (! timeout) {
264
                /* error - no ack */
265
                mutex_unlock(&mgr->msg_mutex);
266
                snd_printk(KERN_ERR "error: no reponse on msg %x\n", msg_frame);
267
                return -EIO;
268
        }
269
 
270
        /* retrieve the answer into the same struct mixart_msg */
271
        resp.message_id = 0;
272
        resp.uid = (struct mixart_uid){0,0};
273
        resp.data = resp_data;
274
        resp.size = max_resp_size;
275
 
276
        err = get_msg(mgr, &resp, msg_frame);
277
 
278
        if( request->message_id != resp.message_id )
279
                snd_printk(KERN_ERR "REPONSE ERROR!\n");
280
 
281
        mutex_unlock(&mgr->msg_mutex);
282
        return err;
283
}
284
 
285
 
286
int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
287
                                   struct mixart_msg *request, u32 notif_event)
288
{
289
        int err;
290
        wait_queue_t wait;
291
        long timeout;
292
 
293
        snd_assert(notif_event != 0, return -EINVAL);
294
        snd_assert((notif_event & MSG_TYPE_MASK) == MSG_TYPE_NOTIFY, return -EINVAL);
295
        snd_assert((notif_event & MSG_CANCEL_NOTIFY_MASK) == 0, return -EINVAL);
296
 
297
        mutex_lock(&mgr->msg_mutex);
298
 
299
        init_waitqueue_entry(&wait, current);
300
 
301
        spin_lock_irq(&mgr->msg_lock);
302
        /* send the message */
303
        err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 1, &notif_event);  /* send and mark the notification event pending */
304
        if(err) {
305
                spin_unlock_irq(&mgr->msg_lock);
306
                mutex_unlock(&mgr->msg_mutex);
307
                return err;
308
        }
309
 
310
        set_current_state(TASK_UNINTERRUPTIBLE);
311
        add_wait_queue(&mgr->msg_sleep, &wait);
312
        spin_unlock_irq(&mgr->msg_lock);
313
        timeout = schedule_timeout(MSG_TIMEOUT_JIFFIES);
314
        remove_wait_queue(&mgr->msg_sleep, &wait);
315
 
316
        if (! timeout) {
317
                /* error - no ack */
318
                mutex_unlock(&mgr->msg_mutex);
319
                snd_printk(KERN_ERR "error: notification %x not received\n", notif_event);
320
                return -EIO;
321
        }
322
 
323
        mutex_unlock(&mgr->msg_mutex);
324
        return 0;
325
}
326
 
327
 
328
int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request)
329
{
330
        u32 message_frame;
331
        unsigned long flags;
332
        int err;
333
 
334
        /* just send the message (do not mark it as a pending one) */
335
        spin_lock_irqsave(&mgr->msg_lock, flags);
336
        err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
337
        spin_unlock_irqrestore(&mgr->msg_lock, flags);
338
 
339
        /* the answer will be handled by snd_struct mixart_msgasklet()  */
340
        atomic_inc(&mgr->msg_processed);
341
 
342
        return err;
343
}
344
 
345
 
346
/* common buffer of tasklet and interrupt to send/receive messages */
347
static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4];
348
 
349
 
350
void snd_mixart_msg_tasklet(unsigned long arg)
351
{
352
        struct mixart_mgr *mgr = ( struct mixart_mgr*)(arg);
353
        struct mixart_msg resp;
354
        u32 msg, addr, type;
355
        int err;
356
 
357
        spin_lock(&mgr->lock);
358
 
359
        while (mgr->msg_fifo_readptr != mgr->msg_fifo_writeptr) {
360
                msg = mgr->msg_fifo[mgr->msg_fifo_readptr];
361
                mgr->msg_fifo_readptr++;
362
                mgr->msg_fifo_readptr %= MSG_FIFO_SIZE;
363
 
364
                /* process the message ... */
365
                addr = msg & ~MSG_TYPE_MASK;
366
                type = msg & MSG_TYPE_MASK;
367
 
368
                switch (type) {
369
                case MSG_TYPE_ANSWER:
370
                        /* answer to a message on that we did not wait for (send_msg_nonblock) */
371
                        resp.message_id = 0;
372
                        resp.data = mixart_msg_data;
373
                        resp.size = sizeof(mixart_msg_data);
374
                        err = get_msg(mgr, &resp, addr);
375
                        if( err < 0 ) {
376
                                snd_printk(KERN_ERR "tasklet: error(%d) reading mf %x\n", err, msg);
377
                                break;
378
                        }
379
 
380
                        switch(resp.message_id) {
381
                        case MSG_STREAM_START_INPUT_STAGE_PACKET:
382
                        case MSG_STREAM_START_OUTPUT_STAGE_PACKET:
383
                        case MSG_STREAM_STOP_INPUT_STAGE_PACKET:
384
                        case MSG_STREAM_STOP_OUTPUT_STAGE_PACKET:
385
                                if(mixart_msg_data[0])
386
                                        snd_printk(KERN_ERR "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", mixart_msg_data[0]);
387
                                break;
388
                        default:
389
                                snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
390
                                           msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
391
                                break;
392
                        }
393
                        break;
394
                case MSG_TYPE_NOTIFY:
395
                        /* msg contains no address ! do not get_msg() ! */
396
                case MSG_TYPE_COMMAND:
397
                        /* get_msg() necessary */
398
                default:
399
                        snd_printk(KERN_ERR "tasklet doesn't know what to do with message %x\n", msg);
400
                } /* switch type */
401
 
402
                /* decrement counter */
403
                atomic_dec(&mgr->msg_processed);
404
 
405
        } /* while there is a msg in fifo */
406
 
407
        spin_unlock(&mgr->lock);
408
}
409
 
410
 
411
irqreturn_t snd_mixart_interrupt(int irq, void *dev_id)
412
{
413
        struct mixart_mgr *mgr = dev_id;
414
        int err;
415
        struct mixart_msg resp;
416
 
417
        u32 msg;
418
        u32 it_reg;
419
 
420
        spin_lock(&mgr->lock);
421
 
422
        it_reg = readl_le(MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET));
423
        if( !(it_reg & MIXART_OIDI) ) {
424
                /* this device did not cause the interrupt */
425
                spin_unlock(&mgr->lock);
426
                return IRQ_NONE;
427
        }
428
 
429
        /* mask all interrupts */
430
        writel_le(MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG(mgr, MIXART_PCI_OMIMR_OFFSET));
431
 
432
        /* outdoorbell register clear */
433
        it_reg = readl(MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET));
434
        writel(it_reg, MIXART_REG(mgr, MIXART_PCI_ODBR_OFFSET));
435
 
436
        /* clear interrupt */
437
        writel_le( MIXART_OIDI, MIXART_REG(mgr, MIXART_PCI_OMISR_OFFSET) );
438
 
439
        /* process interrupt */
440
        while (retrieve_msg_frame(mgr, &msg)) {
441
 
442
                switch (msg & MSG_TYPE_MASK) {
443
                case MSG_TYPE_COMMAND:
444
                        resp.message_id = 0;
445
                        resp.data = mixart_msg_data;
446
                        resp.size = sizeof(mixart_msg_data);
447
                        err = get_msg(mgr, &resp, msg & ~MSG_TYPE_MASK);
448
                        if( err < 0 ) {
449
                                snd_printk(KERN_ERR "interrupt: error(%d) reading mf %x\n", err, msg);
450
                                break;
451
                        }
452
 
453
                        if(resp.message_id == MSG_SERVICES_TIMER_NOTIFY) {
454
                                int i;
455
                                struct mixart_timer_notify *notify;
456
                                notify = (struct mixart_timer_notify *)mixart_msg_data;
457
 
458
                                for(i=0; i<notify->stream_count; i++) {
459
 
460
                                        u32 buffer_id = notify->streams[i].buffer_id;
461
                                        unsigned int chip_number =  (buffer_id & MIXART_NOTIFY_CARD_MASK) >> MIXART_NOTIFY_CARD_OFFSET; /* card0 to 3 */
462
                                        unsigned int pcm_number  =  (buffer_id & MIXART_NOTIFY_PCM_MASK ) >> MIXART_NOTIFY_PCM_OFFSET;  /* pcm0 to 3  */
463
                                        unsigned int sub_number  =   buffer_id & MIXART_NOTIFY_SUBS_MASK;             /* 0 to MIXART_PLAYBACK_STREAMS */
464
                                        unsigned int is_capture  = ((buffer_id & MIXART_NOTIFY_CAPT_MASK) != 0);      /* playback == 0 / capture == 1 */
465
 
466
                                        struct snd_mixart *chip  = mgr->chip[chip_number];
467
                                        struct mixart_stream *stream;
468
 
469
                                        if ((chip_number >= mgr->num_cards) || (pcm_number >= MIXART_PCM_TOTAL) || (sub_number >= MIXART_PLAYBACK_STREAMS)) {
470
                                                snd_printk(KERN_ERR "error MSG_SERVICES_TIMER_NOTIFY buffer_id (%x) pos(%d)\n",
471
                                                           buffer_id, notify->streams[i].sample_pos_low_part);
472
                                                break;
473
                                        }
474
 
475
                                        if (is_capture)
476
                                                stream = &chip->capture_stream[pcm_number];
477
                                        else
478
                                                stream = &chip->playback_stream[pcm_number][sub_number];
479
 
480
                                        if (stream->substream && (stream->status == MIXART_STREAM_STATUS_RUNNING)) {
481
                                                struct snd_pcm_runtime *runtime = stream->substream->runtime;
482
                                                int elapsed = 0;
483
                                                u64 sample_count = ((u64)notify->streams[i].sample_pos_high_part) << 32;
484
                                                sample_count |= notify->streams[i].sample_pos_low_part;
485
 
486
                                                while (1) {
487
                                                        u64 new_elapse_pos = stream->abs_period_elapsed +  runtime->period_size;
488
 
489
                                                        if (new_elapse_pos > sample_count) {
490
                                                                break; /* while */
491
                                                        }
492
                                                        else {
493
                                                                elapsed = 1;
494
                                                                stream->buf_periods++;
495
                                                                if (stream->buf_periods >= runtime->periods)
496
                                                                        stream->buf_periods = 0;
497
 
498
                                                                stream->abs_period_elapsed = new_elapse_pos;
499
                                                        }
500
                                                }
501
                                                stream->buf_period_frag = (u32)( sample_count - stream->abs_period_elapsed );
502
 
503
                                                if(elapsed) {
504
                                                        spin_unlock(&mgr->lock);
505
                                                        snd_pcm_period_elapsed(stream->substream);
506
                                                        spin_lock(&mgr->lock);
507
                                                }
508
                                        }
509
                                }
510
                                break;
511
                        }
512
                        if(resp.message_id == MSG_SERVICES_REPORT_TRACES) {
513
                                if(resp.size > 1) {
514
#ifndef __BIG_ENDIAN
515
                                        /* Traces are text: the swapped msg_data has to be swapped back ! */
516
                                        int i;
517
                                        for(i=0; i<(resp.size/4); i++) {
518
                                                (mixart_msg_data)[i] = cpu_to_be32((mixart_msg_data)[i]);
519
                                        }
520
#endif
521
                                        ((char*)mixart_msg_data)[resp.size - 1] = 0;
522
                                        snd_printdd("MIXART TRACE : %s\n", (char*)mixart_msg_data);
523
                                }
524
                                break;
525
                        }
526
 
527
                        snd_printdd("command %x not handled\n", resp.message_id);
528
                        break;
529
 
530
                case MSG_TYPE_NOTIFY:
531
                        if(msg & MSG_CANCEL_NOTIFY_MASK) {
532
                                msg &= ~MSG_CANCEL_NOTIFY_MASK;
533
                                snd_printk(KERN_ERR "canceled notification %x !\n", msg);
534
                        }
535
                        /* no break, continue ! */
536
                case MSG_TYPE_ANSWER:
537
                        /* answer or notification to a message we are waiting for*/
538
                        spin_lock(&mgr->msg_lock);
539
                        if( (msg & ~MSG_TYPE_MASK) == mgr->pending_event ) {
540
                                wake_up(&mgr->msg_sleep);
541
                                mgr->pending_event = 0;
542
                        }
543
                        /* answer to a message we did't want to wait for */
544
                        else {
545
                                mgr->msg_fifo[mgr->msg_fifo_writeptr] = msg;
546
                                mgr->msg_fifo_writeptr++;
547
                                mgr->msg_fifo_writeptr %= MSG_FIFO_SIZE;
548
                                tasklet_hi_schedule(&mgr->msg_taskq);
549
                        }
550
                        spin_unlock(&mgr->msg_lock);
551
                        break;
552
                case MSG_TYPE_REQUEST:
553
                default:
554
                        snd_printdd("interrupt received request %x\n", msg);
555
                        /* TODO : are there things to do here ? */
556
                        break;
557
                } /* switch on msg type */
558
        } /* while there are msgs */
559
 
560
        /* allow interrupt again */
561
        writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
562
 
563
        spin_unlock(&mgr->lock);
564
 
565
        return IRQ_HANDLED;
566
}
567
 
568
 
569
void snd_mixart_init_mailbox(struct mixart_mgr *mgr)
570
{
571
        writel( 0, MIXART_MEM( mgr, MSG_HOST_RSC_PROTECTION ) );
572
        writel( 0, MIXART_MEM( mgr, MSG_AGENT_RSC_PROTECTION ) );
573
 
574
        /* allow outbound messagebox to generate interrupts */
575
        if(mgr->irq >= 0) {
576
                writel_le( MIXART_ALLOW_OUTBOUND_DOORBELL, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
577
        }
578
        return;
579
}
580
 
581
void snd_mixart_exit_mailbox(struct mixart_mgr *mgr)
582
{
583
        /* no more interrupts on outbound messagebox */
584
        writel_le( MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
585
        return;
586
}
587
 
588
void snd_mixart_reset_board(struct mixart_mgr *mgr)
589
{
590
        /* reset miXart */
591
        writel_be( 1, MIXART_REG(mgr, MIXART_BA1_BRUTAL_RESET_OFFSET) );
592
        return;
593
}

powered by: WebSVN 2.1.0

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