ASoC: tlv320aic3x: Add platform data and reset gpio handling

Handle the reset GPIO within the codec driver in order to follow
the startup protocol for the tlv320aic3x codecs.

Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
Acked-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
This commit is contained in:
Jarkko Nikula 2010-05-05 13:02:03 +03:00 committed by Liam Girdwood
parent 49100c9835
commit 5193d62f18
2 changed files with 42 additions and 0 deletions

View File

@ -0,0 +1,17 @@
/*
* Platform data for Texas Instruments TLV320AIC3x codec
*
* Author: Jarkko Nikula <jhnikula@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __TLV320AIC3x_H__
#define __TLV320AIC3x_H__
struct aic3x_pdata {
int gpio_reset; /* < 0 if not used */
};
#endif

View File

@ -38,6 +38,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <sound/core.h> #include <sound/core.h>
@ -47,6 +48,7 @@
#include <sound/soc-dapm.h> #include <sound/soc-dapm.h>
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include <sound/tlv320aic3x.h>
#include "tlv320aic3x.h" #include "tlv320aic3x.h"
@ -64,6 +66,7 @@ struct aic3x_priv {
struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
unsigned int sysclk; unsigned int sysclk;
int master; int master;
int gpio_reset;
}; };
/* /*
@ -1278,6 +1281,10 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)
snd_soc_unregister_dai(&aic3x_dai); snd_soc_unregister_dai(&aic3x_dai);
snd_soc_unregister_codec(&aic3x->codec); snd_soc_unregister_codec(&aic3x->codec);
if (aic3x->gpio_reset >= 0) {
gpio_set_value(aic3x->gpio_reset, 0);
gpio_free(aic3x->gpio_reset);
}
regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
@ -1302,6 +1309,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
{ {
struct snd_soc_codec *codec; struct snd_soc_codec *codec;
struct aic3x_priv *aic3x; struct aic3x_priv *aic3x;
struct aic3x_pdata *pdata = i2c->dev.platform_data;
int ret, i; int ret, i;
aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
@ -1318,6 +1326,15 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, aic3x); i2c_set_clientdata(i2c, aic3x);
aic3x->gpio_reset = -1;
if (pdata && pdata->gpio_reset >= 0) {
ret = gpio_request(pdata->gpio_reset, "tlv320aic3x reset");
if (ret != 0)
goto err_gpio;
aic3x->gpio_reset = pdata->gpio_reset;
gpio_direction_output(aic3x->gpio_reset, 0);
}
for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
aic3x->supplies[i].supply = aic3x_supply_names[i]; aic3x->supplies[i].supply = aic3x_supply_names[i];
@ -1335,11 +1352,19 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
goto err_enable; goto err_enable;
} }
if (aic3x->gpio_reset >= 0) {
udelay(1);
gpio_set_value(aic3x->gpio_reset, 1);
}
return aic3x_register(codec); return aic3x_register(codec);
err_enable: err_enable:
regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
err_get: err_get:
if (aic3x->gpio_reset >= 0)
gpio_free(aic3x->gpio_reset);
err_gpio:
kfree(aic3x); kfree(aic3x);
return ret; return ret;
} }