2 * rt56xx_ioctl.h -- RT56XX ALSA SoC audio driver IO control
4 * Copyright 2012 Realtek Microelectronics
5 * Author: Bard <bardliao@realtek.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/spi/spi.h>
13 #include <sound/soc.h>
14 #include "rt56xx_ioctl.h"
16 static struct rt56xx_ops rt56xx_ioctl_ops;
18 #if defined(CONFIG_SND_HWDEP) || defined(CONFIG_SND_HWDEP_MODULE)
19 #define RT_CE_CODEC_HWDEP_NAME "rt56xx hwdep "
20 static int rt56xx_hwdep_open(struct snd_hwdep *hw, struct file *file)
22 struct snd_soc_codec *codec = hw->private_data;
23 dev_dbg(codec->dev, "%s()\n", __func__);
27 static int rt56xx_hwdep_release(struct snd_hwdep *hw, struct file *file)
29 struct snd_soc_codec *codec = hw->private_data;
30 dev_dbg(codec->dev, "%s()\n", __func__);
34 static int rt56xx_hwdep_ioctl_common(struct snd_hwdep *hw,
35 struct file *file, unsigned int cmd, unsigned long arg)
37 struct snd_soc_codec *codec = hw->private_data;
38 struct rt56xx_cmd __user *_rt56xx = (struct rt56xx_cmd *)arg;
39 struct rt56xx_cmd rt56xx;
42 if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx))) {
43 dev_err(codec->dev,"copy_from_user faild\n");
46 dev_dbg(codec->dev, "%s(): rt56xx.number=%zu, cmd=%d\n",
47 __func__, rt56xx.number, cmd);
48 buf = kmalloc(sizeof(*buf) * rt56xx.number, GFP_KERNEL);
51 if (copy_from_user(buf, rt56xx.buf, sizeof(*buf) * rt56xx.number)) {
56 case RT_READ_CODEC_REG_IOCTL:
57 for (p = buf; p < buf + rt56xx.number / 2; p++) {
58 *(p + rt56xx.number / 2) = snd_soc_read(codec, *p);
60 if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
64 case RT_WRITE_CODEC_REG_IOCTL:
65 for (p = buf; p < buf + rt56xx.number / 2; p++)
66 snd_soc_write(codec, *p, *(p + rt56xx.number / 2));
69 case RT_READ_CODEC_INDEX_IOCTL:
70 if (NULL == rt56xx_ioctl_ops.index_read)
73 for (p = buf; p < buf + rt56xx.number / 2; p++)
74 *(p+rt56xx.number/2) = rt56xx_ioctl_ops.index_read(
76 if (copy_to_user(rt56xx.buf, buf,
77 sizeof(*buf) * rt56xx.number))
81 case RT_WRITE_CODEC_INDEX_IOCTL:
82 if (NULL == rt56xx_ioctl_ops.index_write)
85 for (p = buf; p < buf + rt56xx.number / 2; p++)
86 rt56xx_ioctl_ops.index_write(codec, *p,
87 *(p+rt56xx.number/2));
91 if (NULL == rt56xx_ioctl_ops.ioctl_common)
94 rt56xx_ioctl_ops.ioctl_common(hw, file, cmd, arg);
106 static int rt56xx_codec_dump_reg(struct snd_hwdep *hw,
107 struct file *file, unsigned long arg)
109 struct snd_soc_codec *codec = hw->private_data;
110 struct rt56xx_cmd __user *_rt56xx =(struct rt56xx_cmd *)arg;
111 struct rt56xx_cmd rt56xx;
112 int i, *buf, number = codec->driver->reg_cache_size;
114 dev_dbg(codec->dev, "enter %s, number = %d\n", __func__, number);
115 if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx)))
118 buf = kmalloc(sizeof(*buf) * number, GFP_KERNEL);
122 for (i = 0; i < number/2; i++) {
124 buf[i + number / 2] = codec->read(codec, buf[i]);
126 if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * i))
128 rt56xx.number = number;
129 if (copy_to_user(_rt56xx, &rt56xx, sizeof(rt56xx)))
139 static int rt56xx_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
140 unsigned int cmd, unsigned long arg)
143 case RT_READ_ALL_CODEC_REG_IOCTL:
144 return rt56xx_codec_dump_reg(hw, file, arg);
147 return rt56xx_hwdep_ioctl_common(hw, file, cmd, arg);
153 int rt56xx_ce_init_hwdep(struct snd_soc_codec *codec)
155 struct snd_hwdep *hw;
156 struct snd_card *card = codec->card->snd_card;
159 dev_dbg(codec->dev, "enter %s\n", __func__);
161 if ((err = snd_hwdep_new(card, RT_CE_CODEC_HWDEP_NAME, 0, &hw)) < 0)
164 strcpy(hw->name, RT_CE_CODEC_HWDEP_NAME);
165 hw->private_data = codec;
166 hw->ops.open = rt56xx_hwdep_open;
167 hw->ops.release = rt56xx_hwdep_release;
168 hw->ops.ioctl = rt56xx_hwdep_ioctl;
172 EXPORT_SYMBOL_GPL(rt56xx_ce_init_hwdep);
175 struct rt56xx_ops *rt56xx_get_ioctl_ops(void)
177 return &rt56xx_ioctl_ops;
179 EXPORT_SYMBOL_GPL(rt56xx_get_ioctl_ops);