Loading sound/soc/codecs/tlv320aic3x.c +39 −42 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> #include <linux/regulator/consumer.h> #include <linux/platform_device.h> #include <sound/core.h> #include <sound/pcm.h> Loading @@ -49,11 +50,18 @@ #include "tlv320aic3x.h" #define AIC3X_VERSION "0.2" #define AIC3X_NUM_SUPPLIES 4 static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = { "IOVDD", /* I/O Voltage */ "DVDD", /* Digital Core Voltage */ "AVDD", /* Analog DAC Voltage */ "DRVDD", /* ADC Analog and Output Driver Voltage */ }; /* codec private data */ struct aic3x_priv { struct snd_soc_codec codec; struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; unsigned int sysclk; int master; }; Loading Loading @@ -999,7 +1007,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: /* all power is driven by DAPM system */ break; case SND_SOC_BIAS_PREPARE: if (aic3x->master) { /* enable pll */ reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); Loading @@ -1007,48 +1016,9 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, reg | PLL_ENABLE); } break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* * all power is driven by DAPM system, * so output power is safe if bypass was set */ if (aic3x->master) { /* disable pll */ reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE); } break; /* fall through and disable pll */ case SND_SOC_BIAS_OFF: /* force all power off */ reg = aic3x_read_reg_cache(codec, LINE1L_2_LADC_CTRL); aic3x_write(codec, LINE1L_2_LADC_CTRL, reg & ~LADC_PWR_ON); reg = aic3x_read_reg_cache(codec, LINE1R_2_RADC_CTRL); aic3x_write(codec, LINE1R_2_RADC_CTRL, reg & ~RADC_PWR_ON); reg = aic3x_read_reg_cache(codec, DAC_PWR); aic3x_write(codec, DAC_PWR, reg & ~(LDAC_PWR_ON | RDAC_PWR_ON)); reg = aic3x_read_reg_cache(codec, HPLOUT_CTRL); aic3x_write(codec, HPLOUT_CTRL, reg & ~HPLOUT_PWR_ON); reg = aic3x_read_reg_cache(codec, HPROUT_CTRL); aic3x_write(codec, HPROUT_CTRL, reg & ~HPROUT_PWR_ON); reg = aic3x_read_reg_cache(codec, HPLCOM_CTRL); aic3x_write(codec, HPLCOM_CTRL, reg & ~HPLCOM_PWR_ON); reg = aic3x_read_reg_cache(codec, HPRCOM_CTRL); aic3x_write(codec, HPRCOM_CTRL, reg & ~HPRCOM_PWR_ON); reg = aic3x_read_reg_cache(codec, MONOLOPM_CTRL); aic3x_write(codec, MONOLOPM_CTRL, reg & ~MONOLOPM_PWR_ON); reg = aic3x_read_reg_cache(codec, LLOPM_CTRL); aic3x_write(codec, LLOPM_CTRL, reg & ~LLOPM_PWR_ON); reg = aic3x_read_reg_cache(codec, RLOPM_CTRL); aic3x_write(codec, RLOPM_CTRL, reg & ~RLOPM_PWR_ON); if (aic3x->master) { /* disable pll */ reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); Loading Loading @@ -1308,6 +1278,9 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) snd_soc_unregister_dai(&aic3x_dai); snd_soc_unregister_codec(&aic3x->codec); regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); kfree(aic3x); aic3x_codec = NULL; Loading @@ -1329,6 +1302,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, { struct snd_soc_codec *codec; struct aic3x_priv *aic3x; int ret, i; aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); if (aic3x == NULL) { Loading @@ -1344,7 +1318,30 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, aic3x); for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) aic3x->supplies[i].supply = aic3x_supply_names[i]; ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies), aic3x->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to request supplies: %d\n", ret); goto err_get; } ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); goto err_enable; } return aic3x_register(codec); err_enable: regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); err_get: kfree(aic3x); return ret; } static int aic3x_i2c_remove(struct i2c_client *client) Loading sound/soc/codecs/tlv320dac33.c +238 −12 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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; }; Loading Loading @@ -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; } Loading Loading @@ -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", Loading @@ -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; Loading Loading @@ -632,6 +683,12 @@ 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); 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; Loading Loading @@ -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 */ Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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, }; Loading Loading @@ -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); Loading @@ -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; Loading Loading
sound/soc/codecs/tlv320aic3x.c +39 −42 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> #include <linux/regulator/consumer.h> #include <linux/platform_device.h> #include <sound/core.h> #include <sound/pcm.h> Loading @@ -49,11 +50,18 @@ #include "tlv320aic3x.h" #define AIC3X_VERSION "0.2" #define AIC3X_NUM_SUPPLIES 4 static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = { "IOVDD", /* I/O Voltage */ "DVDD", /* Digital Core Voltage */ "AVDD", /* Analog DAC Voltage */ "DRVDD", /* ADC Analog and Output Driver Voltage */ }; /* codec private data */ struct aic3x_priv { struct snd_soc_codec codec; struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; unsigned int sysclk; int master; }; Loading Loading @@ -999,7 +1007,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: /* all power is driven by DAPM system */ break; case SND_SOC_BIAS_PREPARE: if (aic3x->master) { /* enable pll */ reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); Loading @@ -1007,48 +1016,9 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec, reg | PLL_ENABLE); } break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* * all power is driven by DAPM system, * so output power is safe if bypass was set */ if (aic3x->master) { /* disable pll */ reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE); } break; /* fall through and disable pll */ case SND_SOC_BIAS_OFF: /* force all power off */ reg = aic3x_read_reg_cache(codec, LINE1L_2_LADC_CTRL); aic3x_write(codec, LINE1L_2_LADC_CTRL, reg & ~LADC_PWR_ON); reg = aic3x_read_reg_cache(codec, LINE1R_2_RADC_CTRL); aic3x_write(codec, LINE1R_2_RADC_CTRL, reg & ~RADC_PWR_ON); reg = aic3x_read_reg_cache(codec, DAC_PWR); aic3x_write(codec, DAC_PWR, reg & ~(LDAC_PWR_ON | RDAC_PWR_ON)); reg = aic3x_read_reg_cache(codec, HPLOUT_CTRL); aic3x_write(codec, HPLOUT_CTRL, reg & ~HPLOUT_PWR_ON); reg = aic3x_read_reg_cache(codec, HPROUT_CTRL); aic3x_write(codec, HPROUT_CTRL, reg & ~HPROUT_PWR_ON); reg = aic3x_read_reg_cache(codec, HPLCOM_CTRL); aic3x_write(codec, HPLCOM_CTRL, reg & ~HPLCOM_PWR_ON); reg = aic3x_read_reg_cache(codec, HPRCOM_CTRL); aic3x_write(codec, HPRCOM_CTRL, reg & ~HPRCOM_PWR_ON); reg = aic3x_read_reg_cache(codec, MONOLOPM_CTRL); aic3x_write(codec, MONOLOPM_CTRL, reg & ~MONOLOPM_PWR_ON); reg = aic3x_read_reg_cache(codec, LLOPM_CTRL); aic3x_write(codec, LLOPM_CTRL, reg & ~LLOPM_PWR_ON); reg = aic3x_read_reg_cache(codec, RLOPM_CTRL); aic3x_write(codec, RLOPM_CTRL, reg & ~RLOPM_PWR_ON); if (aic3x->master) { /* disable pll */ reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); Loading Loading @@ -1308,6 +1278,9 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) snd_soc_unregister_dai(&aic3x_dai); snd_soc_unregister_codec(&aic3x->codec); regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); kfree(aic3x); aic3x_codec = NULL; Loading @@ -1329,6 +1302,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, { struct snd_soc_codec *codec; struct aic3x_priv *aic3x; int ret, i; aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); if (aic3x == NULL) { Loading @@ -1344,7 +1318,30 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, aic3x); for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) aic3x->supplies[i].supply = aic3x_supply_names[i]; ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies), aic3x->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to request supplies: %d\n", ret); goto err_get; } ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); goto err_enable; } return aic3x_register(codec); err_enable: regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); err_get: kfree(aic3x); return ret; } static int aic3x_i2c_remove(struct i2c_client *client) Loading
sound/soc/codecs/tlv320dac33.c +238 −12 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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; }; Loading Loading @@ -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; } Loading Loading @@ -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", Loading @@ -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; Loading Loading @@ -632,6 +683,12 @@ 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); 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; Loading Loading @@ -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 */ Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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, }; Loading Loading @@ -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); Loading @@ -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; Loading