aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2008-12-10 10:38:36 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2008-12-10 14:47:40 -0500
commit78e19a39d3985e2a06354493a70a200c0d432de5 (patch)
treef23c4a127696ccff5d378298790a53ccbb22ff61 /sound/soc
parent0d0cf00a7fc63cee9a4c4a3b8612879b4f7f42ba (diff)
ASoC: Convert WM8900 to do more work at I2C probe time
Redo the instantiation of the WM8900 to do most of the initialisation work when the I2C driver probes rather than when the ASoC device is instantiated, registering the codec with the ASoC core when done. Also move all dynamic allocations into a single kmalloc() to simplify error handling and rename the I2C driver to make output more sensible. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/wm8900.c159
-rw-r--r--sound/soc/codecs/wm8900.h7
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 @@
138struct snd_soc_codec_device soc_codec_dev_wm8900; 138struct snd_soc_codec_device soc_codec_dev_wm8900;
139 139
140struct wm8900_priv { 140struct 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/* 1289static struct snd_soc_codec *wm8900_codec;
1286 * initialise the WM8900 driver 1290
1287 * register the mixer and dsp interfaces with the kernel 1291static int wm8900_i2c_probe(struct i2c_client *i2c,
1288 */ 1292 const struct i2c_device_id *id)
1289static 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
1375card_err:
1376 snd_soc_free_pcms(socdev);
1377 snd_soc_dapm_free(socdev);
1378pcm_err:
1379 kfree(codec->reg_cache);
1380priv_err:
1381 kfree(codec->private_data);
1382 return ret; 1381 return ret;
1383}
1384
1385static struct i2c_client *wm8900_client;
1386 1382
1387static int wm8900_i2c_probe(struct i2c_client *i2c, 1383err_codec:
1388 const struct i2c_device_id *id) 1384 snd_soc_unregister_codec(codec);
1389{ 1385err:
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
1395static int wm8900_i2c_remove(struct i2c_client *client) 1391static 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
1409static struct i2c_driver wm8900_i2c_driver = { 1411static 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
1453card_err:
1454 snd_soc_free_pcms(socdev);
1455 snd_soc_dapm_free(socdev);
1456pcm_err:
1449 return ret; 1457 return ret;
1450} 1458}
1451 1459
@@ -1453,14 +1461,9 @@ static int wm8900_probe(struct platform_device *pdev)
1453static int wm8900_remove(struct platform_device *pdev) 1461static 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
57struct wm8900_setup_data {
58 int i2c_bus;
59 unsigned short i2c_address;
60};
61
62extern struct snd_soc_dai wm8900_dai; 55extern struct snd_soc_dai wm8900_dai;
63extern struct snd_soc_codec_device soc_codec_dev_wm8900; 56extern struct snd_soc_codec_device soc_codec_dev_wm8900;
64 57