mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 12:16:20 +00:00
ALSA: AOA: Convert onyx and tas codecs to new-style i2c drivers
The legacy i2c binding model is going away soon, so convert the AOA codec drivers to the new model or they'll break. Signed-off-by: Jean Delvare <khali@linux-fr.org> Tested-by: Johannes Berg <johannes@sipsolutions.net> Tested-by: Andreas Schwab <schwab@linux-m68k.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
d91dfbb41b
commit
cfbf1eecd7
2 changed files with 95 additions and 47 deletions
|
@ -47,7 +47,7 @@ MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
|
||||||
struct onyx {
|
struct onyx {
|
||||||
/* cache registers 65 to 80, they are write-only! */
|
/* cache registers 65 to 80, they are write-only! */
|
||||||
u8 cache[16];
|
u8 cache[16];
|
||||||
struct i2c_client i2c;
|
struct i2c_client *i2c;
|
||||||
struct aoa_codec codec;
|
struct aoa_codec codec;
|
||||||
u32 initialised:1,
|
u32 initialised:1,
|
||||||
spdif_locked:1,
|
spdif_locked:1,
|
||||||
|
@ -72,7 +72,7 @@ static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value)
|
||||||
*value = onyx->cache[reg-FIRSTREGISTER];
|
*value = onyx->cache[reg-FIRSTREGISTER];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
v = i2c_smbus_read_byte_data(&onyx->i2c, reg);
|
v = i2c_smbus_read_byte_data(onyx->i2c, reg);
|
||||||
if (v < 0)
|
if (v < 0)
|
||||||
return -1;
|
return -1;
|
||||||
*value = (u8)v;
|
*value = (u8)v;
|
||||||
|
@ -84,7 +84,7 @@ static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value);
|
result = i2c_smbus_write_byte_data(onyx->i2c, reg, value);
|
||||||
if (!result)
|
if (!result)
|
||||||
onyx->cache[reg-FIRSTREGISTER] = value;
|
onyx->cache[reg-FIRSTREGISTER] = value;
|
||||||
return result;
|
return result;
|
||||||
|
@ -996,12 +996,45 @@ static void onyx_exit_codec(struct aoa_codec *codec)
|
||||||
onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
|
onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct i2c_driver onyx_driver;
|
|
||||||
|
|
||||||
static int onyx_create(struct i2c_adapter *adapter,
|
static int onyx_create(struct i2c_adapter *adapter,
|
||||||
struct device_node *node,
|
struct device_node *node,
|
||||||
int addr)
|
int addr)
|
||||||
{
|
{
|
||||||
|
struct i2c_board_info info;
|
||||||
|
struct i2c_client *client;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||||
|
strlcpy(info.type, "aoa_codec_onyx", I2C_NAME_SIZE);
|
||||||
|
info.addr = addr;
|
||||||
|
info.platform_data = node;
|
||||||
|
client = i2c_new_device(adapter, &info);
|
||||||
|
if (!client)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We know the driver is already loaded, so the device should be
|
||||||
|
* already bound. If not it means binding failed, which suggests
|
||||||
|
* the device doesn't really exist and should be deleted.
|
||||||
|
* Ideally this would be replaced by better checks _before_
|
||||||
|
* instantiating the device.
|
||||||
|
*/
|
||||||
|
if (!client->driver) {
|
||||||
|
i2c_unregister_device(client);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let i2c-core delete that device on driver removal.
|
||||||
|
* This is safe because i2c-core holds the core_lock mutex for us.
|
||||||
|
*/
|
||||||
|
list_add_tail(&client->detected, &client->driver->clients);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int onyx_i2c_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct device_node *node = client->dev.platform_data;
|
||||||
struct onyx *onyx;
|
struct onyx *onyx;
|
||||||
u8 dummy;
|
u8 dummy;
|
||||||
|
|
||||||
|
@ -1011,20 +1044,12 @@ static int onyx_create(struct i2c_adapter *adapter,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
mutex_init(&onyx->mutex);
|
mutex_init(&onyx->mutex);
|
||||||
onyx->i2c.driver = &onyx_driver;
|
onyx->i2c = client;
|
||||||
onyx->i2c.adapter = adapter;
|
i2c_set_clientdata(client, onyx);
|
||||||
onyx->i2c.addr = addr & 0x7f;
|
|
||||||
strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE);
|
|
||||||
|
|
||||||
if (i2c_attach_client(&onyx->i2c)) {
|
|
||||||
printk(KERN_ERR PFX "failed to attach to i2c\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we try to read from register ONYX_REG_CONTROL
|
/* we try to read from register ONYX_REG_CONTROL
|
||||||
* to check if the codec is present */
|
* to check if the codec is present */
|
||||||
if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
|
if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
|
||||||
i2c_detach_client(&onyx->i2c);
|
|
||||||
printk(KERN_ERR PFX "failed to read control register\n");
|
printk(KERN_ERR PFX "failed to read control register\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
@ -1036,14 +1061,14 @@ static int onyx_create(struct i2c_adapter *adapter,
|
||||||
onyx->codec.node = of_node_get(node);
|
onyx->codec.node = of_node_get(node);
|
||||||
|
|
||||||
if (aoa_codec_register(&onyx->codec)) {
|
if (aoa_codec_register(&onyx->codec)) {
|
||||||
i2c_detach_client(&onyx->i2c);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
printk(KERN_DEBUG PFX "created and attached onyx instance\n");
|
printk(KERN_DEBUG PFX "created and attached onyx instance\n");
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
|
i2c_set_clientdata(client, NULL);
|
||||||
kfree(onyx);
|
kfree(onyx);
|
||||||
return -EINVAL;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int onyx_i2c_attach(struct i2c_adapter *adapter)
|
static int onyx_i2c_attach(struct i2c_adapter *adapter)
|
||||||
|
@ -1080,28 +1105,33 @@ static int onyx_i2c_attach(struct i2c_adapter *adapter)
|
||||||
return onyx_create(adapter, NULL, 0x47);
|
return onyx_create(adapter, NULL, 0x47);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int onyx_i2c_detach(struct i2c_client *client)
|
static int onyx_i2c_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct onyx *onyx = container_of(client, struct onyx, i2c);
|
struct onyx *onyx = i2c_get_clientdata(client);
|
||||||
int err;
|
|
||||||
|
|
||||||
if ((err = i2c_detach_client(client)))
|
|
||||||
return err;
|
|
||||||
aoa_codec_unregister(&onyx->codec);
|
aoa_codec_unregister(&onyx->codec);
|
||||||
of_node_put(onyx->codec.node);
|
of_node_put(onyx->codec.node);
|
||||||
if (onyx->codec_info)
|
if (onyx->codec_info)
|
||||||
kfree(onyx->codec_info);
|
kfree(onyx->codec_info);
|
||||||
|
i2c_set_clientdata(client, onyx);
|
||||||
kfree(onyx);
|
kfree(onyx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id onyx_i2c_id[] = {
|
||||||
|
{ "aoa_codec_onyx", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
static struct i2c_driver onyx_driver = {
|
static struct i2c_driver onyx_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "aoa_codec_onyx",
|
.name = "aoa_codec_onyx",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
.attach_adapter = onyx_i2c_attach,
|
.attach_adapter = onyx_i2c_attach,
|
||||||
.detach_client = onyx_i2c_detach,
|
.probe = onyx_i2c_probe,
|
||||||
|
.remove = onyx_i2c_remove,
|
||||||
|
.id_table = onyx_i2c_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init onyx_init(void)
|
static int __init onyx_init(void)
|
||||||
|
|
|
@ -82,7 +82,7 @@ MODULE_DESCRIPTION("tas codec driver for snd-aoa");
|
||||||
|
|
||||||
struct tas {
|
struct tas {
|
||||||
struct aoa_codec codec;
|
struct aoa_codec codec;
|
||||||
struct i2c_client i2c;
|
struct i2c_client *i2c;
|
||||||
u32 mute_l:1, mute_r:1 ,
|
u32 mute_l:1, mute_r:1 ,
|
||||||
controls_created:1 ,
|
controls_created:1 ,
|
||||||
drc_enabled:1,
|
drc_enabled:1,
|
||||||
|
@ -108,9 +108,9 @@ static struct tas *codec_to_tas(struct aoa_codec *codec)
|
||||||
static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
|
static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
|
||||||
{
|
{
|
||||||
if (len == 1)
|
if (len == 1)
|
||||||
return i2c_smbus_write_byte_data(&tas->i2c, reg, *data);
|
return i2c_smbus_write_byte_data(tas->i2c, reg, *data);
|
||||||
else
|
else
|
||||||
return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data);
|
return i2c_smbus_write_i2c_block_data(tas->i2c, reg, len, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tas3004_set_drc(struct tas *tas)
|
static void tas3004_set_drc(struct tas *tas)
|
||||||
|
@ -882,12 +882,34 @@ static void tas_exit_codec(struct aoa_codec *codec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct i2c_driver tas_driver;
|
|
||||||
|
|
||||||
static int tas_create(struct i2c_adapter *adapter,
|
static int tas_create(struct i2c_adapter *adapter,
|
||||||
struct device_node *node,
|
struct device_node *node,
|
||||||
int addr)
|
int addr)
|
||||||
{
|
{
|
||||||
|
struct i2c_board_info info;
|
||||||
|
struct i2c_client *client;
|
||||||
|
|
||||||
|
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||||
|
strlcpy(info.type, "aoa_codec_tas", I2C_NAME_SIZE);
|
||||||
|
info.addr = addr;
|
||||||
|
info.platform_data = node;
|
||||||
|
|
||||||
|
client = i2c_new_device(adapter, &info);
|
||||||
|
if (!client)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let i2c-core delete that device on driver removal.
|
||||||
|
* This is safe because i2c-core holds the core_lock mutex for us.
|
||||||
|
*/
|
||||||
|
list_add_tail(&client->detected, &client->driver->clients);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tas_i2c_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct device_node *node = client->dev.platform_data;
|
||||||
struct tas *tas;
|
struct tas *tas;
|
||||||
|
|
||||||
tas = kzalloc(sizeof(struct tas), GFP_KERNEL);
|
tas = kzalloc(sizeof(struct tas), GFP_KERNEL);
|
||||||
|
@ -896,17 +918,11 @@ static int tas_create(struct i2c_adapter *adapter,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
mutex_init(&tas->mtx);
|
mutex_init(&tas->mtx);
|
||||||
tas->i2c.driver = &tas_driver;
|
tas->i2c = client;
|
||||||
tas->i2c.adapter = adapter;
|
i2c_set_clientdata(client, tas);
|
||||||
tas->i2c.addr = addr;
|
|
||||||
/* seems that half is a saner default */
|
/* seems that half is a saner default */
|
||||||
tas->drc_range = TAS3004_DRC_MAX / 2;
|
tas->drc_range = TAS3004_DRC_MAX / 2;
|
||||||
strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE);
|
|
||||||
|
|
||||||
if (i2c_attach_client(&tas->i2c)) {
|
|
||||||
printk(KERN_ERR PFX "failed to attach to i2c\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
|
strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
|
||||||
tas->codec.owner = THIS_MODULE;
|
tas->codec.owner = THIS_MODULE;
|
||||||
|
@ -915,14 +931,12 @@ static int tas_create(struct i2c_adapter *adapter,
|
||||||
tas->codec.node = of_node_get(node);
|
tas->codec.node = of_node_get(node);
|
||||||
|
|
||||||
if (aoa_codec_register(&tas->codec)) {
|
if (aoa_codec_register(&tas->codec)) {
|
||||||
goto detach;
|
goto fail;
|
||||||
}
|
}
|
||||||
printk(KERN_DEBUG
|
printk(KERN_DEBUG
|
||||||
"snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n",
|
"snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n",
|
||||||
addr, node->full_name);
|
(unsigned int)client->addr, node->full_name);
|
||||||
return 0;
|
return 0;
|
||||||
detach:
|
|
||||||
i2c_detach_client(&tas->i2c);
|
|
||||||
fail:
|
fail:
|
||||||
mutex_destroy(&tas->mtx);
|
mutex_destroy(&tas->mtx);
|
||||||
kfree(tas);
|
kfree(tas);
|
||||||
|
@ -970,14 +984,11 @@ static int tas_i2c_attach(struct i2c_adapter *adapter)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tas_i2c_detach(struct i2c_client *client)
|
static int tas_i2c_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct tas *tas = container_of(client, struct tas, i2c);
|
struct tas *tas = i2c_get_clientdata(client);
|
||||||
int err;
|
|
||||||
u8 tmp = TAS_ACR_ANALOG_PDOWN;
|
u8 tmp = TAS_ACR_ANALOG_PDOWN;
|
||||||
|
|
||||||
if ((err = i2c_detach_client(client)))
|
|
||||||
return err;
|
|
||||||
aoa_codec_unregister(&tas->codec);
|
aoa_codec_unregister(&tas->codec);
|
||||||
of_node_put(tas->codec.node);
|
of_node_put(tas->codec.node);
|
||||||
|
|
||||||
|
@ -989,13 +1000,20 @@ static int tas_i2c_detach(struct i2c_client *client)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id tas_i2c_id[] = {
|
||||||
|
{ "aoa_codec_tas", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
static struct i2c_driver tas_driver = {
|
static struct i2c_driver tas_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "aoa_codec_tas",
|
.name = "aoa_codec_tas",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
.attach_adapter = tas_i2c_attach,
|
.attach_adapter = tas_i2c_attach,
|
||||||
.detach_client = tas_i2c_detach,
|
.probe = tas_i2c_probe,
|
||||||
|
.remove = tas_i2c_remove,
|
||||||
|
.id_table = tas_i2c_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init tas_init(void)
|
static int __init tas_init(void)
|
||||||
|
|
Loading…
Reference in a new issue