/* * 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__ */