source: svn/trunk/newcon3bcm2_21bu/magnum/portinginterface/ape/7552/bape_playback.c

Last change on this file was 2, checked in by jglee, 11 years ago

first commit

  • Property svn:executable set to *
File size: 27.0 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2006-2012, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bape_playback.c $
11 * $brcm_Revision: Hydra_Software_Devel/13 $
12 * $brcm_Date: 3/5/12 3:52p $
13 *
14 * Module Description: Audio Decoder Interface
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/portinginterface/ape/7422/bape_playback.c $
19 *
20 * Hydra_Software_Devel/13   3/5/12 3:52p jgarrett
21 * SW7425-2522: Handling playback watermark size > fifo size
22 *
23 * Hydra_Software_Devel/12   2/8/12 11:52a jgarrett
24 * SW7346-672: Adding support for changing the playback sample rate on the
25 * fly
26 *
27 * Hydra_Software_Devel/11   8/25/11 1:51p gskerl
28 * SW7425-1119: When trying to stop an already stopped Playback, just
29 * return (instead of trying to stop it).
30 *
31 * Hydra_Software_Devel/10   7/8/11 4:53p gskerl
32 * SW7425-321: Added printing of downstream nodes when an audio path is
33 * started (if bape_startprint is enabled)
34 *
35 * Hydra_Software_Devel/9   6/16/11 11:01a gskerl
36 * SW7425-321: Added call to BAPE_Mixer_P_PrintMixers() just before
37 * starting paths
38 *
39 * Hydra_Software_Devel/8   5/16/11 5:24p piyushg
40 * SW7425-595: Fix bus error while quitting brutus.
41 *
42 * Hydra_Software_Devel/7   5/12/11 4:39p piyushg
43 * SW7425-401: Added PCM playback support for non-interleaved and
44 * multichannel data
45 *
46 * Hydra_Software_Devel/6   4/16/11 12:15p jgarrett
47 * SW7425-371: Removing tab characters
48 *
49 * Hydra_Software_Devel/5   4/6/11 1:23a jgarrett
50 * SW35330-35: Merge to main branch
51 *
52 * Hydra_Software_Devel/SW35330-35/1   4/5/11 12:49p jgarrett
53 * SW35330-35: FMM Abstraction refactoring to support DTV
54 *
55 * Hydra_Software_Devel/4   2/28/11 1:28p jgarrett
56 * SW7422-146: Filter graph reworked to remove mixer dependencies
57 *
58 * Hydra_Software_Devel/3   2/22/11 5:43p jgarrett
59 * SW7422-146: Implemented type renaming based on filter graph review
60 * comments
61 *
62 * Hydra_Software_Devel/2   12/17/10 3:58p jgarrett
63 * SW7422-146: Nexus APE integration on 7422
64 *
65 * Hydra_Software_Devel/1   12/16/10 4:05p jgarrett
66 * SW7422-146: Initial compilable APE for 7422
67 *
68 ***************************************************************************/
69
70#include "bstd.h"
71#include "bkni.h"
72#include "bape.h"
73#include "bape_priv.h"
74#include "bchp_aud_fmm_bf_ctrl.h"
75
76BDBG_MODULE(bape_playback);
77
78BDBG_OBJECT_ID(BAPE_Playback);
79
80static void BAPE_Playback_P_ReArmWatermark(BAPE_PlaybackHandle handle);
81static BERR_Code BAPE_Playback_P_ConfigPathToOutput(BAPE_PathNode *pNode, BAPE_PathConnection *pConnection);
82static BERR_Code BAPE_Playback_P_StartPathToOutput(BAPE_PathNode *pNode, BAPE_PathConnection *pConnection);
83static void BAPE_Playback_P_StopPathToOutput(BAPE_PathNode *pNode, BAPE_PathConnection *pConnection);
84
85void BAPE_Playback_GetDefaultOpenSettings(
86    BAPE_PlaybackOpenSettings *pSettings
87    )
88{
89    BDBG_ASSERT(NULL != pSettings);
90    pSettings->numBuffers = 1;
91    pSettings->bufferSize = 128*1024;
92    pSettings->watermarkThreshold = 64*1024;
93}
94
95BERR_Code BAPE_Playback_Open(
96    BAPE_Handle deviceHandle,
97    unsigned index,
98    const BAPE_PlaybackOpenSettings *pSettings,
99    BAPE_PlaybackHandle *pHandle                    /* [out] */
100    )
101{
102    BERR_Code errCode = BERR_SUCCESS;
103    BAPE_PlaybackHandle handle;
104    BAPE_PlaybackOpenSettings defaultSettings;
105    unsigned i;
106
107    BDBG_OBJECT_ASSERT(deviceHandle, BAPE_Device);
108    BDBG_ASSERT(NULL != pHandle);
109   
110    *pHandle = NULL;
111
112    if ( NULL == pSettings )
113    {
114        BAPE_Playback_GetDefaultOpenSettings(&defaultSettings);
115        pSettings = &defaultSettings;
116    }
117
118    if ( index >= BAPE_CHIP_MAX_PLAYBACKS )
119    {
120        BDBG_ERR(("This chip only supports %u playbacks.  Cannot open playback %u", BAPE_CHIP_MAX_PLAYBACKS, index));
121        return BERR_TRACE(BERR_INVALID_PARAMETER);
122    }
123
124    if ( deviceHandle->playbacks[index] )
125    {
126        BDBG_ERR(("Playback %d already open", index));
127        return BERR_TRACE(BERR_INVALID_PARAMETER);
128    }
129
130    /* TODO: Extend for multichannel and non-interleved */
131    if ( pSettings->numBuffers > BAPE_Channel_eMax ) 
132    {
133        BDBG_ERR(("Maximum num of buffers required for multichannel non-interleved audio playback cannot exceed %u. Requested num buffers is %u", BAPE_Channel_eMax, pSettings->numBuffers));
134        return BERR_TRACE(BERR_INVALID_PARAMETER);
135    }
136
137    handle = BKNI_Malloc(sizeof(BAPE_Playback));
138    if ( NULL == handle )
139    {
140        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
141    }
142    BKNI_Memset(handle, 0, sizeof(BAPE_Playback));
143    handle->deviceHandle = deviceHandle;
144
145    for (i = 0; i < pSettings->numBuffers; i++) 
146    {
147        handle->pBuffer[i] = BMEM_AllocAligned(deviceHandle->memHandle, pSettings->bufferSize, 5, 0);
148        if ( NULL == handle->pBuffer[i] )
149        {
150            errCode = BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
151            goto err_buffer_alloc;
152        }
153    }
154
155    handle->bufferSize = pSettings->bufferSize;
156    if ( pSettings->watermarkThreshold >= pSettings->bufferSize )
157    {
158        BDBG_WRN(("playback watermark threshold %u is larger than the buffer size %u.  Reducing to %u.", pSettings->watermarkThreshold, pSettings->bufferSize, pSettings->bufferSize / 2));
159        handle->threshold = pSettings->bufferSize / 2;
160    }
161    else
162    {
163        handle->threshold = pSettings->watermarkThreshold;
164    }
165    handle->index = index;
166    handle->numBuffers = pSettings->numBuffers;
167    handle->settings.multichannelFormat = BAPE_MultichannelFormat_e2_0;
168    handle->settings.compressedData = false;
169    handle->settings.sampleRate = 44100;
170    BAPE_P_InitPathNode(&handle->node, BAPE_PathNodeType_ePlayback, 0, 1, deviceHandle, handle);
171    BKNI_Snprintf(handle->name, sizeof(handle->name), "Playback %u", index);
172    handle->node.pName = handle->name;
173    handle->node.paths[0].connector.numChannelPairs = 1;
174    handle->node.paths[0].connector.dataSource = BAPE_DataSource_eHostBuffer;
175    handle->node.paths[0].connector.sampleRate = 44100;
176    /* Init node callbacks */
177    handle->node.configPathToOutput = BAPE_Playback_P_ConfigPathToOutput;
178    handle->node.startPathToOutput = BAPE_Playback_P_StartPathToOutput;
179    handle->node.stopPathToOutput = BAPE_Playback_P_StopPathToOutput;
180    BDBG_OBJECT_SET(handle, BAPE_Playback);
181    *pHandle = handle;
182    deviceHandle->playbacks[index] = handle;
183
184    return errCode;
185
186    err_buffer_alloc:
187    for (i = 0; i < pSettings->numBuffers; i++) 
188    {
189        if ( NULL != handle->pBuffer[i] )
190        {
191                        BDBG_ERR(("Hello Are you kidding me"));
192            BMEM_Free(handle->deviceHandle->memHandle, handle->pBuffer[i]);
193        }
194    }
195    return errCode;
196}
197
198void BAPE_Playback_Close(
199    BAPE_PlaybackHandle handle
200    )
201{
202    unsigned i;
203
204    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
205    if ( handle->running )
206    {
207        BDBG_WRN(("Stopping playback %p (%d) on close", handle, handle->index));
208        BAPE_Playback_Stop(handle);
209    }
210
211    /* Disconnect from all mixers, post-processors, and groups */
212    BAPE_Connector_P_RemoveAllConnections(&handle->node.paths[0].connector);
213
214    for (i = 0; i < handle->numBuffers; i++)
215    {
216        if (handle->pBuffer[i]) 
217        {
218            BMEM_Free(handle->deviceHandle->memHandle, handle->pBuffer[i]);
219        }
220    }
221
222    handle->deviceHandle->playbacks[handle->index] = NULL;
223    BDBG_OBJECT_DESTROY(handle, BAPE_Playback);
224    BKNI_Free(handle);
225}
226
227void BAPE_Playback_GetSettings(
228    BAPE_PlaybackHandle handle,
229    BAPE_PlaybackSettings *pSettings    /* [out] */
230    )
231{
232    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
233    BDBG_ASSERT(NULL != pSettings);
234
235    *pSettings = handle->settings;
236}
237
238BERR_Code BAPE_Playback_SetSettings(
239    BAPE_PlaybackHandle handle,
240    const BAPE_PlaybackSettings *pSettings
241    )
242{
243    BERR_Code errCode = BERR_SUCCESS;
244
245    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
246    BDBG_ASSERT(NULL != pSettings);
247
248    /* If we're already running, return error */
249    if ( handle->running )
250    {
251        if ( handle->settings.multichannelFormat != pSettings->multichannelFormat ||
252             handle->settings.compressedData != handle->settings.compressedData )
253        {
254            BDBG_ERR(("Playback %p (%d) is already running.  Cannot data format.", handle, handle->index));
255            return BERR_TRACE(BERR_NOT_SUPPORTED);
256        }
257       
258        if ( handle->startSettings.sampleRate == 0 && handle->settings.sampleRate != pSettings->sampleRate )       
259        {
260            if ( pSettings->sampleRate == 0 )
261            {
262                BDBG_ERR(("Can not use sample rate of 0."));
263                return BERR_TRACE(BERR_INVALID_PARAMETER);
264            }
265            /* Update Sample Rate */
266            BKNI_EnterCriticalSection();
267            handle->node.paths[0].connector.sampleRate = pSettings->sampleRate;
268            BAPE_Connector_P_SampleRateChange_isr(&handle->node.paths[0].connector);
269            BKNI_LeaveCriticalSection();
270        }
271    }
272    else
273    {
274        if ( pSettings->compressedData == true && pSettings->multichannelFormat != BAPE_MultichannelFormat_e2_0 ) 
275        {
276            return BERR_TRACE(BERR_INVALID_PARAMETER);
277        }
278   
279        switch ( pSettings->multichannelFormat ) 
280        {
281        case BAPE_MultichannelFormat_e2_0:
282            handle->node.paths[0].connector.numChannelPairs = 1;
283            break;
284        case BAPE_MultichannelFormat_e5_1:
285            handle->node.paths[0].connector.numChannelPairs = 3;
286            break;
287        case BAPE_MultichannelFormat_e7_1:
288            handle->node.paths[0].connector.numChannelPairs = 4;
289            break;
290        default:
291            return BERR_TRACE(BERR_INVALID_PARAMETER);
292        }
293   
294        handle->node.paths[0].connector.compressed = pSettings->compressedData;
295        errCode = BAPE_Connector_P_FormatChange(&handle->node.paths[BAPE_ConnectorFormat_eStereo].connector);
296        if ( errCode )
297        {
298            errCode = BERR_TRACE(errCode);
299        }
300    }
301
302    handle->settings = *pSettings;
303    return BERR_SUCCESS;
304}
305
306void BAPE_Playback_GetDefaultStartSettings(
307    BAPE_PlaybackStartSettings *pSettings       /* [out] */
308    )
309{
310    BDBG_ASSERT(NULL != pSettings);
311    pSettings->sampleRate = 44100;
312    pSettings->bitsPerSample = 16;
313    pSettings->isStereo = true;
314    pSettings->isSigned = true;
315    pSettings->reverseEndian = false;
316    pSettings->loopEnabled = false;
317    pSettings->startThreshold = 0;
318    pSettings->interleaved = true;
319}
320
321BERR_Code BAPE_Playback_Start(
322    BAPE_PlaybackHandle handle,
323    const BAPE_PlaybackStartSettings *pSettings
324    )
325{
326    BERR_Code errCode;
327    unsigned numBuffers;
328    unsigned sampleRate;
329
330    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
331    BDBG_ASSERT(NULL != pSettings);
332
333    /* If we're already running, return error */
334    if ( handle->running )
335    {
336        BDBG_ERR(("Playback %p (%d) is already running.  Can't start.", handle, handle->index));
337        return BERR_TRACE(BERR_NOT_SUPPORTED);
338    }
339
340    /* Sanity Checks */
341    numBuffers = (pSettings->interleaved == true)?handle->node.paths[0].connector.numChannelPairs: 2 * handle->node.paths[0].connector.numChannelPairs;
342    if ( numBuffers > handle->numBuffers )
343    {
344        BDBG_ERR(("%u buffers are required for the current data format but only %u have been allocated", numBuffers, handle->numBuffers));
345        return BERR_TRACE(BERR_NOT_SUPPORTED);
346    }
347   
348    if ( 0 == pSettings->sampleRate )
349    {
350        sampleRate = handle->settings.sampleRate;
351        if ( 0 == sampleRate )
352        {   
353            BDBG_ERR(("To use a variable sample rate, you must specify a valid rate in BAPE_PlaybackSettings.sampleRate."));
354            return BERR_TRACE(BERR_INVALID_PARAMETER);
355        }
356    }
357    else
358    {
359        sampleRate = pSettings->sampleRate;
360    }
361
362    switch ( pSettings->bitsPerSample )
363    {
364    case 8:
365    case 16:
366    case 32:
367        break;
368    default:
369        BDBG_ERR(("Unsupported bits per sample.  Only 8/16/32 are supported."));
370        return BERR_TRACE(BERR_INVALID_PARAMETER);
371    }
372
373    BDBG_MSG(("Playback %p (%d) Starting", handle, handle->index));
374
375    /* Save start settings */
376    handle->startSettings = *pSettings;
377
378    /* Update data format and sample rate in connector */
379    handle->node.paths[0].connector.sampleRate = sampleRate;
380
381    /* Build Paths  */
382    errCode = BAPE_PathNode_P_AcquirePathResources(&handle->node);
383    if ( errCode )
384    {
385        errCode = BERR_TRACE(errCode);
386        goto err_acquire_resources;
387    }
388
389    /* Prepare network to start */
390    errCode = BAPE_PathNode_P_ConfigurePathResources(&handle->node);
391    if ( errCode )
392    {
393        errCode = BERR_TRACE(errCode);
394        goto err_configure_resources;
395    }
396
397    if ( NULL == handle->pMaster )
398    {
399        BDBG_ERR(("No outputs have been connected to this input capture."));
400        goto err_no_master;
401    }
402
403    /* Install the interrupt handler */
404    if ( handle->interrupts.watermark.pCallback_isr )
405    {
406        errCode = BAPE_SfifoGroup_P_SetFreemarkInterrupt(handle->pMaster->sfifoGroup,
407                                                         handle->interrupts.watermark.pCallback_isr,
408                                                         handle->interrupts.watermark.pParam1,
409                                                         handle->interrupts.watermark.param2);       
410        if ( errCode )
411        {
412            errCode = BERR_TRACE(errCode);
413            goto err_watermark;
414        }
415    }   
416
417    #if BDBG_DEBUG_BUILD
418        BAPE_Mixer_P_PrintMixers(handle->deviceHandle);
419    #endif
420
421    /* Start */
422    errCode = BAPE_PathNode_P_StartPaths(&handle->node);
423    if ( errCode )
424    {
425        errCode = BERR_TRACE(errCode);
426        goto err_start_paths;
427    }
428
429    #if BDBG_DEBUG_BUILD
430        BAPE_Mixer_P_PrintDownstreamNodes(&handle->node);
431    #endif
432
433    /* Success */
434    BDBG_MSG(("Playback %p (%d) Start Successful", handle, handle->index));
435    handle->running = true;
436    BAPE_Playback_P_ReArmWatermark(handle);
437    return BERR_SUCCESS;
438
439err_start_paths:
440    /* Remove the interrupt handler */
441    (void)BAPE_SfifoGroup_P_SetFreemarkInterrupt(handle->pMaster->sfifoGroup, NULL, NULL, 0);
442err_watermark:
443err_no_master:
444    BAPE_PathNode_P_ReleasePathResources(&handle->node);
445err_configure_resources:
446err_acquire_resources:
447    return errCode;
448}
449
450void BAPE_Playback_Stop(
451    BAPE_PlaybackHandle handle
452    )
453{
454    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
455   
456    if ( !handle->running )
457    {
458        BDBG_MSG(("Playback %p (%d) already stopped.", handle, handle->index));
459        return;
460    }
461
462    /* Stop Paths Downstream */
463    BAPE_PathNode_P_StopPaths(&handle->node);
464   
465    /* Remove the interrupt handler */   
466    if ( handle->pMaster && handle->interrupts.watermark.pCallback_isr )
467    {
468        (void)BAPE_SfifoGroup_P_SetFreemarkInterrupt(handle->pMaster->sfifoGroup, NULL, NULL, 0);
469    }
470
471    /* Clear the started flag and flush the buffer */
472    handle->running = false;
473    handle->bufferDepth = 0;
474    handle->pMaster = NULL;
475}
476
477void BAPE_Playback_Flush(
478    BAPE_PlaybackHandle handle
479    )
480{
481    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
482
483    if ( handle->running )
484    {
485        BDBG_ASSERT(NULL != handle->pMaster);
486        BAPE_SfifoGroup_P_Flush(handle->pMaster->sfifoGroup);
487    }
488
489    handle->bufferDepth = 0;
490}
491
492BERR_Code BAPE_Playback_GetBuffer(
493    BAPE_PlaybackHandle handle,
494    BAPE_BufferDescriptor *pBuffers      /* [out] */
495    )
496{   
497    BERR_Code errCode = BERR_SUCCESS;
498    unsigned i;
499
500    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
501    BDBG_ASSERT(NULL != pBuffers);
502
503    BDBG_MSG(("Playback %p (%d) GetBuffer", handle, handle->index));
504
505    BKNI_Memset(pBuffers, 0, sizeof(BAPE_BufferDescriptor));
506   
507    if ( handle->running && !handle->startSettings.loopEnabled )
508    {
509        BDBG_ASSERT(NULL != handle->pMaster);
510        BAPE_SfifoGroup_P_GetBuffer(handle->pMaster->sfifoGroup, pBuffers);
511    }
512    else
513    {
514        /* TODO: Handle non-interleaved and multichannel */
515        pBuffers->numBuffers = handle->node.paths[0].connector.numChannelPairs * 2;
516        pBuffers->interleaved = handle->startSettings.interleaved;
517        pBuffers->bufferSize = handle->bufferSize - handle->bufferDepth;
518
519        if ( pBuffers->bufferSize )
520        {
521            if ( pBuffers->interleaved ) 
522            {
523                for ( i = 0; i < handle->node.paths[0].connector.numChannelPairs; i++) 
524                {
525                    pBuffers->buffers[i*2].pBuffer = (void *)((unsigned)handle->pBuffer[i] + handle->bufferDepth);
526                }
527            }
528            else
529            {
530                for ( i = 0; i < handle->node.paths[0].connector.numChannelPairs; i++) 
531                {
532                    pBuffers->buffers[i*2].pBuffer = (void *)((unsigned)handle->pBuffer[i] + handle->bufferDepth);
533                    pBuffers->buffers[i*2 + 1].pBuffer = (void *)((unsigned)handle->pBuffer[i] + handle->bufferDepth);
534                }
535            }
536        }
537    }
538
539    if ( errCode )
540    {
541        return BERR_TRACE(errCode);
542    }
543
544    return errCode;
545}
546
547BERR_Code BAPE_Playback_CommitData(
548    BAPE_PlaybackHandle handle,
549    unsigned numBytes                   /* Number of bytes written into the buffer */
550    )
551{
552    BERR_Code errCode;
553
554    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
555   
556    if ( handle->running )
557    {
558        BDBG_ASSERT(NULL != handle->pMaster);
559        errCode = BAPE_SfifoGroup_P_CommitData(handle->pMaster->sfifoGroup, numBytes);
560        if ( errCode )
561        {
562            return BERR_TRACE(errCode);
563        }
564    }
565    else
566    {
567        if ( numBytes + handle->bufferDepth > handle->bufferSize )
568        {
569            BDBG_ERR(("Invalid number of bytes passed."));
570            return BERR_TRACE(BERR_INVALID_PARAMETER);
571        }
572        handle->bufferDepth += numBytes;
573    }
574
575    if ( handle->pMaster )
576    {
577        BAPE_SfifoGroup_P_RearmFreemarkInterrupt(handle->pMaster->sfifoGroup);
578    }
579
580    return BERR_SUCCESS;
581}
582
583void BAPE_Playback_GetStatus(
584    BAPE_PlaybackHandle handle,
585    BAPE_PlaybackStatus *pStatus    /* [out] */
586    )
587{
588    BERR_Code errCode;
589   
590    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
591    BDBG_ASSERT(NULL != pStatus);
592   
593    BKNI_Memset(pStatus, 0, sizeof(*pStatus));
594    pStatus->fifoSize = handle->bufferSize;
595   
596    if ( !handle->running )
597    {
598        return;
599    }
600   
601    /* If running, query the SFIFO */
602    BDBG_ASSERT(NULL != handle->pMaster);
603    errCode = BAPE_SfifoGroup_P_GetQueuedBytes(handle->pMaster->sfifoGroup, &pStatus->queuedBytes);
604    if ( errCode )
605    {
606        (void)BERR_TRACE(errCode);
607        return;
608    }
609}
610
611void BAPE_Playback_GetConnector(
612    BAPE_PlaybackHandle handle,
613    BAPE_Connector *pConnector /* [out] */
614    )
615{
616    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
617    *pConnector = &handle->node.paths[0].connector;
618}
619
620void BAPE_Playback_GetInterruptHandlers(
621    BAPE_PlaybackHandle handle,
622    BAPE_PlaybackInterruptHandlers *pInterrupts     /* [out] */
623    )
624{
625    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
626    BDBG_ASSERT(NULL != pInterrupts);
627    *pInterrupts = handle->interrupts;
628}
629
630BERR_Code BAPE_Playback_SetInterruptHandlers(
631    BAPE_PlaybackHandle handle,
632    const BAPE_PlaybackInterruptHandlers *pInterrupts
633    )
634{
635    BERR_Code errCode;
636    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
637    BDBG_ASSERT(NULL != pInterrupts);
638
639    if ( handle->running )
640    {
641        errCode = BAPE_SfifoGroup_P_SetFreemarkInterrupt(handle->pMaster->sfifoGroup,
642                                                         pInterrupts->watermark.pCallback_isr,
643                                                         pInterrupts->watermark.pParam1,
644                                                         pInterrupts->watermark.param2);
645        if ( errCode )
646        {
647            return BERR_TRACE(errCode);
648        }
649    }
650
651    /* These aren't actually used by the interrupt directly, so no need for critical section here. */
652    handle->interrupts = *pInterrupts;
653
654    return BERR_SUCCESS;
655}
656
657static void BAPE_Playback_P_ReArmWatermark(BAPE_PlaybackHandle handle)
658{
659    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
660
661    if ( handle->running )
662    {
663        BDBG_ASSERT(NULL != handle->pMaster);
664        BAPE_SfifoGroup_P_RearmFreemarkInterrupt(handle->pMaster->sfifoGroup);
665    }
666}
667
668static BERR_Code BAPE_Playback_P_ConfigPathToOutput(BAPE_PathNode *pNode, BAPE_PathConnection *pConnection)
669{
670    BAPE_PathConnector *pSource;
671    BAPE_PlaybackHandle handle;
672    BAPE_PathNode *pSink;
673    BERR_Code errCode;
674    unsigned offset;
675    unsigned chPairs;
676    unsigned i;
677
678    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
679    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
680    BDBG_OBJECT_ASSERT(pConnection->pSource, BAPE_PathConnector);
681    BDBG_OBJECT_ASSERT(pConnection->pSink, BAPE_PathNode);
682
683    handle = pNode->pHandle;
684    BDBG_OBJECT_ASSERT(handle, BAPE_Playback);
685
686    pSource = pConnection->pSource;
687    pSink = pConnection->pSink;
688
689    if ( pConnection->sfifoGroup )
690    {
691        BAPE_SfifoGroupSettings sfifoSettings;
692
693        /* Dropping into the FMM - Configure the SFIFO(s) */
694        if ( NULL == handle->pMaster )
695        {
696            handle->pMaster = pConnection;
697        }
698
699        BAPE_SfifoGroup_P_GetSettings(pConnection->sfifoGroup, &sfifoSettings);
700        sfifoSettings.highPriority = (handle->node.paths[0].connector.sampleRate >= 96000)?1:0;
701        sfifoSettings.dataWidth = handle->startSettings.bitsPerSample;
702        sfifoSettings.reverseEndian = handle->startSettings.reverseEndian;
703        sfifoSettings.sampleRepeatEnabled = handle->node.paths[0].connector.compressed?false:true;       /* TODO: Set to false if compressed */
704        sfifoSettings.loopAround = handle->startSettings.loopEnabled;
705        sfifoSettings.wrpointEnabled = false;
706        if ( handle->startSettings.startThreshold > 0 )
707        {
708            if ( handle->startSettings.loopEnabled )
709            {
710                BDBG_WRN(("Playback start threshold is not compatible with the loop setting.  Disabling startThreshold."));
711            }
712            else
713            {
714                sfifoSettings.wrpointEnabled = true;
715            }
716        }
717        /* TODO: Add support for non-interleaved */
718        sfifoSettings.interleaveData = handle->startSettings.interleaved;
719        sfifoSettings.stereoData = handle->startSettings.isStereo;
720        sfifoSettings.signedData = handle->startSettings.isSigned;
721        if ( pConnection != handle->pMaster )
722        {
723            BDBG_MSG(("Linking playback source channel group %#x to master %#x", pConnection->sfifoGroup, handle->pMaster->sfifoGroup));
724            sfifoSettings.master = handle->pMaster->sfifoGroup;
725        }
726        else
727        {
728            sfifoSettings.master = NULL;
729        }
730
731        chPairs = handle->node.paths[0].connector.numChannelPairs;
732        /* Setup Buffers */
733        for ( i = 0; i < chPairs; i++) 
734        {
735            if ( sfifoSettings.interleaveData) 
736            {
737                errCode = BMEM_ConvertAddressToOffset(handle->deviceHandle->memHandle, handle->pBuffer[i*2], &offset);
738                BDBG_ASSERT(BERR_SUCCESS == errCode);
739                sfifoSettings.bufferInfo[i].base = offset;
740                sfifoSettings.bufferInfo[i].writeOffset = handle->bufferDepth;
741                sfifoSettings.bufferInfo[i].length = handle->bufferSize;
742                sfifoSettings.bufferInfo[i].watermark = handle->threshold;
743                if ( handle->startSettings.startThreshold > handle->bufferSize )
744                {
745                    BDBG_WRN(("Start threshold is too large.  Starting with buffer full."));
746                    sfifoSettings.bufferInfo[i].wrpoint = offset + handle->bufferSize - 1;
747                }
748                else if ( handle->startSettings.startThreshold > 0 )
749                {
750                    sfifoSettings.bufferInfo[i].wrpoint = offset + handle->startSettings.startThreshold-1;
751                }
752                else
753                {
754                    sfifoSettings.bufferInfo[i].wrpoint = 0;
755                }
756            }
757            else
758            {
759                errCode = BMEM_ConvertAddressToOffset(handle->deviceHandle->memHandle, handle->pBuffer[i*2], &offset);
760                BDBG_ASSERT(BERR_SUCCESS == errCode);
761                sfifoSettings.bufferInfo[i*2].base = offset;
762                sfifoSettings.bufferInfo[i*2].writeOffset = handle->bufferDepth;
763                sfifoSettings.bufferInfo[i*2].length = handle->bufferSize;
764                sfifoSettings.bufferInfo[i*2].watermark = handle->threshold;
765                if ( handle->startSettings.startThreshold > handle->bufferSize )
766                {
767                    BDBG_WRN(("Start threshold is too large.  Starting with buffer full."));
768                    sfifoSettings.bufferInfo[i*2].wrpoint = offset + handle->bufferSize - 1;
769                }
770                else if ( handle->startSettings.startThreshold > 0 )
771                {
772                    sfifoSettings.bufferInfo[i*2].wrpoint = offset + handle->startSettings.startThreshold-1;
773                }
774                else
775                {
776                    sfifoSettings.bufferInfo[i*2].wrpoint = 0;
777                }
778
779                errCode = BMEM_ConvertAddressToOffset(handle->deviceHandle->memHandle, handle->pBuffer[(i*2) + 1], &offset);
780                BDBG_ASSERT(BERR_SUCCESS == errCode);
781                sfifoSettings.bufferInfo[i*2 + 1].base = offset;
782                sfifoSettings.bufferInfo[i*2 + 1].writeOffset = handle->bufferDepth;
783                sfifoSettings.bufferInfo[i*2 + 1].length = handle->bufferSize;
784                sfifoSettings.bufferInfo[i*2 + 1].watermark = handle->threshold;
785                if ( handle->startSettings.startThreshold > handle->bufferSize )
786                {
787                    BDBG_WRN(("Start threshold is too large.  Starting with buffer full."));
788                    sfifoSettings.bufferInfo[i*2 + 1].wrpoint = offset + handle->bufferSize - 1;
789                }
790                else if ( handle->startSettings.startThreshold > 0 )
791                {
792                    sfifoSettings.bufferInfo[i*2 + 1].wrpoint = offset + handle->startSettings.startThreshold-1;
793                }
794                else
795                {
796                    sfifoSettings.bufferInfo[i*2 + 1].wrpoint = 0;
797                }
798            }
799        }
800        BAPE_SfifoGroup_P_SetSettings(pConnection->sfifoGroup, &sfifoSettings);
801    }
802    /* Other nodes don't require anything done here */
803
804    return BERR_SUCCESS;   
805}
806
807static BERR_Code BAPE_Playback_P_StartPathToOutput(BAPE_PathNode *pNode, BAPE_PathConnection *pConnection)
808{
809    BERR_Code errCode;
810    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
811    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
812    if ( pConnection->sfifoGroup )
813    {
814        errCode = BAPE_SfifoGroup_P_Start(pConnection->sfifoGroup, false);
815        if ( errCode )
816        {
817            return BERR_TRACE(errCode);
818        }
819    }
820    return BERR_SUCCESS;
821}
822
823static void BAPE_Playback_P_StopPathToOutput(BAPE_PathNode *pNode, BAPE_PathConnection *pConnection)
824{
825    BSTD_UNUSED(pNode);
826    if ( pConnection->sfifoGroup )
827    {
828        BAPE_SfifoGroup_P_Stop(pConnection->sfifoGroup);
829    }
830}
831
Note: See TracBrowser for help on using the repository browser.