/** * abe_write_fifo * @mem_bank: currently only ABE_DMEM supported * @addr: FIFO descriptor address ( descriptor fields : READ ptr, WRITE ptr, * FIFO START_ADDR, FIFO END_ADDR) * @data: data to write to FIFO * @number: number of 32-bit words to write to DMEM FIFO * * write DMEM FIFO and update FIFO descriptor, * it is assumed that FIFO descriptor is located in DMEM */ void abe_write_fifo(u32 memory_bank, u32 descr_addr, u32 *data, u32 nb_data32) { u32 fifo_addr[4]; u32 i; /* read FIFO descriptor from DMEM */ abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, descr_addr, &fifo_addr[0], 4 * sizeof(u32)); /* WRITE ptr < FIFO start address */ if (fifo_addr[1] < fifo_addr[2]) abe_dbg_error_log(ABE_FW_FIFO_WRITE_PTR_ERR); /* WRITE ptr > FIFO end address */ if (fifo_addr[1] > fifo_addr[3]) abe_dbg_error_log(ABE_FW_FIFO_WRITE_PTR_ERR); switch (memory_bank) { case ABE_DMEM: for (i = 0; i < nb_data32; i++) { abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, (s32) fifo_addr[1], (u32 *) (data + i), 4); /* increment WRITE pointer */ fifo_addr[1] = fifo_addr[1] + 4; if (fifo_addr[1] > fifo_addr[3]) fifo_addr[1] = fifo_addr[2]; if (fifo_addr[1] == fifo_addr[0]) abe_dbg_error_log(ABE_FW_FIFO_WRITE_PTR_ERR); } /* update WRITE pointer in DMEM */ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, descr_addr + sizeof(u32), &fifo_addr[1], 4); break; default: break; } }
/* * ABE_WRITE_EVENT_GENERATOR * * Parameter : * e: Event Generation Counter, McPDM, DMIC or default. * * Operations : * load the AESS event generator hardware source. Loads the firmware parameters * accordingly. Indicates to the FW which data stream is the most important to preserve * in case all the streams are asynchronous. If the parameter is "default", let the HAL * decide which Event source is the best appropriate based on the opened ports. * * When neither the DMIC and the McPDM are activated the AE will have its EVENT generator programmed * with the EVENT_COUNTER. The event counter will be tuned in order to deliver a pulse frequency higher * than 96 kHz. The DPLL output at 100% OPP is MCLK = (32768kHz x6000) = 196.608kHz * The ratio is (MCLK/96000)+(1<<1) = 2050 * (1<<1) in order to have the same speed at 50% and 100% OPP (only 15 MSB bits are used at OPP50%) * * Return value : * None. */ void abe_write_event_generator(abe_event_id e) { abe_uint32 event, selection, counter, start; _lock_enter _log(id_write_event_generator,e,0,0) counter = EVENT_GENERATOR_COUNTER_DEFAULT; start = EVENT_GENERATOR_ON; abe_current_event_id = e; switch (e) { case EVENT_MCPDM: selection = EVENT_SOURCE_DMA; event = ABE_ATC_MCPDMDL_DMA_REQ; break; case EVENT_DMIC: selection = EVENT_SOURCE_DMA; event = ABE_ATC_DMIC_DMA_REQ; break; case EVENT_TIMER: selection = EVENT_SOURCE_COUNTER; event = 0; break; case EVENT_McBSP: selection = EVENT_SOURCE_COUNTER; event = 0; break; case EVENT_McASP: selection = EVENT_SOURCE_COUNTER; event = 0; break; case EVENT_SLIMBUS: selection = EVENT_SOURCE_COUNTER; event = 0; break; case EVENT_44100: selection = EVENT_SOURCE_COUNTER; event = 0; counter = EVENT_GENERATOR_COUNTER_44100; break; case EVENT_DEFAULT: selection = EVENT_SOURCE_COUNTER; event = 0; break; default: abe_dbg_param |= ERR_API; abe_dbg_error_log(ABE_BLOCK_COPY_ERR); } abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, EVENT_GENERATOR_COUNTER, &counter, 4); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, EVENT_SOURCE_SELECTION, &selection, 4); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, EVENT_GENERATOR_START, &start, 4); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, AUDIO_ENGINE_SCHEDULER, &event, 4); _lock_exit }
/* * ABE_IRQ_PROCESSING * * Parameter : * No parameter * * Operations : * This subroutine is call upon reception of "MA_IRQ_99 ABE_MPU_IRQ" ABE interrupt * This subroutine will check the IRQ_FIFO from the AE and act accordingly. * Some IRQ source are originated for the delivery of "end of time sequenced tasks" * notifications, some are originated from the Ping-Pong protocols, some are generated from * the embedded debugger when the firmware stops on programmable break-points, etc … * * Return value : * None. */ void abe_irq_processing(void) { abe_uint32 clear_abe_irq; abe_uint32 abe_irq_dbg_write_ptr, i, cmem_src, sm_cm = 0; abe_irq_data_t IRQ_data; _lock_enter _log(id_irq_processing,0,0,0) #define IrqFiFoMask ((D_McuIrqFifo_sizeof >> 2) - 1) /* extract the write pointer index from CMEM memory (INITPTR format) */ /* CMEM address of the write pointer in bytes */ cmem_src = MCU_IRQ_FIFO_ptr_labelID * 4; abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_CMEM, cmem_src, (abe_uint32*)&abe_irq_dbg_write_ptr, sizeof (abe_irq_dbg_write_ptr)); abe_irq_dbg_write_ptr = sm_cm >> 16; /* AESS left-pointer index located on MSBs */ abe_irq_dbg_write_ptr &= 0xFF; /* loop on the IRQ FIFO content */ for (i = 0; i < D_McuIrqFifo_sizeof; i++) { /* stop when the FIFO is empty */ if (abe_irq_dbg_write_ptr == abe_irq_dbg_read_ptr) break; /* read the IRQ/DBG FIFO */ abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, D_McuIrqFifo_ADDR + (i << 2), (abe_uint32 *)&IRQ_data, sizeof (IRQ_data)); abe_irq_dbg_read_ptr = (abe_irq_dbg_read_ptr + 1) & IrqFiFoMask; /* select the source of the interrupt */ switch (IRQ_data.tag) { case IRQtag_APS: _log(id_irq_processing,(abe_uint32)(IRQ_data.data),0,1) abe_irq_aps (IRQ_data.data); break; case IRQtag_PP: _log(id_irq_processing,0,0,2) abe_irq_ping_pong (); break; case IRQtag_COUNT: _log(id_irq_processing,(abe_uint32)(IRQ_data.data),0,3) abe_irq_check_for_sequences (IRQ_data.data); break; default: break; } } abe_monitoring(); clear_abe_irq = 1; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, ABE_MCU_IRQSTATUS, &clear_abe_irq, 4); _lock_exit }
/* * ABE_SET_DMIC_FILTER * * Parameter : * DMIC decimation ratio : 16/25/32/40 * * Operations : * Loads in CMEM a specific list of coefficients depending on the DMIC sampling * frequency (2.4MHz or 3.84MHz). This table compensates the DMIC decimator roll-off at 20kHz. * The default table is loaded with the DMIC 2.4MHz recommended configuration. * * Return value : * None. */ void abe_set_dmic_filter(abe_dmic_ratio_t d) { abe_int32 *src; _lock_enter _log(id_set_dmic_filter,d,0,0) switch(d) { case ABE_DEC16: src = (abe_int32 *)abe_dmic_16; break; case ABE_DEC25: src = (abe_int32 *) abe_dmic_25; break; case ABE_DEC32: src = (abe_int32 *) abe_dmic_32; break; default: case ABE_DEC40: src = (abe_int32 *) abe_dmic_40; break; } abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, C_98_48_LP_Coefs_ADDR, (abe_uint32 *)src, C_98_48_LP_Coefs_sizeof << 2); _lock_exit }
/** * abe_1616_irq_pingpong_player_1616bits * * generates data for the cache-flush buffer MODE 16+16 BITS * Return value: * None. */ void abe_1616_irq_pingpong_player_1616bits_441(void) { #if ENABLE_DEFAULT_PLAYERS /* ping-pong access to MM_DL at 44.1kHz stereo 1616 with 20ms packet sizes, 2205Hz */ static s32 idx; u32 i, dst, n_samples, n_bytes; s32 temp[N_SAMPLES_MAX], audio_sample; #define DATA_SIZE 20 const s32 audio_pattern[DATA_SIZE] = { 0, 2531, 4815, 6627, 7791, 8192, 7791, 6627, 4815, 2531, 0, -2531, -4815, -6627, -7791, -8192, -7791, -6627, -4815, -2531 }; /* read the address of the Pong buffer */ abe_read_next_ping_pong_buffer(MM_DL_PORT, &dst, &n_bytes); /* each stereo sample weights 4 bytes (format 16+16) */ n_samples = n_bytes / 4; /* generate a test pattern */ for (i = 0; i < n_samples; i++) { /* circular addressing */ audio_sample = audio_pattern[idx]; idx = (idx >= (DATA_SIZE - 1)) ? 0 : (idx + 1); temp[i] = (audio_sample << 16) | (audio_sample & 0x0000FFFF); //temp[i] = (i << 16)| ((i )& 0x0000FFFF); } abe_set_ping_pong_buffer(MM_DL_PORT, 0); /* copy the pattern (flush it) to DMEM pointer update * not necessary here because the buffer size do not * change from one ping to the other pong */ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, dst, (u32 *) &(temp[0]), n_bytes); abe_set_ping_pong_buffer(MM_DL_PORT, n_bytes); #endif }
/** * abe_1616_irq_pingpong_player_1616bits * * generates data for the cache-flush buffer MODE 16+16 BITS * Return value: * None. */ void abe_1616_irq_pingpong_player_1616bits(void) { #if ENABLE_DEFAULT_PLAYERS /* ping-pong access to MM_DL at 48kHz Mono with 20ms packet sizes */ static s32 idx; u32 i, dst, n_samples, n_bytes; s32 temp[N_SAMPLES_MAX], audio_sample; #define DATA_SIZE 20 /* t = [0:N-1]/N; x = round(16383*sin(2*pi*t)) */ const s32 audio_pattern[DATA_SIZE] = { 0, 5063, 9630, 13254, 15581, 16383, 15581, 13254, 9630, 5063, 0, -5063, -9630, -13254, -15581, -16383, -15581, -13254, -9630, -5063 }; /* read the address of the Pong buffer */ abe_read_next_ping_pong_buffer(MM_DL_PORT, &dst, &n_bytes); /* each stereo sample weights 4 bytes (format 16+16) */ n_samples = n_bytes / 4; /* generate a test pattern */ for (i = 0; i < n_samples; i++) { /* circular addressing */ audio_sample = audio_pattern[idx]; idx = (idx >= (DATA_SIZE - 1)) ? 0 : (idx + 1); temp[i] = (audio_sample << 16) | (audio_sample & 0x0000FFFF); } abe_set_ping_pong_buffer(MM_DL_PORT, 0); /* copy the pattern (flush it) to DMEM pointer update * not necessary here because the buffer size do not * change from one ping to the other pong */ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, dst, (u32 *) &(temp[0]), n_bytes); abe_set_ping_pong_buffer(MM_DL_PORT, n_bytes); #endif }
/* * ABE_READ_NEXT_PING_PONG_BUFFER * * Parameter : * Port_ID : * Returned address to the next buffer (byte offset from DMEM start) * * Operations : * Tell the next base address of the next ping_pong Buffer and its size * * */ void abe_read_next_ping_pong_buffer(abe_port_id port, abe_uint32 *p, abe_uint32 *n) { abe_uint32 sio_pp_desc_address; ABE_SPingPongDescriptor desc_pp; _lock_enter _log(id_read_next_ping_pong_buffer,port,0,0) /* ping_pong is only supported on MM_DL */ if (port != MM_DL_PORT) { abe_dbg_param |= ERR_API; abe_dbg_error_log(ABE_PARAMETER_ERROR); } /* read the port SIO descriptor and extract the current pointer address after reading the counter */ sio_pp_desc_address = D_PingPongDesc_ADDR; abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, sio_pp_desc_address, (abe_uint32*)&desc_pp, sizeof(ABE_SPingPongDescriptor)); if ((desc_pp.counter & 0x1) == 0) { (*p) = desc_pp.nextbuff0_BaseAddr; } else { (*p) = desc_pp.nextbuff1_BaseAddr; } /* translates the number of samples in bytes */ (*n) = abe_size_pingpong; _lock_exit }
/* * ABE_SET_SEQUENCE_TIME_ACCURACY * * Parameter : * patch bit field used to guarantee the code compatibility without conditionnal compilation * Sequence index * * Operations : two counters are implemented in the firmware: * - one "fast" counter, generating an IRQ to the HAL for sequences scheduling, the rate is in the range 1ms .. 100ms * - one "slow" counter, generating an IRQ to the HAL for the management of ASRC drift, the rate is in the range 1s .. 100s * * Return value : * None. */ void abe_set_sequence_time_accuracy(abe_micros_t fast, abe_micros_t slow) { abe_uint32 data; _lock_enter _log(id_set_sequence_time_accuracy,fast,slow,0) data = minimum(MAX_UINT16, (abe_uint32) fast / FW_SCHED_LOOP_FREQ_DIV1000); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_fastCounter_ADDR, (abe_uint32 *)&data, sizeof (data)); data = minimum(MAX_UINT16, (abe_uint32) slow / FW_SCHED_LOOP_FREQ_DIV1000); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_slowCounter_ADDR, (abe_uint32 *)&data, sizeof (data)); _lock_exit }
/* * ABE_SET_PING_PONG_BUFFER * * Parameter : * Port_ID : * New data * * Operations : * Updates the next ping-pong buffer with "size" bytes copied from the * host processor. This API notifies the FW that the data transfer is done. */ void abe_set_ping_pong_buffer(abe_port_id port, abe_uint32 n_bytes) { abe_uint32 sio_pp_desc_address, struct_offset, *src, n_samples, datasize, base_and_size; ABE_SPingPongDescriptor desc_pp; _lock_enter _log(id_set_ping_pong_buffer,port,n_bytes,n_bytes>>8) /* ping_pong is only supported on MM_DL */ if (port != MM_DL_PORT) { abe_dbg_param |= ERR_API; abe_dbg_error_log(ABE_PARAMETER_ERROR); } /* translates the number of bytes in samples */ /* data size in DMEM words */ datasize = abe_dma_port_iter_factor(&((abe_port[port]).format)); /* data size in bytes */ datasize = datasize << 2; n_samples = n_bytes / datasize; abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, D_PingPongDesc_ADDR, (abe_uint32 *)&desc_pp, sizeof(desc_pp)); /* * read the port SIO descriptor and extract the current pointer * address after reading the counter */ if ((desc_pp.counter & 0x1) == 0) { struct_offset = (abe_uint32)&(desc_pp.nextbuff0_BaseAddr) - (abe_uint32)&(desc_pp); base_and_size = desc_pp.nextbuff0_BaseAddr; } else { struct_offset = (abe_uint32)&(desc_pp.nextbuff1_BaseAddr) - (abe_uint32)&(desc_pp); base_and_size = desc_pp.nextbuff1_BaseAddr; } base_and_size = (base_and_size & 0xFFFFL) + ((abe_uint32)n_samples << 16); sio_pp_desc_address = D_PingPongDesc_ADDR + struct_offset; src = &base_and_size; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, sio_pp_desc_address, (abe_uint32 *)&base_and_size, sizeof(abe_uint32)); _lock_exit }
/* * ABE_SET_OPP_PROCESSING * * Parameter : * New processing network and OPP: * 0: Ultra Lowest power consumption audio player (no post-processing, no mixer) * 1: OPP 25% (simple multimedia features, including low-power player) * 2: OPP 50% (multimedia and voice calls) * 3: OPP100% (EANC, multimedia complex use-cases) * * Operations : * Rearranges the FW task network to the corresponding OPP list of features. * The corresponding AE ports are supposed to be set/reset accordingly before this switch. * * Return value : * error code when the new OPP do not corresponds the list of activated features */ void abe_set_opp_processing(abe_opp_t opp) { abe_uint32 dOppMode32, sio_desc_address; ABE_SIODescriptor desc; _lock_enter _log(id_set_opp_processing,opp,0,0) switch(opp){ case ABE_OPP25: /* OPP25% */ dOppMode32 = DOPPMODE32_OPP25; break; case ABE_OPP50: /* OPP50% */ dOppMode32 = DOPPMODE32_OPP50; break; default: abe_dbg_param |= ERR_API; abe_dbg_error_log(ABE_BLOCK_COPY_ERR); case ABE_OPP100: /* OPP100% */ dOppMode32 = DOPPMODE32_OPP100; break; } /* Write Multiframe inside DMEM */ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_maxTaskBytesInSlot_ADDR, &dOppMode32, sizeof(abe_uint32)); sio_desc_address = dmem_port_descriptors + (MM_DL_PORT * sizeof(ABE_SIODescriptor)); abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, sio_desc_address, (abe_uint32*)&desc, sizeof (desc)); if (dOppMode32 == DOPPMODE32_OPP100) desc.smem_addr1 = smem_mm_dl_opp100; /* ASRC input buffer, size 40 */ else desc.smem_addr1 = smem_mm_dl_opp25; /* at OPP 25/50 or without ASRC */ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, sio_desc_address, (abe_uint32*)&desc, sizeof (desc)); _lock_exit }
/* * ABE_HW_CONFIGURATION * * Parameter : * * Operations : * * * Return value : * */ void abe_hw_configuration() { abe_uint32 atc_reg; abe_port_protocol_t *protocol; abe_data_format_t format; /* initializes the ABE ATC descriptors in DMEM - MCPDM_UL */ protocol = &(abe_port[PDM_UL_PORT].protocol); format = abe_port[PDM_UL_PORT].format; abe_init_atc(PDM_UL_PORT); abe_init_io_tasks(PDM_UL_PORT, &format, protocol); /* initializes the ABE ATC descriptors in DMEM - MCPDM_DL */ protocol = &(abe_port[PDM_DL1_PORT].protocol); format = abe_port[PDM_DL1_PORT].format; abe_init_atc(PDM_DL1_PORT); abe_init_io_tasks(PDM_DL1_PORT, &format, protocol); /* one DMIC port enabled = all DMICs enabled, since there is a single DMIC path for all DMICs */ protocol = &(abe_port[DMIC_PORT1].protocol); format = abe_port[DMIC_PORT1].format; abe_init_atc(DMIC_PORT1); abe_init_io_tasks(DMIC_PORT1, &format, protocol); /* enables the DMAreq from AESS AESS_DMAENABLE_SET = 255 */ atc_reg = 0xFF; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, 0x60, &atc_reg, 4); #if 0 /* let the EVENT be configured once the ports are already programmed */ /* enables EVENT_GENERATOR_START=6C from McPDM */ atc_reg = 0x01; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, 0x6C, &atc_reg, 4); // set McPDM_DL as EVENT_SOURCE_SELECTION event = 0L; // source = DMAreq abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, 0x70, &event, 4); event = 2L; // source = MCPDM_DL to AUDIO_ENGINE_SCHEDULER abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, 0x74, &event, 4); #endif }
/** * abe_dbg_log - Log ABE trace inside circular buffer * @x: data to be logged * @y: data to be logged * @z: data to be logged * @t: data to be logged * Parameter : * * abe_dbg_activity_log : global circular buffer holding the data * abe_dbg_activity_log_write_pointer : circular write pointer * * saves data in the log file */ void abe_dbg_log(u32 x, u32 y, u32 z, u32 t) { u32 time_stamp, data; if (abe_dbg_activity_log_write_pointer >= (D_DEBUG_HAL_TASK_sizeof - 2)) abe_dbg_activity_log_write_pointer = 0; /* copy in DMEM trace buffer and CortexA9 local buffer and a small 7 words circular buffer of the DMA trace ending with 0x55555555 (tag for last word) */ abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_DMEM, D_loopCounter_ADDR, (u32 *) &time_stamp, sizeof(time_stamp)); abe_dbg_activity_log[abe_dbg_activity_log_write_pointer] = time_stamp; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_DEBUG_HAL_TASK_ADDR + (abe_dbg_activity_log_write_pointer << 2), (u32 *) &time_stamp, sizeof(time_stamp)); abe_dbg_activity_log_write_pointer++; data = ((x & MAX_UINT8) << 24) | ((y & MAX_UINT8) << 16) | ((z & MAX_UINT8) << 8) | (t & MAX_UINT8); abe_dbg_activity_log[abe_dbg_activity_log_write_pointer] = data; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_DEBUG_HAL_TASK_ADDR + (abe_dbg_activity_log_write_pointer << 2), (u32 *) &data, sizeof(data)); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_DEBUG_FIFO_HAL_ADDR + ((abe_dbg_activity_log_write_pointer << 2) & (D_DEBUG_FIFO_HAL_sizeof - 1)), (u32 *) &data, sizeof(data)); data = ABE_DBG_MAGIC_NUMBER; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_DEBUG_FIFO_HAL_ADDR + (((abe_dbg_activity_log_write_pointer + 1) << 2) & (D_DEBUG_FIFO_HAL_sizeof - 1)), (u32 *) &data, sizeof(data)); abe_dbg_activity_log_write_pointer++; if (abe_dbg_activity_log_write_pointer >= D_DEBUG_HAL_TASK_sizeof) abe_dbg_activity_log_write_pointer = 0; }
/** * @fn abe_load_fwl() * * Operations : * loads the Audio Engine firmware, generate a single pulse on the Event generator * to let execution start, read the version number returned from this execution. * * @see ABE_API.h */ void abe_load_fw_param(abe_uint32 *PMEM, abe_uint32 PMEM_SIZE, abe_uint32 *CMEM, abe_uint32 CMEM_SIZE, abe_uint32 *SMEM, abe_uint32 SMEM_SIZE, abe_uint32 *DMEM, abe_uint32 DMEM_SIZE) { static abe_uint32 warm_boot; abe_uint32 event_gen; _lock_enter _log(id_load_fw_param,0,0,0) #if PC_SIMULATION /* the code is loaded from the Checkers */ #else /* do not load PMEM */ if (warm_boot) { /* Stop the event Generator */ event_gen = 0; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, EVENT_GENERATOR_START, &event_gen, 4); /* Now we are sure the firmware is stalled */ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, 0, CMEM, CMEM_SIZE); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_SMEM, 0, SMEM, SMEM_SIZE); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, 0, DMEM, DMEM_SIZE); /* Restore the event Generator status */ event_gen = 1; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_ATC, EVENT_GENERATOR_START, &event_gen, 4); } else { abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_PMEM, 0, PMEM, PMEM_SIZE); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_CMEM, 0, CMEM, CMEM_SIZE); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_SMEM, 0, SMEM, SMEM_SIZE); abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, 0, DMEM, DMEM_SIZE); } warm_boot = 1; #endif _lock_exit }
/** * abe_default_irq_pingpong_player * * generates data for the cache-flush buffer MODE 16+16 */ void abe_default_irq_pingpong_player(void) { #if ENABLE_DEFAULT_PLAYERS /* ping-pong access to MM_DL at 48kHz Mono with 20ms packet sizes */ #define N_SAMPLES_MAX ((int)(1024)) static s32 idx; u32 i, dst, n_samples, n_bytes; s32 temp[N_SAMPLES_MAX], audio_sample; #define DATA_SIZE 20 /* t = [0:N-1]/N; x = round(16383*sin(2*pi*t)) */ const s32 audio_pattern[DATA_SIZE] = { 0, 5063, 9630, 13254, 15581, 16383, 15581, 13254, 9630, 5063, 0, -5063, -9630, -13254, -15581, -16383, -15581, -13254, -9630, -5063 }; #if 0 #define DATA_SIZE 8 const s32 audio_pattern[DATA_SIZE] = { 0, 11585, 16384, 11585, 0, -11586, -16384, -11586 }; #define DATA_SIZE 12 const s32 audio_pattern[DATA_SIZE] = { 0, 8191, 14188, 16383, 14188, 8191, 0, -8192, -14188, -16383, -14188, -8192 }; const s32 audio_pattern[8] = { 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384 }; #endif /* read the address of the Pong buffer */ abe_read_next_ping_pong_buffer(MM_DL_PORT, &dst, &n_bytes); /* each stereo sample weights 4 bytes (format 16|16) */ n_samples = n_bytes / 4; /* generate a test pattern */ for (i = 0; i < n_samples; i++) { audio_sample = audio_pattern[idx]; idx = (idx >= (DATA_SIZE - 1)) ? 0 : (idx + 1); /* format 16|16 */ temp[i] = ((audio_sample << 16) + audio_sample); } /* copy the pattern (flush it) to DMEM pointer update * not necessary here because the buffer size do not * change from one ping to the other pong */ abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, dst, (u32 *) &(temp[0]), n_bytes); abe_set_ping_pong_buffer(MM_DL_PORT, n_bytes); #endif }
/* * ABE_SELECT_MAIN_PORT * * Parameter : * id : audio port name * * Operations : * tells the FW which is the reference stream for adjusting * the processing on 23/24/25 slots * * Return value: * None. */ void abe_select_main_port (abe_port_id id) { abe_uint32 selection; _lock_enter _log(id_select_main_port,id,0,0) /* flow control */ selection = D_IOdescr_ADDR + id*sizeof(ABE_SIODescriptor) + flow_counter_; /* Is port is McPDM UL no synchronization as algorithm is not working */ if (PDM_UL_PORT == id) selection = 0; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_Slot23_ctrl_ADDR, &selection, 4); _lock_exit }
/* * ABE_READ_REMAINING_DATA * * Parameter : * Port_ID : * size : pointer to the remaining number of 32bits words * * Operations : * computes the remaining amount of data in the buffer. * * Return value : * error code */ void abe_read_remaining_data(abe_port_id port, abe_uint32 *n) { abe_uint32 sio_pp_desc_address; ABE_SPingPongDescriptor desc_pp; _lock_enter _log(id_read_remaining_data,port,0,0) /* * read the port SIO descriptor and extract the * current pointer address after reading the counter */ sio_pp_desc_address = D_PingPongDesc_ADDR; abe_block_copy (COPY_FROM_ABE_TO_HOST, ABE_DMEM, sio_pp_desc_address, (abe_uint32*)&desc_pp, sizeof(ABE_SPingPongDescriptor)); (*n) = desc_pp.workbuff_Samples; _lock_exit }
/** * abe_load_embeddded_patterns * * load test patterns * * S = power (2, 31) * 0.25; * N = 4; B = 2; F=[1/N 1/N]; * gen_and_save('dbg_8k_2.txt', B, F, N, S); * N = 8; B = 2; F=[1/N 2/N]; * gen_and_save('dbg_16k_2.txt', B, F, N, S); * N = 12; B = 2; F=[1/N 2/N]; * gen_and_save('dbg_48k_2.txt', B, F, N, S); * N = 60; B = 2; F=[4/N 8/N]; * gen_and_save('dbg_amic.txt', B, F, N, S); * N = 10; B = 6; F=[1/N 2/N 3/N 1/N 2/N 3/N]; * gen_and_save('dbg_dmic.txt', B, F, N, S); */ void abe_load_embeddded_patterns(void) { u32 i; #define patterns_96k_len 48 const long patterns_96k[patterns_96k_len] = { 1620480, 1452800, 1452800, 838656, 1186304, 0, 838656, -838912, 434176, -1453056, 0, -1677824, -434432, -1453056, -838912, -838912, -1186560, -256, -1453056, 838656, -1620736, 1452800, -1677824, 1677568, -1620736, 1452800, -1453056, 838656, -1186560, 0, -838912, -838912, -434432, -1453056, -256, -1677824, 434176, -1453056, 838656, -838912, 1186304, -256, 1452800, 838656, 1620480, 1452800, 1677568, 1677568, }; #define patterns_48k_len 24 const long patterns_48k[patterns_48k_len] = { 1452800, 838656, 838656, -838912, 0, -1677824, -838912, -838912, -1453056, 838656, -1677824, 1677568, -1453056, 838656, -838912, -838912, -256, -1677824, 838656, -838912, 1452800, 838656, 1677568, 1677568, }; #define patterns_24k_len 12 const long patterns_24k[patterns_24k_len] = { 838656, -838912, -838912, -838912, -1677824, 1677568, -838912, -838912, 838656, -838912, 1677568, 1677568, }; #define patterns_16k_len 8 const long patterns_16k[patterns_16k_len] = { 0, 0, -1677824, -1677824, -256, -256, 1677568, 1677568, }; #define patterns_8k_len 4 const long patterns_8k[patterns_8k_len] = { 1677568, -1677824, 1677568, 1677568, }; for (i = 0; i < patterns_8k_len; i++) abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_SMEM, (S_DBG_8K_PATTERN_ADDR * 8) + (i * 4), (u32 *) (&(patterns_8k[i])), 4); for (i = 0; i < patterns_16k_len; i++) abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_SMEM, (S_DBG_16K_PATTERN_ADDR * 8) + (i * 4), (u32 *) (&(patterns_16k[i])), 4); for (i = 0; i < patterns_24k_len; i++) abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_SMEM, (S_DBG_24K_PATTERN_ADDR * 8) + (i * 4), (u32 *) (&(patterns_24k[i])), 4); for (i = 0; i < patterns_48k_len; i++) abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_SMEM, (S_DBG_48K_PATTERN_ADDR * 8) + (i * 4), (u32 *) (&(patterns_48k[i])), 4); for (i = 0; i < patterns_96k_len; i++) abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_SMEM, (S_DBG_96K_PATTERN_ADDR * 8) + (i * 4), (u32 *) (&(patterns_96k[i])), 4); }
/** * abe_monitoring * * checks the internal status of ABE and HAL */ void abe_monitoring(void) { int i, reset; abe->dbg_param = 0; /* Check AMIC UL filter */ reset = 0; abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_SMEM, S_AMIC_96_48_data_ADDR << 3, &filter_value[0], S_AMIC_96_48_data_sizeof << 3); for (i =0; i < S_AMIC_96_48_data_sizeof << 1; i++) if (filter_value[i] >= 0x700000 && filter_value[i] <= 0x900000) reset = 1; if (reset == 1) { printk(KERN_ERR "Reset AMIC filter \n"); abe_reset_mem(ABE_SMEM, S_AMIC_96_48_data_ADDR << 3, S_AMIC_96_48_data_sizeof << 3); } /* Check VX UL HP filter */ reset = 0; abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_SMEM, S_VX_UL_48_8_HP_data_ADDR << 3, &filter_value[0], S_VX_UL_48_8_HP_data_sizeof << 3); for (i = 0; i < S_VX_UL_48_8_HP_data_sizeof << 1; i++) if (filter_value[i] >= 0x700000 && filter_value[i] <= 0x900000) reset = 1; /* if (reset == 1) { printk(KERN_ERR "Reset VX UL HP filter \n"); abe_reset_mem(ABE_SMEM, S_VX_UL_48_8_HP_data_ADDR << 3, S_VX_UL_48_8_HP_data_sizeof << 3); }*/ /* Check VX UL LP filter */ // reset = 0; abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_SMEM, S_VX_UL_48_8_LP_data_ADDR << 3, &filter_value[0], S_VX_UL_48_8_LP_data_sizeof << 3); for (i = 0; i < S_VX_UL_48_8_LP_data_sizeof << 1; i++) if (filter_value[i] >= 0x700000 && filter_value[i] <= 0x900000) reset = 1; if (reset == 1) { // printk(KERN_ERR "Reset VX UL LP filter \n"); printk(KERN_ERR "Reset VX UL filter \n"); abe_reset_mem(ABE_SMEM, S_VX_UL_48_8_LP_data_ADDR << 3, S_VX_UL_48_8_LP_data_sizeof << 3); abe_reset_mem(ABE_SMEM, S_VX_UL_48_8_HP_data_ADDR << 3, S_VX_UL_48_8_HP_data_sizeof << 3); } /* Check VX DL HP filter */ reset = 0; abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_SMEM, S_VX_DL_8_48_HP_data_ADDR << 3, &filter_value[0], S_VX_DL_8_48_HP_data_sizeof << 3); for (i = 0; i < S_VX_DL_8_48_HP_data_sizeof << 1; i++) if (filter_value[i] >= 0x700000 && filter_value[i] <= 0x900000) reset = 1; // reset = 0; abe_block_copy(COPY_FROM_ABE_TO_HOST, ABE_SMEM, S_VX_DL_8_48_LP_data_ADDR << 3, &filter_value[0], S_VX_DL_8_48_LP_data_sizeof << 3); for (i = 0; i < S_VX_DL_8_48_LP_data_sizeof << 1; i++) if (filter_value[i] >= 0x700000 && filter_value[i] <= 0x900000) reset = 1; if (reset == 1) { // printk(KERN_ERR "Reset VX DL LP filter \n"); printk(KERN_ERR "Reset VX DL filter \n"); abe_reset_mem(ABE_SMEM, S_VX_DL_8_48_LP_data_ADDR << 3, S_VX_DL_8_48_LP_data_sizeof << 3); abe_reset_mem(ABE_SMEM, S_VX_DL_8_48_HP_data_ADDR << 3, S_VX_DL_8_48_HP_data_sizeof << 3); } }
/* * ABE_BUILD_SCHEDULER_TABLE * * Parameter : * * Operations : * * * Return value : * */ void abe_build_scheduler_table() { short VirtAudio_aMultiFrame[PROCESSING_SLOTS][TASKS_IN_SLOT]; abe_uint16 i, n; abe_uint8 *ptr; char aUplinkMuxing[16]; abe_uint32 dFastLoopback; for (ptr = (abe_uint8 *)&(VirtAudio_aMultiFrame[0][0]), i=0; i < sizeof(VirtAudio_aMultiFrame); i++) *ptr++ = 0; VirtAudio_aMultiFrame[0][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_AMIC; VirtAudio_aMultiFrame[0][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_VX_DL; //VirtAudio_aMultiFrame[0][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_ASRC_VX_DL_8; VirtAudio_aMultiFrame[1][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_DL_8_48_BP; VirtAudio_aMultiFrame[1][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_DL_8_48_0SR; VirtAudio_aMultiFrame[1][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_DL_8_48_LP; VirtAudio_aMultiFrame[1][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_MM_DL; // VirtAudio_aMultiFrame[2][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_ASRC_MM_DL; VirtAudio_aMultiFrame[2][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_MM_UL_ROUTING; VirtAudio_aMultiFrame[2][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_MM_UL2_ROUTING; //VirtAudio_aMultiFrame[2][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_MM_UL; #if 0 VirtAudio_aMultiFrame[3][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_TONES_DL; #endif VirtAudio_aMultiFrame[3][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VXRECMixer; VirtAudio_aMultiFrame[3][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VXREC_SPLIT; VirtAudio_aMultiFrame[3][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_SideTone; VirtAudio_aMultiFrame[4][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1Mixer; VirtAudio_aMultiFrame[4][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2Mixer; VirtAudio_aMultiFrame[4][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_SDTMixer; VirtAudio_aMultiFrame[4][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_MM_UL2; VirtAudio_aMultiFrame[5][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EchoMixer; VirtAudio_aMultiFrame[5][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_EQ; VirtAudio_aMultiFrame[5][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_APS_EQ; VirtAudio_aMultiFrame[5][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_GAIN; VirtAudio_aMultiFrame[6][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_EQ; VirtAudio_aMultiFrame[6][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_APS_EQ; VirtAudio_aMultiFrame[6][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_GAIN; VirtAudio_aMultiFrame[8][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EchoMixer; VirtAudio_aMultiFrame[9][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IHF_48_96_0SR; VirtAudio_aMultiFrame[9][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IHF_48_96_LP; VirtAudio_aMultiFrame[9][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IHF_48_96_LP; VirtAudio_aMultiFrame[10][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EARP_48_96_0SR; VirtAudio_aMultiFrame[10][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EARP_48_96_LP; VirtAudio_aMultiFrame[10][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_EARP_48_96_LP; VirtAudio_aMultiFrame[11][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_McPDM_DL; VirtAudio_aMultiFrame[12][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_AMIC; VirtAudio_aMultiFrame[12][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_AMIC_96_48_LP; VirtAudio_aMultiFrame[12][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_AMIC_96_48_DEC; VirtAudio_aMultiFrame[12][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_AMIC_EQ; VirtAudio_aMultiFrame[13][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC1_96_48_LP; VirtAudio_aMultiFrame[13][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC1_96_48_DEC; VirtAudio_aMultiFrame[13][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC1_EQ; VirtAudio_aMultiFrame[13][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC1_SPLIT; VirtAudio_aMultiFrame[14][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC2_96_48_LP; VirtAudio_aMultiFrame[14][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC2_96_48_DEC; VirtAudio_aMultiFrame[14][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC2_EQ; VirtAudio_aMultiFrame[14][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC2_SPLIT; VirtAudio_aMultiFrame[15][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC3_96_48_LP; VirtAudio_aMultiFrame[15][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC3_96_48_DEC; VirtAudio_aMultiFrame[15][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC3_EQ; VirtAudio_aMultiFrame[15][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DMIC3_SPLIT; VirtAudio_aMultiFrame[16][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_AMIC_SPLIT; VirtAudio_aMultiFrame[16][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_APS_IIR; VirtAudio_aMultiFrame[16][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL1_APS_CORE; VirtAudio_aMultiFrame[17][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_APS_IIR; VirtAudio_aMultiFrame[17][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_APS_SPLIT; VirtAudio_aMultiFrame[17][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_L_APS_CORE; VirtAudio_aMultiFrame[17][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_DL2_R_APS_CORE; VirtAudio_aMultiFrame[21][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_UL_ROUTING; VirtAudio_aMultiFrame[21][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_ULMixer; VirtAudio_aMultiFrame[22][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_UL_48_8_LP; VirtAudio_aMultiFrame[22][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_UL_48_8_DEC1; VirtAudio_aMultiFrame[22][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_VX_UL_48_8_BP; VirtAudio_aMultiFrame[23][0] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_McPDM_DL; //VirtAudio_aMultiFrame[23][1] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_ASRC_VX_UL_8; VirtAudio_aMultiFrame[23][2] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_VX_UL; VirtAudio_aMultiFrame[23][3] = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_GAIN_UPDATE; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_multiFrame_ADDR, (abe_uint32*)VirtAudio_aMultiFrame, sizeof(VirtAudio_aMultiFrame)); /* DMIC Fast Loopback */ dFastLoopback = D_tasksList_ADDR + sizeof(ABE_STask)*C_ABE_FW_TASK_IO_DMIC; dFastLoopback = dFastLoopback << 16; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, 0x116C, (abe_uint32*)&dFastLoopback, sizeof(dFastLoopback)); /* reset the uplink router */ n = D_aUplinkRouting_ADDR_END - D_aUplinkRouting_ADDR + 1; for(i = 0; i < n; i++) aUplinkMuxing[i] = ZERO_labelID; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, D_aUplinkRouting_ADDR, (abe_uint32 *)aUplinkMuxing, sizeof(aUplinkMuxing)); }
/* * ABE_INIT_ATC * * Parameter : * prot : protocol being used * * Operations : * load the DMEM ATC/AESS descriptors * * Return value : * */ void abe_init_atc(abe_port_id id) { abe_satcdescriptor_aess desc; abe_uint8 thr, thr1, thr2, iter, data_shift; abe_int32 iterfactor; // load default values of the descriptor desc.rdpt = desc.wrpt = desc.irqdest = desc.cberr = desc.desen =0; desc.reserved0 = desc.reserved1 = desc.reserved2 = 0; desc.srcid = desc.destid = desc.badd = desc.iter = desc.cbsize = 0; switch ((abe_port[id]).protocol.protocol_switch) { case SLIMBUS_PORT_PROT: desc.cbdir = (abe_port[id]).protocol.direction; desc.cbsize = (abe_port[id]).protocol.p.prot_slimbus.buf_size; desc.badd = ((abe_port[id]).protocol.p.prot_slimbus.buf_addr1) >> 4; desc.iter = (abe_port[id]).protocol.p.prot_slimbus.iter; desc.srcid = abe_atc_srcid [(abe_port[id]).protocol.p.prot_slimbus.desc_addr1 >> 3]; desc.nw = 1; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, (abe_port[id]).protocol.p.prot_slimbus.desc_addr1, (abe_uint32*)&desc, sizeof(desc)); desc.badd = (abe_port[id]).protocol.p.prot_slimbus.buf_addr2; desc.srcid = abe_atc_srcid [(abe_port[id]).protocol.p.prot_slimbus.desc_addr2 >> 3]; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, (abe_port[id]).protocol.p.prot_slimbus.desc_addr2, (abe_uint32*)&desc, sizeof(desc)); break; case SERIAL_PORT_PROT: desc.cbdir = (abe_port[id]).protocol.direction; desc.cbsize = (abe_port[id]).protocol.p.prot_serial.buf_size; desc.badd = ((abe_port[id]).protocol.p.prot_serial.buf_addr) >> 4; desc.iter = (abe_port[id]).protocol.p.prot_serial.iter; desc.srcid = abe_atc_srcid [(abe_port[id]).protocol.p.prot_serial.desc_addr >> 3]; desc.nw = 1; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, (abe_port[id]).protocol.p.prot_serial.desc_addr, (abe_uint32*)&desc, sizeof(desc)); break; case DMIC_PORT_PROT: desc.cbdir = ABE_ATC_DIRECTION_IN; desc.cbsize = (abe_port[id]).protocol.p.prot_dmic.buf_size; desc.badd = ((abe_port[id]).protocol.p.prot_dmic.buf_addr) >> 4; desc.iter = DMIC_ITER; desc.srcid = abe_atc_srcid [ABE_ATC_DMIC_DMA_REQ]; desc.nw = 1; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, ABE_ATC_DMIC_DMA_REQ * ATC_SIZE, (abe_uint32*)&desc, sizeof(desc)); break; case MCPDMDL_PORT_PROT: abe_global_mcpdm_control = abe_port[id].protocol.p.prot_mcpdmdl.control; /* Control allowed on McPDM DL */ desc.cbdir = ABE_ATC_DIRECTION_OUT; desc.cbsize = (abe_port[id]).protocol.p.prot_mcpdmdl.buf_size; desc.badd = ((abe_port[id]).protocol.p.prot_mcpdmdl.buf_addr) >> 4; desc.iter = MCPDM_DL_ITER; desc.destid = abe_atc_dstid [ABE_ATC_MCPDMDL_DMA_REQ]; desc.nw = 0; desc.wrpt = desc.iter; /* @@@ pre-load the ATC buffer (?) */ desc.desen = 1; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, ABE_ATC_MCPDMDL_DMA_REQ * ATC_SIZE, (abe_uint32*)&desc, sizeof(desc)); break; case MCPDMUL_PORT_PROT: desc.cbdir = ABE_ATC_DIRECTION_IN; desc.cbsize = (abe_port[id]).protocol.p.prot_mcpdmul.buf_size; desc.badd = ((abe_port[id]).protocol.p.prot_mcpdmul.buf_addr) >> 4; desc.iter = MCPDM_UL_ITER; desc.srcid = abe_atc_srcid [ABE_ATC_MCPDMUL_DMA_REQ]; desc.wrpt = MCPDM_UL_ITER; /* @@@ pre-load the ATC buffer (Virtio bug) */ desc.nw = 1; desc.desen = 1; abe_block_copy(COPY_FROM_HOST_TO_ABE, ABE_DMEM, ABE_ATC_MCPDMUL_DMA_REQ * ATC_SIZE, (abe_uint32*)&desc, sizeof(desc)); break; case PINGPONG_PORT_PROT: /* software protocol, nothing to do on ATC */ break; case DMAREQ_PORT_PROT: desc.cbdir = (abe_port[id]).protocol.direction; desc.cbsize = (abe_port[id]).protocol.p.prot_dmareq.buf_size; desc.badd = ((abe_port[id]).protocol.p.prot_dmareq.buf_addr) >> 4; desc.iter = 1; /* CBPr needs ITER=1. this is the eDMA job to do the iterations */ desc.nw = 0; /* data is sent on DMAreq, and never before data is prepared */ thr = (abe_int8) abe_port[id].protocol.p.prot_dmareq.thr_flow; iterfactor = abe_dma_port_iter_factor (&((abe_port[id]).format)); data_shift = (abe_uint8)((iterfactor > 1)? 1:0); /* shift = 0 for mono, shift = 1 for stereo - see update of ATC pointers in IOtasks */ thr = (abe_uint8)(thr * iterfactor); /* scales the data threshold to the number of words in DMEM per sample */ iter = (abe_uint8) abe_dma_port_iteration(&((abe_port[id]).format)); /* check is input from ABE point of view */ if (abe_port[id].protocol.direction == ABE_ATC_DIRECTION_IN) { /* Firmware compares X+Drift to Thresholds */ thr2 = (abe_uint8)(iter - thr); thr1 = (abe_uint8)(iter + thr); desc.wrpt = ((thr1 + thr2) >> 1) + 2; } else {