|
|
|
@ -50,6 +50,18 @@ |
|
|
|
|
|
|
|
|
|
#define LATENCY_TIME_MS 20 |
|
|
|
|
|
|
|
|
|
#define MODE7_LTHR 10 |
|
|
|
|
#define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10) |
|
|
|
|
|
|
|
|
|
#define BURST_BASEFREQ_HZ 49152000 |
|
|
|
|
|
|
|
|
|
#define SAMPLES_TO_US(rate, samples) \ |
|
|
|
|
(1000000000 / ((rate * 1000) / samples)) |
|
|
|
|
|
|
|
|
|
#define US_TO_SAMPLES(rate, us) \ |
|
|
|
|
(rate / (1000000 / us)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct snd_soc_codec *tlv320dac33_codec; |
|
|
|
|
|
|
|
|
|
enum dac33_state { |
|
|
|
@ -92,9 +104,18 @@ struct tlv320dac33_priv { |
|
|
|
|
enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ |
|
|
|
|
unsigned int nsample; /* burst read amount from host */ |
|
|
|
|
u8 burst_bclkdiv; /* BCLK divider value in burst mode */ |
|
|
|
|
unsigned int burst_rate; /* Interface speed in Burst modes */ |
|
|
|
|
|
|
|
|
|
int keep_bclk; /* Keep the BCLK continuously running
|
|
|
|
|
* in FIFO modes */ |
|
|
|
|
spinlock_t lock; |
|
|
|
|
unsigned long long t_stamp1; /* Time stamp for FIFO modes to */ |
|
|
|
|
unsigned long long t_stamp2; /* calculate the FIFO caused delay */ |
|
|
|
|
|
|
|
|
|
unsigned int mode1_us_burst; /* Time to burst read n number of
|
|
|
|
|
* samples */ |
|
|
|
|
unsigned int mode7_us_to_lthr; /* Time to reach lthr from uthr */ |
|
|
|
|
|
|
|
|
|
enum dac33_state state; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -384,10 +405,14 @@ static int dac33_set_nsample(struct snd_kcontrol *kcontrol, |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
if (ucontrol->value.integer.value[0] < dac33->nsample_min || |
|
|
|
|
ucontrol->value.integer.value[0] > dac33->nsample_max) |
|
|
|
|
ucontrol->value.integer.value[0] > dac33->nsample_max) { |
|
|
|
|
ret = -EINVAL; |
|
|
|
|
else |
|
|
|
|
} else { |
|
|
|
|
dac33->nsample = ucontrol->value.integer.value[0]; |
|
|
|
|
/* Re calculate the burst time */ |
|
|
|
|
dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, |
|
|
|
|
dac33->nsample); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
@ -557,13 +582,34 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) |
|
|
|
|
switch (dac33->fifo_mode) { |
|
|
|
|
case DAC33_FIFO_MODE1: |
|
|
|
|
dac33_write16(codec, DAC33_NSAMPLE_MSB, |
|
|
|
|
DAC33_THRREG(dac33->nsample)); |
|
|
|
|
DAC33_THRREG(dac33->nsample + dac33->alarm_threshold)); |
|
|
|
|
|
|
|
|
|
/* Take the timestamps */ |
|
|
|
|
spin_lock_irq(&dac33->lock); |
|
|
|
|
dac33->t_stamp2 = ktime_to_us(ktime_get()); |
|
|
|
|
dac33->t_stamp1 = dac33->t_stamp2; |
|
|
|
|
spin_unlock_irq(&dac33->lock); |
|
|
|
|
|
|
|
|
|
dac33_write16(codec, DAC33_PREFILL_MSB, |
|
|
|
|
DAC33_THRREG(dac33->alarm_threshold)); |
|
|
|
|
/* Enable Alarm Threshold IRQ with a delay */ |
|
|
|
|
udelay(SAMPLES_TO_US(dac33->burst_rate, |
|
|
|
|
dac33->alarm_threshold)); |
|
|
|
|
dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT); |
|
|
|
|
break; |
|
|
|
|
case DAC33_FIFO_MODE7: |
|
|
|
|
/* Take the timestamp */ |
|
|
|
|
spin_lock_irq(&dac33->lock); |
|
|
|
|
dac33->t_stamp1 = ktime_to_us(ktime_get()); |
|
|
|
|
/* Move back the timestamp with drain time */ |
|
|
|
|
dac33->t_stamp1 -= dac33->mode7_us_to_lthr; |
|
|
|
|
spin_unlock_irq(&dac33->lock); |
|
|
|
|
|
|
|
|
|
dac33_write16(codec, DAC33_PREFILL_MSB, |
|
|
|
|
DAC33_THRREG(10)); |
|
|
|
|
DAC33_THRREG(MODE7_LTHR)); |
|
|
|
|
|
|
|
|
|
/* Enable Upper Threshold IRQ */ |
|
|
|
|
dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MUT); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
dev_warn(codec->dev, "Unhandled FIFO mode: %d\n", |
|
|
|
@ -580,6 +626,11 @@ static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) |
|
|
|
|
|
|
|
|
|
switch (dac33->fifo_mode) { |
|
|
|
|
case DAC33_FIFO_MODE1: |
|
|
|
|
/* Take the timestamp */ |
|
|
|
|
spin_lock_irq(&dac33->lock); |
|
|
|
|
dac33->t_stamp2 = ktime_to_us(ktime_get()); |
|
|
|
|
spin_unlock_irq(&dac33->lock); |
|
|
|
|
|
|
|
|
|
dac33_write16(codec, DAC33_NSAMPLE_MSB, |
|
|
|
|
DAC33_THRREG(dac33->nsample)); |
|
|
|
|
break; |
|
|
|
@ -632,7 +683,13 @@ static irqreturn_t dac33_interrupt_handler(int irq, void *dev) |
|
|
|
|
struct snd_soc_codec *codec = dev; |
|
|
|
|
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
|
|
|
|
|
|
|
|
|
queue_work(dac33->dac33_wq, &dac33->work); |
|
|
|
|
spin_lock(&dac33->lock); |
|
|
|
|
dac33->t_stamp1 = ktime_to_us(ktime_get()); |
|
|
|
|
spin_unlock(&dac33->lock); |
|
|
|
|
|
|
|
|
|
/* Do not schedule the workqueue in Mode7 */ |
|
|
|
|
if (dac33->fifo_mode != DAC33_FIFO_MODE7) |
|
|
|
|
queue_work(dac33->dac33_wq, &dac33->work); |
|
|
|
|
|
|
|
|
|
return IRQ_HANDLED; |
|
|
|
|
} |
|
|
|
@ -782,11 +839,10 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) |
|
|
|
|
case DAC33_FIFO_MODE1: |
|
|
|
|
dac33_write(codec, DAC33_FIFO_IRQ_MODE_B, |
|
|
|
|
DAC33_ATM(DAC33_FIFO_IRQ_MODE_LEVEL)); |
|
|
|
|
dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT); |
|
|
|
|
break; |
|
|
|
|
case DAC33_FIFO_MODE7: |
|
|
|
|
/* Disable all interrupts */ |
|
|
|
|
dac33_write(codec, DAC33_FIFO_IRQ_MASK, 0); |
|
|
|
|
dac33_write(codec, DAC33_FIFO_IRQ_MODE_A, |
|
|
|
|
DAC33_UTM(DAC33_FIFO_IRQ_MODE_LEVEL)); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
/* in FIFO bypass mode, the interrupts are not used */ |
|
|
|
@ -864,10 +920,8 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) |
|
|
|
|
* Configure the threshold levels, and leave 10 sample space |
|
|
|
|
* at the bottom, and also at the top of the FIFO |
|
|
|
|
*/ |
|
|
|
|
dac33_write16(codec, DAC33_UTHR_MSB, |
|
|
|
|
DAC33_THRREG(DAC33_BUFFER_SIZE_SAMPLES - 10)); |
|
|
|
|
dac33_write16(codec, DAC33_LTHR_MSB, |
|
|
|
|
DAC33_THRREG(10)); |
|
|
|
|
dac33_write16(codec, DAC33_UTHR_MSB, DAC33_THRREG(MODE7_UTHR)); |
|
|
|
|
dac33_write16(codec, DAC33_LTHR_MSB, DAC33_THRREG(MODE7_LTHR)); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
@ -886,6 +940,10 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) |
|
|
|
|
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
|
|
|
|
unsigned int nsample_limit; |
|
|
|
|
|
|
|
|
|
/* In bypass mode we don't need to calculate */ |
|
|
|
|
if (!dac33->fifo_mode) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
/* Number of samples (16bit, stereo) in one period */ |
|
|
|
|
dac33->nsample_min = snd_pcm_lib_period_bytes(substream) / 4; |
|
|
|
|
|
|
|
|
@ -919,6 +977,24 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) |
|
|
|
|
|
|
|
|
|
if (dac33->nsample > dac33->nsample_max) |
|
|
|
|
dac33->nsample = dac33->nsample_max; |
|
|
|
|
|
|
|
|
|
switch (dac33->fifo_mode) { |
|
|
|
|
case DAC33_FIFO_MODE1: |
|
|
|
|
dac33->mode1_us_burst = SAMPLES_TO_US(dac33->burst_rate, |
|
|
|
|
dac33->nsample); |
|
|
|
|
dac33->t_stamp1 = 0; |
|
|
|
|
dac33->t_stamp2 = 0; |
|
|
|
|
break; |
|
|
|
|
case DAC33_FIFO_MODE7: |
|
|
|
|
dac33->mode7_us_to_lthr = |
|
|
|
|
SAMPLES_TO_US(substream->runtime->rate, |
|
|
|
|
MODE7_UTHR - MODE7_LTHR + 1); |
|
|
|
|
dac33->t_stamp1 = 0; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int dac33_pcm_prepare(struct snd_pcm_substream *substream, |
|
|
|
@ -963,6 +1039,151 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static snd_pcm_sframes_t dac33_dai_delay( |
|
|
|
|
struct snd_pcm_substream *substream, |
|
|
|
|
struct snd_soc_dai *dai) |
|
|
|
|
{ |
|
|
|
|
struct snd_soc_pcm_runtime *rtd = substream->private_data; |
|
|
|
|
struct snd_soc_device *socdev = rtd->socdev; |
|
|
|
|
struct snd_soc_codec *codec = socdev->card->codec; |
|
|
|
|
struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
|
|
|
|
unsigned long long t0, t1, t_now; |
|
|
|
|
unsigned int time_delta; |
|
|
|
|
int samples_out, samples_in, samples; |
|
|
|
|
snd_pcm_sframes_t delay = 0; |
|
|
|
|
|
|
|
|
|
switch (dac33->fifo_mode) { |
|
|
|
|
case DAC33_FIFO_BYPASS: |
|
|
|
|
break; |
|
|
|
|
case DAC33_FIFO_MODE1: |
|
|
|
|
spin_lock(&dac33->lock); |
|
|
|
|
t0 = dac33->t_stamp1; |
|
|
|
|
t1 = dac33->t_stamp2; |
|
|
|
|
spin_unlock(&dac33->lock); |
|
|
|
|
t_now = ktime_to_us(ktime_get()); |
|
|
|
|
|
|
|
|
|
/* We have not started to fill the FIFO yet, delay is 0 */ |
|
|
|
|
if (!t1) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
if (t0 > t1) { |
|
|
|
|
/*
|
|
|
|
|
* Phase 1: |
|
|
|
|
* After Alarm threshold, and before nSample write |
|
|
|
|
*/ |
|
|
|
|
time_delta = t_now - t0; |
|
|
|
|
samples_out = time_delta ? US_TO_SAMPLES( |
|
|
|
|
substream->runtime->rate, |
|
|
|
|
time_delta) : 0; |
|
|
|
|
|
|
|
|
|
if (likely(dac33->alarm_threshold > samples_out)) |
|
|
|
|
delay = dac33->alarm_threshold - samples_out; |
|
|
|
|
else |
|
|
|
|
delay = 0; |
|
|
|
|
} else if ((t_now - t1) <= dac33->mode1_us_burst) { |
|
|
|
|
/*
|
|
|
|
|
* Phase 2: |
|
|
|
|
* After nSample write (during burst operation) |
|
|
|
|
*/ |
|
|
|
|
time_delta = t_now - t0; |
|
|
|
|
samples_out = time_delta ? US_TO_SAMPLES( |
|
|
|
|
substream->runtime->rate, |
|
|
|
|
time_delta) : 0; |
|
|
|
|
|
|
|
|
|
time_delta = t_now - t1; |
|
|
|
|
samples_in = time_delta ? US_TO_SAMPLES( |
|
|
|
|
dac33->burst_rate, |
|
|
|
|
time_delta) : 0; |
|
|
|
|
|
|
|
|
|
samples = dac33->alarm_threshold; |
|
|
|
|
samples += (samples_in - samples_out); |
|
|
|
|
|
|
|
|
|
if (likely(samples > 0)) |
|
|
|
|
delay = samples; |
|
|
|
|
else |
|
|
|
|
delay = 0; |
|
|
|
|
} else { |
|
|
|
|
/*
|
|
|
|
|
* Phase 3: |
|
|
|
|
* After burst operation, before next alarm threshold |
|
|
|
|
*/ |
|
|
|
|
time_delta = t_now - t0; |
|
|
|
|
samples_out = time_delta ? US_TO_SAMPLES( |
|
|
|
|
substream->runtime->rate, |
|
|
|
|
time_delta) : 0; |
|
|
|
|
|
|
|
|
|
samples_in = dac33->nsample; |
|
|
|
|
samples = dac33->alarm_threshold; |
|
|
|
|
samples += (samples_in - samples_out); |
|
|
|
|
|
|
|
|
|
if (likely(samples > 0)) |
|
|
|
|
delay = samples > DAC33_BUFFER_SIZE_SAMPLES ? |
|
|
|
|
DAC33_BUFFER_SIZE_SAMPLES : samples; |
|
|
|
|
else |
|
|
|
|
delay = 0; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case DAC33_FIFO_MODE7: |
|
|
|
|
spin_lock(&dac33->lock); |
|
|
|
|
t0 = dac33->t_stamp1; |
|
|
|
|
spin_unlock(&dac33->lock); |
|
|
|
|
t_now = ktime_to_us(ktime_get()); |
|
|
|
|
|
|
|
|
|
/* We have not started to fill the FIFO yet, delay is 0 */ |
|
|
|
|
if (!t0) |
|
|
|
|
goto out; |
|
|
|
|
|
|
|
|
|
if (t_now <= t0) { |
|
|
|
|
/*
|
|
|
|
|
* Either the timestamps are messed or equal. Report |
|
|
|
|
* maximum delay |
|
|
|
|
*/ |
|
|
|
|
delay = MODE7_UTHR; |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
time_delta = t_now - t0; |
|
|
|
|
if (time_delta <= dac33->mode7_us_to_lthr) { |
|
|
|
|
/*
|
|
|
|
|
* Phase 1: |
|
|
|
|
* After burst (draining phase) |
|
|
|
|
*/ |
|
|
|
|
samples_out = US_TO_SAMPLES( |
|
|
|
|
substream->runtime->rate, |
|
|
|
|
time_delta); |
|
|
|
|
|
|
|
|
|
if (likely(MODE7_UTHR > samples_out)) |
|
|
|
|
delay = MODE7_UTHR - samples_out; |
|
|
|
|
else |
|
|
|
|
delay = 0; |
|
|
|
|
} else { |
|
|
|
|
/*
|
|
|
|
|
* Phase 2: |
|
|
|
|
* During burst operation |
|
|
|
|
*/ |
|
|
|
|
time_delta = time_delta - dac33->mode7_us_to_lthr; |
|
|
|
|
|
|
|
|
|
samples_out = US_TO_SAMPLES( |
|
|
|
|
substream->runtime->rate, |
|
|
|
|
time_delta); |
|
|
|
|
samples_in = US_TO_SAMPLES( |
|
|
|
|
dac33->burst_rate, |
|
|
|
|
time_delta); |
|
|
|
|
delay = MODE7_LTHR + samples_in - samples_out; |
|
|
|
|
|
|
|
|
|
if (unlikely(delay > MODE7_UTHR)) |
|
|
|
|
delay = MODE7_UTHR; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
dev_warn(codec->dev, "Unhandled FIFO mode: %d\n", |
|
|
|
|
dac33->fifo_mode); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
out: |
|
|
|
|
return delay; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int dac33_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
|
|
|
|
int clk_id, unsigned int freq, int dir) |
|
|
|
|
{ |
|
|
|
@ -1174,6 +1395,7 @@ static struct snd_soc_dai_ops dac33_dai_ops = { |
|
|
|
|
.hw_params = dac33_hw_params, |
|
|
|
|
.prepare = dac33_pcm_prepare, |
|
|
|
|
.trigger = dac33_pcm_trigger, |
|
|
|
|
.delay = dac33_dai_delay, |
|
|
|
|
.set_sysclk = dac33_set_dai_sysclk, |
|
|
|
|
.set_fmt = dac33_set_dai_fmt, |
|
|
|
|
}; |
|
|
|
@ -1214,6 +1436,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, |
|
|
|
|
|
|
|
|
|
mutex_init(&codec->mutex); |
|
|
|
|
mutex_init(&dac33->mutex); |
|
|
|
|
spin_lock_init(&dac33->lock); |
|
|
|
|
INIT_LIST_HEAD(&codec->dapm_widgets); |
|
|
|
|
INIT_LIST_HEAD(&codec->dapm_paths); |
|
|
|
|
|
|
|
|
@ -1238,9 +1461,12 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, |
|
|
|
|
|
|
|
|
|
dac33->power_gpio = pdata->power_gpio; |
|
|
|
|
dac33->burst_bclkdiv = pdata->burst_bclkdiv; |
|
|
|
|
/* Pre calculate the burst rate */ |
|
|
|
|
dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32; |
|
|
|
|
dac33->keep_bclk = pdata->keep_bclk; |
|
|
|
|
dac33->irq = client->irq; |
|
|
|
|
dac33->nsample = NSAMPLE_MAX; |
|
|
|
|
dac33->nsample_max = NSAMPLE_MAX; |
|
|
|
|
/* Disable FIFO use by default */ |
|
|
|
|
dac33->fifo_mode = DAC33_FIFO_BYPASS; |
|
|
|
|
|
|
|
|
|