| // SPDX-License-Identifier: GPL-2.0 |
| /* Copyright (C) 2018 Synaptics Incorporated */ |
| |
| #include <linux/module.h> |
| #include <linux/init.h> |
| #include <linux/spinlock.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/delay.h> |
| #include <linux/input.h> |
| |
| #include <sound/core.h> |
| #include <sound/pcm.h> |
| #include <sound/pcm_params.h> |
| #include <sound/soc.h> |
| |
| #include "api_avio_dhub.h" |
| #include "api_dhub.h" |
| #include "berlin_pcm.h" |
| #include "berlin_capture.h" |
| |
| #define CIC_MAX_DECIMATION_FACTOR 128 |
| #define CIC_MAX_ORDER 5 |
| /* For every 32 bit PCM sample there are |decimation| PDM bits. Since |
| * decimation factor is always a multiple of 32, the PDM buffer sizes are |
| * integer multiples of the PCM buffer sizes. |
| * When adjusting buffer size, check snd_pcm_lib_preallocate_pages_for_all() in |
| * pcm.c. |
| */ |
| #define PCM_SAMPLE_BITS 32 |
| #define PDM_MAX_DMA_BUFFER_SIZE (MAX_CHID * 0x8000) |
| #define PDM_MAX_BUFFER_SIZE (MAX_CHID * 0x10000) |
| #define PCM_DMA_BUFFER_SIZE \ |
| (PDM_MAX_DMA_BUFFER_SIZE / \ |
| (CIC_MAX_DECIMATION_FACTOR / PCM_SAMPLE_BITS)) |
| #define PCM_DMA_MIN_SIZE (PCM_DMA_BUFFER_SIZE >> 1) |
| #define PCM_MAX_BUFFER_SIZE \ |
| (PDM_MAX_BUFFER_SIZE / \ |
| (CIC_MAX_DECIMATION_FACTOR / PCM_SAMPLE_BITS)) |
| |
| #define MUTE_THRESHOLD_MS 300 |
| |
| typedef enum { |
| BERLIN_MIC_MUTE_STATE_UNKNOWN = -1, |
| BERLIN_MIC_MUTE_STATE_UNMUTE = 0, |
| BERLIN_MIC_MUTE_STATE_MUTE = 1 |
| } BERLIN_MIC_MUTE_STATE; |
| |
| struct dc_canceller { |
| int32_t alpha; |
| int32_t last_input; |
| int32_t last_output; |
| }; |
| |
| struct cic_decimator { |
| u32 integrator_stage[CIC_MAX_ORDER]; |
| u32 comb_stage[CIC_MAX_ORDER]; |
| s32 order; |
| s32 decimation; |
| s32 bmax; |
| s32 (*process)(struct cic_decimator *cic, struct dc_canceller *dcc, |
| int32_t sample_rate, uint32_t *data); |
| }; |
| |
| struct berlin_capture { |
| /* |
| * Tracks the base address of the last submitted DMA block. |
| * Moved to next period in ISR. |
| * read in berlin_playback_pointer. |
| */ |
| u32 current_dma_offset; |
| /* |
| * Offset of the next DMA buffer that needs to be decimated in bytes. |
| * Since it is only read/written on a work queue thread, |
| * it does not need locking. |
| */ |
| u32 read_offset; |
| /* |
| * Offset in bytes at which decoded PCM data is being written. |
| * Writing should only be done on a work queue thread; must be locked. |
| * Reading on a work queue thread does not require locking. |
| * Reading outside of a work queue thread requires locking. |
| */ |
| u32 runtime_offset; |
| /* |
| * Number of bytes read but not decoded yet. |
| * Read and write under lock. |
| */ |
| u32 cnt; |
| /* |
| * Is there a submitted DMA request? |
| * Set when a DMA request is submitted to DHUB. |
| * Cleared on 'stop' or ISR. |
| */ |
| bool dma_pending; |
| |
| /* |
| * Indicates if page memory is allocated |
| */ |
| bool pages_allocated; |
| |
| /* |
| * Instance lock between ISR and higher contexts. |
| */ |
| spinlock_t lock; |
| |
| /* DMA buffer */ |
| u8 *dma_area[MAX_CHID]; |
| dma_addr_t dma_addr[MAX_CHID]; |
| u32 dma_bytes_total; |
| u32 dma_bytes_ch; |
| u32 dma_period_total; |
| u32 dma_period_ch; |
| |
| /* hw parameter */ |
| u32 fs; |
| u32 sample_format; |
| u32 channel_num; |
| u32 chid[MAX_CHID]; |
| u32 chid_num; |
| u32 max_ch_inuse; //define how many ch actually used |
| u32 mode; // I2SI_MODE OR PDMI_MODE |
| |
| /* capture status */ |
| bool capturing; |
| |
| struct snd_pcm_substream *ss; |
| struct cic_decimator cic[MAX_CHANNELS]; |
| struct dc_canceller dcc[MAX_CHANNELS]; |
| struct workqueue_struct *wq; |
| struct delayed_work delayed_work; |
| BERLIN_MIC_MUTE_STATE mic_mute_state; |
| u32 zero_chunk_count; |
| struct input_dev *mic_mute; |
| struct berlin_chip *chip; |
| }; |
| |
| static u32 bc_rates[] = { |
| 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000 |
| }; |
| |
| static struct snd_pcm_hw_constraint_list berlin_constraints_rates = { |
| .count = ARRAY_SIZE(bc_rates), |
| .list = bc_rates, |
| .mask = 0, |
| }; |
| |
| /* must always be called under lock. */ |
| static void start_dma_if_needed(struct snd_pcm_substream *ss) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| dma_addr_t dma_src; |
| u32 ch, dma_size, i; |
| bool intr = true; |
| |
| assert_spin_locked(&bc->lock); |
| |
| if (!bc->capturing) { |
| snd_printd("%s: capturing: %u\n", __func__, bc->capturing); |
| return; |
| } |
| |
| if (bc->dma_pending) { |
| snd_printd("%s: DMA pending. Skipping DMA start.\n", __func__); |
| return; |
| } |
| |
| if (bc->cnt > (bc->dma_bytes_ch - bc->dma_period_ch) * bc->chid_num) { |
| berlin_report_xrun(bc->chip, PCM_OVERRUN); |
| snd_printk("%s: overrun: PCM convert too slow.[c%d w%d r%d]\n", |
| __func__, |
| bc->cnt, bc->current_dma_offset, bc->read_offset); |
| return; |
| } |
| |
| for (i = 0; i < bc->chid_num; i++) { |
| ch = bc->chid[i]; |
| dma_src = bc->dma_addr[i] + bc->current_dma_offset; |
| dma_size = bc->dma_period_ch; |
| bc->dma_pending = true; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, ch, |
| dma_src, dma_size, 0, 0, 0, intr, |
| 0, 0); |
| intr = false; |
| } |
| } |
| |
| static void berlin_capture_trigger_start(struct snd_pcm_substream *ss) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| unsigned long flags; |
| dma_addr_t dma_src; |
| u32 dma_size, i, c, ch; |
| bool intr = true; |
| u32 skip_dma_size = 1; |
| u32 queue_dma_cmd_size = 2; |
| |
| spin_lock_irqsave(&bc->lock, flags); |
| if (bc->capturing) { |
| spin_unlock_irqrestore(&bc->lock, flags); |
| return; |
| } |
| |
| bc->capturing = true; |
| |
| dma_size = bc->dma_period_ch; |
| // Queue two DMA commands when trigger start to avoid FIFO overrun |
| /* In each interrupt, write one DMA command, so if interrupts are |
| * handled in time, there will always be 2 DMA commands in queue. |
| * The first interrupt will be raised and stay asserted until cleared. |
| * If the first interrupt isn’t cleared before the second interrupt is |
| * raised, the interrupt line stays asserted. |
| * The overrun happens when IRQ is disabled for longer than 8 ms, such |
| * that IRQ is not served and the next DMA is not set up in time before |
| * FIFO being filled up. |
| * The calculation is based on FIFO size = 2048 bytes, 16khz sampling |
| * rate, stereo and 64 bits per sample for PDM data. |
| * PDM_MAX_DMA_BUFFER_SIZE / (DECIMATION_FACTOR / 32) / |
| * (2 channels * 4 bytes / sample) / (16000 frames / second) |
| * 4096 / (128 / 32) / 8 / 16000 = 0.008 sec |
| * Queueing 2 DMA commands will relax the limit to ~16ms |
| */ |
| // We intentionally let the dma_src in dhub_channel_write_cmd |
| // be the same in the for-loop, because the data in the first few DMA |
| // blocks may be corrupted and we just ignore them. |
| for (i = 0; i < skip_dma_size; i++) { |
| // skip dma cmd will not trigger interrupt |
| intr = false; |
| for (c = 0; c < bc->chid_num; c++) { |
| ch = bc->chid[c]; |
| dma_src = bc->dma_addr[c] + bc->current_dma_offset; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, ch, |
| dma_src, dma_size, 0, 0, 0, intr, |
| 0, 0); |
| } |
| } |
| |
| for (i = 0; i < queue_dma_cmd_size; i++) { |
| intr = true; |
| for (c = 0; c < bc->chid_num; c++) { |
| ch = bc->chid[c]; |
| dma_src = bc->dma_addr[c] + bc->current_dma_offset; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, ch, |
| dma_src, dma_size, 0, 0, 0, intr, |
| 0, 0); |
| intr = false; |
| } |
| if (i < queue_dma_cmd_size - 1) |
| bc->current_dma_offset += dma_size; |
| } |
| bc->dma_pending = true; |
| |
| spin_unlock_irqrestore(&bc->lock, flags); |
| } |
| |
| static void berlin_capture_trigger_stop(struct snd_pcm_substream *ss) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| unsigned long flags; |
| |
| spin_lock_irqsave(&bc->lock, flags); |
| bc->capturing = false; |
| bc->dma_pending = false; |
| spin_unlock_irqrestore(&bc->lock, flags); |
| } |
| |
| static const struct snd_pcm_hardware berlin_capture_hw = { |
| .info = (SNDRV_PCM_INFO_MMAP |
| | SNDRV_PCM_INFO_INTERLEAVED |
| | SNDRV_PCM_INFO_MMAP_VALID |
| | SNDRV_PCM_INFO_PAUSE |
| | SNDRV_PCM_INFO_RESUME), |
| .formats = (SNDRV_PCM_FMTBIT_S32_LE |
| | SNDRV_PCM_FMTBIT_S24_LE |
| | SNDRV_PCM_FMTBIT_S16_LE), |
| .rates = (SNDRV_PCM_RATE_8000_96000 |
| | SNDRV_PCM_RATE_KNOT), |
| .channels_min = MIN_CHANNELS, |
| .channels_max = MAX_CHANNELS, |
| .buffer_bytes_max = PCM_MAX_BUFFER_SIZE, |
| .period_bytes_min = PCM_DMA_MIN_SIZE, |
| .period_bytes_max = PCM_DMA_BUFFER_SIZE, |
| .periods_min = PCM_MAX_BUFFER_SIZE / PCM_DMA_BUFFER_SIZE, |
| .periods_max = PCM_MAX_BUFFER_SIZE / PCM_DMA_MIN_SIZE, |
| .fifo_size = 0 |
| }; |
| |
| /* |
| * This is a passive first-order high pass filter as seen at |
| * https://en.wikipedia.org/wiki/High-pass_filter#Algorithmic_implementation |
| * If f_c = 10 Hz is the frequency cutoff and dt is 1/sample_rate, |
| * then alpha = RC / (RC + dt) |
| * = 1 / (2*pi*f_c * (1/(2*pi*f_c) + dt)) |
| * = 1 / (1 + dt * 2*pi*f_c) |
| * = 0.998 (48 kHz capture) or 0.999 (44.1 kHz capture) |
| * to avoid the float pointer operation, calculate the alpha below: |
| * only 3 frequencies are supported. others would have larger deviation. |
| * The deviation of supported frequency is small. |
| * 1. 96K 60Hz |
| * 0.996088373408729 |
| * N is 8 |
| * |
| * 2. 48K 60Hz |
| * 0.992207229226833 |
| * N is 7 |
| * |
| * 3. 24K 60Hz |
| * 0.984534973857397 |
| * N is 6 |
| */ |
| static int32_t dc_canceller_process(struct dc_canceller *dcc, |
| int32_t sample_rate, int32_t input) |
| { |
| /* formula is: y[i] := α * (y[i-1] + x[i] - x[i-1])*/ |
| int32_t output, n, tmp_val; |
| |
| switch (sample_rate) { |
| case 24000: |
| n = 6; |
| break; |
| case 48000: |
| n = 7; |
| break; |
| case 96000: |
| n = 8; |
| break; |
| default: |
| /* unsupported frequency */ |
| n = -1; |
| break; |
| } |
| /* Y = (1 - 1/2^n) * (y[i-1] + x[i] - x[i-1])*/ |
| if (n > 0) { |
| tmp_val = (input - dcc->last_input + dcc->last_output); |
| output = tmp_val - |
| (tmp_val >> n); |
| dcc->last_input = input; |
| dcc->last_output = output; |
| return output; |
| } |
| snd_printk("invalid sample frequency, skip HFP:%d\n", sample_rate); |
| return input; |
| } |
| |
| static s32 cic_decimator_process(struct cic_decimator *cic, |
| struct dc_canceller *dcc, |
| s32 sample_rate, u32 *data) |
| { |
| return cic->process(cic, dcc, sample_rate, data); |
| } |
| |
| static s32 cic_decimator_process_o4_128x(struct cic_decimator *cic, |
| struct dc_canceller *dcc, |
| s32 sample_rate, u32 *data) |
| { |
| const s32 decimation = 128; |
| const s32 order = 4; |
| s32 block, i, stage; |
| s32 acc, old_acc; |
| |
| for (block = 0; block < decimation / PCM_SAMPLE_BITS; ++block) { |
| uint32_t bits = data[2 * block]; |
| |
| for (i = 0; i < PCM_SAMPLE_BITS; ++i) { |
| acc = ((s32)(bits & 1) << 1) - 1; |
| for (stage = 0; stage < order; ++stage) |
| acc = (cic->integrator_stage[stage] += acc); |
| bits >>= 1; |
| } |
| } |
| |
| acc = cic->integrator_stage[order - 1]; |
| for (stage = 0; stage < order; ++stage) { |
| old_acc = acc; |
| acc -= cic->comb_stage[stage]; |
| cic->comb_stage[stage] = old_acc; |
| } |
| /* apply the HPF here to avoid overflow */ |
| acc = dc_canceller_process(dcc, sample_rate, acc); |
| /* |
| * Normalize output so that a PDM bitstream of all 1s gives |
| * PCM data that eventually settles at INT32_MAX, and a PDM bitstream of |
| * all 0s gives PCM data that eventually settles at INT32_MIN. |
| */ |
| return (acc >= (1 << 28)) ? 0x7fffffff : (acc * 8); |
| } |
| |
| static s32 cic_decimator_process_o5_64x(struct cic_decimator *cic, |
| struct dc_canceller *dcc, |
| s32 sample_rate, u32 *data) |
| { |
| const s32 decimation = 64; |
| const s32 order = 5; |
| s32 block, i, stage; |
| s32 acc, old_acc; |
| |
| for (block = 0; block < decimation / PCM_SAMPLE_BITS; ++block) { |
| u32 bits = data[2 * block]; |
| |
| for (i = 0; i < PCM_SAMPLE_BITS; ++i) { |
| acc = ((s32)(bits & 1) << 1) - 1; |
| for (stage = 0; stage < order; ++stage) |
| acc = (cic->integrator_stage[stage] += acc); |
| bits >>= 1; |
| } |
| } |
| |
| acc = cic->integrator_stage[order - 1]; |
| for (stage = 0; stage < order; ++stage) { |
| old_acc = acc; |
| acc -= cic->comb_stage[stage]; |
| cic->comb_stage[stage] = old_acc; |
| } |
| |
| /* apply the HPF here to avoid overflow */ |
| acc = dc_canceller_process(dcc, sample_rate, acc); |
| /* |
| * Normalize output so that a PDM bitstream of all 1s gives |
| * PCM data that eventually settles at INT32_MAX, and a PDM bitstream of |
| * all 0s gives PCM data that eventually settles at INT32_MIN. |
| */ |
| return (acc >= (1 << 30)) ? 0x7fffffff : (acc * 2); |
| } |
| |
| static s32 cic_decimator_process_o5_32x(struct cic_decimator *cic, |
| struct dc_canceller *dcc, |
| s32 sample_rate, u32 *data) |
| { |
| const s32 decimation = 32; |
| const s32 order = 5; |
| s32 block, i, stage; |
| s32 acc, old_acc; |
| |
| for (block = 0; block < decimation / PCM_SAMPLE_BITS; ++block) { |
| u32 bits = data[2 * block]; |
| |
| for (i = 0; i < PCM_SAMPLE_BITS; ++i) { |
| acc = ((s32)(bits & 1) << 1) - 1; |
| for (stage = 0; stage < order; ++stage) |
| acc = (cic->integrator_stage[stage] += acc); |
| bits >>= 1; |
| } |
| } |
| |
| acc = cic->integrator_stage[order - 1]; |
| for (stage = 0; stage < order; ++stage) { |
| old_acc = acc; |
| acc -= cic->comb_stage[stage]; |
| cic->comb_stage[stage] = old_acc; |
| } |
| |
| /* apply the HPF here to avoid overflow */ |
| acc = dc_canceller_process(dcc, sample_rate, acc); |
| /* |
| * Normalize output so that a PDM bitstream of all 1s gives |
| * PCM data that eventually settles at INT32_MAX, and a PDM bitstream of |
| * all 0s gives PCM data that eventually settles at INT32_MIN. |
| */ |
| return (acc >= (1 << 25)) ? 0x7fffffff : (acc * 64); |
| } |
| |
| static s32 cic_decimator_process_general(struct cic_decimator *cic, |
| struct dc_canceller *dcc, |
| int32_t sample_rate, |
| uint32_t *data) |
| { |
| s32 block, i, stage; |
| s32 acc, old_acc; |
| |
| // decimation must be a multiple of 32. |
| for (block = 0; block < cic->decimation / PCM_SAMPLE_BITS; |
| ++block) { |
| u32 bits = data[2 * block]; |
| |
| for (i = 0; i < PCM_SAMPLE_BITS; ++i) { |
| acc = ((s32)(bits & 1) << 1) - 1; |
| for (stage = 0; stage < cic->order; ++stage) |
| acc = (cic->integrator_stage[stage] += acc); |
| bits >>= 1; |
| } |
| } |
| |
| acc = cic->integrator_stage[cic->order - 1]; |
| for (stage = 0; stage < cic->order; ++stage) { |
| old_acc = acc; |
| acc -= cic->comb_stage[stage]; |
| cic->comb_stage[stage] = old_acc; |
| } |
| |
| /* apply the HPF here to avoid overflow */ |
| acc = dc_canceller_process(dcc, sample_rate, acc); |
| /* |
| * Normalize output so that a PDM bitstream of all 1s gives |
| * PCM data that eventually settles at INT32_MAX, and a PDM bitstream of |
| * all 0s gives PCM data that eventually settles at INT32_MIN. |
| */ |
| return (acc >= |
| (1 << (cic->bmax - 1))) ? |
| 0x7fffffff : (acc * (2 << (31 - cic->bmax))); |
| } |
| |
| static void cic_decimator_init(struct cic_decimator *cic, s32 decimation, |
| s32 order) |
| { |
| memset(cic, 0, sizeof(*cic)); |
| cic->decimation = decimation; |
| cic->order = order; |
| /* |
| * CIC_BMAX = ceil(CIC_ORDER * log2(CIC_DECIMATION_FACTOR * M) |
| * + BITWIDTH_IN) |
| * with M = 1 and BITWIDTH_IN = 1. |
| */ |
| cic->bmax = order * ilog2(decimation) + 1; |
| if (cic->order == 4 && cic->decimation == 128) |
| cic->process = &cic_decimator_process_o4_128x; |
| else if (cic->order == 5 && cic->decimation == 64) |
| cic->process = &cic_decimator_process_o5_64x; |
| else if (cic->order == 5 && cic->decimation == 32) |
| cic->process = &cic_decimator_process_o5_32x; |
| else |
| cic->process = &cic_decimator_process_general; |
| } |
| |
| static int cic_order_from_rate(int sample_rate) |
| { |
| switch (sample_rate) { |
| case 8000: |
| case 11025: |
| case 12000: |
| case 16000: |
| case 22050: |
| case 24000: |
| return 4; |
| case 32000: |
| case 44100: |
| case 48000: |
| case 64000: |
| case 88200: |
| case 96000: |
| return 5; |
| default: |
| break; |
| } |
| return 0; |
| } |
| |
| static int cic_decimation_factor_from_rate(int sample_rate) |
| { |
| switch (sample_rate) { |
| case 8000: |
| case 11025: |
| case 12000: |
| case 16000: |
| case 22050: |
| case 24000: |
| return 128; |
| case 32000: |
| case 44100: |
| case 48000: |
| return 64; |
| case 64000: |
| case 88200: |
| case 96000: |
| return 32; |
| default: |
| break; |
| } |
| return 0; |
| } |
| |
| /* |
| * This is used for checking if stream data is zeros |
| */ |
| static bool is_all_zero(const void *data, size_t length) |
| { |
| const unsigned char *p = data; |
| size_t loop = 0; |
| |
| for (loop = 0; loop < 16; loop++) { |
| if (!length) |
| return true; |
| if (*p) |
| return false; |
| p++; |
| length--; |
| } |
| |
| /* compare the remaining data with first all 0 16 bytes */ |
| return (memcmp(data, p, length) == 0); |
| } |
| |
| static void check_mic_mute_state(struct berlin_capture *bc, |
| u32 read_offset, |
| size_t byte_per_chunk) |
| { |
| struct input_dev *mic_mute = bc->mic_mute; |
| /* # of chunk = # of millisecond * (1second / 1000 millisecond) * \ |
| * (sample/second) * (byte/sample) * (chunks/byte) |
| * = # of millisecond / 1000 * sample_rate(Hz) * (2 channels * \ |
| * 4 bytes/channel-sample) / (byte/chunk) |
| * = (# of millisecond * sample_rate(Hz) * 8) / \ |
| * (1000 * byte_per_chunk) |
| */ |
| const size_t mute_threshold_in_chunk = |
| DIV_ROUND_UP(MUTE_THRESHOLD_MS * bc->fs * 8, |
| 1000 * byte_per_chunk); |
| u32 chid; |
| bool is_all_zeros = true; |
| for (chid = 0; chid < bc->chid_num; chid++) { |
| u32* base = (u32 *)(bc->dma_area[chid] + read_offset); |
| if (!is_all_zero(base, byte_per_chunk)) { |
| is_all_zeros = false; |
| break; |
| } |
| } |
| |
| if (is_all_zeros && (BERLIN_MIC_MUTE_STATE_MUTE != bc->mic_mute_state)) { |
| if (++bc->zero_chunk_count > mute_threshold_in_chunk) { |
| if (BERLIN_MIC_MUTE_STATE_UNKNOWN == bc->mic_mute_state) { |
| /* set_bit avoid key up missing */ |
| set_bit(KEY_MICMUTE, mic_mute->key); |
| } else { |
| input_event(mic_mute, EV_KEY, KEY_MICMUTE, 1); |
| input_sync(mic_mute); |
| } |
| |
| bc->mic_mute_state = BERLIN_MIC_MUTE_STATE_MUTE; |
| } |
| return; |
| } |
| if (!is_all_zeros) { |
| bc->zero_chunk_count = 0; |
| if (BERLIN_MIC_MUTE_STATE_UNMUTE != bc->mic_mute_state) { |
| if (BERLIN_MIC_MUTE_STATE_UNKNOWN != bc->mic_mute_state) { |
| input_event(mic_mute, EV_KEY, KEY_MICMUTE, 0); |
| input_sync(mic_mute); |
| } |
| bc->mic_mute_state = BERLIN_MIC_MUTE_STATE_UNMUTE; |
| } |
| } |
| } |
| |
| static void dc_canceller_init(struct dc_canceller *dcc) |
| { |
| memset(dcc, 0, sizeof(*dcc)); |
| } |
| |
| static void decode_pdm_to_pcm(struct work_struct *work) |
| { |
| struct berlin_capture *bc = |
| container_of(work, struct berlin_capture, delayed_work.work); |
| struct snd_pcm_substream *ss = bc->ss; |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| u32 *src = (u32 *)(bc->dma_area[0] + bc->read_offset); |
| s32 *dst = (s32 *)(runtime->dma_area + bc->runtime_offset); |
| unsigned long flags; |
| const size_t period_size_bytes = |
| frames_to_bytes(runtime, runtime->period_size); |
| const size_t pcm_buffer_size_bytes = |
| frames_to_bytes(runtime, runtime->buffer_size); |
| const size_t pdm_pcm_ratio = |
| bc->cic[0].decimation / PCM_SAMPLE_BITS; |
| const size_t pdms_per_dma_ch = |
| bytes_to_samples(runtime, bc->dma_period_ch); |
| u32 i = 0, j = 0, ch = 0, chid = 0; |
| |
| while (bc->capturing) { |
| spin_lock_irqsave(&bc->lock, flags); |
| if (bc->cnt < bc->dma_period_total) { |
| //restart the DMA if it is broken. |
| if (!bc->dma_pending) |
| start_dma_if_needed(ss); |
| spin_unlock_irqrestore(&bc->lock, flags); |
| return; |
| } |
| spin_unlock_irqrestore(&bc->lock, flags); |
| /* check pdm_data to infer mic mute */ |
| check_mic_mute_state(bc, bc->read_offset, bc->dma_period_ch); |
| |
| if (BERLIN_MIC_MUTE_STATE_UNMUTE == bc->mic_mute_state) { |
| for (i = 0; i < pdms_per_dma_ch; i += 2 * pdm_pcm_ratio) { |
| for (chid = 0; chid < bc->chid_num; chid++) { |
| src = (u32 *)(bc->dma_area[chid] |
| + bc->read_offset); |
| for (j = 0; j < 2; j++) { |
| u32 *pdm_data = src + i + j; |
| s32 pcm_data; |
| |
| ch = 2 * chid + j; |
| // Skip unused ch process as requested |
| if (ch < bc->max_ch_inuse) |
| pcm_data = |
| cic_decimator_process( |
| &bc->cic[ch], |
| &bc->dcc[ch], |
| bc->fs, |
| pdm_data); |
| else |
| pcm_data = 0; |
| *dst++ = pcm_data; |
| } |
| } |
| } |
| } else { |
| /* output zero pcm on mute */ |
| memset(dst, 0, period_size_bytes); |
| } |
| |
| bc->read_offset += bc->dma_period_ch; |
| bc->read_offset %= bc->dma_bytes_ch; |
| spin_lock_irqsave(&bc->lock, flags); |
| /* compress two $DECIMATION_FACTOR 1-bit PDM samples to two |
| * 32-bit PCM samples. |
| */ |
| bc->runtime_offset += period_size_bytes; |
| bc->runtime_offset %= pcm_buffer_size_bytes; |
| bc->cnt -= bc->dma_period_total; |
| spin_unlock_irqrestore(&bc->lock, flags); |
| |
| snd_pcm_period_elapsed(ss); |
| src = (u32 *)(bc->dma_area[0] + bc->read_offset); |
| dst = (s32 *)(runtime->dma_area + bc->runtime_offset); |
| } |
| } |
| |
| static void copy_pcm(struct work_struct *work) |
| { |
| struct berlin_capture *bc = |
| container_of(work, struct berlin_capture, delayed_work.work); |
| struct snd_pcm_substream *ss = bc->ss; |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| size_t period_total = bc->dma_period_total; |
| const size_t pcm_buffer_size_bytes = |
| frames_to_bytes(runtime, runtime->buffer_size); |
| const size_t samples_pcm_dma_ch = |
| bytes_to_samples(runtime, bc->dma_period_ch); |
| u64 *src = (u64 *)(bc->dma_area[0] + bc->runtime_offset); |
| s64 *dst = (s64 *)(runtime->dma_area + bc->runtime_offset); |
| unsigned long flags; |
| u32 i, chid; |
| |
| /* check pcm data to infer mic mute */ |
| check_mic_mute_state(bc, bc->runtime_offset, bc->dma_period_ch); |
| if (bc->chid_num == 1) |
| /* copy data */ |
| memcpy((void *)dst, (void *)src, bc->dma_period_ch); |
| else { |
| for (i = 0; i < samples_pcm_dma_ch; i++) { |
| for (chid = 0; chid < bc->chid_num; chid++) { |
| src = (u64 *)(bc->dma_area[chid] |
| + bc->read_offset) + i; |
| *dst++ = *src++; |
| } |
| } |
| } |
| |
| spin_lock_irqsave(&bc->lock, flags); |
| bc->read_offset += bc->dma_period_ch; |
| bc->read_offset %= bc->dma_bytes_ch; |
| bc->runtime_offset += bc->dma_period_total; |
| bc->runtime_offset %= pcm_buffer_size_bytes; |
| bc->cnt -= period_total; |
| spin_unlock_irqrestore(&bc->lock, flags); |
| |
| snd_pcm_period_elapsed(ss); |
| } |
| |
| /* Must call before hw_param! */ |
| void berlin_capture_set_ch_mode(struct snd_pcm_substream *ss, |
| u32 chid_num, u32 *chid, u32 mode) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| |
| if (bc) { |
| u32 i; |
| |
| for (i = 0; i < chid_num; i++) |
| bc->chid[i] = chid ? chid[i] : -1; |
| bc->chid_num = chid_num; |
| bc->mode = mode; |
| snd_printd("capture chnum %d mode %d\n", chid_num, mode); |
| } |
| } |
| |
| void berlin_capture_set_ch_inuse(struct snd_pcm_substream *ss, |
| u32 ch_num) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| |
| bc->max_ch_inuse = ch_num; |
| } |
| |
| int berlin_capture_hw_free(struct snd_pcm_substream *ss) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| struct berlin_chip *chip = bc->chip; |
| u32 i; |
| |
| for (i = 0; i < bc->chid_num; i++) { |
| /* clear the DMA queue Ddub*/ |
| DhubChannelClear(&AG_dhubHandle.dhub, bc->chid[i], 0); |
| } |
| |
| if (chip && bc->dma_area[0]) { |
| struct platform_device *platform_dev = chip->pdev; |
| |
| flush_delayed_work(&bc->delayed_work); |
| dma_free_coherent(&platform_dev->dev, bc->dma_bytes_total, |
| bc->dma_area[0], bc->dma_addr[0]); |
| for (i = 0; i < MAX_CHID; i++) { |
| bc->dma_area[i] = NULL; |
| bc->dma_addr[i] = 0; |
| } |
| } |
| |
| if (bc->pages_allocated == true) { |
| snd_pcm_lib_free_pages(ss); |
| bc->pages_allocated = false; |
| } |
| return 0; |
| } |
| |
| int berlin_capture_hw_params(struct snd_pcm_substream *ss, |
| struct snd_pcm_hw_params *params) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| struct snd_soc_pcm_runtime *rtd = ss->private_data; |
| struct device *dev = rtd->platform->dev; |
| struct berlin_chip *chip = dev_get_drvdata(dev); |
| struct platform_device *platform_dev = chip->pdev; |
| int err; |
| u32 chid_num, ch, i; |
| unsigned long long mic_sleep_us; |
| const size_t pcm_period_size_bytes = params_period_bytes(params); |
| const size_t pcm_buffer_size_bytes = |
| pcm_period_size_bytes * params_periods(params); |
| |
| if (bc->mode == PDMI_MODE) { |
| INIT_DELAYED_WORK(&bc->delayed_work, decode_pdm_to_pcm); |
| } else if (bc->mode == I2SI_MODE) { |
| INIT_DELAYED_WORK(&bc->delayed_work, copy_pcm); |
| } else { |
| snd_printk("non valid mode %d!", bc->mode); |
| return -EINVAL; |
| } |
| |
| bc->fs = params_rate(params); |
| bc->sample_format = params_format(params); |
| bc->channel_num = params_channels(params); |
| snd_printd("%s: fs:%d ch:%d fmt:%s, bufsize 0x%zx period 0x%zx\n", |
| __func__, |
| bc->fs, bc->channel_num, |
| snd_pcm_format_name(bc->sample_format), |
| pcm_buffer_size_bytes, pcm_period_size_bytes); |
| //in case of odd channel number |
| chid_num = (bc->channel_num + 1) / 2; |
| if (chid_num != bc->chid_num) { |
| snd_printk("chid mis-match with dai [%d %d]\n", |
| chid_num, bc->chid_num); |
| return -EINVAL; |
| } |
| |
| bc->chip = chip; |
| berlin_capture_hw_free(ss); |
| err = snd_pcm_lib_malloc_pages(ss, pcm_buffer_size_bytes); |
| if (err < 0) { |
| snd_printd("fail to alloc pages for buffers %d\n", err); |
| return err; |
| } |
| bc->pages_allocated = true; |
| |
| for (ch = 0; ch < 2 * chid_num; ch++) { |
| s32 cic_order = cic_order_from_rate(bc->fs); |
| s32 decimation = |
| cic_decimation_factor_from_rate(bc->fs); |
| if (cic_order == 0 || decimation == 0) { |
| snd_printk("%s: Can't determine CIC from fs %d\n", |
| __func__, bc->fs); |
| snd_pcm_lib_free_pages(ss); |
| return -EINVAL; |
| } |
| cic_decimator_init(&bc->cic[ch], decimation, cic_order); |
| dc_canceller_init(&bc->dcc[ch]); |
| } |
| |
| if (bc->mode == PDMI_MODE) { |
| bc->dma_bytes_total = pcm_buffer_size_bytes * |
| (bc->cic[0].decimation / PCM_SAMPLE_BITS); |
| bc->dma_period_total = pcm_period_size_bytes * |
| (bc->cic[0].decimation / PCM_SAMPLE_BITS); |
| } else if (bc->mode == I2SI_MODE) { |
| bc->dma_bytes_total = pcm_buffer_size_bytes; |
| bc->dma_period_total = pcm_period_size_bytes; |
| } |
| |
| bc->dma_area[0] = dma_zalloc_coherent(&platform_dev->dev, |
| bc->dma_bytes_total, |
| &bc->dma_addr[0], |
| GFP_KERNEL); |
| if (!bc->dma_area[0]) { |
| snd_printk("%s: failed to allocate DMA area\n", __func__); |
| goto err_dma; |
| } |
| |
| bc->dma_period_ch = bc->dma_period_total / bc->chid_num; |
| bc->dma_bytes_ch = bc->dma_bytes_total / bc->chid_num; |
| for (i = 0; i < bc->chid_num; i++) { |
| bc->dma_area[i] = bc->dma_area[0] + i * bc->dma_bytes_ch; |
| bc->dma_addr[i] = bc->dma_addr[0] + i * bc->dma_bytes_ch; |
| } |
| |
| /* Microphone takes 32768 cycles to wake up. Sleep for |
| * ceil(32768 cycles * (1/samplerate seconds per cycle) * 10^6) us |
| * This is not in trigger_start() because sleep should not happen |
| * in the atomic trigger callback. |
| * http://www.alsa-project.org/~tiwai/writing-an-alsa-driver/\ |
| * ch05s06.html#pcm-interface-operators-trigger-callback |
| */ |
| mic_sleep_us = DIV_ROUND_UP_ULL(32768ull * 1000 * 3000, |
| bc->fs * bc->cic[0].decimation); |
| usleep_range(mic_sleep_us, mic_sleep_us + 100); |
| return 0; |
| |
| err_dma: |
| snd_pcm_lib_free_pages(ss); |
| return -ENOMEM; |
| } |
| |
| int berlin_capture_prepare(struct snd_pcm_substream *ss) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| unsigned long flags; |
| |
| spin_lock_irqsave(&bc->lock, flags); |
| bc->current_dma_offset = 0; |
| bc->read_offset = 0; |
| bc->cnt = 0; |
| bc->runtime_offset = 0; |
| spin_unlock_irqrestore(&bc->lock, flags); |
| return 0; |
| } |
| |
| int berlin_capture_trigger(struct snd_pcm_substream *ss, int cmd) |
| { |
| int ret = 0; |
| |
| switch (cmd) { |
| case SNDRV_PCM_TRIGGER_START: |
| case SNDRV_PCM_TRIGGER_RESUME: |
| case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| berlin_capture_trigger_start(ss); |
| break; |
| case SNDRV_PCM_TRIGGER_STOP: |
| case SNDRV_PCM_TRIGGER_SUSPEND: |
| case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
| berlin_capture_trigger_stop(ss); |
| break; |
| default: |
| ret = -EINVAL; |
| } |
| return ret; |
| } |
| |
| snd_pcm_uframes_t |
| berlin_capture_pointer(struct snd_pcm_substream *ss) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| u32 buf_pos; |
| unsigned long flags; |
| |
| spin_lock_irqsave(&bc->lock, flags); |
| buf_pos = bc->runtime_offset; |
| spin_unlock_irqrestore(&bc->lock, flags); |
| |
| return bytes_to_frames(runtime, buf_pos); |
| } |
| |
| int berlin_capture_isr(struct snd_pcm_substream *ss) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| |
| #if BERLIN_XRUN_ENABLE |
| u32 dhub_cnt; |
| #endif |
| |
| spin_lock(&bc->lock); |
| /* If we are not running, do not chain, and clear pending */ |
| if (!bc->capturing) { |
| bc->dma_pending = false; |
| spin_unlock(&bc->lock); |
| return 0; |
| } |
| |
| /* If we were not pending, avoid pointer manipulation */ |
| if (!bc->dma_pending) { |
| spin_unlock(&bc->lock); |
| return 0; |
| } |
| |
| /* Roll the DMA pointer, and chain if needed */ |
| bc->current_dma_offset += bc->dma_period_ch; |
| bc->current_dma_offset %= bc->dma_bytes_ch; |
| bc->dma_pending = false; |
| bc->cnt += bc->dma_period_total; |
| #if BERLIN_XRUN_ENABLE |
| //TODO: move this check |
| // This number is determined by the HW. We don't reset it |
| dhub_cnt = aio_query_datacnt(bc->chid[0]); |
| dhub_cnt &= 0xffff; |
| /* dhub count is in 64 bit unit, this value is 240*8 = 1920 bytes */ |
| /* the typical value is: 0 */ |
| /* when dhub fifo is full, the count is 256 unit: 256*8 = 2048 bytes */ |
| if (dhub_cnt >= 240) { |
| berlin_report_xrun(bc->chip, FIFO_OVERRUN); |
| snd_printd("[FIFO OVERRUN] Dhub cnt: %d bytes, almost full\n", |
| dhub_cnt * 8); |
| } |
| #endif |
| |
| start_dma_if_needed(ss); |
| spin_unlock(&bc->lock); |
| /* convert PDM signal to PCM data */ |
| queue_delayed_work(bc->wq, &bc->delayed_work, 0); |
| |
| return 0; |
| } |
| |
| int berlin_capture_open(struct snd_pcm_substream *ss) |
| { |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc; |
| int err = snd_pcm_hw_constraint_list(runtime, 0, |
| SNDRV_PCM_HW_PARAM_RATE, |
| &berlin_constraints_rates); |
| int i = 0; |
| |
| if (err < 0) { |
| snd_printk("%s: capture hw_constraint_list fail %d\n", |
| __func__, err); |
| return err; |
| } |
| |
| bc = kzalloc(sizeof(struct berlin_capture), GFP_KERNEL); |
| if (bc == NULL) |
| return -ENOMEM; |
| |
| runtime->private_data = bc; |
| runtime->hw = berlin_capture_hw; |
| |
| bc->dma_pending = false; |
| bc->capturing = false; |
| bc->pages_allocated = false; |
| bc->ss = ss; |
| for (i = 0; i < MAX_CHID; i++) { |
| bc->dma_area[i] = NULL; |
| bc->dma_addr[i] = 0; |
| } |
| bc->wq = alloc_workqueue("berlin_capture", WQ_HIGHPRI | WQ_UNBOUND, 1); |
| if (bc->wq == NULL) { |
| err = -ENOMEM; |
| goto __free_kmem; |
| } |
| |
| bc->mic_mute = input_allocate_device(); |
| if (bc->mic_mute == NULL) { |
| snd_printk("%s: allocate input device fail\n", __func__); |
| err = -ENOMEM; |
| goto __destroy_wq; |
| } |
| bc->mic_mute->name = "mic_state"; |
| bc->mic_mute->evbit[BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY); |
| bc->mic_mute->keybit[BIT_WORD(KEY_MICMUTE)] = BIT_MASK(KEY_MICMUTE); |
| bc->mic_mute_state = BERLIN_MIC_MUTE_STATE_UNKNOWN; |
| bc->max_ch_inuse = MAX_CHANNELS; |
| |
| err = input_register_device(bc->mic_mute); |
| if (err) { |
| snd_printk("%s: fail to register mic_mute_state %d\n", |
| __func__, err); |
| goto __free_inputdev; |
| } |
| |
| spin_lock_init(&bc->lock); |
| |
| return 0; |
| |
| __free_inputdev: |
| if (bc->mic_mute) |
| input_free_device(bc->mic_mute); |
| __destroy_wq: |
| if (bc->wq) { |
| destroy_workqueue(bc->wq); |
| bc->wq = NULL; |
| } |
| __free_kmem: |
| kfree(bc); |
| runtime->private_data = NULL; |
| |
| return err; |
| } |
| |
| int berlin_capture_close(struct snd_pcm_substream *ss) |
| { |
| /* disable audio interrupt */ |
| struct snd_pcm_runtime *runtime = ss->runtime; |
| struct berlin_capture *bc = runtime->private_data; |
| |
| if (bc) { |
| //need flush the delayed work after disable interrupt |
| berlin_capture_hw_free(ss); |
| |
| if (bc->mic_mute) { |
| input_unregister_device(bc->mic_mute); |
| input_free_device(bc->mic_mute); |
| } |
| if (bc->wq) { |
| destroy_workqueue(bc->wq); |
| bc->wq = NULL; |
| } |
| kfree(bc); |
| runtime->private_data = NULL; |
| } |
| |
| snd_printd("%s: substream 0x%p done\n", __func__, ss); |
| return 0; |
| } |
| |