diff options
Diffstat (limited to 'sound/soc/codecs/tlv320dac33.c')
-rw-r--r-- | sound/soc/codecs/tlv320dac33.c | 456 |
1 files changed, 232 insertions, 224 deletions
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 65adc77..d251ff5 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -49,8 +49,6 @@ #define NSAMPLE_MAX 5700 -#define LATENCY_TIME_MS 20 - #define MODE7_LTHR 10 #define MODE7_UTHR (DAC33_BUFFER_SIZE_SAMPLES - 10) @@ -62,11 +60,12 @@ #define US_TO_SAMPLES(rate, us) \ (rate / (1000000 / us)) +#define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \ + ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate))) + static void dac33_calculate_times(struct snd_pcm_substream *substream); static int dac33_prepare_chip(struct snd_pcm_substream *substream); -static struct snd_soc_codec *tlv320dac33_codec; - enum dac33_state { DAC33_IDLE = 0, DAC33_PREFILL, @@ -92,7 +91,7 @@ struct tlv320dac33_priv { struct mutex mutex; struct workqueue_struct *dac33_wq; struct work_struct work; - struct snd_soc_codec codec; + struct snd_soc_codec *codec; struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; struct snd_pcm_substream *substream; int power_gpio; @@ -107,6 +106,10 @@ struct tlv320dac33_priv { * this */ enum dac33_fifo_modes fifo_mode;/* FIFO mode selection */ unsigned int nsample; /* burst read amount from host */ + int mode1_latency; /* latency caused by the i2c writes in + * us */ + int auto_fifo_config; /* Configure the FIFO based on the + * period size */ u8 burst_bclkdiv; /* BCLK divider value in burst mode */ unsigned int burst_rate; /* Interface speed in Burst modes */ @@ -120,7 +123,11 @@ struct tlv320dac33_priv { * samples */ unsigned int mode7_us_to_lthr; /* Time to reach lthr from uthr */ + unsigned int uthr; + enum dac33_state state; + enum snd_soc_control_type control_type; + void *control_data; }; static const u8 dac33_reg[DAC33_CACHEREGNUM] = { @@ -442,6 +449,39 @@ static int dac33_set_nsample(struct snd_kcontrol *kcontrol, return ret; } +static int dac33_get_uthr(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = dac33->uthr; + + return 0; +} + +static int dac33_set_uthr(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + if (dac33->substream) + return -EBUSY; + + if (dac33->uthr == ucontrol->value.integer.value[0]) + return 0; + + if (ucontrol->value.integer.value[0] < (MODE7_LTHR + 10) || + ucontrol->value.integer.value[0] > MODE7_UTHR) + ret = -EINVAL; + else + dac33->uthr = ucontrol->value.integer.value[0]; + + return ret; +} + static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -484,6 +524,22 @@ static const struct soc_enum dac33_fifo_mode_enum = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts), dac33_fifo_mode_texts); +/* L/R Line Output Gain */ +static const char *lr_lineout_gain_texts[] = { + "Line -12dB DAC 0dB", "Line -6dB DAC 6dB", + "Line 0dB DAC 12dB", "Line 6dB DAC 18dB", +}; + +static const struct soc_enum l_lineout_gain_enum = + SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0, + ARRAY_SIZE(lr_lineout_gain_texts), + lr_lineout_gain_texts); + +static const struct soc_enum r_lineout_gain_enum = + SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0, + ARRAY_SIZE(lr_lineout_gain_texts), + lr_lineout_gain_texts); + /* * DACL/R digital volume control: * from 0 dB to -63.5 in 0.5 dB steps @@ -501,15 +557,22 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = { 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), }; -static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = { - SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0, - dac33_get_nsample, dac33_set_nsample), +static const struct snd_kcontrol_new dac33_mode_snd_controls[] = { SOC_ENUM_EXT("FIFO Mode", dac33_fifo_mode_enum, dac33_get_fifo_mode, dac33_set_fifo_mode), }; +static const struct snd_kcontrol_new dac33_fifo_snd_controls[] = { + SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0, + dac33_get_nsample, dac33_set_nsample), + SOC_SINGLE_EXT("UTHR", 0, 0, MODE7_UTHR, 0, + dac33_get_uthr, dac33_set_uthr), +}; + /* Analog bypass */ static const struct snd_kcontrol_new dac33_dapm_abypassl_control = SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1); @@ -605,14 +668,13 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) { - struct snd_soc_codec *codec; - - codec = &dac33->codec; + struct snd_soc_codec *codec = dac33->codec; + unsigned int delay; switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: dac33_write16(codec, DAC33_NSAMPLE_MSB, - DAC33_THRREG(dac33->nsample + dac33->alarm_threshold)); + DAC33_THRREG(dac33->nsample)); /* Take the timestamps */ spin_lock_irq(&dac33->lock); @@ -623,8 +685,9 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) 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)); + delay = SAMPLES_TO_US(dac33->burst_rate, + dac33->alarm_threshold) + 1000; + usleep_range(delay, delay + 500); dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT); break; case DAC33_FIFO_MODE7: @@ -650,9 +713,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) { - struct snd_soc_codec *codec; - - codec = &dac33->codec; + struct snd_soc_codec *codec = dac33->codec; switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: @@ -681,7 +742,7 @@ static void dac33_work(struct work_struct *work) u8 reg; dac33 = container_of(work, struct tlv320dac33_priv, work); - codec = &dac33->codec; + codec = dac33->codec; mutex_lock(&dac33->mutex); switch (dac33->state) { @@ -726,11 +787,11 @@ static irqreturn_t dac33_interrupt_handler(int irq, void *dev) static void dac33_oscwait(struct snd_soc_codec *codec) { - int timeout = 20; + int timeout = 60; u8 reg; do { - msleep(1); + usleep_range(1000, 2000); dac33_read(codec, DAC33_INT_OSC_STATUS, ®); } while (((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) && timeout--); if ((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) @@ -742,8 +803,7 @@ static int dac33_startup(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 snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); /* Stream started, save the substream pointer */ @@ -756,11 +816,14 @@ static void dac33_shutdown(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 snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); dac33->substream = NULL; + + /* Reset the nSample restrictions */ + dac33->nsample_min = 0; + dac33->nsample_max = NSAMPLE_MAX; } static int dac33_hw_params(struct snd_pcm_substream *substream, @@ -768,8 +831,7 @@ static int dac33_hw_params(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 snd_soc_codec *codec = rtd->codec; /* Check parameters for validity */ switch (params_rate(params)) { @@ -807,8 +869,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream, static int dac33_prepare_chip(struct snd_pcm_substream *substream) { 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 snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); unsigned int oscset, ratioset, pwr_ctrl, reg_tmp; u8 aictrl_a, aictrl_b, fifoctrl_a; @@ -985,7 +1046,7 @@ 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(MODE7_UTHR)); + dac33_write16(codec, DAC33_UTHR_MSB, DAC33_THRREG(dac33->uthr)); dac33_write16(codec, DAC33_LTHR_MSB, DAC33_THRREG(MODE7_LTHR)); break; default: @@ -1000,60 +1061,73 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) static void dac33_calculate_times(struct snd_pcm_substream *substream) { 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 snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); + unsigned int period_size = substream->runtime->period_size; + unsigned int rate = substream->runtime->rate; 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; - - /* Number of samples (16bit, stereo) in ALSA buffer */ - dac33->nsample_max = snd_pcm_lib_buffer_bytes(substream) / 4; - /* Subtract one period from the total */ - dac33->nsample_max -= dac33->nsample_min; - - /* Number of samples for LATENCY_TIME_MS / 2 */ - dac33->alarm_threshold = substream->runtime->rate / - (1000 / (LATENCY_TIME_MS / 2)); - - /* Find and fix up the lowest nsmaple limit */ - nsample_limit = substream->runtime->rate / (1000 / LATENCY_TIME_MS); - - if (dac33->nsample_min < nsample_limit) - dac33->nsample_min = nsample_limit; - - if (dac33->nsample < dac33->nsample_min) - dac33->nsample = dac33->nsample_min; - - /* - * Find and fix up the highest nsmaple limit - * In order to not overflow the DAC33 buffer substract the - * alarm_threshold value from the size of the DAC33 buffer - */ - nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold; - - if (dac33->nsample_max > nsample_limit) - dac33->nsample_max = nsample_limit; - - if (dac33->nsample > dac33->nsample_max) - dac33->nsample = dac33->nsample_max; - switch (dac33->fifo_mode) { case DAC33_FIFO_MODE1: + /* Number of samples under i2c latency */ + dac33->alarm_threshold = US_TO_SAMPLES(rate, + dac33->mode1_latency); + if (dac33->auto_fifo_config) { + if (period_size <= dac33->alarm_threshold) + /* + * Configure nSamaple to number of periods, + * which covers the latency requironment. + */ + dac33->nsample = period_size * + ((dac33->alarm_threshold / period_size) + + (dac33->alarm_threshold % period_size ? + 1 : 0)); + else + dac33->nsample = period_size; + } else { + /* nSample time shall not be shorter than i2c latency */ + dac33->nsample_min = dac33->alarm_threshold; + /* + * nSample should not be bigger than alsa buffer minus + * size of one period to avoid overruns + */ + dac33->nsample_max = substream->runtime->buffer_size - + period_size; + nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - + dac33->alarm_threshold; + if (dac33->nsample_max > nsample_limit) + dac33->nsample_max = nsample_limit; + + /* Correct the nSample if it is outside of the ranges */ + if (dac33->nsample < dac33->nsample_min) + dac33->nsample = dac33->nsample_min; + if (dac33->nsample > dac33->nsample_max) + dac33->nsample = dac33->nsample_max; + } + 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: + if (dac33->auto_fifo_config) { + dac33->uthr = UTHR_FROM_PERIOD_SIZE( + period_size, + rate, + dac33->burst_rate) + 9; + if (dac33->uthr > MODE7_UTHR) + dac33->uthr = MODE7_UTHR; + if (dac33->uthr < (MODE7_LTHR + 10)) + dac33->uthr = (MODE7_LTHR + 10); + } dac33->mode7_us_to_lthr = - SAMPLES_TO_US(substream->runtime->rate, - MODE7_UTHR - MODE7_LTHR + 1); + SAMPLES_TO_US(substream->runtime->rate, + dac33->uthr - MODE7_LTHR + 1); dac33->t_stamp1 = 0; break; default: @@ -1066,8 +1140,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, 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 snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); int ret = 0; @@ -1100,11 +1173,10 @@ static snd_pcm_sframes_t dac33_dai_delay( 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 snd_soc_codec *codec = rtd->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); unsigned long long t0, t1, t_now; - unsigned int time_delta; + unsigned int time_delta, uthr; int samples_out, samples_in, samples; snd_pcm_sframes_t delay = 0; @@ -1182,6 +1254,7 @@ static snd_pcm_sframes_t dac33_dai_delay( case DAC33_FIFO_MODE7: spin_lock(&dac33->lock); t0 = dac33->t_stamp1; + uthr = dac33->uthr; spin_unlock(&dac33->lock); t_now = ktime_to_us(ktime_get()); @@ -1194,7 +1267,7 @@ static snd_pcm_sframes_t dac33_dai_delay( * Either the timestamps are messed or equal. Report * maximum delay */ - delay = MODE7_UTHR; + delay = uthr; goto out; } @@ -1208,8 +1281,8 @@ static snd_pcm_sframes_t dac33_dai_delay( substream->runtime->rate, time_delta); - if (likely(MODE7_UTHR > samples_out)) - delay = MODE7_UTHR - samples_out; + if (likely(uthr > samples_out)) + delay = uthr - samples_out; else delay = 0; } else { @@ -1227,8 +1300,8 @@ static snd_pcm_sframes_t dac33_dai_delay( time_delta); delay = MODE7_LTHR + samples_in - samples_out; - if (unlikely(delay > MODE7_UTHR)) - delay = MODE7_UTHR; + if (unlikely(delay > uthr)) + delay = uthr; } break; default: @@ -1325,82 +1398,104 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int dac33_soc_probe(struct platform_device *pdev) +static int dac33_soc_probe(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct tlv320dac33_priv *dac33; + struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); int ret = 0; - BUG_ON(!tlv320dac33_codec); + codec->control_data = dac33->control_data; + codec->hw_write = (hw_write_t) i2c_master_send; + codec->idle_bias_off = 1; + dac33->codec = codec; - codec = tlv320dac33_codec; - socdev->card->codec = codec; - dac33 = snd_soc_codec_get_drvdata(codec); + /* Read the tlv320dac33 ID registers */ + ret = dac33_hard_power(codec, 1); + if (ret != 0) { + dev_err(codec->dev, "Failed to power up codec: %d\n", ret); + goto err_power; + } + dac33_read_id(codec); + dac33_hard_power(codec, 0); + + /* 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 | IRQF_DISABLED, + codec->name, codec); + if (ret < 0) { + dev_err(codec->dev, "Could not request IRQ%d (%d)\n", + dac33->irq, ret); + dac33->irq = -1; + } + if (dac33->irq != -1) { + /* Setup work queue */ + dac33->dac33_wq = + create_singlethread_workqueue("tlv320dac33"); + if (dac33->dac33_wq == NULL) { + free_irq(dac33->irq, codec); + return -ENOMEM; + } - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms\n"); - goto pcm_err; + INIT_WORK(&dac33->work, dac33_work); + } } snd_soc_add_controls(codec, dac33_snd_controls, ARRAY_SIZE(dac33_snd_controls)); - /* Only add the nSample controls, if we have valid IRQ number */ - if (dac33->irq >= 0) - snd_soc_add_controls(codec, dac33_nsample_snd_controls, - ARRAY_SIZE(dac33_nsample_snd_controls)); - + /* Only add the FIFO controls, if we have valid IRQ number */ + if (dac33->irq >= 0) { + snd_soc_add_controls(codec, dac33_mode_snd_controls, + ARRAY_SIZE(dac33_mode_snd_controls)); + /* FIFO usage controls only, if autoio config is not selected */ + if (!dac33->auto_fifo_config) + snd_soc_add_controls(codec, dac33_fifo_snd_controls, + ARRAY_SIZE(dac33_fifo_snd_controls)); + } dac33_add_widgets(codec); - return 0; - -pcm_err: - dac33_hard_power(codec, 0); +err_power: return ret; } -static int dac33_soc_remove(struct platform_device *pdev) +static int dac33_soc_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; + struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - + if (dac33->irq >= 0) { + free_irq(dac33->irq, dac33->codec); + destroy_workqueue(dac33->dac33_wq); + } return 0; } -static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state) +static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int dac33_soc_resume(struct platform_device *pdev) +static int dac33_soc_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = { +static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = { + .read = dac33_read_reg_cache, + .write = dac33_write_locked, + .set_bias_level = dac33_set_bias_level, + .reg_cache_size = ARRAY_SIZE(dac33_reg), + .reg_word_size = sizeof(u8), + .reg_cache_default = dac33_reg, .probe = dac33_soc_probe, .remove = dac33_soc_remove, .suspend = dac33_soc_suspend, .resume = dac33_soc_resume, }; -EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33); #define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) @@ -1416,8 +1511,8 @@ static struct snd_soc_dai_ops dac33_dai_ops = { .set_fmt = dac33_set_dai_fmt, }; -struct snd_soc_dai dac33_dai = { - .name = "tlv320dac33", +static struct snd_soc_dai_driver dac33_dai = { + .name = "tlv320dac33-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -1426,14 +1521,12 @@ struct snd_soc_dai dac33_dai = { .formats = DAC33_FORMATS,}, .ops = &dac33_dai_ops, }; -EXPORT_SYMBOL_GPL(dac33_dai); static int __devinit dac33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tlv320dac33_platform_data *pdata; struct tlv320dac33_priv *dac33; - struct snd_soc_codec *codec; int ret, i; if (client->dev.platform_data == NULL) { @@ -1446,33 +1539,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, if (dac33 == NULL) return -ENOMEM; - codec = &dac33->codec; - snd_soc_codec_set_drvdata(codec, dac33); - codec->control_data = client; - - mutex_init(&codec->mutex); + dac33->control_data = client; mutex_init(&dac33->mutex); spin_lock_init(&dac33->lock); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "tlv320dac33"; - codec->owner = THIS_MODULE; - codec->read = dac33_read_reg_cache; - codec->write = dac33_write_locked; - codec->hw_write = (hw_write_t) i2c_master_send; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = dac33_set_bias_level; - codec->idle_bias_off = 1; - codec->dai = &dac33_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(dac33_reg); - codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg), - GFP_KERNEL); - if (codec->reg_cache == NULL) { - ret = -ENOMEM; - goto error_reg; - } i2c_set_clientdata(client, dac33); @@ -1481,131 +1550,70 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, /* Pre calculate the burst rate */ dac33->burst_rate = BURST_BASEFREQ_HZ / dac33->burst_bclkdiv / 32; dac33->keep_bclk = pdata->keep_bclk; + dac33->auto_fifo_config = pdata->auto_fifo_config; + dac33->mode1_latency = pdata->mode1_latency; + if (!dac33->mode1_latency) + dac33->mode1_latency = 10000; /* 10ms */ dac33->irq = client->irq; dac33->nsample = NSAMPLE_MAX; dac33->nsample_max = NSAMPLE_MAX; + dac33->uthr = MODE7_UTHR; /* Disable FIFO use by default */ dac33->fifo_mode = DAC33_FIFO_BYPASS; - tlv320dac33_codec = codec; - - codec->dev = &client->dev; - dac33_dai.dev = codec->dev; - /* 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(codec->dev, + dev_err(&client->dev, "Failed to request reset GPIO (%d)\n", dac33->power_gpio); - snd_soc_unregister_dai(&dac33_dai); - snd_soc_unregister_codec(codec); - goto error_gpio; + goto err_gpio; } gpio_direction_output(dac33->power_gpio, 0); } - /* 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 | IRQF_DISABLED, - codec->name, codec); - if (ret < 0) { - dev_err(codec->dev, "Could not request IRQ%d (%d)\n", - dac33->irq, ret); - dac33->irq = -1; - } - if (dac33->irq != -1) { - /* Setup work queue */ - dac33->dac33_wq = - create_singlethread_workqueue("tlv320dac33"); - if (dac33->dac33_wq == NULL) { - free_irq(dac33->irq, &dac33->codec); - ret = -ENOMEM; - goto error_wq; - } - - INIT_WORK(&dac33->work, dac33_work); - } - } - for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) dac33->supplies[i].supply = dac33_supply_names[i]; - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies), + ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies), dac33->supplies); if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); + dev_err(&client->dev, "Failed to request supplies: %d\n", ret); goto err_get; } - /* Read the tlv320dac33 ID registers */ - ret = dac33_hard_power(codec, 1); - if (ret != 0) { - dev_err(codec->dev, "Failed to power up codec: %d\n", ret); - goto error_codec; - } - dac33_read_id(codec); - dac33_hard_power(codec, 0); - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto error_codec; - } - - ret = snd_soc_register_dai(&dac33_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - goto error_codec; - } + ret = snd_soc_register_codec(&client->dev, + &soc_codec_dev_tlv320dac33, &dac33_dai, 1); + if (ret < 0) + goto err_register; return ret; - -error_codec: +err_register: regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); err_get: - if (dac33->irq >= 0) { - free_irq(dac33->irq, &dac33->codec); - destroy_workqueue(dac33->dac33_wq); - } -error_wq: if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); -error_gpio: - kfree(codec->reg_cache); -error_reg: - tlv320dac33_codec = NULL; +err_gpio: kfree(dac33); - return ret; } static int __devexit dac33_i2c_remove(struct i2c_client *client) { - struct tlv320dac33_priv *dac33; - - dac33 = i2c_get_clientdata(client); + struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client); if (unlikely(dac33->chip_power)) - dac33_hard_power(&dac33->codec, 0); + dac33_hard_power(dac33->codec, 0); if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); - if (dac33->irq >= 0) - free_irq(dac33->irq, &dac33->codec); regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); - destroy_workqueue(dac33->dac33_wq); - snd_soc_unregister_dai(&dac33_dai); - snd_soc_unregister_codec(&dac33->codec); - kfree(dac33->codec.reg_cache); + snd_soc_unregister_codec(&client->dev); kfree(dac33); - tlv320dac33_codec = NULL; return 0; } @@ -1620,7 +1628,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = { static struct i2c_driver tlv320dac33_i2c_driver = { .driver = { - .name = "tlv320dac33", + .name = "tlv320dac33-codec", .owner = THIS_MODULE, }, .probe = dac33_i2c_probe, |