6db4831e98
Android 14
335 lines
12 KiB
C
335 lines
12 KiB
C
/*
|
|
* Copyright (C) 2014 NXP Semiconductors, All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
*/
|
|
|
|
/**\file
|
|
*
|
|
* The tfa_device interface controls a single I2C device instance by
|
|
* referencing to the device specific context provided by means of the
|
|
* tfa_device structure pointer.
|
|
* Multiple instances of tfa_device structures will be created and maintained
|
|
* by the caller.
|
|
*
|
|
* The API is functionally grouped as:
|
|
* - tfa_dev basic codec interface to probe, start/stop and control the device
|
|
* state
|
|
* - access to internal MTP storage
|
|
* - abstraction for interrupt bits and handling
|
|
* - container reading support
|
|
*/
|
|
#ifndef __TFA_DEVICE_H__
|
|
#define __TFA_DEVICE_H__
|
|
|
|
#include "config.h"
|
|
|
|
struct tfa_device;
|
|
|
|
/*
|
|
* hw/sw feature bit settings in MTP
|
|
*/
|
|
enum featureSupport {
|
|
supportNotSet, /**< default means not set yet */
|
|
supportNo, /**< no support */
|
|
supportYes /**< supported */
|
|
};
|
|
/*
|
|
* supported Digital Audio Interfaces bitmap
|
|
*/
|
|
enum Tfa98xx_DAI {
|
|
Tfa98xx_DAI_I2S = 0x01, /**< I2S only */
|
|
Tfa98xx_DAI_TDM = 0x02, /**< TDM, I2S */
|
|
Tfa98xx_DAI_PDM = 0x04, /**< PDM */
|
|
};
|
|
|
|
/*
|
|
* device ops function structure
|
|
*/
|
|
struct tfa_device_ops {
|
|
enum Tfa98xx_Error (*dsp_msg)(struct tfa_device *tfa, int length,
|
|
const char *buf);
|
|
enum Tfa98xx_Error (*dsp_msg_read)(struct tfa_device *tfa, int length,
|
|
unsigned char *bytes);
|
|
enum Tfa98xx_Error (*reg_read)(struct tfa_device *tfa,
|
|
unsigned char subaddress,
|
|
unsigned short *value);
|
|
enum Tfa98xx_Error (*reg_write)(struct tfa_device *tfa,
|
|
unsigned char subaddress,
|
|
unsigned short value);
|
|
enum Tfa98xx_Error (*mem_read)(struct tfa_device *tfa,
|
|
unsigned int start_offset, int num_words,
|
|
int *pValues);
|
|
enum Tfa98xx_Error (*mem_write)(struct tfa_device *tfa,
|
|
unsigned short address, int value,
|
|
int memtype);
|
|
|
|
// init typically for loading optimal settings
|
|
enum Tfa98xx_Error (*tfa_init)(struct tfa_device *tfa);
|
|
// reset the coolflux dsp
|
|
enum Tfa98xx_Error (*dsp_reset)(struct tfa_device *tfa, int state);
|
|
// ready when clocks are stable to allow DSP subsystem access
|
|
enum Tfa98xx_Error (*dsp_system_stable)(struct tfa_device *tfa,
|
|
int *ready);
|
|
// write the device/type specific delaytables
|
|
enum Tfa98xx_Error (*dsp_write_tables)(struct tfa_device *tfa,
|
|
int sample_rate);
|
|
// Set auto_copy_mtp_to_iic
|
|
enum Tfa98xx_Error (*auto_copy_mtp_to_iic)(struct tfa_device *tfa);
|
|
// Factory trimming for the Boost converter
|
|
enum Tfa98xx_Error (*factory_trimmer)(struct tfa_device *tfa);
|
|
// Set the sw profile in the struct and the hw register
|
|
int (*set_swprof)(struct tfa_device *tfa, unsigned short new_value);
|
|
// Get the sw profile from the hw register
|
|
int (*get_swprof)(struct tfa_device *tfa);
|
|
// Set the sw vstep in the struct and the hw register
|
|
int (*set_swvstep)(struct tfa_device *tfa, unsigned short new_value);
|
|
// Get the sw vstep from the hw register
|
|
int (*get_swvstep)(struct tfa_device *tfa);
|
|
// get status of MTB busy bit
|
|
int (*get_mtpb)(struct tfa_device *tfa);
|
|
// set mute
|
|
enum Tfa98xx_Error (*set_mute)(struct tfa_device *tfa, int mute);
|
|
// Protect FAIM from being corrupted
|
|
enum Tfa98xx_Error (*faim_protect)(struct tfa_device *tfa, int state);
|
|
// Allow to change internal osc. gating settings
|
|
enum Tfa98xx_Error (*set_osc_powerdown)(struct tfa_device *tfa,
|
|
int state);
|
|
};
|
|
|
|
/**
|
|
* Device states and modifier flags to allow a device/type independent fine
|
|
* grained control of the internal state.\n
|
|
* Values below 0x10 are referred to as base states which can be or-ed with
|
|
* state modifiers, from 0x10 and higher.
|
|
*
|
|
*/
|
|
enum tfa_state {
|
|
TFA_STATE_UNKNOWN, /**< unknown or invalid */
|
|
TFA_STATE_POWERDOWN, /**< PLL in powerdown, Algo is up/warm */
|
|
TFA_STATE_INIT_HW, // load I2C/PLL hardware setting (~wait2srcsettings)
|
|
TFA_STATE_INIT_CF, /**< coolflux HW access possible (~initcf) */
|
|
TFA_STATE_INIT_FW, /**< DSP framework active (~patch loaded) */
|
|
TFA_STATE_OPERATING, /**< Amp and Algo running */
|
|
TFA_STATE_FAULT, /**< An alarm or error occurred */
|
|
TFA_STATE_RESET, /**< I2C reset and ACS set */
|
|
/* --sticky state modifiers-- */
|
|
TFA_STATE_MUTE = 0x10, /**< Algo & Amp mute */
|
|
TFA_STATE_UNMUTE = 0x20, /**< Algo & Amp unmute */
|
|
TFA_STATE_CLOCK_ALWAYS = 0x40, // PLL connect to internal oscillator
|
|
TFA_STATE_CLOCK_AUDIO = 0x80, // PLL connect to audio clock (BCK/FS)
|
|
TFA_STATE_LOW_POWER = 0x100, /**< lowest possible power state */
|
|
};
|
|
|
|
/**
|
|
* This is the main tfa device context structure, it will carry all information
|
|
* that is needed to handle a single I2C device instance.
|
|
* All functions dealing with the device will need access to the fields herein.
|
|
*/
|
|
struct tfa_device {
|
|
int dev_idx; /**< device container index */
|
|
int in_use;
|
|
int buffer_size; /**< lowest level max buffer size */
|
|
int has_msg; /**< support direct dsp messaging */
|
|
unsigned char slave_address; /**< I2C slave address (not shifted) */
|
|
unsigned short rev; /**< full revid of this device */
|
|
unsigned char tfa_family; /**< tfa1/tfa2 */
|
|
enum featureSupport supportDrc;
|
|
enum featureSupport supportFramework;
|
|
enum featureSupport support_saam;
|
|
int sw_feature_bits[2]; /**< cached copy of sw feature bits */
|
|
int hw_feature_bits; /**< cached copy of hw feature bits */
|
|
int profile; /**< active profile */
|
|
int vstep; /**< active vstep */
|
|
unsigned char spkr_count;
|
|
unsigned char spkr_select;
|
|
unsigned char support_tcoef; /**< legacy tfa9887, will be removed */
|
|
enum Tfa98xx_DAI daimap; /**< supported audio interface types */
|
|
int mohm[3]; // speaker calibration values in milli ohms -1 is error
|
|
struct tfa_device_ops dev_ops;
|
|
uint16_t interrupt_enable[3];
|
|
uint16_t interrupt_status[3];
|
|
int ext_dsp; // respond to external DSP: -1:none, 0:no_dsp, 1:cold,
|
|
// 2:warm
|
|
int bus; /* TODO fix ext_dsp and bus handling */
|
|
int tfadsp_event; /**< enum tfadsp_event_en is for external registry */
|
|
int verbose; /**< verbosity level for debug print output */
|
|
enum tfa_state state; // last known state or-ed with optional
|
|
// state_modifier
|
|
struct nxpTfaContainer *cnt; /**< the loaded container file */
|
|
struct nxpTfaVolumeStepRegisterInfo *p_regInfo; // remember vstep for
|
|
// partial updates
|
|
int partial_enable; /**< enable partial updates */
|
|
void *data; // typically pointing to Linux driver structure owning this
|
|
// device
|
|
int convert_dsp32; /**< convert 24 bit DSP messages to 32 bit */
|
|
int sync_iv_delay; /**< synchronize I/V delay at cold start */
|
|
int is_probus_device; /**< probus device: device without internal DSP */
|
|
int needs_reset; // add the reset trigger for SetAlgoParams and SetMBDrc
|
|
// commands
|
|
struct kmem_cache *cachep; /**< Memory allocator handle */
|
|
};
|
|
|
|
/**
|
|
* The tfa_dev_probe is called before accessing any device accessing functions.
|
|
* Access to the tfa device register 3 is attempted and will record the
|
|
* returned id for further use. If no device responds the function will abort.
|
|
* The recorded id will by used by the query functions to fill the remaining
|
|
* relevant data fields of the device structure.
|
|
* Data such as MTP features that requires device access will only be read when
|
|
* explicitly called and the result will be then cached in the struct.
|
|
*
|
|
* A structure pointer passed to this device needs to refer to existing memory
|
|
* space allocated by the caller.
|
|
*
|
|
* @param slave = I2C slave address of the target device (not shifted)
|
|
* @param tfa struct = points to memory that holds the context for this device
|
|
* instance
|
|
*
|
|
* @return
|
|
* - 0 if the I2C device responded to a read of register address 3\n
|
|
* when the device responds but with an unknown id a warning will be
|
|
* printed
|
|
* - -1 if no response from the I2C device
|
|
*
|
|
*/
|
|
int tfa_dev_probe(int slave, struct tfa_device *tfa);
|
|
|
|
/**
|
|
* Start this instance at the profile and vstep as provided.
|
|
* The profile and vstep will be loaded first in case the current value differs
|
|
* from the requested values.
|
|
* Note that this call will not change the mute state of the tfa, which means
|
|
* that of this instance was called in muted state the caller will have to
|
|
* unmute in order to get audio.
|
|
*
|
|
* @param tfa struct = pointer to context of this device instance
|
|
* @param profile the selected profile to run
|
|
* @param vstep the selected vstep to use
|
|
* @return tfa_error enum
|
|
*/
|
|
enum tfa_error tfa_dev_start(struct tfa_device *tfa, int profile, int vstep);
|
|
|
|
/**
|
|
* Stop audio for this instance as gracefully as possible.
|
|
* Audio will be muted and the PLL will be shutdown together with any other
|
|
* device/type specific settings needed to prevent audio artifacts or
|
|
* workarounds.
|
|
*
|
|
* Note that this call will change state of the tfa to mute and powered down.
|
|
*
|
|
* @param tfa struct = pointer to context of this device instance
|
|
* @return tfa_error enum
|
|
*/
|
|
enum tfa_error tfa_dev_stop(struct tfa_device *tfa);
|
|
|
|
/**
|
|
* This interface allows a device/type independent fine grained control of the
|
|
* internal state of the instance.
|
|
* Whenever a base state is requested an attempt is made to actively bring the
|
|
* device into this state. However this may depend on external conditions beyond
|
|
* control of this software layer. Therefore in case the state cannot be set an
|
|
* erro will be returned and the current state remains unchanged. The base
|
|
* states, lower values below 0x10, are all mutually exclusive, they higher ones
|
|
* can also function as a sticky modifier which means for example that operating
|
|
* state could be in either muted or unmuted state. Or in case of init_cf it can
|
|
* be internal clock (always) or external audio clock. This function is intended
|
|
* to be used for device mute/unmute synchronization when called from higher
|
|
* layers. Mostly internal calls will use this to control the startup and
|
|
* profile transitions in a device/type independent way.
|
|
*
|
|
* @param tfa struct = pointer to context of this device instance
|
|
* @param state struct = desired device state after function return
|
|
* @return tfa_error enum
|
|
*/
|
|
enum tfa_error tfa_dev_set_state(struct tfa_device *tfa, enum tfa_state state,
|
|
int is_calibration);
|
|
|
|
/**
|
|
* Retrieve the current state of this instance in an active way.
|
|
* The state field in tfa structure will reflect the result unless an error is
|
|
* returned.
|
|
* Note that the hardware state may change on external events an as such this
|
|
* field should be treated as volatile.
|
|
*
|
|
* @param tfa struct = pointer to context of this device instance
|
|
* @return tfa_error enum
|
|
*
|
|
*/
|
|
enum tfa_state tfa_dev_get_state(struct tfa_device *tfa);
|
|
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/**
|
|
* MTP support functions
|
|
*/
|
|
enum tfa_mtp {
|
|
TFA_MTP_OTC, /**< */
|
|
TFA_MTP_EX, /**< */
|
|
TFA_MTP_RE25, /**< */
|
|
TFA_MTP_RE25_PRIM, /**< */
|
|
TFA_MTP_RE25_SEC, /**< */
|
|
TFA_MTP_LOCK, /**< */
|
|
};
|
|
|
|
/**
|
|
*
|
|
*/
|
|
int tfa_dev_mtp_get(struct tfa_device *tfa, enum tfa_mtp item);
|
|
|
|
/**
|
|
*
|
|
*/
|
|
enum tfa_error tfa_dev_mtp_set(struct tfa_device *tfa, enum tfa_mtp item,
|
|
int value);
|
|
|
|
// irq
|
|
/* tfa2 interrupt support
|
|
* !!! enum tfa9912_irq !!!
|
|
*/
|
|
|
|
/*
|
|
* interrupt bit function to clear
|
|
*/
|
|
int tfa_irq_clear(struct tfa_device *tfa, int bit);
|
|
/*
|
|
* return state of irq or -1 if illegal bit
|
|
*/
|
|
int tfa_irq_get(struct tfa_device *tfa, int bit);
|
|
/*
|
|
* interrupt bit function that operates on the shadow regs in the handle
|
|
*/
|
|
int tfa_irq_ena(struct tfa_device *tfa, int bit, int state);
|
|
/*
|
|
* interrupt bit function that sets the polarity
|
|
*/
|
|
int tfa_irq_set_pol(struct tfa_device *tfa, int bit, int state);
|
|
|
|
/*
|
|
* mask interrupts by disabling them
|
|
*/
|
|
int tfa_irq_mask(struct tfa_device *tfa);
|
|
/*
|
|
* unmask interrupts by enabling them again
|
|
*/
|
|
int tfa_irq_unmask(struct tfa_device *tfa);
|
|
// cnt read
|
|
// debug?
|
|
|
|
void tfanone_ops(struct tfa_device_ops *ops);
|
|
void tfa9872_ops(struct tfa_device_ops *ops);
|
|
void tfa9874_ops(struct tfa_device_ops *ops);
|
|
void tfa9912_ops(struct tfa_device_ops *ops);
|
|
void tfa9888_ops(struct tfa_device_ops *ops);
|
|
void tfa9891_ops(struct tfa_device_ops *ops);
|
|
void tfa9897_ops(struct tfa_device_ops *ops);
|
|
void tfa9896_ops(struct tfa_device_ops *ops);
|
|
void tfa9890_ops(struct tfa_device_ops *ops);
|
|
void tfa9895_ops(struct tfa_device_ops *ops);
|
|
void tfa9894_ops(struct tfa_device_ops *ops);
|
|
|
|
#endif /* __TFA_DEVICE_H__ */
|