1 /* 2 * mtk-afe-fe-dais.c -- Mediatek afe fe dai operator 3 * 4 * Copyright (c) 2016 MediaTek Inc. 5 * Author: Garlic Tseng <garlic.tseng@mediatek.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 and 9 * only version 2 as published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #include <linux/module.h> 18 #include <linux/pm_runtime.h> 19 #include <linux/regmap.h> 20 #include <sound/soc.h> 21 #include "mtk-afe-platform-driver.h" 22 #include "mtk-afe-fe-dai.h" 23 #include "mtk-base-afe.h" 24 25 #define AFE_BASE_END_OFFSET 8 26 27 static int mtk_regmap_update_bits(struct regmap *map, int reg, 28 unsigned int mask, 29 unsigned int val) 30 { 31 if (reg < 0) 32 return 0; 33 return regmap_update_bits(map, reg, mask, val); 34 } 35 36 static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val) 37 { 38 if (reg < 0) 39 return 0; 40 return regmap_write(map, reg, val); 41 } 42 43 int mtk_afe_fe_startup(struct snd_pcm_substream *substream, 44 struct snd_soc_dai *dai) 45 { 46 struct snd_soc_pcm_runtime *rtd = substream->private_data; 47 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); 48 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); 49 struct snd_pcm_runtime *runtime = substream->runtime; 50 int memif_num = rtd->cpu_dai->id; 51 struct mtk_base_afe_memif *memif = &afe->memif[memif_num]; 52 const struct snd_pcm_hardware *mtk_afe_hardware = afe->mtk_afe_hardware; 53 int ret; 54 55 memif->substream = substream; 56 57 snd_pcm_hw_constraint_step(substream->runtime, 0, 58 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16); 59 /* enable agent */ 60 mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg, 61 1 << memif->data->agent_disable_shift, 62 0 << memif->data->agent_disable_shift); 63 64 snd_soc_set_runtime_hwparams(substream, mtk_afe_hardware); 65 66 /* 67 * Capture cannot use ping-pong buffer since hw_ptr at IRQ may be 68 * smaller than period_size due to AFE's internal buffer. 69 * This easily leads to overrun when avail_min is period_size. 70 * One more period can hold the possible unread buffer. 71 */ 72 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 73 int periods_max = mtk_afe_hardware->periods_max; 74 75 ret = snd_pcm_hw_constraint_minmax(runtime, 76 SNDRV_PCM_HW_PARAM_PERIODS, 77 3, periods_max); 78 if (ret < 0) { 79 dev_err(afe->dev, "hw_constraint_minmax failed\n"); 80 return ret; 81 } 82 } 83 84 ret = snd_pcm_hw_constraint_integer(runtime, 85 SNDRV_PCM_HW_PARAM_PERIODS); 86 if (ret < 0) 87 dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n"); 88 89 /* dynamic allocate irq to memif */ 90 if (memif->irq_usage < 0) { 91 int irq_id = mtk_dynamic_irq_acquire(afe); 92 93 if (irq_id != afe->irqs_size) { 94 /* link */ 95 memif->irq_usage = irq_id; 96 } else { 97 dev_err(afe->dev, "%s() error: no more asys irq\n", 98 __func__); 99 ret = -EBUSY; 100 } 101 } 102 return ret; 103 } 104 EXPORT_SYMBOL_GPL(mtk_afe_fe_startup); 105 106 void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream, 107 struct snd_soc_dai *dai) 108 { 109 struct snd_soc_pcm_runtime *rtd = substream->private_data; 110 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); 111 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); 112 struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 113 int irq_id; 114 115 irq_id = memif->irq_usage; 116 117 mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg, 118 1 << memif->data->agent_disable_shift, 119 1 << memif->data->agent_disable_shift); 120 121 if (!memif->const_irq) { 122 mtk_dynamic_irq_release(afe, irq_id); 123 memif->irq_usage = -1; 124 memif->substream = NULL; 125 } 126 } 127 EXPORT_SYMBOL_GPL(mtk_afe_fe_shutdown); 128 129 int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream, 130 struct snd_pcm_hw_params *params, 131 struct snd_soc_dai *dai) 132 { 133 struct snd_soc_pcm_runtime *rtd = substream->private_data; 134 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); 135 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); 136 struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 137 int msb_at_bit33 = 0; 138 int ret, fs = 0; 139 140 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 141 if (ret < 0) 142 return ret; 143 144 msb_at_bit33 = upper_32_bits(substream->runtime->dma_addr) ? 1 : 0; 145 memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr); 146 memif->buffer_size = substream->runtime->dma_bytes; 147 148 /* start */ 149 mtk_regmap_write(afe->regmap, memif->data->reg_ofs_base, 150 memif->phys_buf_addr); 151 /* end */ 152 mtk_regmap_write(afe->regmap, 153 memif->data->reg_ofs_base + AFE_BASE_END_OFFSET, 154 memif->phys_buf_addr + memif->buffer_size - 1); 155 156 /* set MSB to 33-bit */ 157 mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg, 158 1 << memif->data->msb_shift, 159 msb_at_bit33 << memif->data->msb_shift); 160 161 /* set channel */ 162 if (memif->data->mono_shift >= 0) { 163 unsigned int mono = (params_channels(params) == 1) ? 1 : 0; 164 165 mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg, 166 1 << memif->data->mono_shift, 167 mono << memif->data->mono_shift); 168 } 169 170 /* set rate */ 171 if (memif->data->fs_shift < 0) 172 return 0; 173 174 fs = afe->memif_fs(substream, params_rate(params)); 175 176 if (fs < 0) 177 return -EINVAL; 178 179 mtk_regmap_update_bits(afe->regmap, memif->data->fs_reg, 180 memif->data->fs_maskbit << memif->data->fs_shift, 181 fs << memif->data->fs_shift); 182 183 return 0; 184 } 185 EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_params); 186 187 int mtk_afe_fe_hw_free(struct snd_pcm_substream *substream, 188 struct snd_soc_dai *dai) 189 { 190 return snd_pcm_lib_free_pages(substream); 191 } 192 EXPORT_SYMBOL_GPL(mtk_afe_fe_hw_free); 193 194 int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd, 195 struct snd_soc_dai *dai) 196 { 197 struct snd_soc_pcm_runtime *rtd = substream->private_data; 198 struct snd_pcm_runtime * const runtime = substream->runtime; 199 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); 200 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); 201 struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 202 struct mtk_base_afe_irq *irqs = &afe->irqs[memif->irq_usage]; 203 const struct mtk_base_irq_data *irq_data = irqs->irq_data; 204 unsigned int counter = runtime->period_size; 205 int fs; 206 207 dev_dbg(afe->dev, "%s %s cmd=%d\n", __func__, memif->data->name, cmd); 208 209 switch (cmd) { 210 case SNDRV_PCM_TRIGGER_START: 211 case SNDRV_PCM_TRIGGER_RESUME: 212 if (memif->data->enable_shift >= 0) 213 mtk_regmap_update_bits(afe->regmap, 214 memif->data->enable_reg, 215 1 << memif->data->enable_shift, 216 1 << memif->data->enable_shift); 217 218 /* set irq counter */ 219 mtk_regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg, 220 irq_data->irq_cnt_maskbit 221 << irq_data->irq_cnt_shift, 222 counter << irq_data->irq_cnt_shift); 223 224 /* set irq fs */ 225 fs = afe->irq_fs(substream, runtime->rate); 226 227 if (fs < 0) 228 return -EINVAL; 229 230 mtk_regmap_update_bits(afe->regmap, irq_data->irq_fs_reg, 231 irq_data->irq_fs_maskbit 232 << irq_data->irq_fs_shift, 233 fs << irq_data->irq_fs_shift); 234 235 /* enable interrupt */ 236 mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg, 237 1 << irq_data->irq_en_shift, 238 1 << irq_data->irq_en_shift); 239 240 return 0; 241 case SNDRV_PCM_TRIGGER_STOP: 242 case SNDRV_PCM_TRIGGER_SUSPEND: 243 mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg, 244 1 << memif->data->enable_shift, 0); 245 /* disable interrupt */ 246 mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg, 247 1 << irq_data->irq_en_shift, 248 0 << irq_data->irq_en_shift); 249 /* and clear pending IRQ */ 250 mtk_regmap_write(afe->regmap, irq_data->irq_clr_reg, 251 1 << irq_data->irq_clr_shift); 252 return 0; 253 default: 254 return -EINVAL; 255 } 256 } 257 EXPORT_SYMBOL_GPL(mtk_afe_fe_trigger); 258 259 int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, 260 struct snd_soc_dai *dai) 261 { 262 struct snd_soc_pcm_runtime *rtd = substream->private_data; 263 struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); 264 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); 265 struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 266 int hd_audio = 0; 267 268 /* set hd mode */ 269 switch (substream->runtime->format) { 270 case SNDRV_PCM_FORMAT_S16_LE: 271 hd_audio = 0; 272 break; 273 case SNDRV_PCM_FORMAT_S32_LE: 274 hd_audio = 1; 275 break; 276 case SNDRV_PCM_FORMAT_S24_LE: 277 hd_audio = 1; 278 break; 279 default: 280 dev_err(afe->dev, "%s() error: unsupported format %d\n", 281 __func__, substream->runtime->format); 282 break; 283 } 284 285 mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg, 286 1 << memif->data->hd_shift, 287 hd_audio << memif->data->hd_shift); 288 289 return 0; 290 } 291 EXPORT_SYMBOL_GPL(mtk_afe_fe_prepare); 292 293 const struct snd_soc_dai_ops mtk_afe_fe_ops = { 294 .startup = mtk_afe_fe_startup, 295 .shutdown = mtk_afe_fe_shutdown, 296 .hw_params = mtk_afe_fe_hw_params, 297 .hw_free = mtk_afe_fe_hw_free, 298 .prepare = mtk_afe_fe_prepare, 299 .trigger = mtk_afe_fe_trigger, 300 }; 301 EXPORT_SYMBOL_GPL(mtk_afe_fe_ops); 302 303 static DEFINE_MUTEX(irqs_lock); 304 int mtk_dynamic_irq_acquire(struct mtk_base_afe *afe) 305 { 306 int i; 307 308 mutex_lock(&afe->irq_alloc_lock); 309 for (i = 0; i < afe->irqs_size; ++i) { 310 if (afe->irqs[i].irq_occupyed == 0) { 311 afe->irqs[i].irq_occupyed = 1; 312 mutex_unlock(&afe->irq_alloc_lock); 313 return i; 314 } 315 } 316 mutex_unlock(&afe->irq_alloc_lock); 317 return afe->irqs_size; 318 } 319 EXPORT_SYMBOL_GPL(mtk_dynamic_irq_acquire); 320 321 int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id) 322 { 323 mutex_lock(&afe->irq_alloc_lock); 324 if (irq_id >= 0 && irq_id < afe->irqs_size) { 325 afe->irqs[irq_id].irq_occupyed = 0; 326 mutex_unlock(&afe->irq_alloc_lock); 327 return 0; 328 } 329 mutex_unlock(&afe->irq_alloc_lock); 330 return -EINVAL; 331 } 332 EXPORT_SYMBOL_GPL(mtk_dynamic_irq_release); 333 334 int mtk_afe_dai_suspend(struct snd_soc_dai *dai) 335 { 336 struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); 337 struct device *dev = afe->dev; 338 struct regmap *regmap = afe->regmap; 339 int i; 340 341 if (pm_runtime_status_suspended(dev) || afe->suspended) 342 return 0; 343 344 if (!afe->reg_back_up) 345 afe->reg_back_up = 346 devm_kcalloc(dev, afe->reg_back_up_list_num, 347 sizeof(unsigned int), GFP_KERNEL); 348 349 for (i = 0; i < afe->reg_back_up_list_num; i++) 350 regmap_read(regmap, afe->reg_back_up_list[i], 351 &afe->reg_back_up[i]); 352 353 afe->suspended = true; 354 afe->runtime_suspend(dev); 355 return 0; 356 } 357 EXPORT_SYMBOL_GPL(mtk_afe_dai_suspend); 358 359 int mtk_afe_dai_resume(struct snd_soc_dai *dai) 360 { 361 struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); 362 struct device *dev = afe->dev; 363 struct regmap *regmap = afe->regmap; 364 int i = 0; 365 366 if (pm_runtime_status_suspended(dev) || !afe->suspended) 367 return 0; 368 369 afe->runtime_resume(dev); 370 371 if (!afe->reg_back_up) 372 dev_dbg(dev, "%s no reg_backup\n", __func__); 373 374 for (i = 0; i < afe->reg_back_up_list_num; i++) 375 mtk_regmap_write(regmap, afe->reg_back_up_list[i], 376 afe->reg_back_up[i]); 377 378 afe->suspended = false; 379 return 0; 380 } 381 EXPORT_SYMBOL_GPL(mtk_afe_dai_resume); 382 383 MODULE_DESCRIPTION("Mediatek simple fe dai operator"); 384 MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>"); 385 MODULE_LICENSE("GPL v2"); 386 387