source: svn/trunk/newcon3bcm2_21bu/dta/src/settop_api/bsettop_pcm.c

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

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 12.3 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2003-2006, 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:  $
11 * $brcm_Revision:  $
12 * $brcm_Date: $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log:  $
19 *
20 ***************************************************************************/
21#include "bsettop_pcm.h"
22#include "ministd.h"
23#include "bstd.h"
24#if (BCHP_CHIP!=7552)
25#include "brap.h"
26#include "brap_dspchn.h"
27#endif
28#include "gist.h"
29#include "cache_util.h"
30
31BDBG_MODULE(pcm);
32
33struct bpcm_play
34{
35        unsigned index;
36        pcm_play_state_t state;
37        bdisplay_t display;
38        bpcm_play_settings settings;
39#if (BCHP_CHIP!=7552)
40        BRAP_ChannelHandle hRapPcmPbCh;
41        BRAP_PcmBufInfo pcmBufInfo;
42#endif
43};
44
45struct bpcm_play s_pcm[BPCM_PLAYBACK_CHANNELS] = 
46{ 
47        {
48                0,
49                ePCM_PLAY_STATE_CLOSED,
50                NULL,
51                { /* bpcm_play_settings */
52                        { 16, 48000, 2}, /* bpcm_settings */
53                        NULL, 
54                        NULL
55                },
56#if (BCHP_CHIP!=7552)
57                NULL,
58                { 
59                        { NULL,NULL,NULL,NULL,0,0,0 },
60                        { NULL,NULL,NULL,NULL,0,0,0 }
61                }
62#endif
63        }
64};
65
66#if (BCHP_CHIP!=7552)
67extern void boutput_remove_decode_association(BRAP_ChannelHandle hRapCh);
68extern void boutput_add_decode_association(BRAP_ChannelHandle hRapCh);
69#endif
70static bresult b_pcm_rap_open(bpcm_play_t pcmplay
71                                                                        )
72{
73#if (BCHP_CHIP!=7552)
74    BRAP_ChannelSettings    chSettings;
75    BERR_Code err = BERR_SUCCESS;
76
77    /* Get default settings and parameters for this DEC channel */
78    err = BRAP_GetDefaultChannelSettings(GetRAP(), &chSettings);
79    if (err != BERR_SUCCESS)
80    {
81        BDBG_ERR(("Get Decode Channel Default Settings failed for PCM PB Channel id %d", pcmplay->index));
82        return BERR_TRACE(err);
83    }
84
85    chSettings.eChType       = BRAP_ChannelType_ePcmPlayback;
86    chSettings.eChSubType    = BRAP_ChannelSubType_eNone;
87
88        /*  OpenTimeMem testing */     
89        chSettings.sChnRBufPool.uiMaxNumInChPairs[0]=0;
90        chSettings.sChnRBufPool.uiMaxNumOutChPairs[0]=0;
91        chSettings.sChnRBufPool.uiMaxNumRBuf=2;
92        chSettings.sChnRBufPool.sBufSettings.pLeftBufferStart=NULL;
93        chSettings.sChnRBufPool.sBufSettings.pRightBufferStart=NULL;
94        chSettings.sChnRBufPool.sBufSettings.uiSize=0;
95        chSettings.sChnRBufPool.sBufSettings.uiWaterMark=0;
96        chSettings.bOpenTimeWrToRbuf = true;
97 
98    /* Open the RAP Decode Channel */
99        err = BRAP_OpenChannel(GetRAP(), &(pcmplay->hRapPcmPbCh), &(chSettings));
100        if (BERR_SUCCESS != err)
101        {
102                printf ("\n BRAP_Open_Channel Failure %x", err);
103        return BERR_TRACE(err);
104        }
105        boutput_add_decode_association(pcmplay->hRapPcmPbCh);
106
107    return err;
108#else
109        return b_ok;
110#endif
111}
112static bresult b_pcm_rap_close(bpcm_play_t pcmplay
113                                                                        )
114{
115#if (BCHP_CHIP!=7552)
116        BERR_Code err;
117        boutput_remove_decode_association(pcmplay->hRapPcmPbCh);
118        err = BRAP_CloseChannel(pcmplay->hRapPcmPbCh);
119        pcmplay->hRapPcmPbCh = NULL;
120        return err;
121#else
122        return b_ok;
123#endif
124}
125static void
126b_pcm_stop(bpcm_play_t pcmplay)
127{
128#if (BCHP_CHIP!=7552)
129        unsigned int flags;
130        flags = bos_enter_critical();
131        if (pcmplay->hRapPcmPbCh)
132        {
133                BRAP_StopChannel(pcmplay->hRapPcmPbCh);
134        }
135        pcmplay->state = ePCM_PLAY_STATE_STOPPED;
136        bos_exit_critical(flags);
137        return;
138#endif
139}
140
141#if 0
142static bool
143b_pcm_check_underflow(bpcm_play_t pcmplay, uint32_t read_offset)
144{
145        return false;
146}
147
148/****************************************************************
149* INPUTS:       data - opaque data reference
150* OUTPUTS:      None
151* RETURNS:      None
152* FUNCTION: process audio interrupts
153****************************************************************/
154static void bpcm_isr(void *data)
155{
156        //bpcm_play_t pcmplay = (bpcm_play_t)data;
157}
158#endif
159
160/*
161Summary:
162        Open a PCM playback channel.
163*/
164bpcm_play_t bpcm_play_open(
165                                                  bobject_t id                            /* id corresponds to the pcm playback channel. */
166                                                  )
167{
168#if (BCHP_CHIP!=7552)
169        unsigned int flags;
170        bpcm_play_t pcmplay;
171
172        if (id >= BPCM_PLAYBACK_CHANNELS)
173        {
174                BDBG_ERR(("%s: Invalid channel id specified (must be less than %d)!\n", __FUNCTION__, BPCM_PLAYBACK_CHANNELS));
175                return(bpcm_play_t)NULL;
176        }
177
178        pcmplay = &s_pcm[id];
179
180        flags = bos_enter_critical();
181        if (pcmplay->state > ePCM_PLAY_STATE_CLOSED)
182        {
183                bos_exit_critical(flags);
184                BDBG_ERR(("PCM%d: Playback channel is already open!\n", id));
185                return(bpcm_play_t)NULL;
186        }
187        bos_exit_critical(flags);
188
189        /* Check to see whether we have any playback channel already initialised */
190        flags = bos_enter_critical();
191        if (b_pcm_rap_open(pcmplay) == b_ok)
192        {       
193                pcmplay->state = ePCM_PLAY_STATE_OPENED;
194        }
195        else
196                pcmplay = NULL;
197        bos_exit_critical(flags);
198
199        return pcmplay;
200#else
201        return NULL;
202#endif
203}
204
205/*
206Summary:
207        Close a PCM playback channel.
208Description:
209        Playback must already be stopped.
210*/
211void bpcm_play_close(
212                                        bpcm_play_t pcmplay
213                                        )
214{
215        unsigned int flags;
216
217        BDBG_ASSERT(pcmplay);
218
219        b_pcm_stop(pcmplay);
220
221        flags = bos_enter_critical();
222        b_pcm_rap_close(pcmplay);
223        pcmplay->state = ePCM_PLAY_STATE_CLOSED;
224
225        bos_exit_critical(flags);
226}
227
228static bresult b_pcm_start( bpcm_play_t pcmplay)
229{
230#if (BCHP_CHIP!=7552)
231        BERR_Code err;
232        unsigned flags;
233        BRAP_ChannelParams sChParams;
234        flags = bos_enter_critical();
235        if (pcmplay->state == ePCM_PLAY_STATE_STARTED)
236        {
237                bos_exit_critical(flags);
238                return BERR_INVALID_PARAMETER;
239        }
240
241        /* Get default parameters for a RAP Decode channel start operation */
242        err = BRAP_GetDefaultChannelParams(pcmplay->hRapPcmPbCh, &sChParams);
243        BDBG_ASSERT(err == BERR_SUCCESS);
244       
245    /* Now store the user params properly into sPbChInfo[uiCurPbChId].sPbParams */
246    if (pcmplay->settings.pcm.bits_per_sample == 8)
247                sChParams.eInputBitsPerSample = BRAP_InputBitsPerSample_e8;
248        else if (pcmplay->settings.pcm.bits_per_sample == 16)
249                sChParams.eInputBitsPerSample = BRAP_InputBitsPerSample_e16;
250
251        if (pcmplay->settings.pcm.channels != 2)
252                sChParams.eBufDataMode = BRAP_BufDataMode_eMono;
253        else
254                sChParams.eBufDataMode = BRAP_BufDataMode_eStereoInterleaved;
255
256        sChParams.bLoopAroundEn = true;   
257
258        if (pcmplay->settings.pcm.sample_rate == 32000)
259                sChParams.eInputSR = BAVC_AudioSamplingRate_e32k;
260        else if (pcmplay->settings.pcm.sample_rate == 44100)
261                sChParams.eInputSR = BAVC_AudioSamplingRate_e44_1k;
262        else if (pcmplay->settings.pcm.sample_rate == 48000)
263                sChParams.eInputSR = BAVC_AudioSamplingRate_e48k;
264
265        sChParams.bPlayback = true;
266
267        /* Start RAP Playback operation */
268        err = BRAP_StartChannel(pcmplay->hRapPcmPbCh, &sChParams);
269        if(err != BERR_SUCCESS)
270        {
271                BDBG_ERR(("RAP Decode Channel %d Start failed", pcmplay->index));
272                bos_exit_critical(flags);
273                return BERR_TRACE(err);
274        }
275        pcmplay->state = ePCM_PLAY_STATE_STARTED;
276
277        bos_exit_critical(flags);
278#endif
279        return b_ok;
280}
281
282/*
283Summary:
284        Start playing PCM audio.
285*/
286
287bresult bpcm_play_start(
288                                           bpcm_play_t pcmplay,
289                                           bdisplay_t display,                             /* which output to play to. */
290                                           bpcm_play_settings *settings
291                                           )
292{
293#if (BCHP_CHIP!=7552)
294        unsigned flags;
295        BERR_Code err;
296        BRAP_ChannelConfigParams sChConfigParams;
297        BDBG_ASSERT(pcmplay);
298
299        flags = bos_enter_critical();
300
301        if (pcmplay->state != ePCM_PLAY_STATE_OPENED)
302        {
303                bos_exit_critical(flags);
304                return BERR_INVALID_PARAMETER;
305        }
306
307        memcpy(&(pcmplay->settings),settings,sizeof(bpcm_play_settings));
308        pcmplay->display = display;
309
310                /* Get the default decoder configuration parameter */
311        err = BRAP_GetDefaultChannelConfig(pcmplay->hRapPcmPbCh, BRAP_DSPCHN_AudioType_ePcm, &sChConfigParams);
312        BDBG_ASSERT(err == BERR_SUCCESS);
313
314        sChConfigParams.uChConfigParams.sDecConfigParams.eOutputMode = BRAP_OutputMode_e2_0;
315        sChConfigParams.uChConfigParams.sDecConfigParams.bOutputLfeOn = true;
316        err = BRAP_SetChannelConfig(pcmplay->hRapPcmPbCh, &sChConfigParams);
317        BDBG_ASSERT(err == BERR_SUCCESS);
318
319        bos_exit_critical(flags);
320#endif
321        return b_ok;
322}
323
324/*
325Summary:
326        Get status information.
327*/
328bresult bpcm_play_get_status(
329                                                        bpcm_play_t pcmplay,
330                                                        bpcm_play_status *status /* [out] */
331                                                        )
332{
333#if (BCHP_CHIP!=7552)
334        unsigned int flags;
335        BERR_Code err;
336        BRAP_PcmBufInfo pcmBufInfo;
337
338        BDBG_ASSERT(pcmplay);
339        BKNI_Memset(status,0,sizeof(bpcm_play_status));
340        flags = bos_enter_critical();
341        status->state = pcmplay->state;
342        status->index = pcmplay->index;
343        if ((pcmplay->state == ePCM_PLAY_STATE_OPENED) || (pcmplay->state == ePCM_PLAY_STATE_STARTED))
344        {
345                /* Get the ring buffer info */
346                err = BRAP_PB_GetBufInfo(pcmplay->hRapPcmPbCh, &(pcmBufInfo));
347                if(err != BERR_SUCCESS)
348                {
349                        bos_exit_critical(flags);
350                        return BERR_TRACE(err);
351                }
352                status->fifo_size = (uint32_t)pcmplay->pcmBufInfo.sLtOrSnglBufInfo.pEndPtr - 
353                                                                (uint32_t)pcmplay->pcmBufInfo.sLtOrSnglBufInfo.pBasePtr;
354                status->queued_bytes = status->fifo_size - pcmBufInfo.sLtOrSnglBufInfo.uiTotalSize ;
355                status->buffer_base = pcmBufInfo.sLtOrSnglBufInfo.pBasePtr;
356        }
357        bos_exit_critical(flags);
358#endif
359        return b_ok;
360}
361
362/**
363Summary:
364Get space available in the pcm playback buffer.
365
366Description:
367This is a non-destructive call. You can call it as many times as you want.
368After writing data into the buffer, you should call bpcm_play_write_complete
369to report how much of the buffer was used.
370**/
371bresult bpcm_play_get_buffer(
372                                                        bpcm_play_t pcmplay,
373                                                        void **data,
374                                                        size_t *length
375                                                        )
376{
377#if (BCHP_CHIP!=7552)
378        unsigned int flags;
379        BRAP_PcmBufInfo pcmBufInfo;
380        BERR_Code err;
381
382        BDBG_ASSERT(pcmplay);
383
384        flags = bos_enter_critical();
385
386        *length = 0;*data = NULL;
387        if ((pcmplay->state != ePCM_PLAY_STATE_STARTED) && (pcmplay->state != ePCM_PLAY_STATE_OPENED))
388        {
389                bos_exit_critical(flags);
390                return BERR_TRACE(BERR_INVALID_PARAMETER);
391        }
392        else
393        {
394                /* Get the ring buffer info */
395                err = BRAP_PB_GetBufInfo(pcmplay->hRapPcmPbCh, &(pcmBufInfo));
396                if(err != BERR_SUCCESS)
397                {
398                        bos_exit_critical(flags);
399                        return BERR_TRACE(err);
400                }
401                *data = pcmBufInfo.sLtOrSnglBufInfo.pWritePtr;
402                *length = pcmBufInfo.sLtOrSnglBufInfo.uiContiguousSize;
403        }
404        bos_exit_critical(flags);
405#endif
406        return b_ok;
407}
408
409/**
410Summary:
411**/
412bresult bpcm_play_write_complete(
413                                                                bpcm_play_t pcmplay,
414                                                                size_t amount_written
415                                                                )
416{
417#if (BCHP_CHIP!=7552)
418        unsigned int flags;
419        BRAP_PcmBufSzUpdt       pcmBufSzUpdt;
420        BERR_Code err;
421        BDBG_ASSERT(pcmplay);
422
423        flush_dcache((uint32_t)pcmplay->pcmBufInfo.sLtOrSnglBufInfo.pWritePtr, 
424                                 (uint32_t)pcmplay->pcmBufInfo.sLtOrSnglBufInfo.pWritePtr + amount_written);
425        flags = bos_enter_critical();
426        pcmBufSzUpdt.uiLtOrSnglBufSzUpdt = amount_written;
427        pcmBufSzUpdt.uiRtBufSzUpdt = 0;
428        err = BRAP_PB_UpdateBufUsg(pcmplay->hRapPcmPbCh,&pcmBufSzUpdt);
429        err = BRAP_PB_BufferWriteDone(pcmplay->hRapPcmPbCh);
430        bos_exit_critical(flags);
431
432        /* we do a started check within that function */
433        if (pcmplay->state == ePCM_PLAY_STATE_OPENED)
434        {
435                b_pcm_start(pcmplay);
436        }
437#endif
438        return b_ok;
439}
440
441/*
442Summary:
443Stop PCM playback
444*/
445bresult bpcm_play_stop(
446                                          bpcm_play_t pcmplay
447                                          )
448{
449
450        BDBG_ASSERT(BPCM_PLAYBACK_CHANNELS);
451
452        b_pcm_stop(pcmplay);
453
454        return b_ok;
455}
456
457static void
458b_pcm_nocallback(void *context)
459{
460        return;
461}
462
463void 
464bpcm_play_settings_init(bpcm_play_settings *settings, bpcm_play_t pcmplay)
465{
466        settings->pcm.bits_per_sample = 16;
467        settings->pcm.sample_rate = 48000;
468        settings->pcm.channels = 2;
469        settings->callback_context = NULL;
470        settings->callback = b_pcm_nocallback;
471        return;
472}
473
474#ifdef CONFIG_PCM_TEST
475#include "bsettop.h"
476#include "bsettop_hdmi.h"
477void square_wave(char* ptr,int samples)
478{
479        int i;
480        for (i = 0; i < samples; i +=8)
481        {
482                ptr[i] = 0xF1;
483                ptr[i+1] = 0xF1;
484                ptr[i+2] = 0xF1;
485                ptr[i+3] = 0xF1;
486
487                ptr[i+4] = 0;
488                ptr[i+5] = 0;
489                ptr[i+6] = 0;
490                ptr[i+7] = 0;
491        }
492}
493
494void 
495bpcm_play_test(void)
496{
497        bpcm_play_settings settings;
498        bpcm_play_t pcmplay;
499        size_t length;
500        void *write_ptr;
501        bdisplay_t display;
502        bsettop_hdmi_t hdmi;
503        bresult rc;
504        int cnt = 0xFFFF;
505
506        bsettop_init(0);
507
508        display = bdisplay_open(0);
509        BDBG_ASSERT(display);
510        rc = bsettop_hdmi_open(&hdmi,display);
511        BDBG_ASSERT(rc == b_ok);
512        pcmplay = bpcm_play_open(0);
513        BDBG_ASSERT(pcmplay);
514        bpcm_play_settings_init(&settings,pcmplay);
515
516        settings.pcm.bits_per_sample = 8;
517        settings.pcm.sample_rate = 48000;
518        settings.pcm.channels = 1;
519
520        /* only works for 1 channel 8 bps */
521        bpcm_play_start(pcmplay,NULL,&settings);
522
523        while (cnt--)
524        {
525                if (bpcm_play_get_buffer(pcmplay,&write_ptr,&length) == b_ok)
526                {
527                        square_wave((char*)write_ptr,length);
528                        bpcm_play_write_complete(pcmplay,length);
529                }
530                else
531                {
532                        BDBG_WRN(("bpcm_play_get_buffer failed %d",cnt)); 
533                }
534        }
535
536        return;
537}
538#endif
Note: See TracBrowser for help on using the repository browser.