Merge branch 'for-2.6.31' into for-2.6.32
[pandora-kernel.git] / sound / soc / codecs / max9877.c
1 /*
2  * max9877.c  --  amp driver for max9877
3  *
4  * Copyright (C) 2009 Samsung Electronics Co.Ltd
5  * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6  *
7  *  This program is free software; you can redistribute  it and/or modify it
8  *  under  the terms of  the GNU General  Public License as published by the
9  *  Free Software Foundation;  either version 2 of the  License, or (at your
10  *  option) any later version.
11  *
12  */
13
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/i2c.h>
17 #include <sound/soc.h>
18 #include <sound/tlv.h>
19
20 #include "max9877.h"
21
22 static struct i2c_client *i2c;
23
24 static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 };
25
26 static void max9877_write_regs(void)
27 {
28         if (i2c_master_send(i2c, max9877_regs, 5) != 5)
29                 dev_err(&i2c->dev, "i2c write failed\n");
30 }
31
32 static int max9877_get_reg(struct snd_kcontrol *kcontrol,
33                 struct snd_ctl_elem_value *ucontrol)
34 {
35         struct soc_mixer_control *mc =
36                 (struct soc_mixer_control *)kcontrol->private_value;
37         unsigned int reg = mc->reg;
38         unsigned int shift = mc->shift;
39         unsigned int mask = mc->max;
40         unsigned int invert = mc->invert;
41
42         ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
43
44         if (invert)
45                 ucontrol->value.integer.value[0] =
46                         mask - ucontrol->value.integer.value[0];
47
48         return 0;
49 }
50
51 static int max9877_set_reg(struct snd_kcontrol *kcontrol,
52                 struct snd_ctl_elem_value *ucontrol)
53 {
54         struct soc_mixer_control *mc =
55                 (struct soc_mixer_control *)kcontrol->private_value;
56         unsigned int reg = mc->reg;
57         unsigned int shift = mc->shift;
58         unsigned int mask = mc->max;
59         unsigned int invert = mc->invert;
60         unsigned int val = (ucontrol->value.integer.value[0] & mask);
61
62         if (invert)
63                 val = mask - val;
64
65         if (((max9877_regs[reg] >> shift) & mask) == val)
66                 return 0;
67
68         max9877_regs[reg] &= ~(mask << shift);
69         max9877_regs[reg] |= val << shift;
70         max9877_write_regs();
71
72         return 1;
73 }
74
75 static int max9877_get_2reg(struct snd_kcontrol *kcontrol,
76                 struct snd_ctl_elem_value *ucontrol)
77 {
78         struct soc_mixer_control *mc =
79                 (struct soc_mixer_control *)kcontrol->private_value;
80         unsigned int reg = mc->reg;
81         unsigned int reg2 = mc->rreg;
82         unsigned int shift = mc->shift;
83         unsigned int mask = mc->max;
84
85         ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
86         ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask;
87
88         return 0;
89 }
90
91 static int max9877_set_2reg(struct snd_kcontrol *kcontrol,
92                 struct snd_ctl_elem_value *ucontrol)
93 {
94         struct soc_mixer_control *mc =
95                 (struct soc_mixer_control *)kcontrol->private_value;
96         unsigned int reg = mc->reg;
97         unsigned int reg2 = mc->rreg;
98         unsigned int shift = mc->shift;
99         unsigned int mask = mc->max;
100         unsigned int val = (ucontrol->value.integer.value[0] & mask);
101         unsigned int val2 = (ucontrol->value.integer.value[1] & mask);
102         unsigned int change = 1;
103
104         if (((max9877_regs[reg] >> shift) & mask) == val)
105                 change = 0;
106
107         if (((max9877_regs[reg2] >> shift) & mask) == val2)
108                 change = 0;
109
110         if (change) {
111                 max9877_regs[reg] &= ~(mask << shift);
112                 max9877_regs[reg] |= val << shift;
113                 max9877_regs[reg2] &= ~(mask << shift);
114                 max9877_regs[reg2] |= val2 << shift;
115                 max9877_write_regs();
116         }
117
118         return change;
119 }
120
121 static int max9877_get_out_mode(struct snd_kcontrol *kcontrol,
122                 struct snd_ctl_elem_value *ucontrol)
123 {
124         u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK;
125
126         if (value)
127                 value -= 1;
128
129         ucontrol->value.integer.value[0] = value;
130         return 0;
131 }
132
133 static int max9877_set_out_mode(struct snd_kcontrol *kcontrol,
134                 struct snd_ctl_elem_value *ucontrol)
135 {
136         u8 value = ucontrol->value.integer.value[0];
137
138         if (value)
139                 value += 1;
140
141         if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value)
142                 return 0;
143
144         max9877_regs[MAX9877_OUTPUT_MODE] |= value;
145         max9877_write_regs();
146         return 1;
147 }
148
149 static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol,
150                 struct snd_ctl_elem_value *ucontrol)
151 {
152         u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK);
153
154         value = value >> MAX9877_OSC_OFFSET;
155
156         ucontrol->value.integer.value[0] = value;
157         return 0;
158 }
159
160 static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol,
161                 struct snd_ctl_elem_value *ucontrol)
162 {
163         u8 value = ucontrol->value.integer.value[0];
164
165         value = value << MAX9877_OSC_OFFSET;
166         if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value)
167                 return 0;
168
169         max9877_regs[MAX9877_OUTPUT_MODE] |= value;
170         max9877_write_regs();
171         return 1;
172 }
173
174 static const unsigned int max9877_pgain_tlv[] = {
175         TLV_DB_RANGE_HEAD(2),
176         0, 1, TLV_DB_SCALE_ITEM(0, 900, 0),
177         2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0),
178 };
179
180 static const unsigned int max9877_output_tlv[] = {
181         TLV_DB_RANGE_HEAD(4),
182         0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1),
183         8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0),
184         16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0),
185         24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0),
186 };
187
188 static const char *max9877_out_mode[] = {
189         "INA -> SPK",
190         "INA -> HP",
191         "INA -> SPK and HP",
192         "INB -> SPK",
193         "INB -> HP",
194         "INB -> SPK and HP",
195         "INA + INB -> SPK",
196         "INA + INB -> HP",
197         "INA + INB -> SPK and HP",
198 };
199
200 static const char *max9877_osc_mode[] = {
201         "1176KHz",
202         "1100KHz",
203         "700KHz",
204 };
205
206 static const struct soc_enum max9877_enum[] = {
207         SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode),
208         SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode),
209 };
210
211 static const struct snd_kcontrol_new max9877_controls[] = {
212         SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume",
213                         MAX9877_INPUT_MODE, 0, 2, 0,
214                         max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
215         SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume",
216                         MAX9877_INPUT_MODE, 2, 2, 0,
217                         max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
218         SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume",
219                         MAX9877_SPK_VOLUME, 0, 31, 0,
220                         max9877_get_reg, max9877_set_reg, max9877_output_tlv),
221         SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume",
222                         MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0,
223                         max9877_get_2reg, max9877_set_2reg, max9877_output_tlv),
224         SOC_SINGLE_EXT("MAX9877 INB Stereo Switch",
225                         MAX9877_INPUT_MODE, 4, 1, 1,
226                         max9877_get_reg, max9877_set_reg),
227         SOC_SINGLE_EXT("MAX9877 INA Stereo Switch",
228                         MAX9877_INPUT_MODE, 5, 1, 1,
229                         max9877_get_reg, max9877_set_reg),
230         SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch",
231                         MAX9877_INPUT_MODE, 6, 1, 0,
232                         max9877_get_reg, max9877_set_reg),
233         SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch",
234                         MAX9877_OUTPUT_MODE, 6, 1, 0,
235                         max9877_get_reg, max9877_set_reg),
236         SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch",
237                         MAX9877_OUTPUT_MODE, 7, 1, 1,
238                         max9877_get_reg, max9877_set_reg),
239         SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0],
240                         max9877_get_out_mode, max9877_set_out_mode),
241         SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1],
242                         max9877_get_osc_mode, max9877_set_osc_mode),
243 };
244
245 /* This function is called from ASoC machine driver */
246 int max9877_add_controls(struct snd_soc_codec *codec)
247 {
248         return snd_soc_add_controls(codec, max9877_controls,
249                         ARRAY_SIZE(max9877_controls));
250 }
251 EXPORT_SYMBOL_GPL(max9877_add_controls);
252
253 static int __devinit max9877_i2c_probe(struct i2c_client *client,
254                 const struct i2c_device_id *id)
255 {
256         i2c = client;
257
258         max9877_write_regs();
259
260         return 0;
261 }
262
263 static __devexit int max9877_i2c_remove(struct i2c_client *client)
264 {
265         i2c = NULL;
266
267         return 0;
268 }
269
270 static const struct i2c_device_id max9877_i2c_id[] = {
271         { "max9877", 0 },
272         { }
273 };
274 MODULE_DEVICE_TABLE(i2c, max9877_i2c_id);
275
276 static struct i2c_driver max9877_i2c_driver = {
277         .driver = {
278                 .name = "max9877",
279                 .owner = THIS_MODULE,
280         },
281         .probe = max9877_i2c_probe,
282         .remove = __devexit_p(max9877_i2c_remove),
283         .id_table = max9877_i2c_id,
284 };
285
286 static int __init max9877_init(void)
287 {
288         return i2c_add_driver(&max9877_i2c_driver);
289 }
290 module_init(max9877_init);
291
292 static void __exit max9877_exit(void)
293 {
294         i2c_del_driver(&max9877_i2c_driver);
295 }
296 module_exit(max9877_exit);
297
298 MODULE_DESCRIPTION("ASoC MAX9877 amp driver");
299 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
300 MODULE_LICENSE("GPL");