/* * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved. * Copyright 2020 GOODIX, 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 feature_support { SUPPORT_NOT_SET, /**< default means not set yet */ SUPPORT_NO, /**< no support */ SUPPORT_YES /**< supported */ }; /* * supported Digital Audio Interfaces bitmap */ enum tfa98xx_dai_bitmap { 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 { int (*dsp_msg)(void *tfa, int length, const char *buf); int (*dsp_msg_read)(void *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 *p_values); enum tfa98xx_error (*mem_write)(struct tfa_device *tfa, unsigned short address, int value, int memtype); enum tfa98xx_error (*tfa_init)(struct tfa_device *tfa); enum tfa98xx_error (*dsp_reset)(struct tfa_device *tfa, int state); enum tfa98xx_error (*dsp_system_stable)(struct tfa_device *tfa, int *ready); enum tfa98xx_error (*dsp_write_tables)(struct tfa_device *tfa, int sample_rate); enum tfa98xx_error (*auto_copy_mtp_to_iic)(struct tfa_device *tfa); enum tfa98xx_error (*factory_trimmer)(struct tfa_device *tfa); int (*set_swprof)(struct tfa_device *tfa, unsigned short new_value); int (*get_swprof)(struct tfa_device *tfa); int (*set_swvstep)(struct tfa_device *tfa, unsigned short new_value); int (*get_swvstep)(struct tfa_device *tfa); int (*get_mtpb)(struct tfa_device *tfa); enum tfa98xx_error (*set_mute)(struct tfa_device *tfa, int mute); enum tfa98xx_error (*faim_protect)(struct tfa_device *tfa, int state); enum tfa98xx_error (*set_osc_powerdown)(struct tfa_device *tfa, int state); enum tfa98xx_error (*update_lpm)(struct tfa_device *tfa, int state); int (*set_bitfield)(struct tfa_device *tfa, uint16_t bitfield, uint16_t value); enum tfa98xx_error (*get_status)(struct tfa_device *tfa); }; /* * 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, TFA_STATE_POWERDOWN, TFA_STATE_INIT_HW, TFA_STATE_INIT_CF, TFA_STATE_INIT_FW, TFA_STATE_OPERATING, TFA_STATE_FAULT, TFA_STATE_RESET, /* --sticky state modifiers-- */ TFA_STATE_MUTE = 0x10, TFA_STATE_UNMUTE = 0x20, TFA_STATE_CLOCK_ALWAYS = 0x40, TFA_STATE_CLOCK_AUDIO = 0x80, TFA_STATE_LOW_POWER = 0x100, }; enum pool_control { POOL_NOT_SUPPORT, POOL_ALLOC, POOL_FREE, POOL_GET, POOL_RETURN, POOL_MAX_CONTROL }; #define POOL_MAX_INDEX 6 struct tfa98xx_buffer_pool { int size; unsigned char in_use; void *pool; }; /* MAX_HANDLES * ID_BLACKBOX_MAX */ #define LOG_BUFFER_SIZE 24 /* * 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; int in_use; int buffer_size; int has_msg; unsigned char resp_address; unsigned short rev; unsigned char tfa_family; enum feature_support support_drc; enum feature_support support_framework; enum feature_support support_saam; int sw_feature_bits[2]; int hw_feature_bits; int profile; int next_profile; int vstep; unsigned char spkr_count; unsigned char spkr_select; unsigned char support_tcoef; enum tfa98xx_dai_bitmap daimap; int mohm[3]; struct tfa_device_ops dev_ops; uint16_t interrupt_enable[3]; uint16_t interrupt_status[3]; int ext_dsp; int bus; int tfadsp_event; int verbose; enum tfa_state state; struct tfa_container *cnt; struct tfa_volume_step_register_info *p_reg_info; int partial_enable; void *data; int convert_dsp32; int sync_iv_delay; int is_probus_device; int advance_keys_handling; int needs_reset; struct kmem_cache *cachep; char fw_itf_ver[4]; int dev_count; int dev_tfadsp; int set_active; int mute_state; int pause_state; int spkgain; int temp; int spkr_damaged; /* 0: okay, 1: damaged */ int is_cold; int is_bypass; int is_calibrating; int is_configured; int mtpex; int reset_mtpex; int stream_state; /* b0: pstream (Rx), b1: cstream (Tx), b2:SaaM */ int prev_samstream; int first_after_boot; int active_handle; int active_count; int swprof; int ampgain; int individual_msg; int set_device; int set_config; struct tfa98xx_buffer_pool buf_pool[POOL_MAX_INDEX]; struct workqueue_struct *tfacal_wq; struct delayed_work wait_cal_work; int lower_limit_cal; int upper_limit_cal; char fw_lib_ver[3]; int blackbox_enable; int unset_log; int log_data[LOG_BUFFER_SIZE]; int irq_all; int irq_max; int vval_active; int vval_result; /* 0: pass, 1: fail */ int disable_auto_cal; int dummy_cal; int inchannel; }; #if defined(TFA_STEREO_NODE) /* stereo */ /* ref. device order in container file */ /* confirmed by customer on 07/19/2022 v3 */ #define INDEX_0 0 /* dev 0 - left; top (receiver) */ #define INDEX_1 1 /* dev 1 - right; bottom (speaker) */ #else /* mono */ #define INDEX_0 0 /* dev 0 - mono; bottom */ #define INDEX_1 0 /* dev 0 - mono; bottom */ #endif /* TFA_STEREO_NODE */ /* * 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 resp_addr = I2C responder 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 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 resp_addr, 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); enum tfa_error tfa_dev_switch_profile(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 * internal state of the instance. * Whenever a base state is requested an attempt is made to bring device * into this state. However this may depend on external conditions beyond * 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, * 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 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); /* * tfa2 interrupt support * 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); enum tfa98xx_error tfa_get_fw_api_version(struct tfa_device *tfa, unsigned char *pfw_version); enum tfa98xx_error tfa_get_fw_lib_version(struct tfa_device *tfa, unsigned char *plib_version); #define RAMPDOWN_MAX 2 /* 5 or higher if usleep_range works */ enum tfa98xx_error tfa_gain_rampdown(struct tfa_device *tfa, int step, int count); enum tfa98xx_error tfa_gain_restore(struct tfa_device *tfa, int step, int count); int ipi_tfadsp_write(void *tfa, int length, const char *buf); int ipi_tfadsp_read(void *tfa, int length, unsigned char *bytes); #endif /* __TFA_DEVICE_H__ */