Lines Matching full:dmic
24 #include "dmic.h"
30 /* global data shared between all dmic instances */
37 int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *spec_config);
115 static void dai_dmic_update_bits(const struct dai_intel_dmic *dmic, in dai_dmic_update_bits() argument
118 uint32_t dest = dmic->reg_base + reg; in dai_dmic_update_bits()
121 dmic->reg_base, reg, mask, val); in dai_dmic_update_bits()
126 static inline void dai_dmic_write(const struct dai_intel_dmic *dmic, in dai_dmic_write() argument
129 sys_write32(val, dmic->reg_base + reg); in dai_dmic_write()
132 static inline uint32_t dai_dmic_read(const struct dai_intel_dmic *dmic, in dai_dmic_read() argument
135 return sys_read32(dmic->reg_base + reg); in dai_dmic_read()
139 static inline void dai_dmic_claim_ownership(const struct dai_intel_dmic *dmic) in dai_dmic_claim_ownership() argument
141 /* DMIC Owner Select to DSP */ in dai_dmic_claim_ownership()
142 sys_write32(sys_read32(dmic->shim_base + DMICLCTL_OFFSET) | in dai_dmic_claim_ownership()
143 FIELD_PREP(DMICLCTL_OSEL, 0x3), dmic->shim_base + DMICLCTL_OFFSET); in dai_dmic_claim_ownership()
146 static inline void dai_dmic_release_ownership(const struct dai_intel_dmic *dmic) in dai_dmic_release_ownership() argument
148 /* DMIC Owner Select back to Host CPU + DSP */ in dai_dmic_release_ownership()
149 sys_write32(sys_read32(dmic->shim_base + DMICLCTL_OFFSET) & in dai_dmic_release_ownership()
150 ~DMICLCTL_OSEL, dmic->shim_base + DMICLCTL_OFFSET); in dai_dmic_release_ownership()
155 static inline void dai_dmic_claim_ownership(const struct dai_intel_dmic *dmic) {} in dai_dmic_claim_ownership() argument
156 static inline void dai_dmic_release_ownership(const struct dai_intel_dmic *dmic) {} in dai_dmic_release_ownership() argument
160 static inline uint32_t dai_dmic_base(const struct dai_intel_dmic *dmic) in dai_dmic_base() argument
163 return dmic->hdamldmic_base; in dai_dmic_base()
165 return dmic->shim_base; in dai_dmic_base()
170 static inline void dai_dmic_set_sync_period(uint32_t period, const struct dai_intel_dmic *dmic) in dai_dmic_set_sync_period() argument
173 uint32_t base = dai_dmic_base(dmic); in dai_dmic_set_sync_period()
174 /* DMIC Change sync period */ in dai_dmic_set_sync_period()
196 static inline void dai_dmic_clear_sync_period(const struct dai_intel_dmic *dmic) in dai_dmic_clear_sync_period() argument
198 uint32_t base = dai_dmic_base(dmic); in dai_dmic_clear_sync_period()
199 /* DMIC Clean sync period */ in dai_dmic_clear_sync_period()
207 static inline void dai_dmic_sync_prepare(const struct dai_intel_dmic *dmic) in dai_dmic_sync_prepare() argument
209 uint32_t base = dai_dmic_base(dmic); in dai_dmic_sync_prepare()
216 static void dmic_sync_trigger(const struct dai_intel_dmic *dmic) in dmic_sync_trigger() argument
218 uint32_t base = dai_dmic_base(dmic); in dmic_sync_trigger()
234 static inline void dai_dmic_set_sync_period(uint32_t period, const struct dai_intel_dmic *dmic) {} in dai_dmic_set_sync_period() argument
235 static inline void dai_dmic_clear_sync_period(const struct dai_intel_dmic *dmic) {} in dai_dmic_clear_sync_period() argument
236 static inline void dai_dmic_sync_prepare(const struct dai_intel_dmic *dmic) {} in dai_dmic_sync_prepare() argument
237 static void dmic_sync_trigger(const struct dai_intel_dmic *dmic) {} in dmic_sync_trigger() argument
241 static void dai_dmic_start_fifo_packers(struct dai_intel_dmic *dmic, int fifo_index) in dai_dmic_start_fifo_packers() argument
245 dai_dmic_update_bits(dmic, fifo_index * PDM_CHANNEL_REGS_SIZE + OUTCONTROL, in dai_dmic_start_fifo_packers()
250 static void dai_dmic_stop_fifo_packers(struct dai_intel_dmic *dmic, in dai_dmic_stop_fifo_packers() argument
254 dai_dmic_update_bits(dmic, fifo_index * PDM_CHANNEL_REGS_SIZE + OUTCONTROL, in dai_dmic_stop_fifo_packers()
259 /* On DMIC IRQ event trace the status register that contains the status and
264 struct dai_intel_dmic *dmic = ((struct device *)data)->data; in dai_dmic_irq_handler() local
269 val0 = dai_dmic_read(dmic, OUTSTAT); in dai_dmic_irq_handler()
270 val1 = dai_dmic_read(dmic, OUTSTAT + PDM_CHANNEL_REGS_SIZE); in dai_dmic_irq_handler()
275 dai_dmic_write(dmic, OUTSTAT, val0); in dai_dmic_irq_handler()
276 dai_dmic_stop_fifo_packers(dmic, 0); in dai_dmic_irq_handler()
281 dai_dmic_write(dmic, OUTSTAT + PDM_CHANNEL_REGS_SIZE, val1); in dai_dmic_irq_handler()
282 dai_dmic_stop_fifo_packers(dmic, 1); in dai_dmic_irq_handler()
286 static inline void dai_dmic_dis_clk_gating(const struct dai_intel_dmic *dmic) in dai_dmic_dis_clk_gating() argument
288 /* Disable DMIC clock gating */ in dai_dmic_dis_clk_gating()
290 sys_write32((sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET) | DMICLVSCTL_DCGD), in dai_dmic_dis_clk_gating()
291 dmic->vshim_base + DMICLVSCTL_OFFSET); in dai_dmic_dis_clk_gating()
293 sys_write32((sys_read32(dmic->shim_base + DMICLCTL_OFFSET) | DMICLCTL_DCGD), in dai_dmic_dis_clk_gating()
294 dmic->shim_base + DMICLCTL_OFFSET); in dai_dmic_dis_clk_gating()
298 static inline void dai_dmic_en_clk_gating(const struct dai_intel_dmic *dmic) in dai_dmic_en_clk_gating() argument
300 /* Enable DMIC clock gating */ in dai_dmic_en_clk_gating()
302 sys_write32((sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET) & ~DMICLVSCTL_DCGD), in dai_dmic_en_clk_gating()
303 dmic->vshim_base + DMICLVSCTL_OFFSET); in dai_dmic_en_clk_gating()
305 sys_write32((sys_read32(dmic->shim_base + DMICLCTL_OFFSET) & ~DMICLCTL_DCGD), in dai_dmic_en_clk_gating()
306 dmic->shim_base + DMICLCTL_OFFSET); in dai_dmic_en_clk_gating()
311 static inline void dai_dmic_program_channel_map(const struct dai_intel_dmic *dmic, in dai_dmic_program_channel_map() argument
317 uint32_t reg_add = dmic->shim_base + DMICXPCMSyCM_OFFSET + 0x0004*index; in dai_dmic_program_channel_map()
321 ARG_UNUSED(dmic); in dai_dmic_program_channel_map()
327 static inline void dai_dmic_en_power(const struct dai_intel_dmic *dmic) in dai_dmic_en_power() argument
329 uint32_t base = dai_dmic_base(dmic); in dai_dmic_en_power()
330 /* Enable DMIC power */ in dai_dmic_en_power()
341 static inline void dai_dmic_dis_power(const struct dai_intel_dmic *dmic) in dai_dmic_dis_power() argument
343 uint32_t base = dai_dmic_base(dmic); in dai_dmic_dis_power()
344 /* Disable DMIC power */ in dai_dmic_dis_power()
349 static int dai_dmic_probe(struct dai_intel_dmic *dmic) in dai_dmic_probe() argument
354 dmic->state = DAI_STATE_NOT_READY; in dai_dmic_probe()
356 /* Enable DMIC power */ in dai_dmic_probe()
357 dai_dmic_en_power(dmic); in dai_dmic_probe()
359 /* Disable dynamic clock gating for dmic before touching any reg */ in dai_dmic_probe()
360 dai_dmic_dis_clk_gating(dmic); in dai_dmic_probe()
362 /* DMIC Change sync period */ in dai_dmic_probe()
363 dai_dmic_set_sync_period(CONFIG_DAI_DMIC_PLATFORM_SYNC_PERIOD, dmic); in dai_dmic_probe()
365 /* DMIC Owner Select to DSP */ in dai_dmic_probe()
366 dai_dmic_claim_ownership(dmic); in dai_dmic_probe()
368 irq_enable(dmic->irq); in dai_dmic_probe()
373 static int dai_dmic_remove(struct dai_intel_dmic *dmic) in dai_dmic_remove() argument
380 irq_disable(dmic->irq); in dai_dmic_remove()
392 /* Disable DMIC clock and power */ in dai_dmic_remove()
393 dai_dmic_en_clk_gating(dmic); in dai_dmic_remove()
394 dai_dmic_dis_power(dmic); in dai_dmic_remove()
396 /* DMIC Clean sync period */ in dai_dmic_remove()
397 dai_dmic_clear_sync_period(dmic); in dai_dmic_remove()
399 /* DMIC Owner Select back to Host CPU + DSP */ in dai_dmic_remove()
400 dai_dmic_release_ownership(dmic); in dai_dmic_remove()
417 /* Set DMIC timestamp registers */ in dai_timestamp_dmic_start()
419 /* First point CDMAS to GPDMA channel that is used by DMIC in dai_timestamp_dmic_start()
442 /* Read DMIC timestamp registers */ in dai_timestamp_dmic_get()
469 static void dai_dmic_gain_ramp(struct dai_intel_dmic *dmic) in dai_dmic_gain_ramp() argument
476 /* Currently there's no DMIC HW internal mutings and wait times in dai_dmic_gain_ramp()
481 LOG_DBG("DMIC gain ramp"); in dai_dmic_gain_ramp()
484 * At run-time dmic->gain is only changed in this function, and this in dai_dmic_gain_ramp()
490 if (dmic->gain == DMIC_HW_FIR_GAIN_MAX << 11) in dai_dmic_gain_ramp()
493 key = k_spin_lock(&dmic->lock); in dai_dmic_gain_ramp()
498 dmic->startcount++; in dai_dmic_gain_ramp()
499 dmic->gain = q_multsr_sat_32x32(dmic->gain, dmic->gain_coef, Q_SHIFT_GAIN_X_GAIN_COEF); in dai_dmic_gain_ramp()
504 gval = dmic->gain >> 11; in dai_dmic_gain_ramp()
506 /* Note that DMIC gain value zero has a special purpose. Value zero in dai_dmic_gain_ramp()
512 dmic->gain = DMIC_HW_FIR_GAIN_MAX << 11; in dai_dmic_gain_ramp()
517 if (!dmic->enable[i]) in dai_dmic_gain_ramp()
520 if (dmic->startcount == DMIC_UNMUTE_CIC) in dai_dmic_gain_ramp()
521 dai_dmic_update_bits(dmic, dmic_base[i] + CIC_CONTROL, in dai_dmic_gain_ramp()
524 if (dmic->startcount == DMIC_UNMUTE_FIR) { in dai_dmic_gain_ramp()
525 dai_dmic_update_bits(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * in dai_dmic_gain_ramp()
526 dmic->dai_config_params.dai_index + FIR_CONTROL, in dai_dmic_gain_ramp()
532 dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * in dai_dmic_gain_ramp()
533 dmic->dai_config_params.dai_index + OUT_GAIN_LEFT, val); in dai_dmic_gain_ramp()
534 dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * in dai_dmic_gain_ramp()
535 dmic->dai_config_params.dai_index + OUT_GAIN_RIGHT, val); in dai_dmic_gain_ramp()
537 dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * in dai_dmic_gain_ramp()
538 dmic->dai_config_params.dai_index + OUT_GAIN_LEFT, in dai_dmic_gain_ramp()
539 dmic->gain_left); in dai_dmic_gain_ramp()
540 dai_dmic_write(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * in dai_dmic_gain_ramp()
541 dmic->dai_config_params.dai_index + OUT_GAIN_RIGHT, in dai_dmic_gain_ramp()
542 dmic->gain_right); in dai_dmic_gain_ramp()
546 k_spin_unlock(&dmic->lock, key); in dai_dmic_gain_ramp()
549 static void dai_dmic_start(struct dai_intel_dmic *dmic) in dai_dmic_start() argument
558 key = k_spin_lock(&dmic->lock); in dai_dmic_start()
559 LOG_DBG("dmic_start(), dai_index = %d", dmic->dai_config_params.dai_index); in dai_dmic_start()
560 dmic->startcount = 0; in dai_dmic_start()
563 dmic->gain_coef = db2lin_fixed(LOGRAMP_CONST_TERM / dmic->unmute_time_ms); in dai_dmic_start()
566 dmic->gain = Q_SHIFT_LEFT(db2lin_fixed(LOGRAMP_START_DB), 20, 30); in dai_dmic_start()
568 dai_dmic_sync_prepare(dmic); in dai_dmic_start()
570 dai_dmic_start_fifo_packers(dmic, dmic->dai_config_params.dai_index); in dai_dmic_start()
574 dai_dmic_update_bits(dmic, dmic_base[i] + CIC_CONTROL, in dai_dmic_start()
578 dai_dmic_read(dmic, dmic_base[i] + CIC_CONTROL)); in dai_dmic_start()
581 mic_a = dmic->enable[i] & 1; in dai_dmic_start()
582 mic_b = (dmic->enable[i] & 2) >> 1; in dai_dmic_start()
583 start_fir = dmic->enable[i] > 0; in dai_dmic_start()
592 dai_dmic_update_bits(dmic, dmic_base[i] + CIC_CONTROL, in dai_dmic_start()
597 dai_dmic_update_bits(dmic, dmic_base[i] + MIC_CONTROL, in dai_dmic_start()
603 dai_dmic_update_bits(dmic, dmic_base[i] + CIC_CONTROL, in dai_dmic_start()
606 dai_dmic_update_bits(dmic, dmic_base[i] + MIC_CONTROL, in dai_dmic_start()
610 dai_dmic_update_bits(dmic, dmic_base[i] + CIC_CONTROL, in dai_dmic_start()
613 dai_dmic_update_bits(dmic, dmic_base[i] + MIC_CONTROL, in dai_dmic_start()
618 dai_dmic_update_bits(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * in dai_dmic_start()
619 dmic->dai_config_params.dai_index + FIR_CONTROL, in dai_dmic_start()
629 dai_dmic_update_bits(dmic, dmic_base[i] + CIC_CONTROL, in dai_dmic_start()
633 dai_dmic_read(dmic, dmic_base[i] + CIC_CONTROL)); in dai_dmic_start()
638 dai_dmic_global.active_fifos_mask |= BIT(dmic->dai_config_params.dai_index); in dai_dmic_start()
639 dai_dmic_global.pause_mask &= ~BIT(dmic->dai_config_params.dai_index); in dai_dmic_start()
641 dmic->state = DAI_STATE_RUNNING; in dai_dmic_start()
642 k_spin_unlock(&dmic->lock, key); in dai_dmic_start()
644 dmic_sync_trigger(dmic); in dai_dmic_start()
650 static void dai_dmic_stop(struct dai_intel_dmic *dmic, bool stop_is_pause) in dai_dmic_stop() argument
656 key = k_spin_lock(&dmic->lock); in dai_dmic_stop()
658 dai_dmic_stop_fifo_packers(dmic, dmic->dai_config_params.dai_index); in dai_dmic_stop()
664 /* Clear bit dmic->dai_config_params.dai_index for active FIFO. in dai_dmic_stop()
668 dai_dmic_global.active_fifos_mask &= ~BIT(dmic->dai_config_params.dai_index); in dai_dmic_stop()
670 dai_dmic_global.pause_mask |= BIT(dmic->dai_config_params.dai_index); in dai_dmic_stop()
672 dai_dmic_global.pause_mask &= ~BIT(dmic->dai_config_params.dai_index); in dai_dmic_stop()
677 dai_dmic_update_bits(dmic, dmic_base[i] + CIC_CONTROL, in dai_dmic_stop()
683 dai_dmic_update_bits(dmic, dmic_base[i] + FIR_CHANNEL_REGS_SIZE * in dai_dmic_stop()
684 dmic->dai_config_params.dai_index + FIR_CONTROL, in dai_dmic_stop()
689 k_spin_unlock(&dmic->lock, key); in dai_dmic_stop()
696 const struct dai_intel_dmic *dmic = (const struct dai_intel_dmic *)dev->data; in dai_dmic_get_properties() local
699 prop->fifo_address = dmic->fifo.offset; in dai_dmic_get_properties()
700 prop->fifo_depth = dmic->fifo.depth; in dai_dmic_get_properties()
701 prop->dma_hs_id = dmic->fifo.handshake; in dai_dmic_get_properties()
710 struct dai_intel_dmic *dmic = (struct dai_intel_dmic *)dev->data; in dai_dmic_trigger() local
721 if (dmic->state == DAI_STATE_PAUSED || in dai_dmic_trigger()
722 dmic->state == DAI_STATE_PRE_RUNNING) { in dai_dmic_trigger()
723 dai_dmic_start(dmic); in dai_dmic_trigger()
724 dmic->state = DAI_STATE_RUNNING; in dai_dmic_trigger()
726 LOG_ERR("dmic_trigger(): state is not prepare or paused, dmic->state = %u", in dai_dmic_trigger()
727 dmic->state); in dai_dmic_trigger()
731 dai_dmic_stop(dmic, false); in dai_dmic_trigger()
732 dmic->state = DAI_STATE_PRE_RUNNING; in dai_dmic_trigger()
735 dai_dmic_stop(dmic, true); in dai_dmic_trigger()
736 dmic->state = DAI_STATE_PAUSED; in dai_dmic_trigger()
739 dai_dmic_gain_ramp(dmic); in dai_dmic_trigger()
750 struct dai_intel_dmic *dmic = (struct dai_intel_dmic *)dev->data; in dai_dmic_get_config() local
760 *cfg = dmic->dai_config_params; in dai_dmic_get_config()
769 struct dai_intel_dmic *dmic = (struct dai_intel_dmic *)dev->data; in dai_dmic_set_config() local
771 int di = dmic->dai_config_params.dai_index; in dai_dmic_set_config()
786 dai_dmic_program_channel_map(dmic, cfg, di); in dai_dmic_set_config()
788 key = k_spin_lock(&dmic->lock); in dai_dmic_set_config()
791 #error DMIC TPLG is not yet implemented in dai_dmic_set_config()
794 ret = dai_dmic_set_config_nhlt(dmic, bespoke_cfg); in dai_dmic_set_config()
797 dmic->unmute_time_ms = dmic_get_unmute_ramp_from_samplerate(dmic->dai_config_params.rate); in dai_dmic_set_config()
799 #error No DMIC config selected in dai_dmic_set_config()
807 dmic->state = DAI_STATE_PRE_RUNNING; in dai_dmic_set_config()
810 k_spin_unlock(&dmic->lock, key); in dai_dmic_set_config()
816 struct dai_intel_dmic *dmic = (struct dai_intel_dmic *)dev->data; in dai_dmic_probe_wrapper() local
820 key = k_spin_lock(&dmic->lock); in dai_dmic_probe_wrapper()
822 if (dmic->sref == 0) { in dai_dmic_probe_wrapper()
823 ret = dai_dmic_probe(dmic); in dai_dmic_probe_wrapper()
827 dmic->sref++; in dai_dmic_probe_wrapper()
830 k_spin_unlock(&dmic->lock, key); in dai_dmic_probe_wrapper()
837 struct dai_intel_dmic *dmic = (struct dai_intel_dmic *)dev->data; in dai_dmic_remove_wrapper() local
841 key = k_spin_lock(&dmic->lock); in dai_dmic_remove_wrapper()
843 if (--dmic->sref == 0) { in dai_dmic_remove_wrapper()
844 ret = dai_dmic_remove(dmic); in dai_dmic_remove_wrapper()
847 k_spin_unlock(&dmic->lock, key); in dai_dmic_remove_wrapper()