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