aboutsummaryrefslogtreecommitdiff
path: root/techpack/audio/asoc/codecs/tfa98xx/inc/tfa_device.h
blob: a5f03dd8a2beb035d95aa26a078f6d72bae95b23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/*
 * Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
 * Copyright 2020 GOODIX
 *
 * 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);

	enum Tfa98xx_Error (*tfa_init)(struct tfa_device *tfa); /**< init typically for loading optimal settings */
	enum Tfa98xx_Error (*dsp_reset)(struct tfa_device *tfa, int state); /**< reset the coolflux dsp */
	enum Tfa98xx_Error (*dsp_system_stable)(struct tfa_device *tfa, int *ready); /**< ready when clocks are stable to allow DSP subsystem access */
	enum Tfa98xx_Error (*dsp_write_tables)(struct tfa_device *tfa, int sample_rate); /**< write the device/type specific delaytables */
	enum Tfa98xx_Error (*auto_copy_mtp_to_iic)(struct tfa_device *tfa); /**< Set auto_copy_mtp_to_iic */
	enum Tfa98xx_Error (*factory_trimmer)(struct tfa_device *tfa); /**< Factory trimming for the Boost converter */
	int (*set_swprof)(struct tfa_device *tfa, unsigned short new_value); /**< Set the sw profile in the struct and the hw register */
	int (*get_swprof)(struct tfa_device *tfa); /**< Get the sw profile from the hw register */
	int (*set_swvstep)(struct tfa_device *tfa, unsigned short new_value); /**< Set the sw vstep in the struct and the hw register */
	int (*get_swvstep)(struct tfa_device *tfa); /**< Get the sw vstep from the hw register */
	int (*get_mtpb)(struct tfa_device *tfa); /**< get status of MTB busy bit*/
	enum Tfa98xx_Error (*set_mute)(struct tfa_device *tfa, int mute); /**< set mute */
	enum Tfa98xx_Error (*faim_protect)(struct tfa_device *tfa, int state); /**< Protect FAIM from being corrupted  */
	enum Tfa98xx_Error (*set_osc_powerdown)(struct tfa_device *tfa, int state); /**< Allow to change internal osc. gating settings */
	enum Tfa98xx_Error (*update_lpm)(struct tfa_device *tfa, int state); /**< Allow to change lowpowermode settings */
};

/**
 * 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 TfaContainer *cnt;/**< the loaded container file */
	struct TfaVolumeStepRegisterInfo *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 advance_keys_handling;
	int needs_reset; /**< add the reset trigger for SetAlgoParams and SetMBDrc commands */
	struct kmem_cache *cachep;	/**< Memory allocator handle */
	char fw_itf_ver[4];          /* Firmware ITF version */
};

/**
 * 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
 */
/*[nxp34663] CR: support 16bit/24bit/32bit audio data. begin*/
#ifdef __KERNEL__
enum tfa_error tfa_dev_start(struct tfa_device *tfa, int next_profile, int vstep, u8 pcm_format);
#else
enum tfa_error tfa_dev_start(struct tfa_device *tfa, int next_profile, int vstep);
#endif
/*[nxp34663] CR: support 16bit/24bit/32bit audio data. end*/

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

#endif /* __TFA_DEVICE_H__ */