TAS2562 driver original release
[tas256xsw-android/tas2562-android-driver.git] / tas2562-misc.c
1 /*
2 ** =============================================================================
3 ** Copyright (c) 2016  Texas Instruments Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify it under
6 ** the terms of the GNU General Public License as published by the Free Software
7 ** Foundation; version 2.
8 **
9 ** This program is distributed in the hope that it will be useful, but WITHOUT
10 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 ** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 ** File:
13 **     tas2562-misc.c
14 **
15 ** Description:
16 **     misc driver for Texas Instruments TAS2562 High Performance 4W Smart Amplifier
17 **
18 ** =============================================================================
19 */
21 #define DEBUG
22 #include <linux/module.h>
23 #include <linux/moduleparam.h>
24 #include <linux/init.h>
25 #include <linux/delay.h>
26 #include <linux/pm.h>
27 #include <linux/i2c.h>
28 #include <linux/gpio.h>
29 #include <linux/regulator/consumer.h>
30 #include <linux/firmware.h>
31 #include <linux/regmap.h>
32 #include <linux/of.h>
33 #include <linux/of_gpio.h>
34 #include <linux/slab.h>
35 #include <linux/syscalls.h>
36 #include <linux/fcntl.h>
37 #include <linux/miscdevice.h>
38 #include <linux/uaccess.h>
40 #include "tas2562.h"
41 #include "tas2562-misc.h"
42 #include <linux/dma-mapping.h>
44 static int g_logEnable = 1;
45 static struct tas2562_priv *g_tas2562;
47 static int tas2562_file_open(struct inode *inode, struct file *file)
48 {
49         struct tas2562_priv *pTAS2562 = g_tas2562;
51         if (!try_module_get(THIS_MODULE))
52                 return -ENODEV;
54         file->private_data = (void *)pTAS2562;
56         if (g_logEnable)
57                 dev_info(pTAS2562->dev, "%s\n", __func__);
58         return 0;
59 }
61 static int tas2562_file_release(struct inode *inode, struct file *file)
62 {
63         struct tas2562_priv *pTAS2562 = (struct tas2562_priv *)file->private_data;
65         if (g_logEnable)
66                 dev_info(pTAS2562->dev, "%s\n", __func__);
68         file->private_data = (void *)NULL;
69         module_put(THIS_MODULE);
71         return 0;
72 }
74 static ssize_t tas2562_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
75 {
76         struct tas2562_priv *pTAS2562 = (struct tas2562_priv *)file->private_data;
77         int ret = 0;
78         unsigned int nValue = 0;
79         unsigned char value = 0;
80         unsigned char *p_kBuf = NULL;
82         mutex_lock(&pTAS2562->file_lock);
84         switch (pTAS2562->mnDBGCmd) {
85         case TIAUDIO_CMD_REG_READ:
86         {
87                 if (g_logEnable)
88                         dev_info(pTAS2562->dev,
89                                 "TIAUDIO_CMD_REG_READ: current_reg = 0x%x, count=%d\n",
90                                 pTAS2562->mnCurrentReg, (int)count);
91                 if (count == 1) {
92                         ret = pTAS2562->read(pTAS2562, pTAS2562->mnCurrentReg, &nValue);
93                         if (ret < 0) {
94                                 dev_err(pTAS2562->dev, "dev read fail %d\n", ret);
95                                 break;
96                         }
98                         value = (u8)nValue;
99                         if (g_logEnable)
100                                 dev_info(pTAS2562->dev, "TIAUDIO_CMD_REG_READ: nValue=0x%x, value=0x%x\n",
101                                         nValue, value);
102                         ret = copy_to_user(buf, &value, 1);
103                         if (ret != 0) {
104                                 /* Failed to copy all the data, exit */
105                                 dev_err(pTAS2562->dev, "copy to user fail %d\n", ret);
106                         }
107                 } else if (count > 1) {
108                         p_kBuf = kzalloc(count, GFP_KERNEL);
109                         if (p_kBuf != NULL) {
110                                 ret = pTAS2562->bulk_read(pTAS2562, pTAS2562->mnCurrentReg, p_kBuf, count);
111                                 if (ret < 0) {
112                                         dev_err(pTAS2562->dev, "dev bulk read fail %d\n", ret);
113                                 } else {
114                                         ret = copy_to_user(buf, p_kBuf, count);
115                                         if (ret != 0) {
116                                                 /* Failed to copy all the data, exit */
117                                                 dev_err(pTAS2562->dev, "copy to user fail %d\n", ret);
118                                         }
119                                 }
121                                 kfree(p_kBuf);
122                         } else {
123                                 dev_err(pTAS2562->dev, "read no mem\n");
124                         }
125                 }
126         }
127         break;
128         }
129         pTAS2562->mnDBGCmd = 0;
131         mutex_unlock(&pTAS2562->file_lock);
132         return count;
135 static ssize_t tas2562_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
137         struct tas2562_priv *pTAS2562 = (struct tas2562_priv *)file->private_data;
138         int ret = 0;
139         unsigned char *p_kBuf = NULL;
140         unsigned int reg = 0;
141         unsigned int len = 0;
143         mutex_lock(&pTAS2562->file_lock);
145         p_kBuf = kzalloc(count, GFP_KERNEL);
146         if (p_kBuf == NULL) {
147                 dev_err(pTAS2562->dev, "write no mem\n");
148                 goto err;
149         }
151         ret = copy_from_user(p_kBuf, buf, count);
152         if (ret != 0) {
153                 dev_err(pTAS2562->dev, "copy_from_user failed.\n");
154                 goto err;
155         }
157         pTAS2562->mnDBGCmd = p_kBuf[0];
158         switch (pTAS2562->mnDBGCmd) {
159         case TIAUDIO_CMD_REG_WITE:
160         if (count > 5) {
161                 reg = ((unsigned int)p_kBuf[1] << 24) +
162                         ((unsigned int)p_kBuf[2] << 16) +
163                         ((unsigned int)p_kBuf[3] << 8) +
164                         (unsigned int)p_kBuf[4];
165                 len = count - 5;
166                 if (len == 1) {
167                         ret = pTAS2562->write(pTAS2562, reg, p_kBuf[5]);
168                         if (g_logEnable)
169                                 dev_info(pTAS2562->dev,
170                                         "TIAUDIO_CMD_REG_WITE, Reg=0x%x, Val=0x%x\n",
171                                         reg, p_kBuf[5]);
172                 } else {
173                         ret = pTAS2562->bulk_write(pTAS2562, reg, &p_kBuf[5], len);
174                 }
175         } else {
176                 dev_err(pTAS2562->dev, "%s, write len fail, count=%d.\n",
177                         __func__, (int)count);
178         }
179         pTAS2562->mnDBGCmd = 0;
180         break;
182         case TIAUDIO_CMD_REG_READ:
183         if (count == 5) {
184                 pTAS2562->mnCurrentReg = ((unsigned int)p_kBuf[1] << 24) +
185                         ((unsigned int)p_kBuf[2] << 16) +
186                         ((unsigned int)p_kBuf[3] << 8) +
187                         (unsigned int)p_kBuf[4];
188                 if (g_logEnable) {
189                         dev_info(pTAS2562->dev,
190                                 "TIAUDIO_CMD_REG_READ, whole=0x%x\n",
191                                 pTAS2562->mnCurrentReg);
192                 }
193         } else {
194                 dev_err(pTAS2562->dev, "read len fail.\n");
195         }
196         break;
197         }
198 err:
199         if (p_kBuf != NULL)
200                 kfree(p_kBuf);
202         mutex_unlock(&pTAS2562->file_lock);
204         return count;
207 static const struct file_operations fops = {
208         .owner = THIS_MODULE,
209         .read = tas2562_file_read,
210         .write = tas2562_file_write,
211         .unlocked_ioctl = NULL,
212         .open = tas2562_file_open,
213         .release = tas2562_file_release,
214 };
216 #define MODULE_NAME     "tas2562"
217 static struct miscdevice tas2562_misc = {
218         .minor = MISC_DYNAMIC_MINOR,
219         .name = MODULE_NAME,
220         .fops = &fops,
221 };
223 int tas2562_register_misc(struct tas2562_priv *pTAS2562)
225         int ret = 0;
227         g_tas2562 = pTAS2562;
228         ret = misc_register(&tas2562_misc);
229         if (ret) {
230                 dev_err(pTAS2562->dev, "TAS2562 misc fail: %d\n", ret);
231         }
233         dev_info(pTAS2562->dev, "%s, leave\n", __func__);
235         return ret;
238 int tas2562_deregister_misc(struct tas2562_priv *pTAS2562)
240         misc_deregister(&tas2562_misc);
241         return 0;
244 MODULE_AUTHOR("Texas Instruments Inc.");
245 MODULE_DESCRIPTION("TAS2562 Misc Smart Amplifier driver");
246 MODULE_LICENSE("GPL v2");