xref: /openbmc/linux/sound/soc/codecs/wm1250-ev1.c (revision eaefb38f344d12321cd5372d1c8ad35d264d1b35)
14bb3f43cSMark Brown /*
24bb3f43cSMark Brown  * Driver for the 1250-EV1 audio I/O module
34bb3f43cSMark Brown  *
44bb3f43cSMark Brown  * Copyright 2011 Wolfson Microelectronics plc
54bb3f43cSMark Brown  *
64bb3f43cSMark Brown  *  This program is free software; you can redistribute  it and/or modify it
74bb3f43cSMark Brown  *  under  the terms of  the GNU General  Public License as published by the
84bb3f43cSMark Brown  *  Free Software Foundation;  either version 2 of the  License, or (at your
94bb3f43cSMark Brown  *  option) any later version.
104bb3f43cSMark Brown  *
114bb3f43cSMark Brown  */
124bb3f43cSMark Brown 
134bb3f43cSMark Brown #include <linux/init.h>
144bb3f43cSMark Brown #include <linux/module.h>
154bb3f43cSMark Brown #include <linux/i2c.h>
164bb3f43cSMark Brown 
174bb3f43cSMark Brown #include <sound/soc.h>
184bb3f43cSMark Brown #include <sound/soc-dapm.h>
194bb3f43cSMark Brown 
204bb3f43cSMark Brown static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = {
214bb3f43cSMark Brown SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0),
224bb3f43cSMark Brown SND_SOC_DAPM_DAC("DAC", "wm1250-ev1 Playback", SND_SOC_NOPM, 0, 0),
234bb3f43cSMark Brown 
244bb3f43cSMark Brown SND_SOC_DAPM_INPUT("WM1250 Input"),
25979f4869SAxel Lin SND_SOC_DAPM_OUTPUT("WM1250 Output"),
264bb3f43cSMark Brown };
274bb3f43cSMark Brown 
284bb3f43cSMark Brown static const struct snd_soc_dapm_route wm1250_ev1_dapm_routes[] = {
294bb3f43cSMark Brown 	{ "ADC", NULL, "WM1250 Input" },
304bb3f43cSMark Brown 	{ "WM1250 Output", NULL, "DAC" },
314bb3f43cSMark Brown };
324bb3f43cSMark Brown 
334bb3f43cSMark Brown static struct snd_soc_dai_driver wm1250_ev1_dai = {
344bb3f43cSMark Brown 	.name = "wm1250-ev1",
354bb3f43cSMark Brown 	.playback = {
364bb3f43cSMark Brown 		.stream_name = "Playback",
374bb3f43cSMark Brown 		.channels_min = 1,
384bb3f43cSMark Brown 		.channels_max = 1,
394bb3f43cSMark Brown 		.rates = SNDRV_PCM_RATE_8000,
404bb3f43cSMark Brown 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
414bb3f43cSMark Brown 	},
424bb3f43cSMark Brown 	.capture = {
434bb3f43cSMark Brown 		.stream_name = "Capture",
444bb3f43cSMark Brown 		.channels_min = 1,
454bb3f43cSMark Brown 		.channels_max = 1,
464bb3f43cSMark Brown 		.rates = SNDRV_PCM_RATE_8000,
474bb3f43cSMark Brown 		.formats = SNDRV_PCM_FMTBIT_S16_LE,
484bb3f43cSMark Brown 	},
494bb3f43cSMark Brown };
504bb3f43cSMark Brown 
514bb3f43cSMark Brown static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
524bb3f43cSMark Brown 	.dapm_widgets = wm1250_ev1_dapm_widgets,
534bb3f43cSMark Brown 	.num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets),
544bb3f43cSMark Brown 	.dapm_routes = wm1250_ev1_dapm_routes,
554bb3f43cSMark Brown 	.num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes),
564bb3f43cSMark Brown };
574bb3f43cSMark Brown 
584bb3f43cSMark Brown static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
59*eaefb38fSMark Brown 				      const struct i2c_device_id *i2c_id)
604bb3f43cSMark Brown {
61*eaefb38fSMark Brown 	int ret, id, board, rev;
62*eaefb38fSMark Brown 
63*eaefb38fSMark Brown 	board = i2c_smbus_read_byte_data(i2c, 0);
64*eaefb38fSMark Brown 	if (board < 0) {
65*eaefb38fSMark Brown 		dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
66*eaefb38fSMark Brown 		return ret;
67*eaefb38fSMark Brown 	}
68*eaefb38fSMark Brown 
69*eaefb38fSMark Brown 	id = (board & 0xfe) >> 2;
70*eaefb38fSMark Brown 	rev = board & 0x3;
71*eaefb38fSMark Brown 
72*eaefb38fSMark Brown 	if (id != 1) {
73*eaefb38fSMark Brown 		dev_err(&i2c->dev, "Unknown board ID %d\n", id);
74*eaefb38fSMark Brown 		return -ENODEV;
75*eaefb38fSMark Brown 	}
76*eaefb38fSMark Brown 
77*eaefb38fSMark Brown 	dev_info(&i2c->dev, "revision %d\n", rev);
78*eaefb38fSMark Brown 
794bb3f43cSMark Brown 	return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
804bb3f43cSMark Brown 				      &wm1250_ev1_dai, 1);
814bb3f43cSMark Brown }
824bb3f43cSMark Brown 
834bb3f43cSMark Brown static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
844bb3f43cSMark Brown {
854bb3f43cSMark Brown 	snd_soc_unregister_codec(&i2c->dev);
864bb3f43cSMark Brown 
874bb3f43cSMark Brown 	return 0;
884bb3f43cSMark Brown }
894bb3f43cSMark Brown 
904bb3f43cSMark Brown static const struct i2c_device_id wm1250_ev1_i2c_id[] = {
914bb3f43cSMark Brown 	{ "wm1250-ev1", 0 },
924bb3f43cSMark Brown 	{ }
934bb3f43cSMark Brown };
94420dd718SMark Brown MODULE_DEVICE_TABLE(i2c, wm1250_ev1_i2c_id);
954bb3f43cSMark Brown 
964bb3f43cSMark Brown static struct i2c_driver wm1250_ev1_i2c_driver = {
974bb3f43cSMark Brown 	.driver = {
984bb3f43cSMark Brown 		.name = "wm1250-ev1",
994bb3f43cSMark Brown 		.owner = THIS_MODULE,
1004bb3f43cSMark Brown 	},
1014bb3f43cSMark Brown 	.probe =    wm1250_ev1_probe,
1024bb3f43cSMark Brown 	.remove =   __devexit_p(wm1250_ev1_remove),
1034bb3f43cSMark Brown 	.id_table = wm1250_ev1_i2c_id,
1044bb3f43cSMark Brown };
1054bb3f43cSMark Brown 
1064bb3f43cSMark Brown static int __init wm1250_ev1_modinit(void)
1074bb3f43cSMark Brown {
1084bb3f43cSMark Brown 	int ret = 0;
1094bb3f43cSMark Brown 
1104bb3f43cSMark Brown 	ret = i2c_add_driver(&wm1250_ev1_i2c_driver);
1114bb3f43cSMark Brown 	if (ret != 0)
1124bb3f43cSMark Brown 		pr_err("Failed to register WM1250-EV1 I2C driver: %d\n", ret);
1134bb3f43cSMark Brown 
1144bb3f43cSMark Brown 	return ret;
1154bb3f43cSMark Brown }
1164bb3f43cSMark Brown module_init(wm1250_ev1_modinit);
1174bb3f43cSMark Brown 
1184bb3f43cSMark Brown static void __exit wm1250_ev1_exit(void)
1194bb3f43cSMark Brown {
1204bb3f43cSMark Brown 	i2c_del_driver(&wm1250_ev1_i2c_driver);
1214bb3f43cSMark Brown }
1224bb3f43cSMark Brown module_exit(wm1250_ev1_exit);
1234bb3f43cSMark Brown 
1244bb3f43cSMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1254bb3f43cSMark Brown MODULE_DESCRIPTION("WM1250-EV1 audio I/O module driver");
1264bb3f43cSMark Brown MODULE_LICENSE("GPL");
127