Remove some unused code
[tas256xsw-android/tas2563-android-driver.git] / tiload.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 **
13 ** File:
14 **     tiload.c
15 **
16 ** Description:
17 **     utility for TAS2563 Android in-system tuning
18 **
19 ** =============================================================================
20 */
23 #include <linux/module.h>
24 #include <linux/moduleparam.h>
25 #include <linux/init.h>
26 #include <linux/kernel.h>
27 #include <linux/fs.h>
28 #include <linux/types.h>
29 #include <linux/kdev_t.h>
30 #include <linux/cdev.h>
31 #include <linux/device.h>
32 #include <linux/io.h>
33 #include <linux/delay.h>
34 #include <linux/i2c.h>
35 #include <linux/platform_device.h>
36 #include <linux/uaccess.h>
38 #include "tiload.h"
40 /* enable debug prints in the driver */
41 //#define DEBUG
43 static struct cdev *tiload_cdev;
44 static int tiload_major; /* Dynamic allocation of Mjr No. */
45 static int tiload_opened; /* Dynamic allocation of Mjr No. */
46 static struct tas2563_priv *g_TAS2563;
47 struct class *tiload_class;
48 static unsigned int magic_num;
50 static char gPage;
51 static char gBook;
52 /******************************** Debug section *****************************/
55 /*----------------------------------------------------------------------------
56  * Function : tiload_open
57  *
58  * Purpose  : open method for tiload programming interface
59  *----------------------------------------------------------------------------
60  */
61 static int tiload_open(struct inode *in, struct file *filp)
62 {
63         struct tas2563_priv *pTAS2563 = g_TAS2563;
65         dev_info(pTAS2563->dev, "%s\n", __func__);
67         if (tiload_opened) {
68                 dev_info(pTAS2563->dev, "%s device is already opened\n", "tiload");
69                 return -EINVAL;
70         }
71         filp->private_data = (void *)pTAS2563;
72         tiload_opened++;
73         return 0;
74 }
76 /*----------------------------------------------------------------------------
77  * Function : tiload_release
78  *
79  * Purpose  : close method for tiload programming interface
80  *----------------------------------------------------------------------------
81  */
82 static int tiload_release(struct inode *in, struct file *filp)
83 {
84         struct tas2563_priv *pTAS2563 = (struct tas2563_priv *)filp->private_data;
86         dev_info(pTAS2563->dev, "%s\n", __func__);
87         filp->private_data = NULL;
88         tiload_opened--;
89         return 0;
90 }
92 #define MAX_LENGTH 128
93 /*----------------------------------------------------------------------------
94  * Function : tiload_read
95  *
96  * Purpose  : read from codec
97  *----------------------------------------------------------------------------
98  */
99 static ssize_t tiload_read(struct file *filp, char __user *buf,
100         size_t count, loff_t *offset)
102         struct tas2563_priv *pTAS2563 = (struct tas2563_priv *)filp->private_data;
103         static char rd_data[MAX_LENGTH + 1];
104         unsigned int nCompositeRegister = 0, Value = 0;
105         char reg_addr;
106         size_t size;
107         int ret = 0;
108 #ifdef DEBUG
109         /* int i; */
110 #endif
112         dev_info(pTAS2563->dev, "%s\n", __func__);
113         if (count > MAX_LENGTH) {
114                 dev_err(pTAS2563->dev, "Max %d bytes can be read\n", MAX_LENGTH);
115                 return -EINVAL;
116         }
118         /* copy register address from user space  */
119         size = copy_from_user(&reg_addr, buf, 1);
120         if (size != 0) {
121                 dev_err(pTAS2563->dev, "read: copy_from_user failure\n");
122                 return -EINVAL;
123         }
125         size = count;
127         nCompositeRegister = BPR_REG(gBook, gPage, reg_addr);
128         dev_dbg(pTAS2563->dev, " nCompositeRegister:0x%x  gBook:0x%x gpage:0x%x \n", nCompositeRegister, gBook, gPage);
129         if (count == 1) {
130                 ret =
131                         pTAS2563->read(pTAS2563, 0x80000000 | nCompositeRegister, &Value);
132                 if (ret >= 0)
133                         rd_data[0] = (char) Value;
134         } else if (count > 1) {
135                 ret =
136                         pTAS2563->bulk_read(pTAS2563, 0x80000000 | nCompositeRegister,
137                         rd_data, size);
138         }
139         if (ret < 0)
140                 dev_err(pTAS2563->dev, "%s, %d, ret=%d, count=%zu error happen!\n",
141                         __func__, __LINE__, ret, count);
143 #ifdef DEBUG
144         dev_info(pTAS2563->dev, "read size = %d, reg_addr= %x , count = %d\n",
145                 (int) size, reg_addr, (int) count);
146 /*      for (i = 0; i < (int) size; i++) {
147 *               dev_dbg(pTAS2563->dev, "rd_data[%d]=%x\n", i, rd_data[i]);
148 *       }
149 */
150 #endif
151         if (size != count)
152                 dev_err(pTAS2563->dev, "read %d registers from the codec\n", (int) size);
154         if (copy_to_user(buf, rd_data, size) != 0) {
155                 dev_err(pTAS2563->dev, "copy_to_user failed\n");
156                 return -EINVAL;
157         }
159         return size;
162 /*
163  *----------------------------------------------------------------------------
164  * Function : tiload_write
165  *
166  * Purpose  : write to codec
167  *----------------------------------------------------------------------------
168  */
169 static ssize_t tiload_write(struct file *filp, const char __user *buf,
170         size_t count, loff_t *offset)
172         struct tas2563_priv *pTAS2563 = (struct tas2563_priv *)filp->private_data;
173         static char wr_data[MAX_LENGTH + 1];
174         char *pData = wr_data;
175         size_t size;
176         unsigned int nCompositeRegister = 0;
177         unsigned int nRegister;
178         int ret = 0;
179 #ifdef DEBUG
180         /* int i; */
181 #endif
182         dev_info(pTAS2563->dev, "%s\n", __func__);
184         if (count > MAX_LENGTH) {
185                 dev_err(pTAS2563->dev, "Max %d bytes can be read\n", MAX_LENGTH);
186                 return -EINVAL;
187         }
189         /* copy buffer from user space  */
190         size = copy_from_user(wr_data, buf, count);
191         if (size != 0) {
192                 dev_err(pTAS2563->dev, "copy_from_user failure %d\n", (int) size);
193                 return -EINVAL;
194         }
195 #ifdef DEBUG
196         dev_info(pTAS2563->dev, "write size = %zu\n", count);
197 /* for (i = 0; i < (int) count; i++) {
198 *               dev_info(pTAS2563->dev, "wr_data[%d]=%x\n", i, wr_data[i]);
199 *       }
200 */
201 #endif
202         nRegister = wr_data[0];
203         size = count;
204         if ((nRegister == 127) && (gPage == 0)) {
205                 gBook = wr_data[1];
206                 return size;
207         }
209         if (nRegister == 0) {
210                 gPage = wr_data[1];
211                 pData++;
212                 count--;
213         }
215         nCompositeRegister = BPR_REG(gBook, gPage, nRegister);
216         if (count == 2) {
217                 ret =
218                         pTAS2563->write(pTAS2563, 0x80000000 | nCompositeRegister,
219                         pData[1]);
220         } else if (count > 2) {
221                 ret =
222                         pTAS2563->bulk_write(pTAS2563, 0x80000000 | nCompositeRegister,
223                         &pData[1], count - 1);
224         }
226         if (ret < 0)
227                 dev_err(pTAS2563->dev, "%s, %d, ret=%d, count=%zu, ERROR Happen\n", __func__,
228                         __LINE__, ret, count);
230         return size;
233 static void tiload_route_IO(struct tas2563_priv *pTAS2563, unsigned int bLock)
235         if (bLock)
236                 pTAS2563->write(pTAS2563, 0xAFFEAFFE, 0xBABEBABE);
237         else
238                 pTAS2563->write(pTAS2563, 0xBABEBABE, 0xAFFEAFFE);
241 static long tiload_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
243         struct tas2563_priv *pTAS2563 = (struct tas2563_priv *)filp->private_data;
244         long num = 0;
245         void __user *argp = (void __user *) arg;
246         int val;
247         struct BPR bpr;
249         dev_info(pTAS2563->dev, "%s, cmd=0x%x\n", __func__, cmd);
250 /*  if (_IOC_TYPE(cmd) != TILOAD_IOC_MAGIC)
251  *      return -ENOTTY;
252  */
254         switch (cmd) {
255         case TILOAD_IOMAGICNUM_GET:
256                 num = copy_to_user(argp, &magic_num, sizeof(int));
257                 break;
258         case TILOAD_IOMAGICNUM_SET:
259                 num = copy_from_user(&magic_num, argp, sizeof(int));
260                 dev_info(pTAS2563->dev, "TILOAD_IOMAGICNUM_SET\n");
261                 tiload_route_IO(pTAS2563, magic_num);
262                 break;
263         case TILOAD_BPR_READ:
264                 break;
265         case TILOAD_BPR_WRITE:
266                 num = copy_from_user(&bpr, argp, sizeof(struct BPR));
267                 dev_info(pTAS2563->dev, "TILOAD_BPR_WRITE: 0x%02X, 0x%02X, 0x%02X\n\r", bpr.nBook,
268                         bpr.nPage, bpr.nRegister);
269                 break;
270         case TILOAD_IOCTL_SET_CHL:
271                 break;
273         case TILOAD_IOCTL_SET_CONFIG:
274                 num = copy_from_user(&val, argp, sizeof(val));
275                 pTAS2563->set_config(pTAS2563, val);
276                 break;
277         case TILOAD_IOCTL_SET_CALIBRATION:
278                 num = copy_from_user(&val, argp, sizeof(val));
279                 pTAS2563->set_calibration(pTAS2563, val);
280                 break;
282         default:
283                 break;
284         }
285         return num;
288 #ifdef CONFIG_COMPAT
289 static long tiload_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
291         struct tas2563_priv *pTAS2563 = (struct tas2563_priv *)filp->private_data;
292         long nResult = 0;
294         switch (cmd) {
295         case TILOAD_COMPAT_IOMAGICNUM_GET:
296                 dev_info(pTAS2563->dev, "%s, TILOAD_COMPAT_IOMAGICNUM_GET=0x%x\n",
297                         __func__, cmd);
298                 nResult = tiload_ioctl(filp, TILOAD_IOMAGICNUM_GET,
299                         (unsigned long) compat_ptr(arg));
300                 break;
302         case TILOAD_COMPAT_IOMAGICNUM_SET:
303                 dev_info(pTAS2563->dev, "%s, TILOAD_COMPAT_IOMAGICNUM_SET=0x%x\n",
304                         __func__, cmd);
305                 nResult = tiload_ioctl(filp, TILOAD_IOMAGICNUM_SET,
306                         (unsigned long) compat_ptr(arg));
307                 break;
309         case TILOAD_COMPAT_BPR_READ:
310                 dev_info(pTAS2563->dev, "%s, TILOAD_COMPAT_BPR_READ=0x%x\n",
311                         __func__, cmd);
312                 nResult = tiload_ioctl(filp, TILOAD_BPR_READ,
313                         (unsigned long) compat_ptr(arg));
314                 break;
316         case TILOAD_COMPAT_BPR_WRITE:
317                 dev_info(pTAS2563->dev, "%s, TILOAD_COMPAT_BPR_WRITE=0x%x\n",
318                         __func__, cmd);
319                 nResult = tiload_ioctl(filp, TILOAD_BPR_WRITE,
320                         (unsigned long) compat_ptr(arg));
321                 break;
323         case TILOAD_COMPAT_IOCTL_SET_CHL:
324                 dev_info(pTAS2563->dev, "%s, TILOAD_COMPAT_IOCTL_SET_CHL=0x%x\n",
325                         __func__, cmd);
326                 nResult = tiload_ioctl(filp, TILOAD_IOCTL_SET_CHL,
327                         (unsigned long) compat_ptr(arg));
328                 break;
330         case TILOAD_COMPAT_IOCTL_SET_CONFIG:
331                 dev_info(pTAS2563->dev, "%s, TILOAD_COMPAT_IOCTL_SET_CONFIG=0x%x\n",
332                         __func__, cmd);
333                 nResult = tiload_ioctl(filp, TILOAD_IOCTL_SET_CONFIG,
334                         (unsigned long) compat_ptr(arg));
335                 break;
337         case TILOAD_COMPAT_IOCTL_SET_CALIBRATION:
338                 dev_info(pTAS2563->dev, "%s, TILOAD_COMPAT_IOCTL_SET_CALIBRATION=0x%x\n",
339                         __func__, cmd);
340                 nResult = tiload_ioctl(filp, TILOAD_IOCTL_SET_CALIBRATION,
341                         (unsigned long) compat_ptr(arg));
342                 break;
344         default:
345                 dev_err(pTAS2563->dev, "%s, unsupport compat ioctl=0x%x\n",
346                         __func__, cmd);
347                 break;
348         }
350         return nResult;
352 #endif
354 /*********** File operations structure for tiload *************/
355 static const struct file_operations tiload_fops = {
356         .owner = THIS_MODULE,
357         .open = tiload_open,
358         .release = tiload_release,
359         .read = tiload_read,
360         .write = tiload_write,
361         .unlocked_ioctl = tiload_ioctl,
362 #ifdef CONFIG_COMPAT
363         .compat_ioctl = tiload_compat_ioctl,
364 #endif
365 };
367 /*----------------------------------------------------------------------------
368  * Function : tiload_driver_init
369  *
370  * Purpose  : Register a char driver for dynamic tiload programming
371  *----------------------------------------------------------------------------
372  */
373 int tiload_driver_init(struct tas2563_priv *pTAS2563)
375         int result;
376         dev_t dev = MKDEV(tiload_major, 0);
378         g_TAS2563 = pTAS2563;
380         dev_info(pTAS2563->dev, "%s\n", __func__);
382         result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
383         if (result < 0) {
384                 dev_err(pTAS2563->dev, "cannot allocate major number %d\n", tiload_major);
385                 return result;
386         }
387         tiload_class = class_create(THIS_MODULE, DEVICE_NAME);
388         tiload_major = MAJOR(dev);
389         dev_info(pTAS2563->dev, "allocated Major Number: %d\n", tiload_major);
391         tiload_cdev = cdev_alloc();
392         cdev_init(tiload_cdev, &tiload_fops);
393         tiload_cdev->owner = THIS_MODULE;
394         tiload_cdev->ops = &tiload_fops;
396         if (device_create(tiload_class, NULL, dev, NULL, "tiload_node") == NULL)
397                 dev_err(pTAS2563->dev, "Device creation failed\n");
399         if (cdev_add(tiload_cdev, dev, 1) < 0) {
400                 dev_err(pTAS2563->dev, "tiload_driver: cdev_add failed\n");
401                 unregister_chrdev_region(dev, 1);
402                 tiload_cdev = NULL;
403                 return 1;
404         }
405         dev_info(pTAS2563->dev, "Registered TiLoad driver, Major number: %d\n", tiload_major);
406         /* class_device_create(tiload_class, NULL, dev, NULL, DEVICE_NAME, 0); */
407         return 0;
410 MODULE_AUTHOR("Texas Instruments Inc.");
411 MODULE_DESCRIPTION("Utility for TAS2563 Android in-system tuning");
412 MODULE_LICENSE("GPL v2");