first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+557
View File
@@ -0,0 +1,557 @@
/*
* Copyright (C) 2009-2010 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <debug.h>
#include <AssertMacros.h>
#include <platform/memmap.h>
#include <platform.h>
#include <sys/task.h>
#include <iop.h>
#include <qwi.h>
#include <EmbeddedIOPProtocol.h>
#include <arch.h>
#include "iop_audio_protocol.h"
#include "AudioCodecA5.h"
#include "clock_stepping.h"
#ifdef DO_PROFILING
// doing peak heap check requires heap.c to support it
//#define DO_PEAKHEAPCHECK
// doing peak heap check requires task.c to support it
//#define DO_PEAKSTACKCHECK
#include <platform/timer.h>
#include <arch/arm/arm.h>
#define kPerformanceSize 16
struct PerformanceDetails
{
bool valid;
utime_t time;
uint32_t cycles;
};
struct PerformanceDetails performanceDetails[kPerformanceSize];
void PerformanceSnapShotReset()
{
memset(performanceDetails, 0, sizeof(performanceDetails));
}
void PerformanceSnapShotStart(uint32_t which)
{
if (which >= kPerformanceSize)
return;
performanceDetails[which].time = system_time();
performanceDetails[which].cycles = arm_read_pmreg(ARM_PMCCNTR);
}
void PerformanceSnapShotEnd(uint32_t which)
{
if (which >= kPerformanceSize)
return;
performanceDetails[which].valid = true;
performanceDetails[which].time = system_time() - performanceDetails[which].time;
performanceDetails[which].cycles = arm_read_pmreg(ARM_PMCCNTR) - performanceDetails[which].cycles;
}
void SetupProfiling(IOPAUDIO_METRICS* metrics)
{
// mapping from enum to event monitors from the A5 TRM
static const uint32_t eventtable[ACLKCycles-ICacheAccesses] = { 0x14, 0x1, 0x4, 0x3, 0x6, 0x7, 0xF, 0x8, 0x12, 0x10 };
// reset our user defined performance counters.
PerformanceSnapShotReset();
// select wich events we are going to monitor
uint32_t evt0 = 0x03; // by default we measure dcache fills
uint32_t evt1 = 0x04; // by default we measure dcache accesses
uint32_t i = ICacheAccesses;
// choose the event monitor to follow. We only choose the first two we find
for (;i < ACLKCycles; ++i)
{
if (metrics->mMetricsItemsValid & (1 << i))
{
evt0 = eventtable[(i - ICacheAccesses)];
break;
}
}
++i;
for (;i < ACLKCycles; ++i)
{
if (metrics->mMetricsItemsValid & (1 << i))
{
evt1 = eventtable[(i - ICacheAccesses)];
break;
}
}
#ifdef DO_PEAKSTACKCHECK
if (metrics->mMetricsItemsValid & (1<<PeakStackUsage))
reset_stack_usage("audio", 1024);
#endif // DO_PEAKSTACKCHECK
#ifdef DO_PEAKHEAPCHECK
if (metrics->mMetricsItemsValid & (1<<PeakHeapUsage))
heap_reset_peak_mem();
#endif // DO_PEAKHEAPCHECK
arm_write_pmreg(ARM_PMOVSR, ~0); /* clear overflow status */
arm_write_pmreg(ARM_PMSELR, 0); /* set event 0... */
arm_write_pmreg(ARM_PMXEVTYPER, evt0);
arm_write_pmreg(ARM_PMSELR, 1); /* set event 1... */
arm_write_pmreg(ARM_PMXEVTYPER, evt1);
arm_write_pmreg(ARM_PMCNTENSET, (1<<31) | (1<<1) | (1<<0)); /* enable cycles and events 0 and 1 */
arm_write_pmreg(ARM_PMCR, 2); /* clear counters */
arm_write_pmreg(ARM_PMCR, 1); /* enable all enabled counters */
metrics->mMetricsFields[ProcessTimeUSec] = system_time();
metrics->mMetricsFields[ProcessCycles] = arm_read_pmreg(ARM_PMCCNTR);
}
void EndProfiling(IOPAUDIO_METRICS* metrics)
{
uint32_t evt0, evt1, cycles;
arm_write_pmreg(ARM_PMCNTENCLR, ~0); /* disable all counters */
utime_t timeEnd = system_time();
arm_write_pmreg(ARM_PMSELR, 0);
evt0 = arm_read_pmreg(ARM_PMXEVCNTR); /* read event 0 */
arm_write_pmreg(ARM_PMSELR, 1);
evt1 = arm_read_pmreg(ARM_PMXEVCNTR); /* read event 1 */
cycles = arm_read_pmreg(ARM_PMCCNTR); /* read cycles */
if (arm_read_pmreg(ARM_PMOVSR))
dprintf(DEBUG_CRITICAL, "*** counter overflow ***\n");
uint32_t i = ICacheAccesses;
// choose the event monitor to follow. We only choose the first two we find
for (;i < ACLKCycles; ++i)
{
if (metrics->mMetricsItemsValid & (1 << i))
{
metrics->mMetricsFields[i] = evt0;
break;
}
}
++i;
for (;i < ACLKCycles; ++i)
{
if (metrics->mMetricsItemsValid & (1 << i))
{
metrics->mMetricsFields[i] = evt1;
break;
}
}
if (metrics->mMetricsItemsValid & (1<<ProcessTimeUSec))
metrics->mMetricsFields[ProcessTimeUSec] = timeEnd - metrics->mMetricsFields[ProcessTimeUSec];
if (metrics->mMetricsItemsValid & (1<<ProcessCycles))
metrics->mMetricsFields[ProcessCycles] = cycles - metrics->mMetricsFields[ProcessCycles];
if (metrics->mMetricsItemsValid & (1<<HeapInUsage))
metrics->mMetricsFields[HeapInUsage] = heap_get_free_mem();
#ifdef DO_PEAKHEAPCHECK
if (metrics->mMetricsItemsValid & (1<<PeakHeapUsage))
metrics->mMetricsFields[PeakHeapUsage] = heap_get_peak_mem();
#endif // DO_PEAKHEAPCHECK
#ifdef DO_PEAKSTACKCHECK
if (metrics->mMetricsItemsValid & (1<<PeakStackUsage))
metrics->mMetricsFields[PeakStackUsage] = get_stack_usage("audio");
#endif // DO_PEAKSTACKCHECK
for (uint32_t i = 0; i < kPerformanceSize; ++i)
{
if ((ReservedStart+i) >= MetricsFieldsSize)
break;
if (performanceDetails[i].valid)
{
metrics->mMetricsFields[ReservedStart+i] = performanceDetails[i].time;
metrics->mMetricsItemsValid |= 1<<(ReservedStart+i);
}
}
}
#else
void PerformanceSnapShotStart(uint32_t which) {}
void PerformanceSnapShotEnd(uint32_t which) {}
void SetupProfiling(IOPAUDIO_METRICS* metrics) {}
void EndProfiling(IOPAUDIO_METRICS* metrics) { metrics->mMetricsItemsValid = 0; }
#endif
static bool audio_message_process(void);
static int iop_audio_task(void *cfg);
static void iop_audio_sleep(int mode);
IOP_FUNCTION(audio, iop_audio_task, 64*1024, AUDIO_CONTROL_CHANNEL);
IOP_SLEEP_HOOK(audio, iop_audio_sleep);
static int audio_channel;
#define kMaxCodecs 8
static AudioCodec sTokens[kMaxCodecs] = { NULL, };
// return true if registered, false if could not.
static bool
Register(AudioCodec audioCodec)
{
for (size_t i = 0; i < kMaxCodecs; ++i)
if (!sTokens[i])
{
sTokens[i] = audioCodec;
return true;
}
return false;
}
static void
Unregister(AudioCodec audioCodec)
{
for (size_t i = 0; i < kMaxCodecs; ++i)
if (sTokens[i] == audioCodec)
sTokens[i] = NULL;
}
static bool
isAudioCodecValid(AudioCodec audioCodec)
{
for (size_t i = 0; i < kMaxCodecs; ++i)
if (sTokens[i] == audioCodec)
return true;
return false;
}
static int
iop_audio_task(void *cfg)
{
struct iop_channel_config *channel = (struct iop_channel_config *)cfg;
struct task_event* audio_message_event = (struct task_event*) malloc(sizeof(struct task_event));
dprintf(DEBUG_SPEW, "@@ Audio task starting\n");
check(kIOPAUDIO_COMMAND_SIZE == sizeof(IOPAUDIO_Command));
/* establish the host communications channel */
event_init(audio_message_event, EVENT_FLAG_AUTO_UNSIGNAL, false);
dprintf(DEBUG_SPEW, "** opening audio channel\n");
audio_channel = qwi_instantiate_channel("audio command",
QWI_ROLE_CONSUMER,
channel->ring_size,
(void *)mem_static_map_cached(channel->ring_base),
(qwi_channel_hook)event_signal,
audio_message_event);
#if WITH_VFP && !WITH_VFP_ALWAYS_ON
/* Little doubt we'll need VFP/Neon */
arch_task_fp_enable(true);
#endif
for (;;) {
dprintf(DEBUG_SPEW, "@@ waiting for message on audio channel\n");
while (audio_message_process()) {
// eat all available messages
}
event_wait(audio_message_event);
}
return(0);
}
static bool
audio_message_process(void)
{
uint32_t message;
IOPAUDIO_Command* command;
dprintf(DEBUG_SPEW, "@@ handling host message\n");
/* look to see if there's an item waiting for us */
if (qwi_receive_item(audio_channel, &message) == -1)
return(false);
// set the clocks high
SetClockState(kClockRequestMessageProcess, kClockValueHigh);
dprintf(DEBUG_SPEW, "@@ received audio message\n");
/* find the command structure based on the message */
command = (IOPAUDIO_Command*)mem_static_map_cached(message);
/*
* Flush any cached item contents we might have lying around - we are guaranteed
* that the command size is a multiple of our cacheline size.
*/
platform_cache_operation(CACHE_INVALIDATE,
(void *)command,
sizeof(*command));
/*
* TODO: make this part of the API and push this
* architecture-specific command handling down into the s5l8920x
* platform directory.
*/
switch (command->iopaudio.mOpcode) {
case kIOPAUDIO_OPCODE_CREATE:
{
AudioComponent comp = NULL;
AudioComponentDescription desc;
desc.componentType = command->create.mComponentDesc.mComponentType;
desc.componentSubType = command->create.mComponentDesc.mComponentSubType;
desc.componentManufacturer = command->create.mComponentDesc.mComponentManufacturer;
desc.componentFlags = command->create.mComponentDesc.mComponentFlags;
desc.componentFlagsMask = command->create.mComponentDesc.mComponentFlagsMask;
comp = AudioComponentFindNext(comp, &desc);
if(comp == NULL)
{
dprintf(DEBUG_CRITICAL, "Could not find AudioComponent\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_CODECERROR;
break;
}
dprintf(DEBUG_CRITICAL, "found component\n");
AudioCodec audioCodec = NULL;
size_t err = AudioComponentInstanceNew(comp, &audioCodec);
command->iopaudio.Codec.mCodecStatus = err;
if (err != 0 || audioCodec == NULL)
{
dprintf(DEBUG_CRITICAL, "Could not create audioCodec\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_CODECERROR;
break;
}
const void *magicCookie = (command->create.mAdditionalParametersSizeBytes) ? command->create.mAdditionalParameters : 0;
err = AudioCodecInitialize(audioCodec, &(command->create.mInputFormat), &(command->create.mOutputFormat), magicCookie, command->create.mAdditionalParametersSizeBytes);
command->iopaudio.Codec.mCodecStatus = err;
if (err != 0)
{
dprintf(DEBUG_CRITICAL, "Could not initialize audioCodec\n");
AudioComponentInstanceDispose(audioCodec);
command->iopaudio.mStatus = kIOPAUDIO_STATUS_CODECERROR;
break;
}
if (!Register(audioCodec))
{
dprintf(DEBUG_CRITICAL, "Could not register audioCodec\n");
AudioComponentInstanceDispose(audioCodec);
command->iopaudio.mStatus = kIOPAUDIO_STATUS_CODECERROR;
break;
}
command->iopaudio.mStatus = kIOPAUDIO_STATUS_SUCCESS;
command->iopaudio.Codec.mIOPToken = (uint32_t)audioCodec;
dprintf(DEBUG_CRITICAL, "Created codec with id %x\n", command->iopaudio.Codec.mIOPToken);
}
break;
case kIOPAUDIO_OPCODE_DESTROY:
{
AudioCodec audioCodec = (AudioCodec)command->iopaudio.Codec.mIOPToken;
if (!isAudioCodecValid(audioCodec))
{
dprintf(DEBUG_CRITICAL, "Codec not valid\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
AudioComponentInstanceDispose(audioCodec);
Unregister(audioCodec);
command->iopaudio.mStatus = kIOPAUDIO_STATUS_SUCCESS;
}
break;
case kIOPAUDIO_OPCODE_RESET:
{
AudioCodec audioCodec = (AudioCodec)command->iopaudio.Codec.mIOPToken;
if (!isAudioCodecValid(audioCodec))
{
dprintf(DEBUG_CRITICAL, "Codec not valid\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
size_t err = AudioCodecReset(audioCodec);
command->iopaudio.Codec.mCodecStatus = err;
command->iopaudio.mStatus = kIOPAUDIO_STATUS_SUCCESS;
}
break;
case kIOPAUDIO_OPCODE_GETPROPINFO:
{
AudioCodec audioCodec = (AudioCodec)command->iopaudio.Codec.mIOPToken;
if (isAudioCodecValid(audioCodec))
{
dprintf(DEBUG_CRITICAL, "Codec not valid\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
size_t err = AudioCodecGetPropertyInfo(audioCodec, command->get_propinfo.mPropertyID, (size_t*)&command->get_propinfo.mPropertySize, (bool*)&command->get_propinfo.mPropertyWritable);
command->iopaudio.Codec.mCodecStatus = err;
command->iopaudio.mStatus = kIOPAUDIO_STATUS_SUCCESS;
}
break;
case kIOPAUDIO_OPCODE_GETPROPERTY:
{
AudioCodec audioCodec = (AudioCodec)command->iopaudio.Codec.mIOPToken;
if (isAudioCodecValid(audioCodec))
{
dprintf(DEBUG_CRITICAL, "Codec not valid\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
// <rdar://problem/8466788> update getProperty and setProperty to limit property address
size_t max_size_for_property = sizeof(*command) - ((uint32_t)&command->get_property.mPropertyData - (uint32_t)command);
if (max_size_for_property < command->get_property.mPropertySizeBytes)
{
dprintf(DEBUG_CRITICAL, "Parameters not valid\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
// the message should be cleaned before and after we use it, so do not need to clean ourselves
void* property = (void*)command->get_property.mPropertyData;
size_t err = AudioCodecGetProperty(audioCodec, command->get_property.mPropertyID, (size_t*)&command->get_property.mPropertySizeBytes, property);
command->iopaudio.Codec.mCodecStatus = err;
command->iopaudio.mStatus = kIOPAUDIO_STATUS_SUCCESS;
}
break;
case kIOPAUDIO_OPCODE_SETPROPERTY:
{
AudioCodec audioCodec = (AudioCodec)command->iopaudio.Codec.mIOPToken;
if (isAudioCodecValid(audioCodec))
{
dprintf(DEBUG_CRITICAL, "Codec not valid\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
// <rdar://problem/8466788> update getProperty and setProperty to limit property address
size_t max_size_for_property = sizeof(*command) - ((uint32_t)&command->get_property.mPropertyData - (uint32_t)command);
if (max_size_for_property < command->get_property.mPropertySizeBytes)
{
dprintf(DEBUG_CRITICAL, "Parameters not valid\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
// the message should be cleaned before and after we use it, so do not need to clean ourselves
void* property = (void*)command->get_property.mPropertyData;
size_t err = AudioCodecSetProperty(audioCodec, command->set_property.mPropertyID, command->set_property.mPropertySizeBytes, property);
command->iopaudio.Codec.mCodecStatus = err;
command->iopaudio.mStatus = kIOPAUDIO_STATUS_SUCCESS;
}
break;
case kIOPAUDIO_OPCODE_PROCESSFRAME:
{
AudioCodec audioCodec = (AudioCodec)command->iopaudio.Codec.mIOPToken;
if (!isAudioCodecValid(audioCodec))
{
dprintf(DEBUG_CRITICAL, "Codec not valid\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
// <rdar://problem/8486723> function_audio should make sure parameters to processSingleFrame (input, output buffers) are valid
// make sure the parameters are not-null.
if (!command->process_frame.mSrcAddr
|| !command->process_frame.mSrcSizeBytes
|| !command->process_frame.mDstAddr
|| !command->process_frame.mDstSizeBytes)
{
dprintf(DEBUG_CRITICAL, "Parameters not valid\n");
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
const void* src = (const void*)mem_static_map_cached(command->process_frame.mSrcAddr);
void* dst = (void*)mem_static_map_cached(command->process_frame.mDstAddr);
// the onus is on the caller to make sure the cache is aligned
void* lineBase = (void*)((uint32_t)src & ~(CPU_CACHELINE_SIZE-1));
size_t sizeToClean = ((((uint32_t)src & (CPU_CACHELINE_SIZE-1)) + command->process_frame.mSrcSizeBytes)/CPU_CACHELINE_SIZE + 1) * CPU_CACHELINE_SIZE;
platform_cache_operation(CACHE_CLEAN | CACHE_INVALIDATE, lineBase, sizeToClean);
SetupProfiling(&command->process_frame.mMetrics);
void* packet_dst = dst;
uint16_t numPackets = command->process_frame.mNumPackets;
size_t remaining_dst_size = command->process_frame.mDstSizeBytes;
size_t total_dst_size = 0;
size_t total_src_size = 0;
//sanity check, if the multi frame fields are not used
if(0 == numPackets)
{
numPackets = 1;
command->process_frame.mPacketSize[0] = command->process_frame.mSrcSizeBytes;
}
for(uint16_t i = 0; i < numPackets; ++i)
{
size_t src_size = command->process_frame.mPacketSize[i];
//make sure we dont go pass all of the valid input data
if(total_src_size + src_size > command->process_frame.mSrcSizeBytes)
break;
size_t packet_dst_size = remaining_dst_size; //the current mp3 decoder doesn't take dst size that's bigger than the packet output size
dprintf(DEBUG_SPEW, "IOP_Audio start %d of %d, input %p size %zu, output %p, size %zu\n", i+1, numPackets, src, src_size, packet_dst, packet_dst_size);
size_t err = AudioCodecProcessSinglePacket(audioCodec, src, &src_size, packet_dst, &packet_dst_size);
command->iopaudio.Codec.mCodecStatus = err;
if(err)
break;
packet_dst += packet_dst_size;
remaining_dst_size -= packet_dst_size;
total_dst_size += packet_dst_size;
src += src_size;
total_src_size += src_size;
//for encoding, write the size back to the msg
command->process_frame.mPacketSize[i] = packet_dst_size;
}
command->process_frame.mSrcSizeBytes = total_src_size;
command->process_frame.mDstSizeBytes = total_dst_size;
//dprintf(DEBUG_CRITICAL, "Decoded/Encoded Total SrcSize %d, dstSize %d\n", command->process_frame.mSrcSizeBytes, command->process_frame.mDstSizeBytes);
EndProfiling(&command->process_frame.mMetrics);
// the onus is on the caller to make sure the cache is aligned
lineBase = (void*)((uint32_t)dst & ~(CPU_CACHELINE_SIZE-1));
sizeToClean = ((((uint32_t)dst & (CPU_CACHELINE_SIZE-1)) + command->process_frame.mDstSizeBytes)/CPU_CACHELINE_SIZE + 1) * CPU_CACHELINE_SIZE;
platform_cache_operation(CACHE_CLEAN, lineBase, sizeToClean);
command->iopaudio.mStatus = kIOPAUDIO_STATUS_SUCCESS;
}
break;
default:
dprintf(DEBUG_CRITICAL, "@@ ERROR: unrecognised audio opcode 0x%x\n",
command->iopaudio.mOpcode);
command->iopaudio.mStatus = kIOPAUDIO_STATUS_PARAM_INVALID;
break;
}
dprintf(DEBUG_SPEW, "@@ done processing audio message with status 0x%08x\n", command->iopaudio.mStatus);
platform_cache_operation(CACHE_CLEAN,
(void *)command,
sizeof(IOPAUDIO_Command));
qwi_send_item(audio_channel, message);
dprintf(DEBUG_SPEW, "@@ signaled completion of audio message to host\n");
// set the clocks low
SetClockState(kClockRequestMessageProcess, kClockValueLow);
return(true);
}
static void
iop_audio_sleep(int mode)
{
}
@@ -0,0 +1,292 @@
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#ifndef _IOP_AUDIO_PROTOCOL_H_
#define _IOP_AUDIO_PROTOCOL_H_
#include <sys/types.h>
/*
* Command size is (somewhat) tunable.
*
* The principal consideration here is the maximum scatter/gather list size
* this permits.
*/
#define kIOPAUDIO_COMMAND_SIZE (512)
/*
* IOPAUDIO_opcode_t: identifies the command sent and from the AE2
*/
typedef uint32_t IOPAUDIO_opcode_t;
#define kIOPAUDIO_OPCODE_UNKNOWN ((IOPAUDIO_opcode_t) 0)
/*
* Commands for communicating with AudioCodecs library
*/
#define kIOPAUDIO_OPCODE_CREATE ((IOPAUDIO_opcode_t) 3)
#define kIOPAUDIO_OPCODE_DESTROY ((IOPAUDIO_opcode_t) 4)
#define kIOPAUDIO_OPCODE_RESET ((IOPAUDIO_opcode_t) 5)
#define kIOPAUDIO_OPCODE_PROCESSFRAME ((IOPAUDIO_opcode_t) 6)
#define kIOPAUDIO_OPCODE_GETPROPINFO ((IOPAUDIO_opcode_t) 7)
#define kIOPAUDIO_OPCODE_GETPROPERTY ((IOPAUDIO_opcode_t) 8)
#define kIOPAUDIO_OPCODE_SETPROPERTY ((IOPAUDIO_opcode_t) 9)
/*
* IOPAUDIO_status_t: result from commands
*/
typedef uint32_t IOPAUDIO_status_t;
#define kIOPAUDIO_STATUS_UNKNOWN ((IOPAUDIO_status_t) 0)
#define kIOPAUDIO_STATUS_SUCCESS ((IOPAUDIO_status_t) 1)
#define kIOPAUDIO_STATUS_FAILURE ((IOPAUDIO_status_t) 0x80000000)
#define kIOPAUDIO_STATUS_DEVICE_ERROR ((IOPAUDIO_status_t) 0x80000001)
#define kIOPAUDIO_STATUS_DEVICE_TIMEOUT ((IOPAUDIO_status_t) 0x80000002)
#define kIOPAUDIO_STATUS_DMA_TIMEOUT ((IOPAUDIO_status_t) 0x80000003)
#define kIOPAUDIO_STATUS_PARAM_INVALID ((IOPAUDIO_status_t) 0x80000004)
#define kIOPAUDIO_STATUS_UNIMPLEMENTED ((IOPAUDIO_status_t) 0x80000005)
#define kIOPAUDIO_STATUS_CODECERROR ((IOPAUDIO_status_t) 0x80000010)
/*
* IOPAUDIO_token_t: The opaque token to use for audio processing
*/
typedef uint32_t IOPAUDIO_token_t;
typedef uint32_t IOPAUDIO_codecstatus_t;
/*
* IOPAUDIO_CODEC contains the pair of token and codec status
*/
struct _IOPAUDIO_CODEC
{
IOPAUDIO_token_t mIOPToken;
IOPAUDIO_codecstatus_t mCodecStatus;
};
typedef struct _IOPAUDIO_CODEC IOPAUDIO_CODEC;
// Token for sending messages to the iop_audio system itself
#define kIOPAUDIO_system_token_t ((IOPAUDIO_opcode_t) 0xFFFFFFFF)
/*
* IOPAUDIO_status_t result from commands
*/
struct _IOPAUDIO
{
IOPAUDIO_opcode_t mOpcode;
IOPAUDIO_status_t mStatus;
IOPAUDIO_CODEC Codec;
};
typedef struct _IOPAUDIO IOPAUDIO;
struct _FunctionAudioAudioComponentDescription
{
uint32_t mComponentType;
uint32_t mComponentSubType;
uint32_t mComponentManufacturer;
uint32_t mComponentFlags;
uint32_t mComponentFlagsMask;
};
typedef struct _FunctionAudioAudioComponentDescription FunctionAudioAudioComponentDescription;
struct _FunctionAudioAudioStreamBasicDescription
{
uint64_t mSampleRate;
uint32_t mFormatID;
uint32_t mFormatFlags;
uint32_t mBytesPerPacket;
uint32_t mFramesPerPacket;
uint32_t mBytesPerFrame;
uint32_t mChannelsPerFrame;
uint32_t mBitsPerChannel;
uint32_t mReserved;
};
typedef struct _FunctionAudioAudioStreamBasicDescription FunctionAudioAudioStreamBasicDescription;
enum MetricsFields
{
ProcessTimeUSec = 0,
ProcessCycles,
PeakStackUsage,
HeapInUsage,
PeakHeapUsage,
ICacheAccesses, // these are measured by A5 performance monitors
ICacheMisses,
DCacheAccesses,
DCacheMisses,
Loads,
Stores,
UnalignedLoadStores,
InstructionsExecuted,
CorrectPredictedBranches,
IncorrectPredictedBranches,
ACLKCycles, // these are measured by AE2 performance monitors
ACLKCyclesInWFI,
SRAMBytesRead,
SRAMBytesWrite,
SRAMBytesReadWrite,
DRAMBytesRead,
DRAMBytesWrite,
DRAMBytesReadWrite,
ReservedStart,
MetricsFieldsSize = 32
};
struct _IOPAUDIO_METRICS
{
uint32_t mMetricsItemsValid; // bitmap marking which values are valid
uint32_t mMetricsFields[MetricsFieldsSize];
};
typedef struct _IOPAUDIO_METRICS IOPAUDIO_METRICS;
/*
* Messages. Message layout is dependent on the opcode. For instance, if
* the opcode is kIOPAUDIO_OPCODE_CREATE, then the message will be interpreted
* as IOPAUDIO_CREATE.
* It is the senders responsiblity to make sure a message is set correctly.
*/
/*
* IOPAUDIO_CREATE message
* Message used to create a new audio process.
* If message succeeds, iopToken will contain the token used for processing.
* Fill the input and output with necessary parameters. Additional parameters
* passed through the additional_paramters pointer.
*
* It is decoder specific how additional data is laid out.
*/
struct _IOPAUDIO_CREATE
{
IOPAUDIO mIOPHeader;
FunctionAudioAudioComponentDescription mComponentDesc;
FunctionAudioAudioStreamBasicDescription mInputFormat;
FunctionAudioAudioStreamBasicDescription mOutputFormat;
uint32_t mAdditionalParametersSizeBytes;
uint8_t mAdditionalParameters[];
};
typedef struct _IOPAUDIO_CREATE IOPAUDIO_CREATE;
/*
* IOPAUDIO_DESTROY message
* Message used to destroy a token.
* If message succeeds, iopToken is no longer valid.
*/
struct _IOPAUDIO_DESTROY
{
IOPAUDIO mIOPHeader;
};
typedef struct _IOPAUDIO_DESTROY IOPAUDIO_DESTROY;
/*
* IOPAUDIO_RESET message
* Message used to reset an audio process
* If message succeeds, iopToken is reset to the starting state.
*/
struct _IOPAUDIO_RESET
{
IOPAUDIO mIOPHeader;
};
typedef struct _IOPAUDIO_RESET IOPAUDIO_RESET;
/*
* IOPAUDIO_GETPROPINFO message
* Message used to get property information. mPropertyID is the 4-char code
* indicating what property to get info on.
* If message succeeds, size and writablility are set.
*/
struct _IOPAUDIO_GETPROPINFO
{
IOPAUDIO mIOPHeader;
uint32_t mPropertyID;
uint32_t mPropertySize;
uint32_t mPropertyWritable;
};
typedef struct _IOPAUDIO_GETPROPINFO IOPAUDIO_GETPROPINFO;
/*
* IOPAUDIO_GETPROPERTY message
* Message used to get property. mPropertyID is the 4-char code indicating what
* property to get.
* Addr passed in is the physical address where should be written. It can
* point within the message or point to some other buffer that IOP can access.
* If message succeeds, the property is written to the Addr.
*/
struct _IOPAUDIO_GETPROPERTY
{
IOPAUDIO mIOPHeader;
uint32_t mPropertyID;
uint32_t mPropertySizeBytes;
uint8_t mPropertyData[];
};
typedef struct _IOPAUDIO_GETPROPERTY IOPAUDIO_GETPROPERTY;
/*
* IOPAUDIO_SETPROPERTY message
* Message used to set property. mPropertyID is the 4-char code indicating what
* property to set.
* Addr passed in is the physical address which has the data to write. It can
* point within the message or point to some other buffer that IOP can access.
* If message succeeds, the property is written to the Addr.
*/
struct _IOPAUDIO_SETPROPERTY
{
IOPAUDIO mIOPHeader;
uint32_t mPropertyID;
uint32_t mPropertySizeBytes;
uint8_t mPropertyData[];
};
typedef struct _IOPAUDIO_SETPROPERTY IOPAUDIO_SETPROPERTY;
/*
* IOPAUDIO_PROCESSFRAME message
* Process audio from the src_addr to the dst_addr. On input, src_size is
* the size of the source data, dst_size is the size available to write into.
* On output, src_size is the amount of data consumed, dst_size is the amount
* of data written.
* Metrics may or may not be filled in, depending on the build.
*/
struct _IOPAUDIO_PROCESSFRAME
{
IOPAUDIO mIOPHeader;
uint32_t mSrcAddr;
uint32_t mDstAddr;
uint32_t mSrcSizeBytes;
uint32_t mDstSizeBytes;
IOPAUDIO_METRICS mMetrics;
//add packet information for multple packets
uint16_t mNumPackets;
uint16_t mPacketSize[];
};
typedef struct _IOPAUDIO_PROCESSFRAME IOPAUDIO_PROCESSFRAME;
union _IOPAUDIO_Command
{
IOPAUDIO iopaudio;
IOPAUDIO_CREATE create;
IOPAUDIO_DESTROY destroy;
IOPAUDIO_RESET reset;
IOPAUDIO_PROCESSFRAME process_frame;
IOPAUDIO_GETPROPINFO get_propinfo;
IOPAUDIO_GETPROPERTY get_property;
IOPAUDIO_SETPROPERTY set_property;
uint8_t _pad[kIOPAUDIO_COMMAND_SIZE];
};
typedef union _IOPAUDIO_Command IOPAUDIO_Command;
#endif // _IOP_AUDIO_PROTOCOL_H_
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
*
* This document is the property of Apple Computer, Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Computer, Inc.
*/
/*
* Empty namespace std stubs
*/
namespace std
{
void __throw_bad_alloc()
{}
void __throw_length_error(char const*)
{}
};
+35
View File
@@ -0,0 +1,35 @@
# Copyright (C) 2010 Apple Inc. All rights reserved.
#
# This document is the property of Apple Inc.
# It is considered confidential and proprietary.
#
# This document may not be reproduced or transmitted in any form,
# in whole or in part, without the express written permission of
# Apple Inc.
#
#
# Audio driver
#
LOCAL_DIR := $(GET_LOCAL_DIR)
OPTIONS += WITH_FUNCTION_AUDIO=1
IOP_FUNCTIONS += AUDIO
ALL_OBJS += $(LOCAL_DIR)/iop_audio.o \
$(LOCAL_DIR)/libstd_stub.o
INSTALL_HEADERS += $(LOCAL_DIR)/iop_audio_protocol.h
# We need 64 k for stack
# and 372064 for heap
# 192512 of which will be in SRAM
export IOP_HEAP_REQUIRED := $(call ADD,$(IOP_HEAP_REQUIRED),245088)
GLOBAL_INCLUDES += $(SDKROOT)/usr/local/standalone/firmware \
$(SDKROOT)/usr/local/standalone/firmware/include \
# $(SDKROOT)/../../../usr/local/standalone/firmware/Accelerate.framework/Frameworks/vecLib.framework/Headers
PREBUILT_STATICLIBS += $(SDKROOT)/usr/local/standalone/firmware/libm.a \
$(SDKROOT)/usr/local/standalone/firmware/libvDSP.a \
$(SDKROOT)/usr/local/standalone/firmware/libAudioCodecsA5.a