1/*
2 * Copyright (C) 2004-2010 NXP Software
3 * Copyright (C) 2010 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/****************************************************************************************/
19/*                                                                                      */
20/*    Includes                                                                          */
21/*                                                                                      */
22/****************************************************************************************/
23
24#include "LVDBE.h"
25#include "LVDBE_Private.h"
26
27/****************************************************************************************/
28/*                                                                                      */
29/* FUNCTION:                 LVDBE_Memory                                               */
30/*                                                                                      */
31/* DESCRIPTION:                                                                         */
32/*    This function is used for memory allocation and free. It can be called in         */
33/*    two ways:                                                                         */
34/*                                                                                      */
35/*        hInstance = NULL                Returns the memory requirements               */
36/*        hInstance = Instance handle        Returns the memory requirements and        */
37/*                                        allocated base addresses for the instance     */
38/*                                                                                      */
39/*    When this function is called for memory allocation (hInstance=NULL) the memory    */
40/*  base address pointers are NULL on return.                                           */
41/*                                                                                      */
42/*    When the function is called for free (hInstance = Instance Handle) the memory     */
43/*  table returns the allocated memory and base addresses used during initialisation.   */
44/*                                                                                      */
45/* PARAMETERS:                                                                          */
46/*  hInstance                Instance Handle                                            */
47/*  pMemoryTable             Pointer to an empty memory definition table                */
48/*    pCapabilities           Pointer to the instance capabilities                      */
49/*                                                                                      */
50/* RETURNS:                                                                             */
51/*  LVDBE_SUCCESS            Succeeded                                                  */
52/*                                                                                      */
53/* NOTES:                                                                               */
54/*    1.    This function may be interrupted by the LVDBE_Process function              */
55/*                                                                                      */
56/****************************************************************************************/
57
58LVDBE_ReturnStatus_en LVDBE_Memory(LVDBE_Handle_t            hInstance,
59                                   LVDBE_MemTab_t            *pMemoryTable,
60                                   LVDBE_Capabilities_t      *pCapabilities)
61{
62
63    LVM_UINT32          ScratchSize;
64    LVDBE_Instance_t    *pInstance = (LVDBE_Instance_t *)hInstance;
65
66
67    /*
68     * Fill in the memory table
69     */
70    if (hInstance == LVM_NULL)
71    {
72        /*
73         * Instance memory
74         */
75        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Size         = sizeof(LVDBE_Instance_t);
76        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Alignment    = LVDBE_INSTANCE_ALIGN;
77        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Type         = LVDBE_PERSISTENT;
78        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
79
80        /*
81         * Data memory
82         */
83        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size         = sizeof(LVDBE_Data_t);
84        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Alignment    = LVDBE_PERSISTENT_DATA_ALIGN;
85        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Type         = LVDBE_PERSISTENT_DATA;
86        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
87
88        /*
89         * Coef memory
90         */
91        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size         = sizeof(LVDBE_Coef_t);
92        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Alignment    = LVDBE_PERSISTENT_COEF_ALIGN;
93        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Type         = LVDBE_PERSISTENT_COEF;
94        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
95
96        /*
97         * Scratch memory
98         */
99        ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
100        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Size         = ScratchSize;
101        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Alignment    = LVDBE_SCRATCH_ALIGN;
102        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Type         = LVDBE_SCRATCH;
103        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
104    }
105    else
106    {
107        /* Read back memory allocation table */
108        *pMemoryTable = pInstance->MemoryTable;
109    }
110
111    return(LVDBE_SUCCESS);
112}
113
114
115/****************************************************************************************/
116/*                                                                                      */
117/* FUNCTION:                 LVDBE_Init                                                 */
118/*                                                                                      */
119/* DESCRIPTION:                                                                         */
120/*    Create and initialisation function for the Dynamic Bass Enhancement module        */
121/*                                                                                      */
122/*    This function can be used to create an algorithm instance by calling with         */
123/*    hInstance set to NULL. In this case the algorithm returns the new instance        */
124/*    handle.                                                                           */
125/*                                                                                      */
126/*    This function can be used to force a full re-initialisation of the algorithm      */
127/*    by calling with hInstance = Instance Handle. In this case the memory table        */
128/*    should be correct for the instance, this can be ensured by calling the function   */
129/*    DBE_Memory before calling this function.                                          */
130/*                                                                                      */
131/* PARAMETERS:                                                                          */
132/*  hInstance                  Instance handle                                          */
133/*  pMemoryTable             Pointer to the memory definition table                     */
134/*  pCapabilities              Pointer to the instance capabilities                     */
135/*                                                                                      */
136/* RETURNS:                                                                             */
137/*  LVDBE_SUCCESS            Initialisation succeeded                                   */
138/*  LVDBE_ALIGNMENTERROR    Instance or scratch memory on incorrect alignment           */
139/*    LVDBE_NULLADDRESS        Instance or scratch memory has a NULL pointer            */
140/*                                                                                      */
141/* NOTES:                                                                               */
142/*  1.     The instance handle is the pointer to the base address of the first memory   */
143/*        region.                                                                       */
144/*    2.    This function must not be interrupted by the LVDBE_Process function         */
145/*                                                                                      */
146/****************************************************************************************/
147
148LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t         *phInstance,
149                                   LVDBE_MemTab_t       *pMemoryTable,
150                                   LVDBE_Capabilities_t *pCapabilities)
151{
152
153    LVDBE_Instance_t      *pInstance;
154    LVMixer3_1St_st       *pMixer_Instance;
155    LVMixer3_2St_st       *pBypassMixer_Instance;
156    LVM_INT16             i;
157    LVM_INT32             MixGain;
158
159
160    /*
161     * Set the instance handle if not already initialised
162     */
163    if (*phInstance == LVM_NULL)
164    {
165        *phInstance = (LVDBE_Handle_t)pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress;
166    }
167    pInstance =(LVDBE_Instance_t  *)*phInstance;
168
169
170    /*
171     * Check the memory table for NULL pointers and incorrectly aligned data
172     */
173    for (i=0; i<LVDBE_NR_MEMORY_REGIONS; i++)
174    {
175        if (pMemoryTable->Region[i].Size!=0)
176        {
177            if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
178            {
179                return(LVDBE_NULLADDRESS);
180            }
181            if (((uintptr_t)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){
182                return(LVDBE_ALIGNMENTERROR);
183            }
184        }
185    }
186
187
188    /*
189     * Save the memory table in the instance structure
190     */
191    pInstance->Capabilities = *pCapabilities;
192
193
194    /*
195     * Save the memory table in the instance structure
196     */
197    pInstance->MemoryTable = *pMemoryTable;
198
199
200    /*
201     * Set the default instance parameters
202     */
203    pInstance->Params.CentreFrequency   =    LVDBE_CENTRE_55HZ;
204    pInstance->Params.EffectLevel       =    0;
205    pInstance->Params.HeadroomdB        =    0;
206    pInstance->Params.HPFSelect         =    LVDBE_HPF_OFF;
207    pInstance->Params.OperatingMode     =    LVDBE_OFF;
208    pInstance->Params.SampleRate        =    LVDBE_FS_8000;
209    pInstance->Params.VolumeControl     =    LVDBE_VOLUME_OFF;
210    pInstance->Params.VolumedB          =    0;
211
212
213    /*
214     * Set pointer to data and coef memory
215     */
216    pInstance->pData = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress;
217    pInstance->pCoef = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress;
218
219
220    /*
221     * Initialise the filters
222     */
223    LVDBE_SetFilters(pInstance,                 /* Set the filter taps and coefficients */
224                     &pInstance->Params);
225
226
227    /*
228     * Initialise the AGC
229     */
230    LVDBE_SetAGC(pInstance,                                     /* Set the AGC gain */
231                 &pInstance->Params);
232    pInstance->pData->AGCInstance.AGC_Gain = pInstance->pData->AGCInstance.AGC_MaxGain;
233                                                /* Default to the bass boost setting */
234
235    // initialize the mixer with some fixes values since otherwise LVDBE_SetVolume ends up
236    // reading uninitialized data
237    pMixer_Instance = &pInstance->pData->BypassVolume;
238    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],0x00007FFF,0x00007FFF);
239
240    /*
241     * Initialise the volume
242     */
243    LVDBE_SetVolume(pInstance,                                         /* Set the Volume */
244                    &pInstance->Params);
245
246    pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target;
247                                                /* Initialise as the target */
248
249    MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
250    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],MixGain,MixGain);
251
252    /* Configure the mixer process path */
253    pMixer_Instance->MixerStream[0].CallbackParam = 0;
254    pMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
255    pMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
256    pMixer_Instance->MixerStream[0].CallbackSet = 0;
257
258    /*
259     * Initialise the clicks minimisation BypassMixer
260     */
261
262    pBypassMixer_Instance = &pInstance->pData->BypassMixer;
263
264    /*
265     * Setup the mixer gain for the processed path
266     */
267    pBypassMixer_Instance->MixerStream[0].CallbackParam = 0;
268    pBypassMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
269    pBypassMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
270    pBypassMixer_Instance->MixerStream[0].CallbackSet=0;
271    LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[0],0,0);
272    LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
273        LVDBE_BYPASS_MIXER_TC,pInstance->Params.SampleRate,2);
274    /*
275     * Setup the mixer gain for the unprocessed path
276     */
277    pBypassMixer_Instance->MixerStream[1].CallbackParam = 0;
278    pBypassMixer_Instance->MixerStream[1].pCallbackHandle = LVM_NULL;
279    pBypassMixer_Instance->MixerStream[1].pCallBack = LVM_NULL;
280    pBypassMixer_Instance->MixerStream[1].CallbackSet=0;
281    LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1],0x00007FFF,0x00007FFF);
282    LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
283        LVDBE_BYPASS_MIXER_TC,pInstance->Params.SampleRate,2);
284
285    return(LVDBE_SUCCESS);
286}
287
288