Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * cs_dsp.h  --  Cirrus Logic DSP firmware support
0004  *
0005  * Based on sound/soc/codecs/wm_adsp.h
0006  *
0007  * Copyright 2012 Wolfson Microelectronics plc
0008  * Copyright (C) 2015-2021 Cirrus Logic, Inc. and
0009  *                         Cirrus Logic International Semiconductor Ltd.
0010  */
0011 #ifndef __CS_DSP_H
0012 #define __CS_DSP_H
0013 
0014 #include <linux/bits.h>
0015 #include <linux/device.h>
0016 #include <linux/firmware.h>
0017 #include <linux/list.h>
0018 #include <linux/regmap.h>
0019 
0020 #define CS_ADSP2_REGION_0 BIT(0)
0021 #define CS_ADSP2_REGION_1 BIT(1)
0022 #define CS_ADSP2_REGION_2 BIT(2)
0023 #define CS_ADSP2_REGION_3 BIT(3)
0024 #define CS_ADSP2_REGION_4 BIT(4)
0025 #define CS_ADSP2_REGION_5 BIT(5)
0026 #define CS_ADSP2_REGION_6 BIT(6)
0027 #define CS_ADSP2_REGION_7 BIT(7)
0028 #define CS_ADSP2_REGION_8 BIT(8)
0029 #define CS_ADSP2_REGION_9 BIT(9)
0030 #define CS_ADSP2_REGION_1_9 (CS_ADSP2_REGION_1 | \
0031         CS_ADSP2_REGION_2 | CS_ADSP2_REGION_3 | \
0032         CS_ADSP2_REGION_4 | CS_ADSP2_REGION_5 | \
0033         CS_ADSP2_REGION_6 | CS_ADSP2_REGION_7 | \
0034         CS_ADSP2_REGION_8 | CS_ADSP2_REGION_9)
0035 #define CS_ADSP2_REGION_ALL (CS_ADSP2_REGION_0 | CS_ADSP2_REGION_1_9)
0036 
0037 #define CS_DSP_DATA_WORD_SIZE                3
0038 #define CS_DSP_DATA_WORD_BITS                (3 * BITS_PER_BYTE)
0039 
0040 #define CS_DSP_ACKED_CTL_TIMEOUT_MS          100
0041 #define CS_DSP_ACKED_CTL_N_QUICKPOLLS        10
0042 #define CS_DSP_ACKED_CTL_MIN_VALUE           0
0043 #define CS_DSP_ACKED_CTL_MAX_VALUE           0xFFFFFF
0044 
0045 /**
0046  * struct cs_dsp_region - Describes a logical memory region in DSP address space
0047  * @type:   Memory region type
0048  * @base:   Address of region
0049  */
0050 struct cs_dsp_region {
0051     int type;
0052     unsigned int base;
0053 };
0054 
0055 /**
0056  * struct cs_dsp_alg_region - Describes a logical algorithm region in DSP address space
0057  * @list:   List node for internal use
0058  * @alg:    Algorithm id
0059  * @ver:    Expected algorithm version
0060  * @type:   Memory region type
0061  * @base:   Address of region
0062  */
0063 struct cs_dsp_alg_region {
0064     struct list_head list;
0065     unsigned int alg;
0066     unsigned int ver;
0067     int type;
0068     unsigned int base;
0069 };
0070 
0071 /**
0072  * struct cs_dsp_coeff_ctl - Describes a coefficient control
0073  * @list:       List node for internal use
0074  * @dsp:        DSP instance associated with this control
0075  * @cache:      Cached value of the control
0076  * @fw_name:        Name of the firmware
0077  * @subname:        Name of the control parsed from the WMFW
0078  * @subname_len:    Length of subname
0079  * @offset:     Offset of control within alg_region in words
0080  * @len:        Length of the cached value in bytes
0081  * @type:       One of the WMFW_CTL_TYPE_ control types defined in wmfw.h
0082  * @flags:      Bitfield of WMFW_CTL_FLAG_ control flags defined in wmfw.h
0083  * @set:        Flag indicating the value has been written by the user
0084  * @enabled:        Flag indicating whether control is enabled
0085  * @alg_region:     Logical region associated with this control
0086  * @priv:       For use by the client
0087  */
0088 struct cs_dsp_coeff_ctl {
0089     struct list_head list;
0090     struct cs_dsp *dsp;
0091     void *cache;
0092     const char *fw_name;
0093     /* Subname is needed to match with firmware */
0094     const char *subname;
0095     unsigned int subname_len;
0096     unsigned int offset;
0097     size_t len;
0098     unsigned int type;
0099     unsigned int flags;
0100     unsigned int set:1;
0101     unsigned int enabled:1;
0102     struct cs_dsp_alg_region alg_region;
0103 
0104     void *priv;
0105 };
0106 
0107 struct cs_dsp_ops;
0108 struct cs_dsp_client_ops;
0109 
0110 /**
0111  * struct cs_dsp - Configuration and state of a Cirrus Logic DSP
0112  * @name:       The name of the DSP instance
0113  * @rev:        Revision of the DSP
0114  * @num:        DSP instance number
0115  * @type:       Type of DSP
0116  * @dev:        Driver model representation of the device
0117  * @regmap:     Register map of the device
0118  * @ops:        Function pointers for internal callbacks
0119  * @client_ops:     Function pointers for client callbacks
0120  * @base:       Address of the DSP registers
0121  * @base_sysinfo:   Address of the sysinfo register (Halo only)
0122  * @sysclk_reg:     Address of the sysclk register (ADSP1 only)
0123  * @sysclk_mask:    Mask of frequency bits within sysclk register (ADSP1 only)
0124  * @sysclk_shift:   Shift of frequency bits within sysclk register (ADSP1 only)
0125  * @alg_regions:    List of currently loaded algorithm regions
0126  * @fw_file_name:   Filename of the current firmware
0127  * @fw_name:        Name of the current firmware
0128  * @fw_id:      ID of the current firmware, obtained from the wmfw
0129  * @fw_id_version:  Version of the firmware, obtained from the wmfw
0130  * @fw_vendor_id:   Vendor of the firmware, obtained from the wmfw
0131  * @mem:        DSP memory region descriptions
0132  * @num_mems:       Number of memory regions in this DSP
0133  * @fw_ver:     Version of the wmfw file format
0134  * @booted:     Flag indicating DSP has been configured
0135  * @running:        Flag indicating DSP is executing firmware
0136  * @ctl_list:       Controls defined within the loaded DSP firmware
0137  * @lock_regions:   Enable MPU traps on specified memory regions
0138  * @pwr_lock:       Lock used to serialize accesses
0139  * @debugfs_root:   Debugfs directory for this DSP instance
0140  * @wmfw_file_name: Filename of the currently loaded firmware
0141  * @bin_file_name:  Filename of the currently loaded coefficients
0142  */
0143 struct cs_dsp {
0144     const char *name;
0145     int rev;
0146     int num;
0147     int type;
0148     struct device *dev;
0149     struct regmap *regmap;
0150 
0151     const struct cs_dsp_ops *ops;
0152     const struct cs_dsp_client_ops *client_ops;
0153 
0154     unsigned int base;
0155     unsigned int base_sysinfo;
0156     unsigned int sysclk_reg;
0157     unsigned int sysclk_mask;
0158     unsigned int sysclk_shift;
0159 
0160     struct list_head alg_regions;
0161 
0162     const char *fw_name;
0163     unsigned int fw_id;
0164     unsigned int fw_id_version;
0165     unsigned int fw_vendor_id;
0166 
0167     const struct cs_dsp_region *mem;
0168     int num_mems;
0169 
0170     int fw_ver;
0171 
0172     bool booted;
0173     bool running;
0174 
0175     struct list_head ctl_list;
0176 
0177     struct mutex pwr_lock;
0178 
0179     unsigned int lock_regions;
0180 
0181 #ifdef CONFIG_DEBUG_FS
0182     struct dentry *debugfs_root;
0183     char *wmfw_file_name;
0184     char *bin_file_name;
0185 #endif
0186 };
0187 
0188 /**
0189  * struct cs_dsp_client_ops - client callbacks
0190  * @control_add:    Called under the pwr_lock when a control is created
0191  * @control_remove: Called under the pwr_lock when a control is destroyed
0192  * @pre_run:        Called under the pwr_lock by cs_dsp_run() before the core is started
0193  * @post_run:       Called under the pwr_lock by cs_dsp_run() after the core is started
0194  * @pre_stop:       Called under the pwr_lock by cs_dsp_stop() before the core is stopped
0195  * @post_stop:      Called under the pwr_lock by cs_dsp_stop() after the core is stopped
0196  * @watchdog_expired:   Called when a watchdog expiry is detected
0197  *
0198  * These callbacks give the cs_dsp client an opportunity to respond to events
0199  * or to perform actions atomically.
0200  */
0201 struct cs_dsp_client_ops {
0202     int (*control_add)(struct cs_dsp_coeff_ctl *ctl);
0203     void (*control_remove)(struct cs_dsp_coeff_ctl *ctl);
0204     int (*pre_run)(struct cs_dsp *dsp);
0205     int (*post_run)(struct cs_dsp *dsp);
0206     void (*pre_stop)(struct cs_dsp *dsp);
0207     void (*post_stop)(struct cs_dsp *dsp);
0208     void (*watchdog_expired)(struct cs_dsp *dsp);
0209 };
0210 
0211 int cs_dsp_adsp1_init(struct cs_dsp *dsp);
0212 int cs_dsp_adsp2_init(struct cs_dsp *dsp);
0213 int cs_dsp_halo_init(struct cs_dsp *dsp);
0214 
0215 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp,
0216               const struct firmware *wmfw_firmware, char *wmfw_filename,
0217               const struct firmware *coeff_firmware, char *coeff_filename,
0218               const char *fw_name);
0219 void cs_dsp_adsp1_power_down(struct cs_dsp *dsp);
0220 int cs_dsp_power_up(struct cs_dsp *dsp,
0221             const struct firmware *wmfw_firmware, char *wmfw_filename,
0222             const struct firmware *coeff_firmware, char *coeff_filename,
0223             const char *fw_name);
0224 void cs_dsp_power_down(struct cs_dsp *dsp);
0225 int cs_dsp_run(struct cs_dsp *dsp);
0226 void cs_dsp_stop(struct cs_dsp *dsp);
0227 
0228 void cs_dsp_remove(struct cs_dsp *dsp);
0229 
0230 int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq);
0231 void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp);
0232 void cs_dsp_halo_bus_error(struct cs_dsp *dsp);
0233 void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp);
0234 
0235 void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root);
0236 void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp);
0237 
0238 int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int event_id);
0239 int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
0240                 const void *buf, size_t len);
0241 int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
0242                void *buf, size_t len);
0243 struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type,
0244                     unsigned int alg);
0245 
0246 int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr,
0247                    unsigned int num_words, __be32 *data);
0248 int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 *data);
0249 int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 data);
0250 void cs_dsp_remove_padding(u32 *buf, int nwords);
0251 
0252 struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
0253                          int type, unsigned int id);
0254 
0255 const char *cs_dsp_mem_region_name(unsigned int type);
0256 
0257 /**
0258  * struct cs_dsp_chunk - Describes a buffer holding data formatted for the DSP
0259  * @data:   Pointer to underlying buffer memory
0260  * @max:    Pointer to end of the buffer memory
0261  * @bytes:  Number of bytes read/written into the memory chunk
0262  * @cache:  Temporary holding data as it is formatted
0263  * @cachebits:  Number of bits of data currently in cache
0264  */
0265 struct cs_dsp_chunk {
0266     u8 *data;
0267     u8 *max;
0268     int bytes;
0269 
0270     u32 cache;
0271     int cachebits;
0272 };
0273 
0274 /**
0275  * cs_dsp_chunk() - Create a DSP memory chunk
0276  * @data: Pointer to the buffer that will be used to store data
0277  * @size: Size of the buffer in bytes
0278  *
0279  * Return: A cs_dsp_chunk structure
0280  */
0281 static inline struct cs_dsp_chunk cs_dsp_chunk(void *data, int size)
0282 {
0283     struct cs_dsp_chunk ch = {
0284         .data = data,
0285         .max = data + size,
0286     };
0287 
0288     return ch;
0289 }
0290 
0291 /**
0292  * cs_dsp_chunk_end() - Check if a DSP memory chunk is full
0293  * @ch: Pointer to the chunk structure
0294  *
0295  * Return: True if the whole buffer has been read/written
0296  */
0297 static inline bool cs_dsp_chunk_end(struct cs_dsp_chunk *ch)
0298 {
0299     return ch->data == ch->max;
0300 }
0301 
0302 /**
0303  * cs_dsp_chunk_bytes() - Number of bytes written/read from a DSP memory chunk
0304  * @ch: Pointer to the chunk structure
0305  *
0306  * Return: Number of bytes read/written to the buffer
0307  */
0308 static inline int cs_dsp_chunk_bytes(struct cs_dsp_chunk *ch)
0309 {
0310     return ch->bytes;
0311 }
0312 
0313 /**
0314  * cs_dsp_chunk_valid_addr() - Check if an address is in a DSP memory chunk
0315  * @ch: Pointer to the chunk structure
0316  *
0317  * Return: True if the given address is within the buffer
0318  */
0319 static inline bool cs_dsp_chunk_valid_addr(struct cs_dsp_chunk *ch, void *addr)
0320 {
0321     return (u8 *)addr >= ch->data && (u8 *)addr < ch->max;
0322 }
0323 
0324 int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val);
0325 int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch);
0326 int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits);
0327 
0328 #endif