diff options
-rw-r--r-- | sound/soc/codecs/wm8900.c | 159 | ||||
-rw-r--r-- | sound/soc/codecs/wm8900.h | 7 |
2 files changed, 81 insertions, 85 deletions
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index ebf58fba1beb..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 | }; |
@@ -1282,16 +1286,28 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1282 | return 0; | 1286 | return 0; |
1283 | } | 1287 | } |
1284 | 1288 | ||
1285 | /* | 1289 | static struct snd_soc_codec *wm8900_codec; |
1286 | * initialise the WM8900 driver | 1290 | |
1287 | * register the mixer and dsp interfaces with the kernel | 1291 | static int wm8900_i2c_probe(struct i2c_client *i2c, |
1288 | */ | 1292 | const struct i2c_device_id *id) |
1289 | static int wm8900_init(struct snd_soc_device *socdev) | ||
1290 | { | 1293 | { |
1291 | struct snd_soc_codec *codec = socdev->codec; | 1294 | struct wm8900_priv *wm8900; |
1292 | int ret = 0; | 1295 | struct snd_soc_codec *codec; |
1293 | unsigned int reg; | 1296 | unsigned int reg; |
1294 | 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); | ||
1295 | 1311 | ||
1296 | codec->name = "WM8900"; | 1312 | codec->name = "WM8900"; |
1297 | codec->owner = THIS_MODULE; | 1313 | codec->owner = THIS_MODULE; |
@@ -1299,33 +1315,28 @@ static int wm8900_init(struct snd_soc_device *socdev) | |||
1299 | codec->write = wm8900_write; | 1315 | codec->write = wm8900_write; |
1300 | codec->dai = &wm8900_dai; | 1316 | codec->dai = &wm8900_dai; |
1301 | codec->num_dai = 1; | 1317 | codec->num_dai = 1; |
1302 | codec->reg_cache_size = WM8900_MAXREG; | 1318 | codec->hw_write = (hw_write_t)i2c_master_send; |
1303 | codec->reg_cache = kmemdup(wm8900_reg_defaults, | 1319 | codec->control_data = i2c; |
1304 | sizeof(wm8900_reg_defaults), GFP_KERNEL); | 1320 | codec->set_bias_level = wm8900_set_bias_level; |
1305 | 1321 | codec->dev = &i2c->dev; | |
1306 | if (codec->reg_cache == NULL) | ||
1307 | return -ENOMEM; | ||
1308 | 1322 | ||
1309 | reg = wm8900_read(codec, WM8900_REG_ID); | 1323 | reg = wm8900_read(codec, WM8900_REG_ID); |
1310 | if (reg != 0x8900) { | 1324 | if (reg != 0x8900) { |
1311 | 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); |
1312 | reg); | 1326 | ret = -ENODEV; |
1313 | return -ENODEV; | 1327 | goto err; |
1314 | } | ||
1315 | |||
1316 | codec->private_data = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1317 | if (codec->private_data == NULL) { | ||
1318 | ret = -ENOMEM; | ||
1319 | goto priv_err; | ||
1320 | } | 1328 | } |
1321 | 1329 | ||
1322 | /* Read back from the chip */ | 1330 | /* Read back from the chip */ |
1323 | reg = wm8900_chip_read(codec, WM8900_REG_POWER1); | 1331 | reg = wm8900_chip_read(codec, WM8900_REG_POWER1); |
1324 | reg = (reg >> 12) & 0xf; | 1332 | reg = (reg >> 12) & 0xf; |
1325 | dev_info(&i2c_client->dev, "WM8900 revision %d\n", reg); | 1333 | dev_info(&i2c->dev, "WM8900 revision %d\n", reg); |
1326 | 1334 | ||
1327 | wm8900_reset(codec); | 1335 | wm8900_reset(codec); |
1328 | 1336 | ||
1337 | /* Turn the chip on */ | ||
1338 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1339 | |||
1329 | /* Latch the volume update bits */ | 1340 | /* Latch the volume update bits */ |
1330 | wm8900_write(codec, WM8900_REG_LINVOL, | 1341 | wm8900_write(codec, WM8900_REG_LINVOL, |
1331 | wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); | 1342 | wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); |
@@ -1351,52 +1362,43 @@ static int wm8900_init(struct snd_soc_device *socdev) | |||
1351 | /* Set the DAC and mixer output bias */ | 1362 | /* Set the DAC and mixer output bias */ |
1352 | wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); | 1363 | wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); |
1353 | 1364 | ||
1354 | /* Register pcms */ | 1365 | wm8900_dai.dev = &i2c->dev; |
1355 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1356 | if (ret < 0) { | ||
1357 | dev_err(&i2c_client->dev, "Failed to register new PCMs\n"); | ||
1358 | goto pcm_err; | ||
1359 | } | ||
1360 | 1366 | ||
1361 | /* Turn the chip on */ | 1367 | wm8900_codec = codec; |
1362 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1363 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1364 | 1368 | ||
1365 | wm8900_add_controls(codec); | 1369 | ret = snd_soc_register_codec(codec); |
1366 | wm8900_add_widgets(codec); | 1370 | if (ret != 0) { |
1371 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | ||
1372 | goto err; | ||
1373 | } | ||
1367 | 1374 | ||
1368 | ret = snd_soc_init_card(socdev); | 1375 | ret = snd_soc_register_dai(&wm8900_dai); |
1369 | if (ret < 0) { | 1376 | if (ret != 0) { |
1370 | dev_err(&i2c_client->dev, "Failed to register card\n"); | 1377 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); |
1371 | goto card_err; | 1378 | goto err_codec; |
1372 | } | 1379 | } |
1373 | return ret; | ||
1374 | 1380 | ||
1375 | card_err: | ||
1376 | snd_soc_free_pcms(socdev); | ||
1377 | snd_soc_dapm_free(socdev); | ||
1378 | pcm_err: | ||
1379 | kfree(codec->reg_cache); | ||
1380 | priv_err: | ||
1381 | kfree(codec->private_data); | ||
1382 | return ret; | 1381 | return ret; |
1383 | } | ||
1384 | |||
1385 | static struct i2c_client *wm8900_client; | ||
1386 | 1382 | ||
1387 | static int wm8900_i2c_probe(struct i2c_client *i2c, | 1383 | err_codec: |
1388 | const struct i2c_device_id *id) | 1384 | snd_soc_unregister_codec(codec); |
1389 | { | 1385 | err: |
1390 | wm8900_client = i2c; | 1386 | kfree(wm8900); |
1391 | wm8900_dai.dev = &i2c->dev; | 1387 | wm8900_codec = NULL; |
1392 | return snd_soc_register_dai(&wm8900_dai); | 1388 | return ret; |
1393 | } | 1389 | } |
1394 | 1390 | ||
1395 | static int wm8900_i2c_remove(struct i2c_client *client) | 1391 | static int wm8900_i2c_remove(struct i2c_client *client) |
1396 | { | 1392 | { |
1397 | snd_soc_unregister_dai(&wm8900_dai); | 1393 | snd_soc_unregister_dai(&wm8900_dai); |
1394 | snd_soc_unregister_codec(wm8900_codec); | ||
1395 | |||
1396 | wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF); | ||
1397 | |||
1398 | wm8900_dai.dev = NULL; | 1398 | wm8900_dai.dev = NULL; |
1399 | wm8900_client = NULL; | 1399 | kfree(wm8900_codec->private_data); |
1400 | wm8900_codec = NULL; | ||
1401 | |||
1400 | return 0; | 1402 | return 0; |
1401 | } | 1403 | } |
1402 | 1404 | ||
@@ -1408,7 +1410,7 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); | |||
1408 | 1410 | ||
1409 | static struct i2c_driver wm8900_i2c_driver = { | 1411 | static struct i2c_driver wm8900_i2c_driver = { |
1410 | .driver = { | 1412 | .driver = { |
1411 | .name = "WM8900 I2C codec", | 1413 | .name = "WM8900", |
1412 | .owner = THIS_MODULE, | 1414 | .owner = THIS_MODULE, |
1413 | }, | 1415 | }, |
1414 | .probe = wm8900_i2c_probe, | 1416 | .probe = wm8900_i2c_probe, |
@@ -1422,30 +1424,36 @@ static int wm8900_probe(struct platform_device *pdev) | |||
1422 | struct snd_soc_codec *codec; | 1424 | struct snd_soc_codec *codec; |
1423 | int ret = 0; | 1425 | int ret = 0; |
1424 | 1426 | ||
1425 | if (!wm8900_client) { | 1427 | if (!wm8900_codec) { |
1426 | dev_err(&pdev->dev, "I2C client not yet instantiated\n"); | 1428 | dev_err(&pdev->dev, "I2C client not yet instantiated\n"); |
1427 | return -ENODEV; | 1429 | return -ENODEV; |
1428 | } | 1430 | } |
1429 | 1431 | ||
1430 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 1432 | codec = wm8900_codec; |
1431 | if (codec == NULL) | ||
1432 | return -ENOMEM; | ||
1433 | |||
1434 | mutex_init(&codec->mutex); | ||
1435 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1436 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1437 | |||
1438 | socdev->codec = codec; | 1433 | socdev->codec = codec; |
1439 | 1434 | ||
1440 | 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 | } | ||
1441 | 1441 | ||
1442 | codec->hw_write = (hw_write_t)i2c_master_send; | 1442 | wm8900_add_controls(codec); |
1443 | codec->control_data = wm8900_client; | 1443 | wm8900_add_widgets(codec); |
1444 | |||
1445 | ret = snd_soc_init_card(socdev); | ||
1446 | if (ret < 0) { | ||
1447 | dev_err(&pdev->dev, "Failed to register card\n"); | ||
1448 | goto card_err; | ||
1449 | } | ||
1444 | 1450 | ||
1445 | ret = wm8900_init(socdev); | 1451 | return ret; |
1446 | if (ret != 0) | ||
1447 | kfree(codec); | ||
1448 | 1452 | ||
1453 | card_err: | ||
1454 | snd_soc_free_pcms(socdev); | ||
1455 | snd_soc_dapm_free(socdev); | ||
1456 | pcm_err: | ||
1449 | return ret; | 1457 | return ret; |
1450 | } | 1458 | } |
1451 | 1459 | ||
@@ -1453,14 +1461,9 @@ static int wm8900_probe(struct platform_device *pdev) | |||
1453 | static int wm8900_remove(struct platform_device *pdev) | 1461 | static int wm8900_remove(struct platform_device *pdev) |
1454 | { | 1462 | { |
1455 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1463 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1456 | struct snd_soc_codec *codec = socdev->codec; | ||
1457 | |||
1458 | if (codec->control_data) | ||
1459 | wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1460 | 1464 | ||
1461 | snd_soc_free_pcms(socdev); | 1465 | snd_soc_free_pcms(socdev); |
1462 | snd_soc_dapm_free(socdev); | 1466 | snd_soc_dapm_free(socdev); |
1463 | kfree(codec); | ||
1464 | 1467 | ||
1465 | return 0; | 1468 | return 0; |
1466 | } | 1469 | } |
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h index 2249a446ad37..fd15007d10c7 100644 --- a/sound/soc/codecs/wm8900.h +++ b/sound/soc/codecs/wm8900.h | |||
@@ -52,13 +52,6 @@ | |||
52 | #define WM8900_DAC_CLKDIV_5_5 0x14 | 52 | #define WM8900_DAC_CLKDIV_5_5 0x14 |
53 | #define WM8900_DAC_CLKDIV_6 0x18 | 53 | #define WM8900_DAC_CLKDIV_6 0x18 |
54 | 54 | ||
55 | #define WM8900_ | ||
56 | |||
57 | struct wm8900_setup_data { | ||
58 | int i2c_bus; | ||
59 | unsigned short i2c_address; | ||
60 | }; | ||
61 | |||
62 | extern struct snd_soc_dai wm8900_dai; | 55 | extern struct snd_soc_dai wm8900_dai; |
63 | extern struct snd_soc_codec_device soc_codec_dev_wm8900; | 56 | extern struct snd_soc_codec_device soc_codec_dev_wm8900; |
64 | 57 | ||