1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * wm_adsp.h -- Wolfson ADSP support 4 * 5 * Copyright 2012 Wolfson Microelectronics plc 6 * 7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 8 */ 9 10 #ifndef __WM_ADSP_H 11 #define __WM_ADSP_H 12 13 #include <sound/soc.h> 14 #include <sound/soc-dapm.h> 15 #include <sound/compress_driver.h> 16 17 #include "wmfw.h" 18 19 /* Return values for wm_adsp_compr_handle_irq */ 20 #define WM_ADSP_COMPR_OK 0 21 #define WM_ADSP_COMPR_VOICE_TRIGGER 1 22 23 #define WM_ADSP2_REGION_0 BIT(0) 24 #define WM_ADSP2_REGION_1 BIT(1) 25 #define WM_ADSP2_REGION_2 BIT(2) 26 #define WM_ADSP2_REGION_3 BIT(3) 27 #define WM_ADSP2_REGION_4 BIT(4) 28 #define WM_ADSP2_REGION_5 BIT(5) 29 #define WM_ADSP2_REGION_6 BIT(6) 30 #define WM_ADSP2_REGION_7 BIT(7) 31 #define WM_ADSP2_REGION_8 BIT(8) 32 #define WM_ADSP2_REGION_9 BIT(9) 33 #define WM_ADSP2_REGION_1_9 (WM_ADSP2_REGION_1 | \ 34 WM_ADSP2_REGION_2 | WM_ADSP2_REGION_3 | \ 35 WM_ADSP2_REGION_4 | WM_ADSP2_REGION_5 | \ 36 WM_ADSP2_REGION_6 | WM_ADSP2_REGION_7 | \ 37 WM_ADSP2_REGION_8 | WM_ADSP2_REGION_9) 38 #define WM_ADSP2_REGION_ALL (WM_ADSP2_REGION_0 | WM_ADSP2_REGION_1_9) 39 40 struct wm_adsp_region { 41 int type; 42 unsigned int base; 43 }; 44 45 struct wm_adsp_alg_region { 46 struct list_head list; 47 unsigned int alg; 48 int type; 49 unsigned int base; 50 }; 51 52 struct wm_adsp_compr; 53 struct wm_adsp_compr_buf; 54 struct wm_adsp_ops; 55 56 struct wm_adsp { 57 const char *part; 58 const char *name; 59 const char *fwf_name; 60 int rev; 61 int num; 62 int type; 63 struct device *dev; 64 struct regmap *regmap; 65 struct snd_soc_component *component; 66 67 const struct wm_adsp_ops *ops; 68 69 unsigned int base; 70 unsigned int base_sysinfo; 71 unsigned int sysclk_reg; 72 unsigned int sysclk_mask; 73 unsigned int sysclk_shift; 74 75 struct list_head alg_regions; 76 77 unsigned int fw_id; 78 unsigned int fw_id_version; 79 unsigned int fw_vendor_id; 80 81 const struct wm_adsp_region *mem; 82 int num_mems; 83 84 int fw; 85 int fw_ver; 86 87 bool preloaded; 88 bool booted; 89 bool running; 90 bool fatal_error; 91 92 struct list_head ctl_list; 93 94 struct work_struct boot_work; 95 96 struct list_head compr_list; 97 struct list_head buffer_list; 98 99 struct mutex pwr_lock; 100 101 unsigned int lock_regions; 102 103 #ifdef CONFIG_DEBUG_FS 104 struct dentry *debugfs_root; 105 char *wmfw_file_name; 106 char *bin_file_name; 107 #endif 108 109 }; 110 111 struct wm_adsp_ops { 112 unsigned int sys_config_size; 113 114 bool (*validate_version)(struct wm_adsp *dsp, unsigned int version); 115 unsigned int (*parse_sizes)(struct wm_adsp *dsp, 116 const char * const file, 117 unsigned int pos, 118 const struct firmware *firmware); 119 int (*setup_algs)(struct wm_adsp *dsp); 120 unsigned int (*region_to_reg)(struct wm_adsp_region const *mem, 121 unsigned int offset); 122 123 void (*show_fw_status)(struct wm_adsp *dsp); 124 void (*stop_watchdog)(struct wm_adsp *dsp); 125 126 int (*enable_memory)(struct wm_adsp *dsp); 127 void (*disable_memory)(struct wm_adsp *dsp); 128 int (*lock_memory)(struct wm_adsp *dsp, unsigned int lock_regions); 129 130 int (*enable_core)(struct wm_adsp *dsp); 131 void (*disable_core)(struct wm_adsp *dsp); 132 133 int (*start_core)(struct wm_adsp *dsp); 134 void (*stop_core)(struct wm_adsp *dsp); 135 }; 136 137 #define WM_ADSP1(wname, num) \ 138 SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ 139 wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) 140 141 #define WM_ADSP2_PRELOAD_SWITCH(wname, num) \ 142 SOC_SINGLE_EXT(wname " Preload Switch", SND_SOC_NOPM, num, 1, 0, \ 143 wm_adsp2_preloader_get, wm_adsp2_preloader_put) 144 145 #define WM_ADSP2(wname, num, event_fn) \ 146 SND_SOC_DAPM_SPK(wname " Preload", NULL), \ 147 { .id = snd_soc_dapm_supply, .name = wname " Preloader", \ 148 .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ 149 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD, \ 150 .subseq = 100, /* Ensure we run after SYSCLK supply widget */ }, \ 151 { .id = snd_soc_dapm_out_drv, .name = wname, \ 152 .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp_event, \ 153 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } 154 155 #define WM_ADSP_FW_CONTROL(dspname, num) \ 156 SOC_ENUM_EXT(dspname " Firmware", wm_adsp_fw_enum[num], \ 157 wm_adsp_fw_get, wm_adsp_fw_put) 158 159 extern const struct soc_enum wm_adsp_fw_enum[]; 160 161 int wm_adsp1_init(struct wm_adsp *dsp); 162 int wm_adsp2_init(struct wm_adsp *dsp); 163 void wm_adsp2_remove(struct wm_adsp *dsp); 164 int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component); 165 int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component); 166 int wm_halo_init(struct wm_adsp *dsp); 167 168 int wm_adsp1_event(struct snd_soc_dapm_widget *w, 169 struct snd_kcontrol *kcontrol, int event); 170 171 int wm_adsp_early_event(struct snd_soc_dapm_widget *w, 172 struct snd_kcontrol *kcontrol, int event); 173 174 irqreturn_t wm_adsp2_bus_error(int irq, void *data); 175 irqreturn_t wm_halo_bus_error(int irq, void *data); 176 irqreturn_t wm_halo_wdt_expire(int irq, void *data); 177 178 int wm_adsp_event(struct snd_soc_dapm_widget *w, 179 struct snd_kcontrol *kcontrol, int event); 180 181 int wm_adsp2_set_dspclk(struct snd_soc_dapm_widget *w, unsigned int freq); 182 183 int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, 184 struct snd_ctl_elem_value *ucontrol); 185 int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, 186 struct snd_ctl_elem_value *ucontrol); 187 int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, 188 struct snd_ctl_elem_value *ucontrol); 189 int wm_adsp_fw_put(struct snd_kcontrol *kcontrol, 190 struct snd_ctl_elem_value *ucontrol); 191 192 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream); 193 int wm_adsp_compr_free(struct snd_soc_component *component, 194 struct snd_compr_stream *stream); 195 int wm_adsp_compr_set_params(struct snd_soc_component *component, 196 struct snd_compr_stream *stream, 197 struct snd_compr_params *params); 198 int wm_adsp_compr_get_caps(struct snd_soc_component *component, 199 struct snd_compr_stream *stream, 200 struct snd_compr_caps *caps); 201 int wm_adsp_compr_trigger(struct snd_soc_component *component, 202 struct snd_compr_stream *stream, int cmd); 203 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp); 204 int wm_adsp_compr_pointer(struct snd_soc_component *component, 205 struct snd_compr_stream *stream, 206 struct snd_compr_tstamp *tstamp); 207 int wm_adsp_compr_copy(struct snd_soc_component *component, 208 struct snd_compr_stream *stream, 209 char __user *buf, size_t count); 210 int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type, 211 unsigned int alg, void *buf, size_t len); 212 int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type, 213 unsigned int alg, void *buf, size_t len); 214 215 #endif 216