diff options
Diffstat (limited to 'sound/soc/codecs/wm8990.c')
-rw-r--r-- | sound/soc/codecs/wm8990.c | 226 |
1 files changed, 54 insertions, 172 deletions
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index dd8d909788c1..b25243382966 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -32,6 +32,8 @@ | |||
32 | 32 | ||
33 | /* codec private data */ | 33 | /* codec private data */ |
34 | struct wm8990_priv { | 34 | struct wm8990_priv { |
35 | enum snd_soc_control_type control_type; | ||
36 | void *control_data; | ||
35 | unsigned int sysclk; | 37 | unsigned int sysclk; |
36 | unsigned int pcmclk; | 38 | unsigned int pcmclk; |
37 | }; | 39 | }; |
@@ -1114,8 +1116,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, | |||
1114 | struct snd_soc_dai *dai) | 1116 | struct snd_soc_dai *dai) |
1115 | { | 1117 | { |
1116 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1118 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1117 | struct snd_soc_device *socdev = rtd->socdev; | 1119 | struct snd_soc_codec *codec = rtd->codec; |
1118 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1119 | u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); | 1120 | u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); |
1120 | 1121 | ||
1121 | audio1 &= ~WM8990_AIF_WL_MASK; | 1122 | audio1 &= ~WM8990_AIF_WL_MASK; |
@@ -1293,10 +1294,9 @@ static struct snd_soc_dai_ops wm8990_dai_ops = { | |||
1293 | .set_sysclk = wm8990_set_dai_sysclk, | 1294 | .set_sysclk = wm8990_set_dai_sysclk, |
1294 | }; | 1295 | }; |
1295 | 1296 | ||
1296 | struct snd_soc_dai wm8990_dai = { | 1297 | static struct snd_soc_dai_driver wm8990_dai = { |
1297 | /* ADC/DAC on primary */ | 1298 | /* ADC/DAC on primary */ |
1298 | .name = "WM8990 ADC/DAC Primary", | 1299 | .name = "wm8990-hifi", |
1299 | .id = 1, | ||
1300 | .playback = { | 1300 | .playback = { |
1301 | .stream_name = "Playback", | 1301 | .stream_name = "Playback", |
1302 | .channels_min = 1, | 1302 | .channels_min = 1, |
@@ -1311,21 +1311,15 @@ struct snd_soc_dai wm8990_dai = { | |||
1311 | .formats = WM8990_FORMATS,}, | 1311 | .formats = WM8990_FORMATS,}, |
1312 | .ops = &wm8990_dai_ops, | 1312 | .ops = &wm8990_dai_ops, |
1313 | }; | 1313 | }; |
1314 | EXPORT_SYMBOL_GPL(wm8990_dai); | ||
1315 | 1314 | ||
1316 | static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) | 1315 | static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1317 | { | 1316 | { |
1318 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1319 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1320 | |||
1321 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1317 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1322 | return 0; | 1318 | return 0; |
1323 | } | 1319 | } |
1324 | 1320 | ||
1325 | static int wm8990_resume(struct platform_device *pdev) | 1321 | static int wm8990_resume(struct snd_soc_codec *codec) |
1326 | { | 1322 | { |
1327 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1328 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1329 | int i; | 1323 | int i; |
1330 | u8 data[2]; | 1324 | u8 data[2]; |
1331 | u16 *cache = codec->reg_cache; | 1325 | u16 *cache = codec->reg_cache; |
@@ -1347,38 +1341,21 @@ static int wm8990_resume(struct platform_device *pdev) | |||
1347 | * initialise the WM8990 driver | 1341 | * initialise the WM8990 driver |
1348 | * register the mixer and dsp interfaces with the kernel | 1342 | * register the mixer and dsp interfaces with the kernel |
1349 | */ | 1343 | */ |
1350 | static int wm8990_init(struct snd_soc_device *socdev) | 1344 | static int wm8990_probe(struct snd_soc_codec *codec) |
1351 | { | 1345 | { |
1352 | struct snd_soc_codec *codec = socdev->card->codec; | 1346 | struct wm8990_priv *wm8990 = snd_soc_codec_get_drvdata(codec); |
1347 | int ret; | ||
1353 | u16 reg; | 1348 | u16 reg; |
1354 | int ret = 0; | ||
1355 | |||
1356 | codec->name = "WM8990"; | ||
1357 | codec->owner = THIS_MODULE; | ||
1358 | codec->set_bias_level = wm8990_set_bias_level; | ||
1359 | codec->dai = &wm8990_dai; | ||
1360 | codec->num_dai = 2; | ||
1361 | codec->reg_cache_size = ARRAY_SIZE(wm8990_reg); | ||
1362 | codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL); | ||
1363 | |||
1364 | if (codec->reg_cache == NULL) | ||
1365 | return -ENOMEM; | ||
1366 | 1349 | ||
1350 | codec->control_data = wm8990->control_data; | ||
1367 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1351 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1368 | if (ret < 0) { | 1352 | if (ret < 0) { |
1369 | printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); | 1353 | printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); |
1370 | goto pcm_err; | 1354 | return ret; |
1371 | } | 1355 | } |
1372 | 1356 | ||
1373 | wm8990_reset(codec); | 1357 | wm8990_reset(codec); |
1374 | 1358 | ||
1375 | /* register pcms */ | ||
1376 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1377 | if (ret < 0) { | ||
1378 | printk(KERN_ERR "wm8990: failed to create pcms\n"); | ||
1379 | goto pcm_err; | ||
1380 | } | ||
1381 | |||
1382 | /* charge output caps */ | 1359 | /* charge output caps */ |
1383 | codec->bias_level = SND_SOC_BIAS_OFF; | 1360 | codec->bias_level = SND_SOC_BIAS_OFF; |
1384 | wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1361 | wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -1400,47 +1377,52 @@ static int wm8990_init(struct snd_soc_device *socdev) | |||
1400 | ARRAY_SIZE(wm8990_snd_controls)); | 1377 | ARRAY_SIZE(wm8990_snd_controls)); |
1401 | wm8990_add_widgets(codec); | 1378 | wm8990_add_widgets(codec); |
1402 | 1379 | ||
1403 | return ret; | 1380 | return 0; |
1381 | } | ||
1404 | 1382 | ||
1405 | pcm_err: | 1383 | /* power down chip */ |
1406 | kfree(codec->reg_cache); | 1384 | static int wm8990_remove(struct snd_soc_codec *codec) |
1407 | return ret; | 1385 | { |
1386 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1387 | return 0; | ||
1408 | } | 1388 | } |
1409 | 1389 | ||
1410 | /* If the i2c layer weren't so broken, we could pass this kind of data | 1390 | static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { |
1411 | around */ | 1391 | .probe = wm8990_probe, |
1412 | static struct snd_soc_device *wm8990_socdev; | 1392 | .remove = wm8990_remove, |
1393 | .suspend = wm8990_suspend, | ||
1394 | .resume = wm8990_resume, | ||
1395 | .set_bias_level = wm8990_set_bias_level, | ||
1396 | .reg_cache_size = ARRAY_SIZE(wm8990_reg), | ||
1397 | .reg_word_size = sizeof(u16), | ||
1398 | .reg_cache_default = wm8990_reg, | ||
1399 | }; | ||
1413 | 1400 | ||
1414 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1401 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1415 | 1402 | static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, | |
1416 | /* | 1403 | const struct i2c_device_id *id) |
1417 | * WM891 2 wire address is determined by GPIO5 | ||
1418 | * state during powerup. | ||
1419 | * low = 0x34 | ||
1420 | * high = 0x36 | ||
1421 | */ | ||
1422 | |||
1423 | static int wm8990_i2c_probe(struct i2c_client *i2c, | ||
1424 | const struct i2c_device_id *id) | ||
1425 | { | 1404 | { |
1426 | struct snd_soc_device *socdev = wm8990_socdev; | 1405 | struct wm8990_priv *wm8990; |
1427 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1428 | int ret; | 1406 | int ret; |
1429 | 1407 | ||
1430 | i2c_set_clientdata(i2c, codec); | 1408 | wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); |
1431 | codec->control_data = i2c; | 1409 | if (wm8990 == NULL) |
1410 | return -ENOMEM; | ||
1432 | 1411 | ||
1433 | ret = wm8990_init(socdev); | 1412 | i2c_set_clientdata(i2c, wm8990); |
1434 | if (ret < 0) | 1413 | wm8990->control_data = i2c; |
1435 | pr_err("failed to initialise WM8990\n"); | ||
1436 | 1414 | ||
1415 | ret = snd_soc_register_codec(&i2c->dev, | ||
1416 | &soc_codec_dev_wm8990, &wm8990_dai, 1); | ||
1417 | if (ret < 0) | ||
1418 | kfree(wm8990); | ||
1437 | return ret; | 1419 | return ret; |
1438 | } | 1420 | } |
1439 | 1421 | ||
1440 | static int wm8990_i2c_remove(struct i2c_client *client) | 1422 | static __devexit int wm8990_i2c_remove(struct i2c_client *client) |
1441 | { | 1423 | { |
1442 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1424 | snd_soc_unregister_codec(&client->dev); |
1443 | kfree(codec->reg_cache); | 1425 | kfree(i2c_get_clientdata(client)); |
1444 | return 0; | 1426 | return 0; |
1445 | } | 1427 | } |
1446 | 1428 | ||
@@ -1452,134 +1434,34 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id); | |||
1452 | 1434 | ||
1453 | static struct i2c_driver wm8990_i2c_driver = { | 1435 | static struct i2c_driver wm8990_i2c_driver = { |
1454 | .driver = { | 1436 | .driver = { |
1455 | .name = "WM8990 I2C Codec", | 1437 | .name = "wm8990-codec", |
1456 | .owner = THIS_MODULE, | 1438 | .owner = THIS_MODULE, |
1457 | }, | 1439 | }, |
1458 | .probe = wm8990_i2c_probe, | 1440 | .probe = wm8990_i2c_probe, |
1459 | .remove = wm8990_i2c_remove, | 1441 | .remove = __devexit_p(wm8990_i2c_remove), |
1460 | .id_table = wm8990_i2c_id, | 1442 | .id_table = wm8990_i2c_id, |
1461 | }; | 1443 | }; |
1462 | |||
1463 | static int wm8990_add_i2c_device(struct platform_device *pdev, | ||
1464 | const struct wm8990_setup_data *setup) | ||
1465 | { | ||
1466 | struct i2c_board_info info; | ||
1467 | struct i2c_adapter *adapter; | ||
1468 | struct i2c_client *client; | ||
1469 | int ret; | ||
1470 | |||
1471 | ret = i2c_add_driver(&wm8990_i2c_driver); | ||
1472 | if (ret != 0) { | ||
1473 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
1474 | return ret; | ||
1475 | } | ||
1476 | |||
1477 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
1478 | info.addr = setup->i2c_address; | ||
1479 | strlcpy(info.type, "wm8990", I2C_NAME_SIZE); | ||
1480 | |||
1481 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
1482 | if (!adapter) { | ||
1483 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
1484 | setup->i2c_bus); | ||
1485 | goto err_driver; | ||
1486 | } | ||
1487 | |||
1488 | client = i2c_new_device(adapter, &info); | ||
1489 | i2c_put_adapter(adapter); | ||
1490 | if (!client) { | ||
1491 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
1492 | (unsigned int)info.addr); | ||
1493 | goto err_driver; | ||
1494 | } | ||
1495 | |||
1496 | return 0; | ||
1497 | |||
1498 | err_driver: | ||
1499 | i2c_del_driver(&wm8990_i2c_driver); | ||
1500 | return -ENODEV; | ||
1501 | } | ||
1502 | #endif | 1444 | #endif |
1503 | 1445 | ||
1504 | static int wm8990_probe(struct platform_device *pdev) | 1446 | static int __init wm8990_modinit(void) |
1505 | { | 1447 | { |
1506 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1448 | int ret = 0; |
1507 | struct wm8990_setup_data *setup; | ||
1508 | struct snd_soc_codec *codec; | ||
1509 | struct wm8990_priv *wm8990; | ||
1510 | int ret; | ||
1511 | |||
1512 | setup = socdev->codec_data; | ||
1513 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
1514 | if (codec == NULL) | ||
1515 | return -ENOMEM; | ||
1516 | |||
1517 | wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); | ||
1518 | if (wm8990 == NULL) { | ||
1519 | kfree(codec); | ||
1520 | return -ENOMEM; | ||
1521 | } | ||
1522 | |||
1523 | snd_soc_codec_set_drvdata(codec, wm8990); | ||
1524 | socdev->card->codec = codec; | ||
1525 | mutex_init(&codec->mutex); | ||
1526 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1527 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1528 | wm8990_socdev = socdev; | ||
1529 | |||
1530 | ret = -ENODEV; | ||
1531 | |||
1532 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1449 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1533 | if (setup->i2c_address) { | 1450 | ret = i2c_add_driver(&wm8990_i2c_driver); |
1534 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1535 | ret = wm8990_add_i2c_device(pdev, setup); | ||
1536 | } | ||
1537 | #endif | ||
1538 | |||
1539 | if (ret != 0) { | 1451 | if (ret != 0) { |
1540 | kfree(snd_soc_codec_get_drvdata(codec)); | 1452 | printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n", |
1541 | kfree(codec); | 1453 | ret); |
1542 | } | 1454 | } |
1455 | #endif | ||
1543 | return ret; | 1456 | return ret; |
1544 | } | 1457 | } |
1458 | module_init(wm8990_modinit); | ||
1545 | 1459 | ||
1546 | /* power down chip */ | 1460 | static void __exit wm8990_exit(void) |
1547 | static int wm8990_remove(struct platform_device *pdev) | ||
1548 | { | 1461 | { |
1549 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1550 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1551 | |||
1552 | if (codec->control_data) | ||
1553 | wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1554 | snd_soc_free_pcms(socdev); | ||
1555 | snd_soc_dapm_free(socdev); | ||
1556 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1462 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1557 | i2c_unregister_device(codec->control_data); | ||
1558 | i2c_del_driver(&wm8990_i2c_driver); | 1463 | i2c_del_driver(&wm8990_i2c_driver); |
1559 | #endif | 1464 | #endif |
1560 | kfree(snd_soc_codec_get_drvdata(codec)); | ||
1561 | kfree(codec); | ||
1562 | |||
1563 | return 0; | ||
1564 | } | ||
1565 | |||
1566 | struct snd_soc_codec_device soc_codec_dev_wm8990 = { | ||
1567 | .probe = wm8990_probe, | ||
1568 | .remove = wm8990_remove, | ||
1569 | .suspend = wm8990_suspend, | ||
1570 | .resume = wm8990_resume, | ||
1571 | }; | ||
1572 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); | ||
1573 | |||
1574 | static int __init wm8990_modinit(void) | ||
1575 | { | ||
1576 | return snd_soc_register_dai(&wm8990_dai); | ||
1577 | } | ||
1578 | module_init(wm8990_modinit); | ||
1579 | |||
1580 | static void __exit wm8990_exit(void) | ||
1581 | { | ||
1582 | snd_soc_unregister_dai(&wm8990_dai); | ||
1583 | } | 1465 | } |
1584 | module_exit(wm8990_exit); | 1466 | module_exit(wm8990_exit); |
1585 | 1467 | ||