blob: 20158d168ab131a00fb690fe3eefb94d7b047068 [file] [log] [blame]
/*************************************************************************************
* Copyright (C) 2007-2011
* Copyright ? 2007 Marvell International Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
***************************************************************************************/
#include <linux/module.h>
#include <linux/atomic.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/socket.h>
#include <linux/spinlock.h>
#include <linux/file.h>
#include <linux/completion.h>
#include <asm/cacheflush.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/hwdep.h>
#include <sound/info.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/pcm-indirect.h>
#include <sound/rawmidi.h>
#include "berlin_memmap.h"
#include "api_avio_dhub.h"
#include "api_dhub.h"
#include "api_aio.h"
#include "api_avpll.h"
#include "api_capture.h"
#include "pcm.h"
#define CIC_MIN_DECIMATION_FACTOR 128
#define CIC_MAX_ORDER 5
/* For every 32 bit PCM sample there are |decimation_factor| 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.
All sizes are in bytes unless specified otherwise.
*/
#define PCM_SAMPLE_SIZE_BITS 32
#define PDM_MIN_DMA_BUFFER_SIZE 1024
#define PDM_MAX_DMA_BUFFER_SIZE 8192
#define PDM_MAX_BUFFER_SIZE (8 * 8192)
#define PCM_MIN_DMA_BUFFER_SIZE (PDM_MIN_DMA_BUFFER_SIZE / (CIC_MIN_DECIMATION_FACTOR / PCM_SAMPLE_SIZE_BITS))
#define PCM_MAX_DMA_BUFFER_SIZE (PDM_MAX_DMA_BUFFER_SIZE / (CIC_MIN_DECIMATION_FACTOR / PCM_SAMPLE_SIZE_BITS))
#define PCM_MAX_BUFFER_SIZE (PDM_MAX_BUFFER_SIZE / (CIC_MIN_DECIMATION_FACTOR / PCM_SAMPLE_SIZE_BITS))
#define MAX_CHANNELS 2
#define MIC_MUTE_THRESHOLD_IN_MS 300
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 :
#if defined(CONFIG_SND_SOC_BERLIN_SLOWER_16KHZ_PDM_CLOCK)
return 4;
#else
return 5;
#endif
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 22050 :
case 24000 :
return 128;
case 16000 :
#if defined(CONFIG_SND_SOC_BERLIN_SLOWER_16KHZ_PDM_CLOCK)
return 96;
#else
return 128;
#endif
case 32000 :
#if defined(CONFIG_SND_SOC_BERLIN_SLOWER_16KHZ_PDM_CLOCK)
return 96;
#else
return 64;
#endif
case 44100 :
case 48000 :
case 64000 :
case 88200 :
case 96000 :
return 64;
default:
break;
}
return 0;
}
struct cic_decimator {
uint32_t integrator_stage[CIC_MAX_ORDER];
uint32_t comb_stage[CIC_MAX_ORDER];
int order;
int decimation_factor;
int bmax;
int32_t (*process) (struct cic_decimator *cic, uint32_t *data);
};
#define DC_HPF_CUTOFF_HZ 60
struct dc_canceller {
float alpha;
float last_input;
float last_output;
};
struct snd_berlin_card_capture {
/*
* Tracks the base address of the last submitted DMA block.
* Moved to next period in ISR.
* read in snd_berlin_playback_pointer.
*/
unsigned int 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.
*/
unsigned int 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.
*/
unsigned int runtime_offset;
/*
* Number of bytes read but not decoded yet.
* Read and write under lock.
*/
unsigned int cnt;
bool need_audio_unmute;
/*
* 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;
/* PDM DMA buffer */
unsigned char *pdm_dma_area;
dma_addr_t pdm_dma_addr;
unsigned int pdm_dma_bytes;
unsigned int pdm_dma_period_size;
/* hw parameter */
unsigned int sample_rate;
unsigned int sample_format;
unsigned int channel_num;
unsigned int chan_id;
/* capture status */
bool capturing;
struct snd_pcm_substream *substream;
struct cic_decimator cic[MAX_CHANNELS];
struct dc_canceller dcc[MAX_CHANNELS];
struct workqueue_struct *wq;
struct delayed_work delayed_work;
};
static unsigned int berlin_capture_rates[] = {
8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000
};
static struct snd_pcm_hw_constraint_list berlin_constraints_rates = {
.count = ARRAY_SIZE(berlin_capture_rates),
.list = berlin_capture_rates,
.mask = 0,
};
static int hw_rule_period_restricts_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule* rule)
{
struct snd_interval *period_bytes =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES);
// Decimation factor 96 or 128 not possible.
if (period_bytes->min * 3 > PDM_MAX_DMA_BUFFER_SIZE) {
const struct snd_interval rate_interval = {
.min = 44100,
.max = 96000
};
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
snd_interval_refine(rate, &rate_interval);
}
return 0;
}
static int hw_rule_buffer_restricts_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule* rule)
{
struct snd_interval *buffer_bytes =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
// Decimation factor 96 or 128 not possible.
if (buffer_bytes->min * 3 > PDM_MAX_BUFFER_SIZE) {
const struct snd_interval rate_interval = {
.min = 44100,
.max = 96000
};
struct snd_interval *rate = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_RATE);
snd_interval_refine(rate, &rate_interval);
}
return 0;
}
static int hw_rule_sample_rate_restricts_period_and_buffer(
struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule* rule)
{
struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
const int decimation_factor = cic_decimation_factor_from_rate(rate->max);
// PDM DMA buffer size and PDM buffer size are hardware limitations.
const struct snd_interval period_byte_interval = {
.min = 0,
.max = PDM_MAX_DMA_BUFFER_SIZE / (decimation_factor / PCM_SAMPLE_SIZE_BITS)
};
const struct snd_interval buffer_byte_interval = {
.min = 0,
.max = PDM_MAX_BUFFER_SIZE / (decimation_factor / PCM_SAMPLE_SIZE_BITS)
};
struct snd_interval *period_bytes =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES);
struct snd_interval *buffer_bytes =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
snd_interval_refine(period_bytes, &period_byte_interval);
snd_interval_refine(buffer_bytes, &buffer_byte_interval);
return 0;
}
/* This sets the clock divider. Target division rate for the rate
|sample_rate| should be:
avpll_frequency / (sample_rate * n_channels * sample_bits * (decimation_factor / 64)).
For 48kHz, this is 24576000/(48000*2*32*1) = 8. */
static void berlin_set_aio(unsigned int sample_rate)
{
unsigned int div;
// update berlin_capture_rates if any rates are added or removed.
switch (sample_rate) {
case 8000 :
case 11025 :
case 12000 :
div = AIO_DIV16; // normally AIO_DIV32 but we doubled the decimation factor
break;
case 16000 :
#if defined(CONFIG_SND_SOC_BERLIN_SLOWER_16KHZ_PDM_CLOCK)
div = AIO_DIV16;
#else
div = AIO_DIV8; // normally AIO_DIV16 but we doubled the decimation factor
#endif
break;
case 22050 :
case 24000 :
div = AIO_DIV8; // normally AIO_DIV16 but we doubled the decimation factor
break;
case 32000 :
case 44100 :
case 48000 :
div = AIO_DIV8;
break;
case 64000 :
case 88200 :
case 96000 :
div = AIO_DIV4;
break;
default:
break;
}
PdmSetup(CAP_ID, HD_CLK, div, 0, 4, 0, AUDCH_CTRL_MUTE_MUTE_ON); // clk divider is div
}
static void berlin_set_pll(unsigned int sample_rate)
{
int apll;
switch (sample_rate) {
case 11025 :
case 22050 :
case 44100 :
case 88200 :
apll = 22579200;
break;
case 8000 :
case 64000 :
apll = 16384000;
break;
case 12000 :
case 24000 :
case 48000 :
case 96000 :
apll = 24576000;
break;
case 16000 :
case 32000 :
#if defined(CONFIG_SND_SOC_BERLIN_SLOWER_16KHZ_PDM_CLOCK)
apll = 24576000;
#else
apll = 16384000;
#endif
break;
default :
apll = 24576000;
break;
}
// WARNING: AVPLL channel 3 is reserved for I2S playback. DO NOT
// set parameters for it here
AVPLL_Set(0, 4, apll);
Avio_SetHdclk();
}
/* must always be called under lock. */
static void start_dma_if_needed(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
const unsigned int chanId = berlin_capture->chan_id;
dma_addr_t dma_source_address;
int dma_size;
assert_spin_locked(&berlin_capture->lock);
if (!berlin_capture->capturing) {
snd_printd("%s: capturing: %u\n", __func__, berlin_capture->capturing);
return;
}
if (berlin_capture->dma_pending) {
snd_printd("%s: DMA pending. Skipping DMA start...\n", __func__);
return;
}
if (berlin_capture->cnt > (berlin_capture->pdm_dma_bytes - berlin_capture->pdm_dma_period_size)) {
berlin_report_xrun(PCM_OVERRUN);
snd_printk("%s: overrun: PCM conversion too slow.\n", __func__);
return;
}
#if 0
dma_source_address = runtime->dma_addr +
berlin_capture->current_dma_offset;
#else
dma_source_address = berlin_capture->pdm_dma_addr +
berlin_capture->current_dma_offset;
#endif
dma_size = berlin_capture->pdm_dma_period_size;
berlin_capture->dma_pending = true;
dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId,
dma_source_address, dma_size, 0, 0, 0, 1, 0, 0);
}
static void snd_berlin_capture_trigger_start(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
const unsigned int chanId = berlin_capture->chan_id;
unsigned long flags;
dma_addr_t dma_source_address;
int dma_size, i;
spin_lock_irqsave(&berlin_capture->lock, flags);
if (berlin_capture->capturing) {
spin_unlock_irqrestore(&berlin_capture->lock, flags);
return;
}
berlin_capture->capturing = true;
berlin_capture->need_audio_unmute = true;
dma_size = berlin_capture->pdm_dma_period_size;
// 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_source_address 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 < 2; i++) {
dma_source_address = berlin_capture->pdm_dma_addr +
berlin_capture->current_dma_offset;
dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId,
dma_source_address, dma_size, 0, 0, 0, 1,
0, 0);
}
berlin_capture->dma_pending = true;
spin_unlock_irqrestore(&berlin_capture->lock, flags);
snd_printd("%s: finished.\n", __func__);
}
static void snd_berlin_capture_trigger_stop(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
unsigned long flags;
spin_lock_irqsave(&berlin_capture->lock, flags);
PdmMuteEn(berlin_capture->chan_id, AUDCH_CTRL_MUTE_MUTE_ON);
berlin_capture->capturing = false;
berlin_capture->dma_pending = false;
spin_unlock_irqrestore(&berlin_capture->lock, flags);
snd_printd("%s: finished.\n", __func__);
}
static const struct snd_pcm_hardware snd_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,
.rates = (SNDRV_PCM_RATE_8000_96000
| SNDRV_PCM_RATE_KNOT),
.rate_min = 8000,
.rate_max = 96000,
.channels_min = MAX_CHANNELS,
.channels_max = MAX_CHANNELS,
.buffer_bytes_max = PCM_MAX_BUFFER_SIZE,
.period_bytes_min = PCM_MIN_DMA_BUFFER_SIZE,
.period_bytes_max = PCM_MAX_DMA_BUFFER_SIZE,
.periods_min = 2,
.periods_max = PCM_MAX_BUFFER_SIZE / PCM_MIN_DMA_BUFFER_SIZE,
.fifo_size = 0
};
static void snd_berlin_capture_runtime_free(struct snd_pcm_runtime *runtime)
{
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
if (berlin_capture) {
if (berlin_capture->wq) {
destroy_workqueue(berlin_capture->wq);
berlin_capture->wq = NULL;
}
kfree(berlin_capture);
runtime->private_data = 0;
}
}
static int32_t cic_decimator_process(struct cic_decimator *cic, uint32_t *data) {
return cic->process(cic, data);
}
static int32_t cic_decimator_process_o4_128x(struct cic_decimator *cic, uint32_t *data) {
const int decimation_factor = 128;
const int order = 4;
int block, i, stage;
int32_t acc, old_acc;
for (block = 0; block < decimation_factor / PCM_SAMPLE_SIZE_BITS; ++block) {
uint32_t bits = data[MAX_CHANNELS * block];
for (i = 0; i < PCM_SAMPLE_SIZE_BITS; ++i) {
acc = (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 < cic->order; ++stage) {
old_acc = acc;
acc -= cic->comb_stage[stage];
cic->comb_stage[stage] = old_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 int32_t cic_decimator_process_o5_64x(struct cic_decimator *cic, uint32_t *data) {
const int decimation_factor = 64;
const int order = 5;
int block, i, stage;
int32_t acc, old_acc;
for (block = 0; block < decimation_factor / PCM_SAMPLE_SIZE_BITS; ++block) {
uint32_t bits = data[MAX_CHANNELS * block];
for (i = 0; i < PCM_SAMPLE_SIZE_BITS; ++i) {
acc = (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 < cic->order; ++stage) {
old_acc = acc;
acc -= cic->comb_stage[stage];
cic->comb_stage[stage] = old_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 int32_t cic_decimator_process_o4_96x(struct cic_decimator *cic, uint32_t *data) {
const int decimation_factor = 96;
const int order = 4;
int block, i, stage;
int32_t acc, old_acc;
for (block = 0; block < decimation_factor / PCM_SAMPLE_SIZE_BITS; ++block) {
uint32_t bits = data[MAX_CHANNELS * block];
for (i = 0; i < PCM_SAMPLE_SIZE_BITS; ++i) {
acc = (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 < cic->order; ++stage) {
old_acc = acc;
acc -= cic->comb_stage[stage];
cic->comb_stage[stage] = old_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 << 27)) ? 0x7fffffff : (acc * 16);
}
static int32_t cic_decimator_process_general(struct cic_decimator *cic, uint32_t *data) {
int block, i, stage;
int32_t acc, old_acc;
// decimation_factor must be a multiple of 32.
for (block = 0; block < cic->decimation_factor / PCM_SAMPLE_SIZE_BITS; ++block) {
uint32_t bits = data[MAX_CHANNELS * block];
for (i = 0; i < PCM_SAMPLE_SIZE_BITS; ++i) {
acc = (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;
}
/*
* 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, int decimation_factor, int order) {
memset(cic, 0, sizeof(*cic));
cic->decimation_factor = decimation_factor;
cic->order = order;
/*
* CIC_BMAX = ceil(CIC_ORDER * log2(CIC_DECIMATION_FACTOR * M) + BITWIDTH_IN)
* with M = 1 and BITWIDTH_IN = 1.
*/
if (cic->order == 4 && cic->decimation_factor == 96) {
cic->bmax = 28;
} else {
cic->bmax = order * ilog2(decimation_factor) + 1;
if (!is_power_of_2(decimation_factor)) {
snd_printk("%s: Warning! CIC_BMAX calculation may be off.\n", __func__);
}
}
if (cic->order == 4 && cic->decimation_factor == 128) {
cic->process = &cic_decimator_process_o4_128x;
} else if (cic->order == 5 && cic->decimation_factor == 64) {
cic->process = &cic_decimator_process_o5_64x;
} else if (cic->order == 4 && cic->decimation_factor == 96) {
cic->process = &cic_decimator_process_o4_96x;
} else {
cic->process = &cic_decimator_process_general;
}
snd_printk("%s: order %d, %dx, bmax: %d\n", __func__, cic->order, cic->decimation_factor, cic->bmax);
}
static int32_t map_float_to_int32(float value) {
return value * (1 << 30);
}
static float map_int32_to_float(int32_t value) {
return value * (1.0f / (1 << 30));
}
static void dc_canceller_init(struct dc_canceller *dcc) {
memset(dcc, 0, sizeof(*dcc));
}
/*
* 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)
*/
static float dc_canceller_process(struct dc_canceller *dcc, float input) {
float output = dcc->alpha * (input - dcc->last_input + dcc->last_output);
dcc->last_input = input;
dcc->last_output = output;
return output;
}
/*
* This is used for checking if PDM stream data is zeros
*/
static const char zero_block [PDM_MAX_DMA_BUFFER_SIZE] = {0};
void check_mic_mute_state(uint32_t* base, size_t length_per_chunk,
unsigned int sample_rate, struct snd_pcm_substream *substream) {
struct snd_berlin_chip *chip = substream->pcm->card->private_data;
struct input_dev *mic_mute_state_input = chip->mic_mute_state_input;
const size_t byte_per_chunk = 4*length_per_chunk;
/* # 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(MIC_MUTE_THRESHOLD_IN_MS * sample_rate * 8,
1000 * byte_per_chunk);
bool is_all_zeros = !memcmp(base, zero_block, byte_per_chunk);
if (is_all_zeros && !chip->is_mic_mute) {
if (++chip->zero_chunk_count > mute_threshold_in_chunk) {
chip->is_mic_mute = 1;
input_event(mic_mute_state_input, EV_KEY, KEY_MICMUTE, 1);
input_sync(mic_mute_state_input);
}
return;
}
if (!is_all_zeros) {
chip->zero_chunk_count = 0;
if (chip->is_mic_mute) {
chip->is_mic_mute = 0;
input_event(mic_mute_state_input, EV_KEY, KEY_MICMUTE, 0);
input_sync(mic_mute_state_input);
}
}
}
static void decode_pdm_to_pcm(struct work_struct *work)
{
struct snd_berlin_card_capture *berlin_capture = container_of(work,
struct snd_berlin_card_capture, delayed_work.work);
struct snd_pcm_substream *substream = berlin_capture->substream;
struct snd_berlin_chip *chip = substream->pcm->card->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
uint32_t *src = (uint32_t*) (berlin_capture->pdm_dma_area + berlin_capture->read_offset);
int32_t *dst = (int32_t*) (runtime->dma_area + berlin_capture->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_samples_per_pcm_sample =
berlin_capture->cic[0].decimation_factor / PCM_SAMPLE_SIZE_BITS;
const size_t pdm_samples_per_pcm_frame =
pdm_samples_per_pcm_sample * berlin_capture->channel_num;
const size_t pdm_samples_per_pdm_dma_buffer =
bytes_to_samples(runtime, berlin_capture->pdm_dma_period_size);
while (berlin_capture->capturing) {
size_t i = 0, ch = 0;
spin_lock_irqsave(&berlin_capture->lock, flags);
if (berlin_capture->cnt < berlin_capture->pdm_dma_period_size) {
start_dma_if_needed(substream);
spin_unlock_irqrestore(&berlin_capture->lock, flags);
return ;
}
spin_unlock_irqrestore(&berlin_capture->lock, flags);
/* check pdm_data to infer mic mute */
check_mic_mute_state(src, pdm_samples_per_pdm_dma_buffer,
berlin_capture->sample_rate, substream);
if (chip->is_mic_mute) {
memset(dst, 0, period_size_bytes);
} else {
for (i = 0; i < pdm_samples_per_pdm_dma_buffer;
i += pdm_samples_per_pcm_frame) {
for (ch=0; ch < berlin_capture->channel_num; ch++) {
uint32_t *pdm_data = src + i + ch;
int32_t pcm_data;
float temp;
pcm_data = cic_decimator_process(
&berlin_capture->cic[ch], pdm_data);
temp = map_int32_to_float(pcm_data);
temp = dc_canceller_process(&berlin_capture->dcc[ch], temp);
pcm_data = map_float_to_int32(temp);
*dst++ = pcm_data;
}
}
}
berlin_capture->read_offset += berlin_capture->pdm_dma_period_size;
berlin_capture->read_offset %= berlin_capture->pdm_dma_bytes;
spin_lock_irqsave(&berlin_capture->lock, flags);
/* compress two $DECIMATION_FACTOR 1-bit PDM samples to two
* 32-bit PCM samples. */
berlin_capture->runtime_offset += period_size_bytes;
berlin_capture->runtime_offset %= pcm_buffer_size_bytes;
berlin_capture->cnt -= berlin_capture->pdm_dma_period_size;
spin_unlock_irqrestore(&berlin_capture->lock, flags);
snd_pcm_period_elapsed(substream);
src = (uint32_t*) (berlin_capture->pdm_dma_area + berlin_capture->read_offset);
dst = (int32_t*) (runtime->dma_area + berlin_capture->runtime_offset);
}
}
int snd_berlin_capture_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture;
size_t ch;
int err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&berlin_constraints_rates);
if (err < 0)
return err;
// Ensure PDM buffer sizes do not exceed hardware limits.
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
&hw_rule_period_restricts_rate, NULL,
SNDRV_PCM_HW_PARAM_RATE);
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
&hw_rule_buffer_restricts_rate, NULL,
SNDRV_PCM_HW_PARAM_RATE);
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&hw_rule_sample_rate_restricts_period_and_buffer,
NULL, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1);
berlin_capture = kzalloc(sizeof(struct snd_berlin_card_capture), GFP_KERNEL);
if (berlin_capture == NULL)
return -ENOMEM;
berlin_capture->dma_pending = false;
berlin_capture->capturing = false;
berlin_capture->pages_allocated = false;
berlin_capture->substream = substream;
berlin_capture->chan_id = CAP_ID;
for (ch = 0; ch < MAX_CHANNELS; ch++) {
dc_canceller_init(&berlin_capture->dcc[ch]);
}
berlin_capture->wq = alloc_workqueue("berlin_capture", WQ_HIGHPRI | WQ_UNBOUND, 1);
if (berlin_capture->wq == NULL)
return -ENOMEM;
INIT_DELAYED_WORK(&berlin_capture->delayed_work, decode_pdm_to_pcm);
spin_lock_init(&berlin_capture->lock);
runtime->private_data = berlin_capture;
runtime->private_free = snd_berlin_capture_runtime_free;
runtime->hw = snd_berlin_capture_hw;
/* enable audio interrupt */
DhubEnableIntr(0, &AG_dhubHandle, berlin_capture->chan_id, 1);
snd_printk("%s: finished.\n", __func__);
return 0;
}
int snd_berlin_capture_close(struct snd_pcm_substream *substream)
{
/* disable audio interrupt */
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
DhubEnableIntr(0, &AG_dhubHandle, berlin_capture->chan_id, 0);
snd_printk("%s: finished.\n", __func__);
return 0;
}
int snd_berlin_capture_hw_free(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
snd_printk("%s\n", __func__);
flush_delayed_work(&berlin_capture->delayed_work);
if (berlin_capture->pdm_dma_area) {
dma_free_coherent(NULL, berlin_capture->pdm_dma_bytes,
berlin_capture->pdm_dma_area,
berlin_capture->pdm_dma_addr);
berlin_capture->pdm_dma_area = NULL;
berlin_capture->pdm_dma_addr = 0;
}
if (berlin_capture->pages_allocated == true) {
snd_pcm_lib_free_pages(substream);
berlin_capture->pages_allocated = false;
}
return 0;
}
int snd_berlin_capture_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
int err;
unsigned long flags;
size_t ch;
unsigned long long microphone_sleep_time_us;
const size_t pcm_buffer_size_bytes = params_buffer_bytes(params);
const size_t pcm_period_size_bytes = pcm_buffer_size_bytes / params_periods(params);
snd_berlin_capture_hw_free(substream);
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
if (err < 0) {
snd_printk("pcm_lib_malloc failed to allocated pages for buffers\n");
return err;
}
berlin_capture->pages_allocated = true;
snd_printk("%s: sample_rate:%d channels:%d format:%s "
"period_size: %d bytes buffer_size: %d bytes\n", __func__,
params_rate(params), params_channels(params),
snd_pcm_format_name(params_format(params)),
params_period_bytes(params),
params_buffer_bytes(params));
berlin_capture->sample_rate = params_rate(params);
berlin_capture->sample_format = params_format(params);
berlin_capture->channel_num = params_channels(params);
for (ch = 0; ch < berlin_capture->channel_num; ch++) {
int cic_order = cic_order_from_rate(berlin_capture->sample_rate);
int decimation_factor = cic_decimation_factor_from_rate(berlin_capture->sample_rate);
if (cic_order == 0 || decimation_factor == 0) {
snd_printk("%s: Cannot determine CIC order or decimation factor from sample rate %d\n",
__func__, berlin_capture->sample_rate);
snd_pcm_lib_free_pages(substream);
return -EINVAL;
}
cic_decimator_init(&berlin_capture->cic[ch],
decimation_factor, cic_order);
berlin_capture->dcc[ch].alpha =
1.0f / (1 + 2 * 3.14159f * DC_HPF_CUTOFF_HZ /
berlin_capture->sample_rate);
}
berlin_capture->pdm_dma_bytes =
pcm_buffer_size_bytes *
(berlin_capture->cic[0].decimation_factor / PCM_SAMPLE_SIZE_BITS);
berlin_capture->pdm_dma_period_size =
pcm_period_size_bytes *
(berlin_capture->cic[0].decimation_factor / PCM_SAMPLE_SIZE_BITS);
if (berlin_capture->pdm_dma_bytes > PDM_MAX_BUFFER_SIZE) {
snd_printk("%s: PDM buffer size too large: %d\n", __func__, berlin_capture->pdm_dma_bytes);
snd_pcm_lib_free_pages(substream);
return -EINVAL;
}
berlin_capture->pdm_dma_area = dma_zalloc_coherent(
NULL, berlin_capture->pdm_dma_bytes,
&berlin_capture->pdm_dma_addr, GFP_KERNEL);
if (!berlin_capture->pdm_dma_area) {
snd_printk("%s: failed to allocate PDM DMA area\n", __func__);
goto err_pdm_dma;
}
/* AVPLL configuration */
berlin_set_pll(berlin_capture->sample_rate);
spin_lock_irqsave(&berlin_capture->lock, flags);
/* AIO configuration */
berlin_set_aio(berlin_capture->sample_rate);
PdmMuteEn(berlin_capture->chan_id, AUDCH_CTRL_MUTE_MUTE_ON);
PdmRxStart(berlin_capture->chan_id, 0);
spin_unlock_irqrestore(&berlin_capture->lock, flags);
/* Microphone takes 32768 cycles to wake up. Sleep for
* ceil(32768 cycles * (1/sample_rate seconds per cycle) * 10^6 us/sec) us
* This is not in trigger_start() because sleeps should not be happening
* in the atomic trigger callback.
* http://www.alsa-project.org/~tiwai/writing-an-alsa-driver/ch05s06.html#pcm-interface-operators-trigger-callback
* */
microphone_sleep_time_us = DIV_ROUND_UP_ULL(32768ull * 1000 * 1000,
berlin_capture->sample_rate * berlin_capture->cic[0].decimation_factor);
usleep_range(microphone_sleep_time_us,
microphone_sleep_time_us + 100);
return 0;
err_pdm_dma:
snd_pcm_lib_free_pages(substream);
return -ENOMEM;
}
int snd_berlin_capture_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
unsigned long flags;
spin_lock_irqsave(&berlin_capture->lock, flags);
berlin_capture->current_dma_offset = 0;
berlin_capture->read_offset = 0;
berlin_capture->cnt = 0;
berlin_capture->runtime_offset = 0;
spin_unlock_irqrestore(&berlin_capture->lock, flags);
return 0;
}
int snd_berlin_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
snd_berlin_capture_trigger_start(substream);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
snd_berlin_capture_trigger_stop(substream);
break;
default:
ret = -EINVAL;
}
return ret;
}
snd_pcm_uframes_t
snd_berlin_capture_pointer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
uint32_t buf_pos;
unsigned long flags;
spin_lock_irqsave(&berlin_capture->lock, flags);
buf_pos = berlin_capture->runtime_offset;
spin_unlock_irqrestore(&berlin_capture->lock, flags);
return bytes_to_frames(runtime, buf_pos);
}
int snd_berlin_capture_isr(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_berlin_card_capture *berlin_capture = runtime->private_data;
unsigned long flags;
// FIFO fullness
unsigned int dhub_cnt;
UNSG32 addr;
spin_lock_irqsave(&berlin_capture->lock, flags);
/* If we are not running, do not chain, and clear pending */
if (!berlin_capture->capturing) {
berlin_capture->dma_pending = false;
spin_unlock_irqrestore(&berlin_capture->lock, flags);
return IRQ_HANDLED;
}
/* If we were not pending, avoid pointer manipulation */
if (!berlin_capture->dma_pending) {
spin_unlock_irqrestore(&berlin_capture->lock, flags);
return IRQ_HANDLED;
}
if (berlin_capture->need_audio_unmute) {
berlin_capture->need_audio_unmute = false;
PdmMuteEn(berlin_capture->chan_id, AUDCH_CTRL_MUTE_MUTE_OFF);
berlin_capture->current_dma_offset += berlin_capture->pdm_dma_period_size;
berlin_capture->current_dma_offset %= berlin_capture->pdm_dma_bytes;
berlin_capture->dma_pending = false;
start_dma_if_needed(substream);
spin_unlock_irqrestore(&berlin_capture->lock, flags);
return 0;
}
/* Roll the DMA pointer, and chain if needed */
berlin_capture->current_dma_offset += berlin_capture->pdm_dma_period_size;
berlin_capture->current_dma_offset %= berlin_capture->pdm_dma_bytes;
berlin_capture->dma_pending = false;
berlin_capture->cnt += berlin_capture->pdm_dma_period_size;
/* to query the consumer data count register to check fifo fullness */
addr = AG_DHUB_BASE + RA_dHubReg_HBO + 0x80 +
berlin_capture->chan_id * 4 * 2 + 4;
// This number is determined by the HW. We don't reset it
dhub_cnt = (*((volatile unsigned int*)(addr)));
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, which is: 256*8 = 2048 bytes*/
if (dhub_cnt >= 240) {
berlin_report_xrun(FIFO_OVERRUN);
snd_printk("[FIFO OVERRUN] Dhub cnt: %d bytes, FIFO almost full \n",
dhub_cnt * 8);
}
start_dma_if_needed(substream);
spin_unlock_irqrestore(&berlin_capture->lock, flags);
/* convert PDM signal to PCM data */
queue_delayed_work(berlin_capture->wq, &berlin_capture->delayed_work, 0);
return 0;
}