/* * The internal FIFO is 24576 bytes long * It can be configured to hold 16bit or 24bit samples * In 16bit configuration the FIFO can hold 6144 stereo samples * In 24bit configuration the FIFO can hold 4096 stereo samples
*/ #define DAC33_FIFO_SIZE_16BIT 6144 #define DAC33_FIFO_SIZE_24BIT 4096 #define DAC33_MODE7_MARGIN 10 /* Safety margin for FIFO in Mode7 */
struct tlv320dac33_priv { struct mutex mutex; struct work_struct work; struct snd_soc_component *component; struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; struct snd_pcm_substream *substream; int power_gpio; int chip_power; int irq; unsignedint refclk;
unsignedint alarm_threshold; /* set to be half of LATENCY_TIME_MS */ enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ unsignedint fifo_size; /* Size of the FIFO in samples */ unsignedint nsample; /* burst read amount from host */ int mode1_latency; /* latency caused by the i2c writes in
* us */
u8 burst_bclkdiv; /* BCLK divider value in burst mode */
u8 *reg_cache; unsignedint burst_rate; /* Interface speed in Burst modes */
int keep_bclk; /* Keep the BCLK continuously running
* in FIFO modes */
spinlock_t lock; unsignedlonglong t_stamp1; /* Time stamp for FIFO modes to */ unsignedlonglong t_stamp2; /* calculate the FIFO caused delay */
unsignedint mode1_us_burst; /* Time to burst read n number of
* samples */ unsignedint mode7_us_to_lthr; /* Time to reach lthr from uthr */
if (dac33->chip_power) { /* We need to set autoincrement mode for 16 bit writes */
data[0] |= DAC33_I2C_ADDR_AUTOINC;
ret = i2c_master_send(dac33->i2c, data, 3); if (ret != 3)
dev_err(component->dev, "Write failed (%d)\n", ret); else
ret = 0;
}
/* Stop the DAI clock */
reg = dac33_read_reg_cache(component, DAC33_SER_AUDIOIF_CTRL_B);
reg &= ~DAC33_BCLKON;
dac33_write(component, DAC33_SER_AUDIOIF_CTRL_B, reg);
/* Power down the Oscillator, and DACs */
reg = dac33_read_reg_cache(component, DAC33_PWR_CTRL);
reg &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB);
dac33_write(component, DAC33_PWR_CTRL, reg);
}
staticint dac33_hard_power(struct snd_soc_component *component, int power)
{ struct tlv320dac33_priv *dac33 = snd_soc_component_get_drvdata(component); int ret = 0;
mutex_lock(&dac33->mutex);
/* Safety check */ if (unlikely(power == dac33->chip_power)) {
dev_dbg(component->dev, "Trying to set the same power state: %s\n",
power ? "ON" : "OFF"); gotoexit;
}
if (power) {
ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies),
dac33->supplies); if (ret != 0) {
dev_err(component->dev, "Failed to enable supplies: %d\n", ret); gotoexit;
}
if (dac33->power_gpio >= 0)
gpio_set_value(dac33->power_gpio, 1);
if (dac33->fifo_mode == ucontrol->value.enumerated.item[0]) return 0; /* Do not allow changes while stream is running*/ if (snd_soc_component_active(component)) return -EPERM;
if (ucontrol->value.enumerated.item[0] >= DAC33_FIFO_LAST_MODE)
ret = -EINVAL; else
dac33->fifo_mode = ucontrol->value.enumerated.item[0];
/* * DACL/R digital volume control: * from 0 dB to -63.5 in 0.5 dB steps * Need to be inverted later on: * 0x00 == 0 dB * 0x7f == -63.5 dB
*/ static DECLARE_TLV_DB_SCALE(dac_digivol_tlv, -6350, 50, 0);
staticconststruct snd_kcontrol_new dac33_snd_controls[] = {
SOC_DOUBLE_R_TLV("DAC Digital Playback Volume",
DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL,
0, 0x7f, 1, dac_digivol_tlv),
SOC_DOUBLE_R("DAC Digital Playback Switch",
DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, 7, 1, 1),
SOC_DOUBLE_R("Line to Line Out Volume",
DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1),
SOC_ENUM("Left Line Output Gain", l_lineout_gain_enum),
SOC_ENUM("Right Line Output Gain", r_lineout_gain_enum),
};
/* Analog bypass */
SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0,
&dac33_dapm_abypassl_control),
SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0,
&dac33_dapm_abypassr_control),
SND_SOC_DAPM_MUX("Left LOM Inverted From", SND_SOC_NOPM, 0, 0,
&dac33_dapm_left_lom_control),
SND_SOC_DAPM_MUX("Right LOM Inverted From", SND_SOC_NOPM, 0, 0,
&dac33_dapm_right_lom_control), /* * For DAPM path, when only the anlog bypass path is enabled, and the * LOP inverted from the corresponding DAC side. * This is needed, so we can attach the DAC power supply in this case.
*/
SND_SOC_DAPM_PGA("Left Bypass PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("Right Bypass PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amplifier",
DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0),
SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amplifier",
DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0),
staticint dac33_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level)
{ int ret;
switch (level) { case SND_SOC_BIAS_ON: break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { /* Coming from OFF, switch on the component */
ret = dac33_hard_power(component, 1); if (ret != 0) return ret;
dac33_init_chip(component);
} break; case SND_SOC_BIAS_OFF: /* Do not power off, when the component is already off */ if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) return 0;
ret = dac33_hard_power(component, 0); if (ret != 0) return ret; break;
}
switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: /* Take the timestamp */
spin_lock_irqsave(&dac33->lock, flags);
dac33->t_stamp2 = ktime_to_us(ktime_get());
spin_unlock_irqrestore(&dac33->lock, flags);
dac33_write16(component, DAC33_NSAMPLE_MSB,
DAC33_THRREG(dac33->nsample)); break; case DAC33_FIFO_MODE7: /* At the moment we are not using interrupts in mode7 */ break; default:
dev_warn(component->dev, "Unhandled FIFO mode: %d\n",
dac33->fifo_mode); break;
}
}
/* * tlv320dac33 is strict on the sequence of the register writes, if the register * writes happens in different order, than dac33 might end up in unknown state. * Use the known, working sequence of register writes to initialize the dac33.
*/ staticint dac33_prepare_chip(struct snd_pcm_substream *substream, struct snd_soc_component *component)
{ struct tlv320dac33_priv *dac33 = snd_soc_component_get_drvdata(component); unsignedint oscset, ratioset, pwr_ctrl, reg_tmp;
u8 aictrl_a, aictrl_b, fifoctrl_a;
/* Set interrupts to high active */
dac33_write(component, DAC33_INTP_CTRL_A, DAC33_INTPM_AHIGH);
} else { /* FIFO bypass mode */ /* 50-51 : ASRC Control registers */
dac33_write(component, DAC33_ASRC_CTRL_A, DAC33_SRCBYP);
dac33_write(component, DAC33_ASRC_CTRL_B, 0); /* ??? */
}
/* Interrupt behaviour configuration */ switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1:
dac33_write(component, DAC33_FIFO_IRQ_MODE_B,
DAC33_ATM(DAC33_FIFO_IRQ_MODE_LEVEL)); break; case DAC33_FIFO_MODE7:
dac33_write(component, DAC33_FIFO_IRQ_MODE_A,
DAC33_UTM(DAC33_FIFO_IRQ_MODE_LEVEL)); break; default: /* in FIFO bypass mode, the interrupts are not used */ break;
}
switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: /* * For mode1: * Disable the FIFO bypass (Enable the use of FIFO) * Select nSample mode * BCLK is only running when data is needed by DAC33
*/
fifoctrl_a &= ~DAC33_FBYPAS;
fifoctrl_a &= ~DAC33_FAUTO; if (dac33->keep_bclk)
aictrl_b |= DAC33_BCLKON; else
aictrl_b &= ~DAC33_BCLKON; break; case DAC33_FIFO_MODE7: /* * For mode1: * Disable the FIFO bypass (Enable the use of FIFO) * Select Threshold mode * BCLK is only running when data is needed by DAC33
*/
fifoctrl_a &= ~DAC33_FBYPAS;
fifoctrl_a |= DAC33_FAUTO; if (dac33->keep_bclk)
aictrl_b |= DAC33_BCLKON; else
aictrl_b &= ~DAC33_BCLKON; break; default: /* * For FIFO bypass mode: * Enable the FIFO bypass (Disable the FIFO use) * Set the BCLK as continuous
*/
fifoctrl_a |= DAC33_FBYPAS;
aictrl_b |= DAC33_BCLKON; break;
}
switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1:
dac33_write16(component, DAC33_ATHR_MSB,
DAC33_THRREG(dac33->alarm_threshold)); break; case DAC33_FIFO_MODE7: /* * Configure the threshold levels, and leave 10 sample space * at the bottom, and also at the top of the FIFO
*/
dac33_write16(component, DAC33_UTHR_MSB, DAC33_THRREG(dac33->uthr));
dac33_write16(component, DAC33_LTHR_MSB,
DAC33_THRREG(DAC33_MODE7_MARGIN)); break; default: break;
}
staticint dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
{ struct snd_soc_component *component = dai->component; struct tlv320dac33_priv *dac33 = snd_soc_component_get_drvdata(component); int ret = 0;
switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (dac33->fifo_mode) {
dac33->state = DAC33_PREFILL;
schedule_work(&dac33->work);
} break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (dac33->fifo_mode) {
dac33->state = DAC33_FLUSH;
schedule_work(&dac33->work);
} break; default:
ret = -EINVAL;
}
staticint dac33_soc_probe(struct snd_soc_component *component)
{ struct tlv320dac33_priv *dac33 = snd_soc_component_get_drvdata(component); int ret = 0;
dac33->component = component;
/* Read the tlv320dac33 ID registers */
ret = dac33_hard_power(component, 1); if (ret != 0) {
dev_err(component->dev, "Failed to power up component: %d\n", ret); goto err_power;
}
ret = dac33_read_id(component);
dac33_hard_power(component, 0);
if (ret < 0) {
dev_err(component->dev, "Failed to read chip ID: %d\n", ret);
ret = -ENODEV; goto err_power;
}
/* Check if the IRQ number is valid and request it */ if (dac33->irq >= 0) {
ret = request_irq(dac33->irq, dac33_interrupt_handler,
IRQF_TRIGGER_RISING,
component->name, component); if (ret < 0) {
dev_err(component->dev, "Could not request IRQ%d (%d)\n",
dac33->irq, ret);
dac33->irq = -1;
} if (dac33->irq != -1) {
INIT_WORK(&dac33->work, dac33_work);
}
}
/* Only add the FIFO controls, if we have valid IRQ number */ if (dac33->irq >= 0)
snd_soc_add_component_controls(component, dac33_mode_snd_controls,
ARRAY_SIZE(dac33_mode_snd_controls));
/* Check if the reset GPIO number is valid and request it */ if (dac33->power_gpio >= 0) {
ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); if (ret < 0) {
dev_err(&client->dev, "Failed to request reset GPIO (%d)\n",
dac33->power_gpio); goto err_gpio;
}
gpio_direction_output(dac33->power_gpio, 0);
}
for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++)
dac33->supplies[i].supply = dac33_supply_names[i];
ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies),
dac33->supplies);
if (ret != 0) {
dev_err(&client->dev, "Failed to request supplies: %d\n", ret); goto err_get;
}
ret = devm_snd_soc_register_component(&client->dev,
&soc_component_dev_tlv320dac33, &dac33_dai, 1); if (ret < 0) goto err_get;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.