diff options
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r-- | sound/soc/codecs/tlv320aic3x.c | 233 |
1 files changed, 118 insertions, 115 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index cb0d1bf34b57..3395cf945d56 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -53,6 +53,7 @@ | |||
53 | 53 | ||
54 | /* codec private data */ | 54 | /* codec private data */ |
55 | struct aic3x_priv { | 55 | struct aic3x_priv { |
56 | struct snd_soc_codec codec; | ||
56 | unsigned int sysclk; | 57 | unsigned int sysclk; |
57 | int master; | 58 | int master; |
58 | }; | 59 | }; |
@@ -145,8 +146,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg, | |||
145 | u8 *value) | 146 | u8 *value) |
146 | { | 147 | { |
147 | *value = reg & 0xff; | 148 | *value = reg & 0xff; |
148 | if (codec->hw_read(codec->control_data, value, 1) != 1) | 149 | |
149 | return -EIO; | 150 | value[0] = i2c_smbus_read_byte_data(codec->control_data, value[0]); |
150 | 151 | ||
151 | aic3x_write_reg_cache(codec, reg, *value); | 152 | aic3x_write_reg_cache(codec, reg, *value); |
152 | return 0; | 153 | return 0; |
@@ -1156,11 +1157,13 @@ static int aic3x_resume(struct platform_device *pdev) | |||
1156 | * initialise the AIC3X driver | 1157 | * initialise the AIC3X driver |
1157 | * register the mixer and dsp interfaces with the kernel | 1158 | * register the mixer and dsp interfaces with the kernel |
1158 | */ | 1159 | */ |
1159 | static int aic3x_init(struct snd_soc_device *socdev) | 1160 | static int aic3x_init(struct snd_soc_codec *codec) |
1160 | { | 1161 | { |
1161 | struct snd_soc_codec *codec = socdev->card->codec; | 1162 | int reg; |
1162 | struct aic3x_setup_data *setup = socdev->codec_data; | 1163 | |
1163 | int reg, ret = 0; | 1164 | mutex_init(&codec->mutex); |
1165 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1166 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1164 | 1167 | ||
1165 | codec->name = "tlv320aic3x"; | 1168 | codec->name = "tlv320aic3x"; |
1166 | codec->owner = THIS_MODULE; | 1169 | codec->owner = THIS_MODULE; |
@@ -1177,13 +1180,6 @@ static int aic3x_init(struct snd_soc_device *socdev) | |||
1177 | aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); | 1180 | aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); |
1178 | aic3x_write(codec, AIC3X_RESET, SOFT_RESET); | 1181 | aic3x_write(codec, AIC3X_RESET, SOFT_RESET); |
1179 | 1182 | ||
1180 | /* register pcms */ | ||
1181 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1182 | if (ret < 0) { | ||
1183 | printk(KERN_ERR "aic3x: failed to create pcms\n"); | ||
1184 | goto pcm_err; | ||
1185 | } | ||
1186 | |||
1187 | /* DAC default volume and mute */ | 1183 | /* DAC default volume and mute */ |
1188 | aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON); | 1184 | aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON); |
1189 | aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON); | 1185 | aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON); |
@@ -1250,30 +1246,51 @@ static int aic3x_init(struct snd_soc_device *socdev) | |||
1250 | /* off, with power on */ | 1246 | /* off, with power on */ |
1251 | aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1247 | aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1252 | 1248 | ||
1253 | /* setup GPIO functions */ | 1249 | return 0; |
1254 | aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); | 1250 | } |
1255 | aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4); | ||
1256 | 1251 | ||
1257 | snd_soc_add_controls(codec, aic3x_snd_controls, | 1252 | static struct snd_soc_codec *aic3x_codec; |
1258 | ARRAY_SIZE(aic3x_snd_controls)); | 1253 | |
1259 | aic3x_add_widgets(codec); | 1254 | static int aic3x_register(struct snd_soc_codec *codec) |
1260 | ret = snd_soc_init_card(socdev); | 1255 | { |
1256 | int ret; | ||
1257 | |||
1258 | ret = aic3x_init(codec); | ||
1261 | if (ret < 0) { | 1259 | if (ret < 0) { |
1262 | printk(KERN_ERR "aic3x: failed to register card\n"); | 1260 | dev_err(codec->dev, "Failed to initialise device\n"); |
1263 | goto card_err; | 1261 | return ret; |
1264 | } | 1262 | } |
1265 | 1263 | ||
1266 | return ret; | 1264 | aic3x_codec = codec; |
1267 | 1265 | ||
1268 | card_err: | 1266 | ret = snd_soc_register_codec(codec); |
1269 | snd_soc_free_pcms(socdev); | 1267 | if (ret) { |
1270 | snd_soc_dapm_free(socdev); | 1268 | dev_err(codec->dev, "Failed to register codec\n"); |
1271 | pcm_err: | 1269 | return ret; |
1272 | kfree(codec->reg_cache); | 1270 | } |
1273 | return ret; | 1271 | |
1272 | ret = snd_soc_register_dai(&aic3x_dai); | ||
1273 | if (ret) { | ||
1274 | dev_err(codec->dev, "Failed to register dai\n"); | ||
1275 | snd_soc_unregister_codec(codec); | ||
1276 | return ret; | ||
1277 | } | ||
1278 | |||
1279 | return 0; | ||
1274 | } | 1280 | } |
1275 | 1281 | ||
1276 | static struct snd_soc_device *aic3x_socdev; | 1282 | static int aic3x_unregister(struct aic3x_priv *aic3x) |
1283 | { | ||
1284 | aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF); | ||
1285 | |||
1286 | snd_soc_unregister_dai(&aic3x_dai); | ||
1287 | snd_soc_unregister_codec(&aic3x->codec); | ||
1288 | |||
1289 | kfree(aic3x); | ||
1290 | aic3x_codec = NULL; | ||
1291 | |||
1292 | return 0; | ||
1293 | } | ||
1277 | 1294 | ||
1278 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1295 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1279 | /* | 1296 | /* |
@@ -1288,28 +1305,36 @@ static struct snd_soc_device *aic3x_socdev; | |||
1288 | static int aic3x_i2c_probe(struct i2c_client *i2c, | 1305 | static int aic3x_i2c_probe(struct i2c_client *i2c, |
1289 | const struct i2c_device_id *id) | 1306 | const struct i2c_device_id *id) |
1290 | { | 1307 | { |
1291 | struct snd_soc_device *socdev = aic3x_socdev; | 1308 | struct snd_soc_codec *codec; |
1292 | struct snd_soc_codec *codec = socdev->card->codec; | 1309 | struct aic3x_priv *aic3x; |
1293 | int ret; | ||
1294 | 1310 | ||
1295 | i2c_set_clientdata(i2c, codec); | 1311 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); |
1312 | if (aic3x == NULL) { | ||
1313 | dev_err(&i2c->dev, "failed to create private data\n"); | ||
1314 | return -ENOMEM; | ||
1315 | } | ||
1316 | |||
1317 | codec = &aic3x->codec; | ||
1318 | codec->dev = &i2c->dev; | ||
1319 | codec->private_data = aic3x; | ||
1296 | codec->control_data = i2c; | 1320 | codec->control_data = i2c; |
1321 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1297 | 1322 | ||
1298 | ret = aic3x_init(socdev); | 1323 | i2c_set_clientdata(i2c, aic3x); |
1299 | if (ret < 0) | 1324 | |
1300 | printk(KERN_ERR "aic3x: failed to initialise AIC3X\n"); | 1325 | return aic3x_register(codec); |
1301 | return ret; | ||
1302 | } | 1326 | } |
1303 | 1327 | ||
1304 | static int aic3x_i2c_remove(struct i2c_client *client) | 1328 | static int aic3x_i2c_remove(struct i2c_client *client) |
1305 | { | 1329 | { |
1306 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1330 | struct aic3x_priv *aic3x = i2c_get_clientdata(client); |
1307 | kfree(codec->reg_cache); | 1331 | |
1308 | return 0; | 1332 | return aic3x_unregister(aic3x); |
1309 | } | 1333 | } |
1310 | 1334 | ||
1311 | static const struct i2c_device_id aic3x_i2c_id[] = { | 1335 | static const struct i2c_device_id aic3x_i2c_id[] = { |
1312 | { "tlv320aic3x", 0 }, | 1336 | { "tlv320aic3x", 0 }, |
1337 | { "tlv320aic33", 0 }, | ||
1313 | { } | 1338 | { } |
1314 | }; | 1339 | }; |
1315 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); | 1340 | MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); |
@@ -1320,56 +1345,28 @@ static struct i2c_driver aic3x_i2c_driver = { | |||
1320 | .name = "aic3x I2C Codec", | 1345 | .name = "aic3x I2C Codec", |
1321 | .owner = THIS_MODULE, | 1346 | .owner = THIS_MODULE, |
1322 | }, | 1347 | }, |
1323 | .probe = aic3x_i2c_probe, | 1348 | .probe = aic3x_i2c_probe, |
1324 | .remove = aic3x_i2c_remove, | 1349 | .remove = aic3x_i2c_remove, |
1325 | .id_table = aic3x_i2c_id, | 1350 | .id_table = aic3x_i2c_id, |
1326 | }; | 1351 | }; |
1327 | 1352 | ||
1328 | static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len) | 1353 | static inline void aic3x_i2c_init(void) |
1329 | { | 1354 | { |
1330 | value[0] = i2c_smbus_read_byte_data(client, value[0]); | ||
1331 | return (len == 1); | ||
1332 | } | ||
1333 | |||
1334 | static int aic3x_add_i2c_device(struct platform_device *pdev, | ||
1335 | const struct aic3x_setup_data *setup) | ||
1336 | { | ||
1337 | struct i2c_board_info info; | ||
1338 | struct i2c_adapter *adapter; | ||
1339 | struct i2c_client *client; | ||
1340 | int ret; | 1355 | int ret; |
1341 | 1356 | ||
1342 | ret = i2c_add_driver(&aic3x_i2c_driver); | 1357 | ret = i2c_add_driver(&aic3x_i2c_driver); |
1343 | if (ret != 0) { | 1358 | if (ret) |
1344 | dev_err(&pdev->dev, "can't add i2c driver\n"); | 1359 | printk(KERN_ERR "%s: error regsitering i2c driver, %d\n", |
1345 | return ret; | 1360 | __func__, ret); |
1346 | } | 1361 | } |
1347 | |||
1348 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
1349 | info.addr = setup->i2c_address; | ||
1350 | strlcpy(info.type, "tlv320aic3x", I2C_NAME_SIZE); | ||
1351 | |||
1352 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
1353 | if (!adapter) { | ||
1354 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
1355 | setup->i2c_bus); | ||
1356 | goto err_driver; | ||
1357 | } | ||
1358 | |||
1359 | client = i2c_new_device(adapter, &info); | ||
1360 | i2c_put_adapter(adapter); | ||
1361 | if (!client) { | ||
1362 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
1363 | (unsigned int)info.addr); | ||
1364 | goto err_driver; | ||
1365 | } | ||
1366 | |||
1367 | return 0; | ||
1368 | 1362 | ||
1369 | err_driver: | 1363 | static inline void aic3x_i2c_exit(void) |
1364 | { | ||
1370 | i2c_del_driver(&aic3x_i2c_driver); | 1365 | i2c_del_driver(&aic3x_i2c_driver); |
1371 | return -ENODEV; | ||
1372 | } | 1366 | } |
1367 | #else | ||
1368 | static inline void aic3x_i2c_init(void) { } | ||
1369 | static inline void aic3x_i2c_exit(void) { } | ||
1373 | #endif | 1370 | #endif |
1374 | 1371 | ||
1375 | static int aic3x_probe(struct platform_device *pdev) | 1372 | static int aic3x_probe(struct platform_device *pdev) |
@@ -1377,43 +1374,51 @@ static int aic3x_probe(struct platform_device *pdev) | |||
1377 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1374 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1378 | struct aic3x_setup_data *setup; | 1375 | struct aic3x_setup_data *setup; |
1379 | struct snd_soc_codec *codec; | 1376 | struct snd_soc_codec *codec; |
1380 | struct aic3x_priv *aic3x; | ||
1381 | int ret = 0; | 1377 | int ret = 0; |
1382 | 1378 | ||
1383 | printk(KERN_INFO "AIC3X Audio Codec %s\n", AIC3X_VERSION); | 1379 | codec = aic3x_codec; |
1380 | if (!codec) { | ||
1381 | dev_err(&pdev->dev, "Codec not registered\n"); | ||
1382 | return -ENODEV; | ||
1383 | } | ||
1384 | 1384 | ||
1385 | socdev->card->codec = codec; | ||
1385 | setup = socdev->codec_data; | 1386 | setup = socdev->codec_data; |
1386 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
1387 | if (codec == NULL) | ||
1388 | return -ENOMEM; | ||
1389 | 1387 | ||
1390 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); | 1388 | if (setup) { |
1391 | if (aic3x == NULL) { | 1389 | /* setup GPIO functions */ |
1392 | kfree(codec); | 1390 | aic3x_write(codec, AIC3X_GPIO1_REG, |
1393 | return -ENOMEM; | 1391 | (setup->gpio_func[0] & 0xf) << 4); |
1392 | aic3x_write(codec, AIC3X_GPIO2_REG, | ||
1393 | (setup->gpio_func[1] & 0xf) << 4); | ||
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | codec->private_data = aic3x; | 1396 | /* register pcms */ |
1397 | socdev->card->codec = codec; | 1397 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
1398 | mutex_init(&codec->mutex); | 1398 | if (ret < 0) { |
1399 | INIT_LIST_HEAD(&codec->dapm_widgets); | 1399 | printk(KERN_ERR "aic3x: failed to create pcms\n"); |
1400 | INIT_LIST_HEAD(&codec->dapm_paths); | 1400 | goto pcm_err; |
1401 | |||
1402 | aic3x_socdev = socdev; | ||
1403 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1404 | if (setup->i2c_address) { | ||
1405 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
1406 | codec->hw_read = (hw_read_t) aic3x_i2c_read; | ||
1407 | ret = aic3x_add_i2c_device(pdev, setup); | ||
1408 | } | 1401 | } |
1409 | #else | ||
1410 | /* Add other interfaces here */ | ||
1411 | #endif | ||
1412 | 1402 | ||
1413 | if (ret != 0) { | 1403 | snd_soc_add_controls(codec, aic3x_snd_controls, |
1414 | kfree(codec->private_data); | 1404 | ARRAY_SIZE(aic3x_snd_controls)); |
1415 | kfree(codec); | 1405 | |
1406 | aic3x_add_widgets(codec); | ||
1407 | |||
1408 | ret = snd_soc_init_card(socdev); | ||
1409 | if (ret < 0) { | ||
1410 | printk(KERN_ERR "aic3x: failed to register card\n"); | ||
1411 | goto card_err; | ||
1416 | } | 1412 | } |
1413 | |||
1414 | return ret; | ||
1415 | |||
1416 | card_err: | ||
1417 | snd_soc_free_pcms(socdev); | ||
1418 | snd_soc_dapm_free(socdev); | ||
1419 | |||
1420 | pcm_err: | ||
1421 | kfree(codec->reg_cache); | ||
1417 | return ret; | 1422 | return ret; |
1418 | } | 1423 | } |
1419 | 1424 | ||
@@ -1428,12 +1433,8 @@ static int aic3x_remove(struct platform_device *pdev) | |||
1428 | 1433 | ||
1429 | snd_soc_free_pcms(socdev); | 1434 | snd_soc_free_pcms(socdev); |
1430 | snd_soc_dapm_free(socdev); | 1435 | snd_soc_dapm_free(socdev); |
1431 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1436 | |
1432 | i2c_unregister_device(codec->control_data); | 1437 | kfree(codec->reg_cache); |
1433 | i2c_del_driver(&aic3x_i2c_driver); | ||
1434 | #endif | ||
1435 | kfree(codec->private_data); | ||
1436 | kfree(codec); | ||
1437 | 1438 | ||
1438 | return 0; | 1439 | return 0; |
1439 | } | 1440 | } |
@@ -1448,13 +1449,15 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); | |||
1448 | 1449 | ||
1449 | static int __init aic3x_modinit(void) | 1450 | static int __init aic3x_modinit(void) |
1450 | { | 1451 | { |
1451 | return snd_soc_register_dai(&aic3x_dai); | 1452 | aic3x_i2c_init(); |
1453 | |||
1454 | return 0; | ||
1452 | } | 1455 | } |
1453 | module_init(aic3x_modinit); | 1456 | module_init(aic3x_modinit); |
1454 | 1457 | ||
1455 | static void __exit aic3x_exit(void) | 1458 | static void __exit aic3x_exit(void) |
1456 | { | 1459 | { |
1457 | snd_soc_unregister_dai(&aic3x_dai); | 1460 | aic3x_i2c_exit(); |
1458 | } | 1461 | } |
1459 | module_exit(aic3x_exit); | 1462 | module_exit(aic3x_exit); |
1460 | 1463 | ||