diff options
Diffstat (limited to 'sound/soc/codecs/wm8900.c')
-rw-r--r-- | sound/soc/codecs/wm8900.c | 262 |
1 files changed, 107 insertions, 155 deletions
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 3b326c9b5586..6767de10ded0 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -138,6 +138,10 @@ | |||
138 | struct snd_soc_codec_device soc_codec_dev_wm8900; | 138 | struct snd_soc_codec_device soc_codec_dev_wm8900; |
139 | 139 | ||
140 | struct wm8900_priv { | 140 | struct wm8900_priv { |
141 | struct snd_soc_codec codec; | ||
142 | |||
143 | u16 reg_cache[WM8900_MAXREG]; | ||
144 | |||
141 | u32 fll_in; /* FLL input frequency */ | 145 | u32 fll_in; /* FLL input frequency */ |
142 | u32 fll_out; /* FLL output frequency */ | 146 | u32 fll_out; /* FLL output frequency */ |
143 | }; | 147 | }; |
@@ -727,7 +731,8 @@ static int wm8900_add_widgets(struct snd_soc_codec *codec) | |||
727 | } | 731 | } |
728 | 732 | ||
729 | static int wm8900_hw_params(struct snd_pcm_substream *substream, | 733 | static int wm8900_hw_params(struct snd_pcm_substream *substream, |
730 | struct snd_pcm_hw_params *params) | 734 | struct snd_pcm_hw_params *params, |
735 | struct snd_soc_dai *dai) | ||
731 | { | 736 | { |
732 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 737 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
733 | struct snd_soc_device *socdev = rtd->socdev; | 738 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1117,8 +1122,6 @@ struct snd_soc_dai wm8900_dai = { | |||
1117 | }, | 1122 | }, |
1118 | .ops = { | 1123 | .ops = { |
1119 | .hw_params = wm8900_hw_params, | 1124 | .hw_params = wm8900_hw_params, |
1120 | }, | ||
1121 | .dai_ops = { | ||
1122 | .set_clkdiv = wm8900_set_dai_clkdiv, | 1125 | .set_clkdiv = wm8900_set_dai_clkdiv, |
1123 | .set_pll = wm8900_set_dai_pll, | 1126 | .set_pll = wm8900_set_dai_pll, |
1124 | .set_fmt = wm8900_set_dai_fmt, | 1127 | .set_fmt = wm8900_set_dai_fmt, |
@@ -1283,16 +1286,28 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1283 | return 0; | 1286 | return 0; |
1284 | } | 1287 | } |
1285 | 1288 | ||
1286 | /* | 1289 | static struct snd_soc_codec *wm8900_codec; |
1287 | * initialise the WM8900 driver | 1290 | |
1288 | * register the mixer and dsp interfaces with the kernel | 1291 | static int wm8900_i2c_probe(struct i2c_client *i2c, |
1289 | */ | 1292 | const struct i2c_device_id *id) |
1290 | static int wm8900_init(struct snd_soc_device *socdev) | ||
1291 | { | 1293 | { |
1292 | struct snd_soc_codec *codec = socdev->codec; | 1294 | struct wm8900_priv *wm8900; |
1293 | int ret = 0; | 1295 | struct snd_soc_codec *codec; |
1294 | unsigned int reg; | 1296 | unsigned int reg; |
1295 | struct i2c_client *i2c_client = socdev->codec->control_data; | 1297 | int ret; |
1298 | |||
1299 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1300 | if (wm8900 == NULL) | ||
1301 | return -ENOMEM; | ||
1302 | |||
1303 | codec = &wm8900->codec; | ||
1304 | codec->private_data = wm8900; | ||
1305 | codec->reg_cache = &wm8900->reg_cache[0]; | ||
1306 | codec->reg_cache_size = WM8900_MAXREG; | ||
1307 | |||
1308 | mutex_init(&codec->mutex); | ||
1309 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1310 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1296 | 1311 | ||
1297 | codec->name = "WM8900"; | 1312 | codec->name = "WM8900"; |
1298 | codec->owner = THIS_MODULE; | 1313 | codec->owner = THIS_MODULE; |
@@ -1300,33 +1315,28 @@ static int wm8900_init(struct snd_soc_device *socdev) | |||
1300 | codec->write = wm8900_write; | 1315 | codec->write = wm8900_write; |
1301 | codec->dai = &wm8900_dai; | 1316 | codec->dai = &wm8900_dai; |
1302 | codec->num_dai = 1; | 1317 | codec->num_dai = 1; |
1303 | codec->reg_cache_size = WM8900_MAXREG; | 1318 | codec->hw_write = (hw_write_t)i2c_master_send; |
1304 | codec->reg_cache = kmemdup(wm8900_reg_defaults, | 1319 | codec->control_data = i2c; |
1305 | sizeof(wm8900_reg_defaults), GFP_KERNEL); | 1320 | codec->set_bias_level = wm8900_set_bias_level; |
1306 | 1321 | codec->dev = &i2c->dev; | |
1307 | if (codec->reg_cache == NULL) | ||
1308 | return -ENOMEM; | ||
1309 | 1322 | ||
1310 | reg = wm8900_read(codec, WM8900_REG_ID); | 1323 | reg = wm8900_read(codec, WM8900_REG_ID); |
1311 | if (reg != 0x8900) { | 1324 | if (reg != 0x8900) { |
1312 | dev_err(&i2c_client->dev, "Device is not a WM8900 - ID %x\n", | 1325 | dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); |
1313 | reg); | 1326 | ret = -ENODEV; |
1314 | return -ENODEV; | 1327 | goto err; |
1315 | } | ||
1316 | |||
1317 | codec->private_data = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1318 | if (codec->private_data == NULL) { | ||
1319 | ret = -ENOMEM; | ||
1320 | goto priv_err; | ||
1321 | } | 1328 | } |
1322 | 1329 | ||
1323 | /* Read back from the chip */ | 1330 | /* Read back from the chip */ |
1324 | reg = wm8900_chip_read(codec, WM8900_REG_POWER1); | 1331 | reg = wm8900_chip_read(codec, WM8900_REG_POWER1); |
1325 | reg = (reg >> 12) & 0xf; | 1332 | reg = (reg >> 12) & 0xf; |
1326 | dev_info(&i2c_client->dev, "WM8900 revision %d\n", reg); | 1333 | dev_info(&i2c->dev, "WM8900 revision %d\n", reg); |
1327 | 1334 | ||
1328 | wm8900_reset(codec); | 1335 | wm8900_reset(codec); |
1329 | 1336 | ||
1337 | /* Turn the chip on */ | ||
1338 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1339 | |||
1330 | /* Latch the volume update bits */ | 1340 | /* Latch the volume update bits */ |
1331 | wm8900_write(codec, WM8900_REG_LINVOL, | 1341 | wm8900_write(codec, WM8900_REG_LINVOL, |
1332 | wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); | 1342 | wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); |
@@ -1352,160 +1362,98 @@ static int wm8900_init(struct snd_soc_device *socdev) | |||
1352 | /* Set the DAC and mixer output bias */ | 1362 | /* Set the DAC and mixer output bias */ |
1353 | wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); | 1363 | wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); |
1354 | 1364 | ||
1355 | /* Register pcms */ | 1365 | wm8900_dai.dev = &i2c->dev; |
1356 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1357 | if (ret < 0) { | ||
1358 | dev_err(&i2c_client->dev, "Failed to register new PCMs\n"); | ||
1359 | goto pcm_err; | ||
1360 | } | ||
1361 | |||
1362 | /* Turn the chip on */ | ||
1363 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1364 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1365 | |||
1366 | wm8900_add_controls(codec); | ||
1367 | wm8900_add_widgets(codec); | ||
1368 | |||
1369 | ret = snd_soc_register_card(socdev); | ||
1370 | if (ret < 0) { | ||
1371 | dev_err(&i2c_client->dev, "Failed to register card\n"); | ||
1372 | goto card_err; | ||
1373 | } | ||
1374 | return ret; | ||
1375 | |||
1376 | card_err: | ||
1377 | snd_soc_free_pcms(socdev); | ||
1378 | snd_soc_dapm_free(socdev); | ||
1379 | pcm_err: | ||
1380 | kfree(codec->reg_cache); | ||
1381 | priv_err: | ||
1382 | kfree(codec->private_data); | ||
1383 | return ret; | ||
1384 | } | ||
1385 | 1366 | ||
1386 | static struct snd_soc_device *wm8900_socdev; | 1367 | wm8900_codec = codec; |
1387 | 1368 | ||
1388 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1369 | ret = snd_soc_register_codec(codec); |
1389 | 1370 | if (ret != 0) { | |
1390 | static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; | 1371 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); |
1391 | |||
1392 | /* Magic definition of all other variables and things */ | ||
1393 | I2C_CLIENT_INSMOD; | ||
1394 | |||
1395 | static struct i2c_driver wm8900_i2c_driver; | ||
1396 | static struct i2c_client client_template; | ||
1397 | |||
1398 | /* If the i2c layer weren't so broken, we could pass this kind of data | ||
1399 | around */ | ||
1400 | static int wm8900_codec_probe(struct i2c_adapter *adap, int addr, int kind) | ||
1401 | { | ||
1402 | struct snd_soc_device *socdev = wm8900_socdev; | ||
1403 | struct wm8900_setup_data *setup = socdev->codec_data; | ||
1404 | struct snd_soc_codec *codec = socdev->codec; | ||
1405 | struct i2c_client *i2c; | ||
1406 | int ret; | ||
1407 | |||
1408 | if (addr != setup->i2c_address) | ||
1409 | return -ENODEV; | ||
1410 | |||
1411 | dev_err(&adap->dev, "Probe on %x\n", addr); | ||
1412 | |||
1413 | client_template.adapter = adap; | ||
1414 | client_template.addr = addr; | ||
1415 | |||
1416 | i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); | ||
1417 | if (i2c == NULL) { | ||
1418 | kfree(codec); | ||
1419 | return -ENOMEM; | ||
1420 | } | ||
1421 | i2c_set_clientdata(i2c, codec); | ||
1422 | codec->control_data = i2c; | ||
1423 | |||
1424 | ret = i2c_attach_client(i2c); | ||
1425 | if (ret < 0) { | ||
1426 | dev_err(&adap->dev, | ||
1427 | "failed to attach codec at addr %x\n", addr); | ||
1428 | goto err; | 1372 | goto err; |
1429 | } | 1373 | } |
1430 | 1374 | ||
1431 | ret = wm8900_init(socdev); | 1375 | ret = snd_soc_register_dai(&wm8900_dai); |
1432 | if (ret < 0) { | 1376 | if (ret != 0) { |
1433 | dev_err(&adap->dev, "failed to initialise WM8900\n"); | 1377 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); |
1434 | goto err; | 1378 | goto err_codec; |
1435 | } | 1379 | } |
1380 | |||
1436 | return ret; | 1381 | return ret; |
1437 | 1382 | ||
1383 | err_codec: | ||
1384 | snd_soc_unregister_codec(codec); | ||
1438 | err: | 1385 | err: |
1439 | kfree(codec); | 1386 | kfree(wm8900); |
1440 | kfree(i2c); | 1387 | wm8900_codec = NULL; |
1441 | return ret; | 1388 | return ret; |
1442 | } | 1389 | } |
1443 | 1390 | ||
1444 | static int wm8900_i2c_detach(struct i2c_client *client) | 1391 | static int wm8900_i2c_remove(struct i2c_client *client) |
1445 | { | 1392 | { |
1446 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1393 | snd_soc_unregister_dai(&wm8900_dai); |
1447 | i2c_detach_client(client); | 1394 | snd_soc_unregister_codec(wm8900_codec); |
1448 | kfree(codec->reg_cache); | 1395 | |
1449 | kfree(client); | 1396 | wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF); |
1397 | |||
1398 | wm8900_dai.dev = NULL; | ||
1399 | kfree(wm8900_codec->private_data); | ||
1400 | wm8900_codec = NULL; | ||
1401 | |||
1450 | return 0; | 1402 | return 0; |
1451 | } | 1403 | } |
1452 | 1404 | ||
1453 | static int wm8900_i2c_attach(struct i2c_adapter *adap) | 1405 | static const struct i2c_device_id wm8900_i2c_id[] = { |
1454 | { | 1406 | { "wm8900", 0 }, |
1455 | return i2c_probe(adap, &addr_data, wm8900_codec_probe); | 1407 | { } |
1456 | } | 1408 | }; |
1409 | MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); | ||
1457 | 1410 | ||
1458 | /* corgi i2c codec control layer */ | ||
1459 | static struct i2c_driver wm8900_i2c_driver = { | 1411 | static struct i2c_driver wm8900_i2c_driver = { |
1460 | .driver = { | 1412 | .driver = { |
1461 | .name = "WM8900 I2C codec", | 1413 | .name = "WM8900", |
1462 | .owner = THIS_MODULE, | 1414 | .owner = THIS_MODULE, |
1463 | }, | 1415 | }, |
1464 | .attach_adapter = wm8900_i2c_attach, | 1416 | .probe = wm8900_i2c_probe, |
1465 | .detach_client = wm8900_i2c_detach, | 1417 | .remove = wm8900_i2c_remove, |
1466 | .command = NULL, | 1418 | .id_table = wm8900_i2c_id, |
1467 | }; | ||
1468 | |||
1469 | static struct i2c_client client_template = { | ||
1470 | .name = "WM8900", | ||
1471 | .driver = &wm8900_i2c_driver, | ||
1472 | }; | 1419 | }; |
1473 | #endif | ||
1474 | 1420 | ||
1475 | static int wm8900_probe(struct platform_device *pdev) | 1421 | static int wm8900_probe(struct platform_device *pdev) |
1476 | { | 1422 | { |
1477 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1423 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1478 | struct wm8900_setup_data *setup; | ||
1479 | struct snd_soc_codec *codec; | 1424 | struct snd_soc_codec *codec; |
1480 | int ret = 0; | 1425 | int ret = 0; |
1481 | 1426 | ||
1482 | dev_info(&pdev->dev, "WM8900 Audio Codec\n"); | 1427 | if (!wm8900_codec) { |
1483 | 1428 | dev_err(&pdev->dev, "I2C client not yet instantiated\n"); | |
1484 | setup = socdev->codec_data; | 1429 | return -ENODEV; |
1485 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 1430 | } |
1486 | if (codec == NULL) | ||
1487 | return -ENOMEM; | ||
1488 | |||
1489 | mutex_init(&codec->mutex); | ||
1490 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1491 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1492 | 1431 | ||
1432 | codec = wm8900_codec; | ||
1493 | socdev->codec = codec; | 1433 | socdev->codec = codec; |
1494 | 1434 | ||
1495 | codec->set_bias_level = wm8900_set_bias_level; | 1435 | /* Register pcms */ |
1436 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1437 | if (ret < 0) { | ||
1438 | dev_err(&pdev->dev, "Failed to register new PCMs\n"); | ||
1439 | goto pcm_err; | ||
1440 | } | ||
1496 | 1441 | ||
1497 | wm8900_socdev = socdev; | 1442 | wm8900_add_controls(codec); |
1498 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1443 | wm8900_add_widgets(codec); |
1499 | if (setup->i2c_address) { | 1444 | |
1500 | normal_i2c[0] = setup->i2c_address; | 1445 | ret = snd_soc_init_card(socdev); |
1501 | codec->hw_write = (hw_write_t)i2c_master_send; | 1446 | if (ret < 0) { |
1502 | ret = i2c_add_driver(&wm8900_i2c_driver); | 1447 | dev_err(&pdev->dev, "Failed to register card\n"); |
1503 | if (ret != 0) | 1448 | goto card_err; |
1504 | printk(KERN_ERR "can't add i2c driver"); | ||
1505 | } | 1449 | } |
1506 | #else | 1450 | |
1507 | #error Non-I2C interfaces not yet supported | 1451 | return ret; |
1508 | #endif | 1452 | |
1453 | card_err: | ||
1454 | snd_soc_free_pcms(socdev); | ||
1455 | snd_soc_dapm_free(socdev); | ||
1456 | pcm_err: | ||
1509 | return ret; | 1457 | return ret; |
1510 | } | 1458 | } |
1511 | 1459 | ||
@@ -1513,17 +1461,9 @@ static int wm8900_probe(struct platform_device *pdev) | |||
1513 | static int wm8900_remove(struct platform_device *pdev) | 1461 | static int wm8900_remove(struct platform_device *pdev) |
1514 | { | 1462 | { |
1515 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1463 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1516 | struct snd_soc_codec *codec = socdev->codec; | ||
1517 | |||
1518 | if (codec->control_data) | ||
1519 | wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1520 | 1464 | ||
1521 | snd_soc_free_pcms(socdev); | 1465 | snd_soc_free_pcms(socdev); |
1522 | snd_soc_dapm_free(socdev); | 1466 | snd_soc_dapm_free(socdev); |
1523 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1524 | i2c_del_driver(&wm8900_i2c_driver); | ||
1525 | #endif | ||
1526 | kfree(codec); | ||
1527 | 1467 | ||
1528 | return 0; | 1468 | return 0; |
1529 | } | 1469 | } |
@@ -1536,6 +1476,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8900 = { | |||
1536 | }; | 1476 | }; |
1537 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); | 1477 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); |
1538 | 1478 | ||
1479 | static int __init wm8900_modinit(void) | ||
1480 | { | ||
1481 | return i2c_add_driver(&wm8900_i2c_driver); | ||
1482 | } | ||
1483 | module_init(wm8900_modinit); | ||
1484 | |||
1485 | static void __exit wm8900_exit(void) | ||
1486 | { | ||
1487 | i2c_del_driver(&wm8900_i2c_driver); | ||
1488 | } | ||
1489 | module_exit(wm8900_exit); | ||
1490 | |||
1539 | MODULE_DESCRIPTION("ASoC WM8900 driver"); | 1491 | MODULE_DESCRIPTION("ASoC WM8900 driver"); |
1540 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); | 1492 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); |
1541 | MODULE_LICENSE("GPL"); | 1493 | MODULE_LICENSE("GPL"); |