ALSA: hda - targa and targa-2ch fix
[pandora-kernel.git] / sound / pci / hda / hda_hwdep.c
1 /*
2  * HWDEP Interface for HD-audio codec
3  *
4  * Copyright (c) 2007 Takashi Iwai <tiwai@suse.de>
5  *
6  *  This driver is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This driver is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19  */
20
21 #include <linux/init.h>
22 #include <linux/slab.h>
23 #include <linux/pci.h>
24 #include <linux/compat.h>
25 #include <linux/mutex.h>
26 #include <linux/ctype.h>
27 #include <sound/core.h>
28 #include "hda_codec.h"
29 #include "hda_local.h"
30 #include <sound/hda_hwdep.h>
31 #include <sound/minors.h>
32
33 /* hint string pair */
34 struct hda_hint {
35         const char *key;
36         const char *val;        /* contained in the same alloc as key */
37 };
38
39 /*
40  * write/read an out-of-bound verb
41  */
42 static int verb_write_ioctl(struct hda_codec *codec,
43                             struct hda_verb_ioctl __user *arg)
44 {
45         u32 verb, res;
46
47         if (get_user(verb, &arg->verb))
48                 return -EFAULT;
49         res = snd_hda_codec_read(codec, verb >> 24, 0,
50                                  (verb >> 8) & 0xffff, verb & 0xff);
51         if (put_user(res, &arg->res))
52                 return -EFAULT;
53         return 0;
54 }
55
56 static int get_wcap_ioctl(struct hda_codec *codec,
57                           struct hda_verb_ioctl __user *arg)
58 {
59         u32 verb, res;
60         
61         if (get_user(verb, &arg->verb))
62                 return -EFAULT;
63         res = get_wcaps(codec, verb >> 24);
64         if (put_user(res, &arg->res))
65                 return -EFAULT;
66         return 0;
67 }
68
69
70 /*
71  */
72 static int hda_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
73                            unsigned int cmd, unsigned long arg)
74 {
75         struct hda_codec *codec = hw->private_data;
76         void __user *argp = (void __user *)arg;
77
78         switch (cmd) {
79         case HDA_IOCTL_PVERSION:
80                 return put_user(HDA_HWDEP_VERSION, (int __user *)argp);
81         case HDA_IOCTL_VERB_WRITE:
82                 return verb_write_ioctl(codec, argp);
83         case HDA_IOCTL_GET_WCAP:
84                 return get_wcap_ioctl(codec, argp);
85         }
86         return -ENOIOCTLCMD;
87 }
88
89 #ifdef CONFIG_COMPAT
90 static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file,
91                                   unsigned int cmd, unsigned long arg)
92 {
93         return hda_hwdep_ioctl(hw, file, cmd, (unsigned long)compat_ptr(arg));
94 }
95 #endif
96
97 static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
98 {
99 #ifndef CONFIG_SND_DEBUG_VERBOSE
100         if (!capable(CAP_SYS_RAWIO))
101                 return -EACCES;
102 #endif
103         return 0;
104 }
105
106 static void clear_hwdep_elements(struct hda_codec *codec)
107 {
108         int i;
109
110         /* clear init verbs */
111         snd_array_free(&codec->init_verbs);
112         /* clear hints */
113         for (i = 0; i < codec->hints.used; i++) {
114                 struct hda_hint *hint = snd_array_elem(&codec->hints, i);
115                 kfree(hint->key); /* we don't need to free hint->val */
116         }
117         snd_array_free(&codec->hints);
118         snd_array_free(&codec->user_pins);
119 }
120
121 static void hwdep_free(struct snd_hwdep *hwdep)
122 {
123         clear_hwdep_elements(hwdep->private_data);
124 }
125
126 int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
127 {
128         char hwname[16];
129         struct snd_hwdep *hwdep;
130         int err;
131
132         sprintf(hwname, "HDA Codec %d", codec->addr);
133         err = snd_hwdep_new(codec->bus->card, hwname, codec->addr, &hwdep);
134         if (err < 0)
135                 return err;
136         codec->hwdep = hwdep;
137         sprintf(hwdep->name, "HDA Codec %d", codec->addr);
138         hwdep->iface = SNDRV_HWDEP_IFACE_HDA;
139         hwdep->private_data = codec;
140         hwdep->private_free = hwdep_free;
141         hwdep->exclusive = 1;
142
143         hwdep->ops.open = hda_hwdep_open;
144         hwdep->ops.ioctl = hda_hwdep_ioctl;
145 #ifdef CONFIG_COMPAT
146         hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
147 #endif
148
149         snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
150         snd_array_init(&codec->hints, sizeof(struct hda_hint), 32);
151         snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
152
153         return 0;
154 }
155
156 #ifdef CONFIG_SND_HDA_RECONFIG
157
158 /*
159  * sysfs interface
160  */
161
162 static int clear_codec(struct hda_codec *codec)
163 {
164         int err;
165
166         err = snd_hda_codec_reset(codec);
167         if (err < 0) {
168                 snd_printk(KERN_ERR "The codec is being used, can't free.\n");
169                 return err;
170         }
171         clear_hwdep_elements(codec);
172         return 0;
173 }
174
175 static int reconfig_codec(struct hda_codec *codec)
176 {
177         int err;
178
179         snd_hda_power_up(codec);
180         snd_printk(KERN_INFO "hda-codec: reconfiguring\n");
181         err = snd_hda_codec_reset(codec);
182         if (err < 0) {
183                 snd_printk(KERN_ERR
184                            "The codec is being used, can't reconfigure.\n");
185                 goto error;
186         }
187         err = snd_hda_codec_configure(codec);
188         if (err < 0)
189                 goto error;
190         /* rebuild PCMs */
191         err = snd_hda_codec_build_pcms(codec);
192         if (err < 0)
193                 goto error;
194         /* rebuild mixers */
195         err = snd_hda_codec_build_controls(codec);
196         if (err < 0)
197                 goto error;
198         err = snd_card_register(codec->bus->card);
199  error:
200         snd_hda_power_down(codec);
201         return err;
202 }
203
204 /*
205  * allocate a string at most len chars, and remove the trailing EOL
206  */
207 static char *kstrndup_noeol(const char *src, size_t len)
208 {
209         char *s = kstrndup(src, len, GFP_KERNEL);
210         char *p;
211         if (!s)
212                 return NULL;
213         p = strchr(s, '\n');
214         if (p)
215                 *p = 0;
216         return s;
217 }
218
219 #define CODEC_INFO_SHOW(type)                                   \
220 static ssize_t type##_show(struct device *dev,                  \
221                            struct device_attribute *attr,       \
222                            char *buf)                           \
223 {                                                               \
224         struct snd_hwdep *hwdep = dev_get_drvdata(dev);         \
225         struct hda_codec *codec = hwdep->private_data;          \
226         return sprintf(buf, "0x%x\n", codec->type);             \
227 }
228
229 #define CODEC_INFO_STR_SHOW(type)                               \
230 static ssize_t type##_show(struct device *dev,                  \
231                              struct device_attribute *attr,     \
232                                         char *buf)              \
233 {                                                               \
234         struct snd_hwdep *hwdep = dev_get_drvdata(dev);         \
235         struct hda_codec *codec = hwdep->private_data;          \
236         return sprintf(buf, "%s\n",                             \
237                        codec->type ? codec->type : "");         \
238 }
239
240 CODEC_INFO_SHOW(vendor_id);
241 CODEC_INFO_SHOW(subsystem_id);
242 CODEC_INFO_SHOW(revision_id);
243 CODEC_INFO_SHOW(afg);
244 CODEC_INFO_SHOW(mfg);
245 CODEC_INFO_STR_SHOW(vendor_name);
246 CODEC_INFO_STR_SHOW(chip_name);
247 CODEC_INFO_STR_SHOW(modelname);
248
249 #define CODEC_INFO_STORE(type)                                  \
250 static ssize_t type##_store(struct device *dev,                 \
251                             struct device_attribute *attr,      \
252                             const char *buf, size_t count)      \
253 {                                                               \
254         struct snd_hwdep *hwdep = dev_get_drvdata(dev);         \
255         struct hda_codec *codec = hwdep->private_data;          \
256         char *after;                                            \
257         codec->type = simple_strtoul(buf, &after, 0);           \
258         return count;                                           \
259 }
260
261 #define CODEC_INFO_STR_STORE(type)                              \
262 static ssize_t type##_store(struct device *dev,                 \
263                             struct device_attribute *attr,      \
264                             const char *buf, size_t count)      \
265 {                                                               \
266         struct snd_hwdep *hwdep = dev_get_drvdata(dev);         \
267         struct hda_codec *codec = hwdep->private_data;          \
268         char *s = kstrndup_noeol(buf, 64);                      \
269         if (!s)                                                 \
270                 return -ENOMEM;                                 \
271         kfree(codec->type);                                     \
272         codec->type = s;                                        \
273         return count;                                           \
274 }
275
276 CODEC_INFO_STORE(vendor_id);
277 CODEC_INFO_STORE(subsystem_id);
278 CODEC_INFO_STORE(revision_id);
279 CODEC_INFO_STR_STORE(vendor_name);
280 CODEC_INFO_STR_STORE(chip_name);
281 CODEC_INFO_STR_STORE(modelname);
282
283 #define CODEC_ACTION_STORE(type)                                \
284 static ssize_t type##_store(struct device *dev,                 \
285                             struct device_attribute *attr,      \
286                             const char *buf, size_t count)      \
287 {                                                               \
288         struct snd_hwdep *hwdep = dev_get_drvdata(dev);         \
289         struct hda_codec *codec = hwdep->private_data;          \
290         int err = 0;                                            \
291         if (*buf)                                               \
292                 err = type##_codec(codec);                      \
293         return err < 0 ? err : count;                           \
294 }
295
296 CODEC_ACTION_STORE(reconfig);
297 CODEC_ACTION_STORE(clear);
298
299 static ssize_t init_verbs_show(struct device *dev,
300                                struct device_attribute *attr,
301                                char *buf)
302 {
303         struct snd_hwdep *hwdep = dev_get_drvdata(dev);
304         struct hda_codec *codec = hwdep->private_data;
305         int i, len = 0;
306         for (i = 0; i < codec->init_verbs.used; i++) {
307                 struct hda_verb *v = snd_array_elem(&codec->init_verbs, i);
308                 len += snprintf(buf + len, PAGE_SIZE - len,
309                                 "0x%02x 0x%03x 0x%04x\n",
310                                 v->nid, v->verb, v->param);
311         }
312         return len;
313 }
314
315 static ssize_t init_verbs_store(struct device *dev,
316                                 struct device_attribute *attr,
317                                 const char *buf, size_t count)
318 {
319         struct snd_hwdep *hwdep = dev_get_drvdata(dev);
320         struct hda_codec *codec = hwdep->private_data;
321         struct hda_verb *v;
322         int nid, verb, param;
323
324         if (sscanf(buf, "%i %i %i", &nid, &verb, &param) != 3)
325                 return -EINVAL;
326         if (!nid || !verb)
327                 return -EINVAL;
328         v = snd_array_new(&codec->init_verbs);
329         if (!v)
330                 return -ENOMEM;
331         v->nid = nid;
332         v->verb = verb;
333         v->param = param;
334         return count;
335 }
336
337 static ssize_t hints_show(struct device *dev,
338                           struct device_attribute *attr,
339                           char *buf)
340 {
341         struct snd_hwdep *hwdep = dev_get_drvdata(dev);
342         struct hda_codec *codec = hwdep->private_data;
343         int i, len = 0;
344         for (i = 0; i < codec->hints.used; i++) {
345                 struct hda_hint *hint = snd_array_elem(&codec->hints, i);
346                 len += snprintf(buf + len, PAGE_SIZE - len,
347                                 "%s = %s\n", hint->key, hint->val);
348         }
349         return len;
350 }
351
352 static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
353 {
354         int i;
355
356         for (i = 0; i < codec->hints.used; i++) {
357                 struct hda_hint *hint = snd_array_elem(&codec->hints, i);
358                 if (!strcmp(hint->key, key))
359                         return hint;
360         }
361         return NULL;
362 }
363
364 static void remove_trail_spaces(char *str)
365 {
366         char *p;
367         if (!*str)
368                 return;
369         p = str + strlen(str) - 1;
370         for (; isspace(*p); p--) {
371                 *p = 0;
372                 if (p == str)
373                         return;
374         }
375 }
376
377 #define MAX_HINTS       1024
378
379 static ssize_t hints_store(struct device *dev,
380                            struct device_attribute *attr,
381                            const char *buf, size_t count)
382 {
383         struct snd_hwdep *hwdep = dev_get_drvdata(dev);
384         struct hda_codec *codec = hwdep->private_data;
385         char *key, *val;
386         struct hda_hint *hint;
387
388         while (isspace(*buf))
389                 buf++;
390         if (!*buf || *buf == '#' || *buf == '\n')
391                 return count;
392         if (*buf == '=')
393                 return -EINVAL;
394         key = kstrndup_noeol(buf, 1024);
395         if (!key)
396                 return -ENOMEM;
397         /* extract key and val */
398         val = strchr(key, '=');
399         if (!val) {
400                 kfree(key);
401                 return -EINVAL;
402         }
403         *val++ = 0;
404         while (isspace(*val))
405                 val++;
406         remove_trail_spaces(key);
407         remove_trail_spaces(val);
408         hint = get_hint(codec, key);
409         if (hint) {
410                 /* replace */
411                 kfree(hint->key);
412                 hint->key = key;
413                 hint->val = val;
414                 return count;
415         }
416         /* allocate a new hint entry */
417         if (codec->hints.used >= MAX_HINTS)
418                 hint = NULL;
419         else
420                 hint = snd_array_new(&codec->hints);
421         if (!hint) {
422                 kfree(key);
423                 return -ENOMEM;
424         }
425         hint->key = key;
426         hint->val = val;
427         return count;
428 }
429
430 static ssize_t pin_configs_show(struct hda_codec *codec,
431                                 struct snd_array *list,
432                                 char *buf)
433 {
434         int i, len = 0;
435         for (i = 0; i < list->used; i++) {
436                 struct hda_pincfg *pin = snd_array_elem(list, i);
437                 len += sprintf(buf + len, "0x%02x 0x%08x\n",
438                                pin->nid, pin->cfg);
439         }
440         return len;
441 }
442
443 static ssize_t init_pin_configs_show(struct device *dev,
444                                      struct device_attribute *attr,
445                                      char *buf)
446 {
447         struct snd_hwdep *hwdep = dev_get_drvdata(dev);
448         struct hda_codec *codec = hwdep->private_data;
449         return pin_configs_show(codec, &codec->init_pins, buf);
450 }
451
452 static ssize_t user_pin_configs_show(struct device *dev,
453                                      struct device_attribute *attr,
454                                      char *buf)
455 {
456         struct snd_hwdep *hwdep = dev_get_drvdata(dev);
457         struct hda_codec *codec = hwdep->private_data;
458         return pin_configs_show(codec, &codec->user_pins, buf);
459 }
460
461 static ssize_t driver_pin_configs_show(struct device *dev,
462                                        struct device_attribute *attr,
463                                        char *buf)
464 {
465         struct snd_hwdep *hwdep = dev_get_drvdata(dev);
466         struct hda_codec *codec = hwdep->private_data;
467         return pin_configs_show(codec, &codec->driver_pins, buf);
468 }
469
470 #define MAX_PIN_CONFIGS         32
471
472 static ssize_t user_pin_configs_store(struct device *dev,
473                                       struct device_attribute *attr,
474                                       const char *buf, size_t count)
475 {
476         struct snd_hwdep *hwdep = dev_get_drvdata(dev);
477         struct hda_codec *codec = hwdep->private_data;
478         int nid, cfg;
479         int err;
480
481         if (sscanf(buf, "%i %i", &nid, &cfg) != 2)
482                 return -EINVAL;
483         if (!nid)
484                 return -EINVAL;
485         err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg);
486         if (err < 0)
487                 return err;
488         return count;
489 }
490
491 #define CODEC_ATTR_RW(type) \
492         __ATTR(type, 0644, type##_show, type##_store)
493 #define CODEC_ATTR_RO(type) \
494         __ATTR_RO(type)
495 #define CODEC_ATTR_WO(type) \
496         __ATTR(type, 0200, NULL, type##_store)
497
498 static struct device_attribute codec_attrs[] = {
499         CODEC_ATTR_RW(vendor_id),
500         CODEC_ATTR_RW(subsystem_id),
501         CODEC_ATTR_RW(revision_id),
502         CODEC_ATTR_RO(afg),
503         CODEC_ATTR_RO(mfg),
504         CODEC_ATTR_RW(vendor_name),
505         CODEC_ATTR_RW(chip_name),
506         CODEC_ATTR_RW(modelname),
507         CODEC_ATTR_RW(init_verbs),
508         CODEC_ATTR_RW(hints),
509         CODEC_ATTR_RO(init_pin_configs),
510         CODEC_ATTR_RW(user_pin_configs),
511         CODEC_ATTR_RO(driver_pin_configs),
512         CODEC_ATTR_WO(reconfig),
513         CODEC_ATTR_WO(clear),
514 };
515
516 /*
517  * create sysfs files on hwdep directory
518  */
519 int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
520 {
521         struct snd_hwdep *hwdep = codec->hwdep;
522         int i;
523
524         for (i = 0; i < ARRAY_SIZE(codec_attrs); i++)
525                 snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card,
526                                           hwdep->device, &codec_attrs[i]);
527         return 0;
528 }
529
530 /*
531  * Look for hint string
532  */
533 const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
534 {
535         struct hda_hint *hint = get_hint(codec, key);
536         return hint ? hint->val : NULL;
537 }
538 EXPORT_SYMBOL_HDA(snd_hda_get_hint);
539
540 int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
541 {
542         const char *p = snd_hda_get_hint(codec, key);
543         if (!p || !*p)
544                 return -ENOENT;
545         switch (toupper(*p)) {
546         case 'T': /* true */
547         case 'Y': /* yes */
548         case '1':
549                 return 1;
550         }
551         return 0;
552 }
553 EXPORT_SYMBOL_HDA(snd_hda_get_bool_hint);
554
555 #endif /* CONFIG_SND_HDA_RECONFIG */