1 /* Speyside modules for Cragganmore - board data probing
3 * Copyright 2011 Wolfson Microelectronics plc
4 * Mark Brown <broonie@opensource.wolfsonmicro.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/export.h>
12 #include <linux/interrupt.h>
13 #include <linux/i2c.h>
14 #include <linux/spi/spi.h>
16 #include <linux/mfd/wm831x/irq.h>
17 #include <linux/mfd/wm831x/gpio.h>
18 #include <linux/mfd/wm8994/pdata.h>
19 #include <linux/mfd/arizona/pdata.h>
21 #include <linux/regulator/machine.h>
23 #include <sound/wm0010.h>
24 #include <sound/wm5100.h>
25 #include <sound/wm8996.h>
26 #include <sound/wm8962.h>
27 #include <sound/wm9081.h>
29 #include <linux/platform_data/spi-s3c64xx.h>
31 #include <mach/crag6410.h>
33 static struct s3c64xx_spi_csinfo wm0010_spi_csinfo = {
34 .line = S3C64XX_GPC(3),
37 static struct wm0010_pdata wm0010_pdata = {
38 .gpio_reset = S3C64XX_GPN(6),
39 .reset_active_high = 1, /* Active high for Glenfarclas Rev 2 */
42 static struct spi_board_info wm1253_devs[] = {
45 .max_speed_hz = 26 * 1000 * 1000,
50 .controller_data = &wm0010_spi_csinfo,
51 .platform_data = &wm0010_pdata,
55 static struct spi_board_info balblair_devs[] = {
58 .max_speed_hz = 26 * 1000 * 1000,
63 .controller_data = &wm0010_spi_csinfo,
64 .platform_data = &wm0010_pdata,
68 static struct wm5100_pdata wm5100_pdata = {
69 .ldo_ena = S3C64XX_GPN(7),
70 .irq_flags = IRQF_TRIGGER_HIGH,
71 .gpio_base = CODEC_GPIO_BASE,
80 .hp_pol = CODEC_GPIO_BASE + 3,
82 { WM5100_MICDET_MICBIAS3, 0, 0 },
83 { WM5100_MICDET_MICBIAS2, 1, 1 },
91 0x2, /* IRQ: CMOS output */
92 0x3, /* CLKOUT: CMOS output */
96 static struct wm8996_retune_mobile_config wm8996_retune[] = {
101 0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
102 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
103 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
110 0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
111 0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
112 0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
117 static struct wm8996_pdata wm8996_pdata __initdata = {
118 .ldo_ena = S3C64XX_GPN(7),
119 .gpio_base = CODEC_GPIO_BASE,
121 .inl_mode = WM8996_DIFFERRENTIAL_1,
122 .inr_mode = WM8996_DIFFERRENTIAL_1,
124 .irq_flags = IRQF_TRIGGER_RISING,
127 0x8001, /* GPIO1 == ADCLRCLK1 */
128 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
129 0x0141, /* GPIO3 == HP_SEL */
130 0x0002, /* GPIO4 == IRQ */
131 0x020e, /* GPIO5 == CLKOUT */
134 .retune_mobile_cfgs = wm8996_retune,
135 .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
138 static struct wm8962_pdata wm8962_pdata __initdata = {
141 WM8962_GPIO_FN_OPCLK,
142 WM8962_GPIO_FN_DMICCLK,
144 0x8000 | WM8962_GPIO_FN_DMICDAT,
145 WM8962_GPIO_FN_IRQ, /* Open drain mode */
147 .in4_dc_measure = true,
150 static struct wm9081_pdata wm9081_pdata __initdata = {
155 static const struct i2c_board_info wm1254_devs[] = {
156 { I2C_BOARD_INFO("wm8996", 0x1a),
157 .platform_data = &wm8996_pdata,
158 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
160 { I2C_BOARD_INFO("wm9081", 0x6c),
161 .platform_data = &wm9081_pdata, },
164 static const struct i2c_board_info wm1255_devs[] = {
165 { I2C_BOARD_INFO("wm5100", 0x1a),
166 .platform_data = &wm5100_pdata,
167 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
169 { I2C_BOARD_INFO("wm9081", 0x6c),
170 .platform_data = &wm9081_pdata, },
173 static const struct i2c_board_info wm1259_devs[] = {
174 { I2C_BOARD_INFO("wm8962", 0x1a),
175 .platform_data = &wm8962_pdata,
176 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
180 static struct regulator_init_data wm8994_ldo1 = {
181 .supply_regulator = "WALLVDD",
184 static struct regulator_init_data wm8994_ldo2 = {
185 .supply_regulator = "WALLVDD",
188 static struct wm8994_pdata wm8994_pdata = {
189 .gpio_base = CODEC_GPIO_BASE,
191 0x3, /* IRQ out, active high, CMOS */
194 { .init_data = &wm8994_ldo1, },
195 { .init_data = &wm8994_ldo2, },
199 static const struct i2c_board_info wm1277_devs[] = {
200 { I2C_BOARD_INFO("wm8958", 0x1a), /* WM8958 is the superset */
201 .platform_data = &wm8994_pdata,
202 .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
206 static struct arizona_pdata wm5102_pdata = {
207 .ldoena = S3C64XX_GPN(7),
208 .gpio_base = CODEC_GPIO_BASE,
209 .irq_active_high = true,
210 .micd_pol_gpio = CODEC_GPIO_BASE + 4,
212 [2] = 0x10000, /* AIF3TXLRCLK */
213 [3] = 0x4, /* OPCLK */
217 static struct s3c64xx_spi_csinfo wm5102_spi_csinfo = {
218 .line = S3C64XX_GPN(5),
221 static struct spi_board_info wm5102_spi_devs[] = {
223 .modalias = "wm5102",
224 .max_speed_hz = 10 * 1000 * 1000,
228 .irq = GLENFARCLAS_PMIC_IRQ_BASE +
230 .controller_data = &wm5102_spi_csinfo,
231 .platform_data = &wm5102_pdata,
235 static const struct i2c_board_info wm6230_i2c_devs[] = {
236 { I2C_BOARD_INFO("wm9081", 0x6c),
237 .platform_data = &wm9081_pdata, },
240 static __devinitdata const struct {
243 const struct i2c_board_info *i2c_devs;
245 const struct spi_board_info *spi_devs;
248 { .id = 0x01, .name = "1250-EV1 Springbank" },
249 { .id = 0x02, .name = "1251-EV1 Jura" },
250 { .id = 0x03, .name = "1252-EV1 Glenlivet" },
251 { .id = 0x06, .name = "WM8997-6721-CS96-EV1 Lapraoig" },
252 { .id = 0x07, .name = "WM5110-6271 Deanston" },
253 { .id = 0x08, .name = "WM8903-6102 Tamdhu" },
254 { .id = 0x09, .name = "WM1811A-6305 Adelphi" },
255 { .id = 0x0a, .name = "WM8996-6272 Blackadder" },
256 { .id = 0x0b, .name = "WM8994-6235 Benromach" },
257 { .id = 0x11, .name = "6249-EV2 Glenfarclas", },
258 { .id = 0x14, .name = "6271-EV1 Lochnagar" },
259 { .id = 0x15, .name = "6320-EV1 Bells",
260 .i2c_devs = wm6230_i2c_devs,
261 .num_i2c_devs = ARRAY_SIZE(wm6230_i2c_devs) },
262 { .id = 0x21, .name = "1275-EV1 Mortlach" },
263 { .id = 0x25, .name = "1274-EV1 Glencadam" },
264 { .id = 0x31, .name = "1253-EV1 Tomatin",
265 .spi_devs = wm1253_devs, .num_spi_devs = ARRAY_SIZE(wm1253_devs) },
266 { .id = 0x32, .name = "XXXX-EV1 Caol Illa" },
267 { .id = 0x33, .name = "XXXX-EV1 Oban" },
268 { .id = 0x34, .name = "WM0010-6320-CS42 Balblair",
269 .spi_devs = balblair_devs,
270 .num_spi_devs = ARRAY_SIZE(balblair_devs) },
271 { .id = 0x39, .name = "1254-EV1 Dallas Dhu",
272 .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
273 { .id = 0x3a, .name = "1259-EV1 Tobermory",
274 .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
275 { .id = 0x3b, .name = "1255-EV1 Kilchoman",
276 .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs) },
277 { .id = 0x3c, .name = "1273-EV1 Longmorn" },
278 { .id = 0x3d, .name = "1277-EV1 Littlemill",
279 .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs) },
280 { .id = 0x3e, .name = "WM5102-6271-EV1-CS127 Amrut",
281 .spi_devs = wm5102_spi_devs,
282 .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs) },
285 static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
286 const struct i2c_device_id *i2c_id)
288 int ret, i, j, id, rev;
290 ret = i2c_smbus_read_byte_data(i2c, 0);
292 dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
296 id = (ret & 0xfe) >> 2;
298 for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
299 if (id == gf_mods[i].id)
302 if (i < ARRAY_SIZE(gf_mods)) {
303 dev_info(&i2c->dev, "%s revision %d\n",
304 gf_mods[i].name, rev + 1);
306 for (j = 0; j < gf_mods[i].num_i2c_devs; j++) {
307 if (!i2c_new_device(i2c->adapter,
308 &(gf_mods[i].i2c_devs[j])))
310 "Failed to register dev: %d\n", ret);
313 spi_register_board_info(gf_mods[i].spi_devs,
314 gf_mods[i].num_spi_devs);
316 dev_warn(&i2c->dev, "Unknown module ID 0x%x revision %d\n",
323 static const struct i2c_device_id wlf_gf_module_id[] = {
324 { "wlf-gf-module", 0 },
328 static struct i2c_driver wlf_gf_module_driver = {
330 .name = "wlf-gf-module",
331 .owner = THIS_MODULE,
333 .probe = wlf_gf_module_probe,
334 .id_table = wlf_gf_module_id,
337 static int __init wlf_gf_module_register(void)
339 return i2c_add_driver(&wlf_gf_module_driver);
341 module_init(wlf_gf_module_register);