diff options
Diffstat (limited to 'sound/soc/codecs/wm8900.c')
-rw-r--r-- | sound/soc/codecs/wm8900.c | 251 |
1 files changed, 122 insertions, 129 deletions
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 5da17a704e5a..33c3b57f3f66 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/spi/spi.h> | ||
26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
@@ -137,11 +138,9 @@ | |||
137 | 138 | ||
138 | #define WM8900_LRC_MASK 0xfc00 | 139 | #define WM8900_LRC_MASK 0xfc00 |
139 | 140 | ||
140 | struct snd_soc_codec_device soc_codec_dev_wm8900; | ||
141 | |||
142 | struct wm8900_priv { | 141 | struct wm8900_priv { |
143 | struct snd_soc_codec codec; | 142 | enum snd_soc_control_type control_type; |
144 | 143 | void *control_data; | |
145 | u16 reg_cache[WM8900_MAXREG]; | 144 | u16 reg_cache[WM8900_MAXREG]; |
146 | 145 | ||
147 | u32 fll_in; /* FLL input frequency */ | 146 | u32 fll_in; /* FLL input frequency */ |
@@ -627,8 +626,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, | |||
627 | struct snd_soc_dai *dai) | 626 | struct snd_soc_dai *dai) |
628 | { | 627 | { |
629 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 628 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
630 | struct snd_soc_device *socdev = rtd->socdev; | 629 | struct snd_soc_codec *codec = rtd->codec; |
631 | struct snd_soc_codec *codec = socdev->card->codec; | ||
632 | u16 reg; | 630 | u16 reg; |
633 | 631 | ||
634 | reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; | 632 | reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; |
@@ -1015,8 +1013,8 @@ static struct snd_soc_dai_ops wm8900_dai_ops = { | |||
1015 | .digital_mute = wm8900_digital_mute, | 1013 | .digital_mute = wm8900_digital_mute, |
1016 | }; | 1014 | }; |
1017 | 1015 | ||
1018 | struct snd_soc_dai wm8900_dai = { | 1016 | static struct snd_soc_dai_driver wm8900_dai = { |
1019 | .name = "WM8900 HiFi", | 1017 | .name = "wm8900-hifi", |
1020 | .playback = { | 1018 | .playback = { |
1021 | .stream_name = "HiFi Playback", | 1019 | .stream_name = "HiFi Playback", |
1022 | .channels_min = 1, | 1020 | .channels_min = 1, |
@@ -1033,7 +1031,6 @@ struct snd_soc_dai wm8900_dai = { | |||
1033 | }, | 1031 | }, |
1034 | .ops = &wm8900_dai_ops, | 1032 | .ops = &wm8900_dai_ops, |
1035 | }; | 1033 | }; |
1036 | EXPORT_SYMBOL_GPL(wm8900_dai); | ||
1037 | 1034 | ||
1038 | static int wm8900_set_bias_level(struct snd_soc_codec *codec, | 1035 | static int wm8900_set_bias_level(struct snd_soc_codec *codec, |
1039 | enum snd_soc_bias_level level) | 1036 | enum snd_soc_bias_level level) |
@@ -1128,10 +1125,8 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, | |||
1128 | return 0; | 1125 | return 0; |
1129 | } | 1126 | } |
1130 | 1127 | ||
1131 | static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | 1128 | static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1132 | { | 1129 | { |
1133 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1134 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1135 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | 1130 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1136 | int fll_out = wm8900->fll_out; | 1131 | int fll_out = wm8900->fll_out; |
1137 | int fll_in = wm8900->fll_in; | 1132 | int fll_in = wm8900->fll_in; |
@@ -1140,7 +1135,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | |||
1140 | /* Stop the FLL in an orderly fashion */ | 1135 | /* Stop the FLL in an orderly fashion */ |
1141 | ret = wm8900_set_fll(codec, 0, 0, 0); | 1136 | ret = wm8900_set_fll(codec, 0, 0, 0); |
1142 | if (ret != 0) { | 1137 | if (ret != 0) { |
1143 | dev_err(&pdev->dev, "Failed to stop FLL\n"); | 1138 | dev_err(codec->dev, "Failed to stop FLL\n"); |
1144 | return ret; | 1139 | return ret; |
1145 | } | 1140 | } |
1146 | 1141 | ||
@@ -1152,10 +1147,8 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) | |||
1152 | return 0; | 1147 | return 0; |
1153 | } | 1148 | } |
1154 | 1149 | ||
1155 | static int wm8900_resume(struct platform_device *pdev) | 1150 | static int wm8900_resume(struct snd_soc_codec *codec) |
1156 | { | 1151 | { |
1157 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1158 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1159 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | 1152 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1160 | u16 *cache; | 1153 | u16 *cache; |
1161 | int i, ret; | 1154 | int i, ret; |
@@ -1176,7 +1169,7 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1176 | 1169 | ||
1177 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); | 1170 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); |
1178 | if (ret != 0) { | 1171 | if (ret != 0) { |
1179 | dev_err(&pdev->dev, "Failed to restart FLL\n"); | 1172 | dev_err(codec->dev, "Failed to restart FLL\n"); |
1180 | return ret; | 1173 | return ret; |
1181 | } | 1174 | } |
1182 | } | 1175 | } |
@@ -1186,60 +1179,33 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1186 | snd_soc_write(codec, i, cache[i]); | 1179 | snd_soc_write(codec, i, cache[i]); |
1187 | kfree(cache); | 1180 | kfree(cache); |
1188 | } else | 1181 | } else |
1189 | dev_err(&pdev->dev, "Unable to allocate register cache\n"); | 1182 | dev_err(codec->dev, "Unable to allocate register cache\n"); |
1190 | 1183 | ||
1191 | return 0; | 1184 | return 0; |
1192 | } | 1185 | } |
1193 | 1186 | ||
1194 | static struct snd_soc_codec *wm8900_codec; | 1187 | static int wm8900_probe(struct snd_soc_codec *codec) |
1195 | |||
1196 | static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | ||
1197 | const struct i2c_device_id *id) | ||
1198 | { | 1188 | { |
1199 | struct wm8900_priv *wm8900; | 1189 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
1200 | struct snd_soc_codec *codec; | 1190 | int ret = 0, reg; |
1201 | unsigned int reg; | ||
1202 | int ret; | ||
1203 | |||
1204 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1205 | if (wm8900 == NULL) | ||
1206 | return -ENOMEM; | ||
1207 | 1191 | ||
1208 | codec = &wm8900->codec; | 1192 | codec->control_data = wm8900->control_data; |
1209 | snd_soc_codec_set_drvdata(codec, wm8900); | 1193 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); |
1210 | codec->reg_cache = &wm8900->reg_cache[0]; | ||
1211 | codec->reg_cache_size = WM8900_MAXREG; | ||
1212 | |||
1213 | mutex_init(&codec->mutex); | ||
1214 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1215 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1216 | |||
1217 | codec->name = "WM8900"; | ||
1218 | codec->owner = THIS_MODULE; | ||
1219 | codec->dai = &wm8900_dai; | ||
1220 | codec->num_dai = 1; | ||
1221 | codec->control_data = i2c; | ||
1222 | codec->set_bias_level = wm8900_set_bias_level; | ||
1223 | codec->volatile_register = wm8900_volatile_register; | ||
1224 | codec->dev = &i2c->dev; | ||
1225 | |||
1226 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | ||
1227 | if (ret != 0) { | 1194 | if (ret != 0) { |
1228 | dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); | 1195 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
1229 | goto err; | 1196 | return ret; |
1230 | } | 1197 | } |
1231 | 1198 | ||
1232 | reg = snd_soc_read(codec, WM8900_REG_ID); | 1199 | reg = snd_soc_read(codec, WM8900_REG_ID); |
1233 | if (reg != 0x8900) { | 1200 | if (reg != 0x8900) { |
1234 | dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); | 1201 | dev_err(codec->dev, "Device is not a WM8900 - ID %x\n", reg); |
1235 | ret = -ENODEV; | 1202 | return -ENODEV; |
1236 | goto err; | ||
1237 | } | 1203 | } |
1238 | 1204 | ||
1239 | /* Read back from the chip */ | 1205 | /* Read back from the chip */ |
1240 | reg = snd_soc_read(codec, WM8900_REG_POWER1); | 1206 | reg = snd_soc_read(codec, WM8900_REG_POWER1); |
1241 | reg = (reg >> 12) & 0xf; | 1207 | reg = (reg >> 12) & 0xf; |
1242 | dev_info(&i2c->dev, "WM8900 revision %d\n", reg); | 1208 | dev_info(codec->dev, "WM8900 revision %d\n", reg); |
1243 | 1209 | ||
1244 | wm8900_reset(codec); | 1210 | wm8900_reset(codec); |
1245 | 1211 | ||
@@ -1271,43 +1237,97 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | |||
1271 | /* Set the DAC and mixer output bias */ | 1237 | /* Set the DAC and mixer output bias */ |
1272 | snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); | 1238 | snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); |
1273 | 1239 | ||
1274 | wm8900_dai.dev = &i2c->dev; | 1240 | snd_soc_add_controls(codec, wm8900_snd_controls, |
1241 | ARRAY_SIZE(wm8900_snd_controls)); | ||
1242 | wm8900_add_widgets(codec); | ||
1275 | 1243 | ||
1276 | wm8900_codec = codec; | 1244 | return 0; |
1245 | } | ||
1277 | 1246 | ||
1278 | ret = snd_soc_register_codec(codec); | 1247 | /* power down chip */ |
1279 | if (ret != 0) { | 1248 | static int wm8900_remove(struct snd_soc_codec *codec) |
1280 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | 1249 | { |
1281 | goto err; | 1250 | wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1282 | } | 1251 | return 0; |
1252 | } | ||
1283 | 1253 | ||
1284 | ret = snd_soc_register_dai(&wm8900_dai); | 1254 | static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { |
1285 | if (ret != 0) { | 1255 | .probe = wm8900_probe, |
1286 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); | 1256 | .remove = wm8900_remove, |
1287 | goto err_codec; | 1257 | .suspend = wm8900_suspend, |
1288 | } | 1258 | .resume = wm8900_resume, |
1259 | .set_bias_level = wm8900_set_bias_level, | ||
1260 | .volatile_register = wm8900_volatile_register, | ||
1261 | .reg_cache_size = sizeof(wm8900_reg_defaults), | ||
1262 | .reg_word_size = sizeof(u16), | ||
1263 | .reg_cache_default = wm8900_reg_defaults, | ||
1264 | }; | ||
1289 | 1265 | ||
1290 | return ret; | 1266 | #if defined(CONFIG_SPI_MASTER) |
1267 | static int __devinit wm8900_spi_probe(struct spi_device *spi) | ||
1268 | { | ||
1269 | struct wm8900_priv *wm8900; | ||
1270 | int ret; | ||
1271 | |||
1272 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1273 | if (wm8900 == NULL) | ||
1274 | return -ENOMEM; | ||
1291 | 1275 | ||
1292 | err_codec: | 1276 | wm8900->control_data = spi; |
1293 | snd_soc_unregister_codec(codec); | 1277 | wm8900->control_type = SND_SOC_SPI; |
1294 | err: | 1278 | spi_set_drvdata(spi, wm8900); |
1295 | kfree(wm8900); | 1279 | |
1296 | wm8900_codec = NULL; | 1280 | ret = snd_soc_register_codec(&spi->dev, |
1281 | &soc_codec_dev_wm8900, &wm8900_dai, 1); | ||
1282 | if (ret < 0) | ||
1283 | kfree(wm8900); | ||
1297 | return ret; | 1284 | return ret; |
1298 | } | 1285 | } |
1299 | 1286 | ||
1300 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) | 1287 | static int __devexit wm8900_spi_remove(struct spi_device *spi) |
1301 | { | 1288 | { |
1302 | snd_soc_unregister_dai(&wm8900_dai); | 1289 | snd_soc_unregister_codec(&spi->dev); |
1303 | snd_soc_unregister_codec(wm8900_codec); | 1290 | kfree(spi_get_drvdata(spi)); |
1291 | return 0; | ||
1292 | } | ||
1304 | 1293 | ||
1305 | wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF); | 1294 | static struct spi_driver wm8900_spi_driver = { |
1295 | .driver = { | ||
1296 | .name = "wm8900-codec", | ||
1297 | .bus = &spi_bus_type, | ||
1298 | .owner = THIS_MODULE, | ||
1299 | }, | ||
1300 | .probe = wm8900_spi_probe, | ||
1301 | .remove = __devexit_p(wm8900_spi_remove), | ||
1302 | }; | ||
1303 | #endif /* CONFIG_SPI_MASTER */ | ||
1304 | |||
1305 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1306 | static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | ||
1307 | const struct i2c_device_id *id) | ||
1308 | { | ||
1309 | struct wm8900_priv *wm8900; | ||
1310 | int ret; | ||
1311 | |||
1312 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1313 | if (wm8900 == NULL) | ||
1314 | return -ENOMEM; | ||
1315 | |||
1316 | i2c_set_clientdata(i2c, wm8900); | ||
1317 | wm8900->control_data = i2c; | ||
1318 | wm8900->control_type = SND_SOC_I2C; | ||
1306 | 1319 | ||
1307 | wm8900_dai.dev = NULL; | 1320 | ret = snd_soc_register_codec(&i2c->dev, |
1308 | kfree(snd_soc_codec_get_drvdata(wm8900_codec)); | 1321 | &soc_codec_dev_wm8900, &wm8900_dai, 1); |
1309 | wm8900_codec = NULL; | 1322 | if (ret < 0) |
1323 | kfree(wm8900); | ||
1324 | return ret; | ||
1325 | } | ||
1310 | 1326 | ||
1327 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) | ||
1328 | { | ||
1329 | snd_soc_unregister_codec(&client->dev); | ||
1330 | kfree(i2c_get_clientdata(client)); | ||
1311 | return 0; | 1331 | return 0; |
1312 | } | 1332 | } |
1313 | 1333 | ||
@@ -1319,71 +1339,44 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); | |||
1319 | 1339 | ||
1320 | static struct i2c_driver wm8900_i2c_driver = { | 1340 | static struct i2c_driver wm8900_i2c_driver = { |
1321 | .driver = { | 1341 | .driver = { |
1322 | .name = "WM8900", | 1342 | .name = "wm8900-codec", |
1323 | .owner = THIS_MODULE, | 1343 | .owner = THIS_MODULE, |
1324 | }, | 1344 | }, |
1325 | .probe = wm8900_i2c_probe, | 1345 | .probe = wm8900_i2c_probe, |
1326 | .remove = __devexit_p(wm8900_i2c_remove), | 1346 | .remove = __devexit_p(wm8900_i2c_remove), |
1327 | .id_table = wm8900_i2c_id, | 1347 | .id_table = wm8900_i2c_id, |
1328 | }; | 1348 | }; |
1349 | #endif | ||
1329 | 1350 | ||
1330 | static int wm8900_probe(struct platform_device *pdev) | 1351 | static int __init wm8900_modinit(void) |
1331 | { | 1352 | { |
1332 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1333 | struct snd_soc_codec *codec; | ||
1334 | int ret = 0; | 1353 | int ret = 0; |
1335 | 1354 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | |
1336 | if (!wm8900_codec) { | 1355 | ret = i2c_add_driver(&wm8900_i2c_driver); |
1337 | dev_err(&pdev->dev, "I2C client not yet instantiated\n"); | 1356 | if (ret != 0) { |
1338 | return -ENODEV; | 1357 | printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n", |
1358 | ret); | ||
1339 | } | 1359 | } |
1340 | 1360 | #endif | |
1341 | codec = wm8900_codec; | 1361 | #if defined(CONFIG_SPI_MASTER) |
1342 | socdev->card->codec = codec; | 1362 | ret = spi_register_driver(&wm8900_spi_driver); |
1343 | 1363 | if (ret != 0) { | |
1344 | /* Register pcms */ | 1364 | printk(KERN_ERR "Failed to register wm8900 SPI driver: %d\n", |
1345 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1365 | ret); |
1346 | if (ret < 0) { | ||
1347 | dev_err(&pdev->dev, "Failed to register new PCMs\n"); | ||
1348 | goto pcm_err; | ||
1349 | } | 1366 | } |
1350 | 1367 | #endif | |
1351 | snd_soc_add_controls(codec, wm8900_snd_controls, | ||
1352 | ARRAY_SIZE(wm8900_snd_controls)); | ||
1353 | wm8900_add_widgets(codec); | ||
1354 | |||
1355 | pcm_err: | ||
1356 | return ret; | 1368 | return ret; |
1357 | } | 1369 | } |
1358 | |||
1359 | /* power down chip */ | ||
1360 | static int wm8900_remove(struct platform_device *pdev) | ||
1361 | { | ||
1362 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1363 | |||
1364 | snd_soc_free_pcms(socdev); | ||
1365 | snd_soc_dapm_free(socdev); | ||
1366 | |||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1370 | struct snd_soc_codec_device soc_codec_dev_wm8900 = { | ||
1371 | .probe = wm8900_probe, | ||
1372 | .remove = wm8900_remove, | ||
1373 | .suspend = wm8900_suspend, | ||
1374 | .resume = wm8900_resume, | ||
1375 | }; | ||
1376 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); | ||
1377 | |||
1378 | static int __init wm8900_modinit(void) | ||
1379 | { | ||
1380 | return i2c_add_driver(&wm8900_i2c_driver); | ||
1381 | } | ||
1382 | module_init(wm8900_modinit); | 1370 | module_init(wm8900_modinit); |
1383 | 1371 | ||
1384 | static void __exit wm8900_exit(void) | 1372 | static void __exit wm8900_exit(void) |
1385 | { | 1373 | { |
1374 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1386 | i2c_del_driver(&wm8900_i2c_driver); | 1375 | i2c_del_driver(&wm8900_i2c_driver); |
1376 | #endif | ||
1377 | #if defined(CONFIG_SPI_MASTER) | ||
1378 | spi_unregister_driver(&wm8900_spi_driver); | ||
1379 | #endif | ||
1387 | } | 1380 | } |
1388 | module_exit(wm8900_exit); | 1381 | module_exit(wm8900_exit); |
1389 | 1382 | ||