ARM64: firefly: Add rk3399-firefly board support
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / aic326x_tiload.c
1 /*
2  * linux/sound/soc/codecs/AIC3262_tiload.c
3  *
4  *
5  * Copyright (C) 2010 Texas Instruments, Inc.
6  *
7  *
8  *
9  * This package is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * History:
18  *
19  * Rev 0.1       Tiload support                 TI         16-09-2010
20  *
21  *          The Tiload programming support is added to AIC3262.
22  *
23  */
24
25 #include <linux/module.h>
26 #include <linux/moduleparam.h>
27 #include <linux/init.h>
28 #include <linux/kernel.h>
29 #include <linux/fs.h>
30 #include <linux/types.h>
31 #include <linux/kdev_t.h>
32 #include <linux/cdev.h>
33 #include <linux/device.h>
34 #include <asm/io.h>
35 #include <linux/delay.h>
36 #include <linux/i2c.h>
37 #include <linux/platform_device.h>
38 #include <sound/soc.h>
39 #include <sound/control.h>
40 #include <linux/switch.h>
41 #include <sound/jack.h>
42 #include <linux/irq.h>
43 #include <linux/interrupt.h>
44
45 #include <linux/mfd/tlv320aic3262-core.h>
46 #include "tlv320aic326x.h"
47 #include "aic326x_tiload.h"
48
49 /* enable debug prints in the driver */
50 //#define DEBUG
51 #undef DEBUG
52
53 #ifdef DEBUG
54 #define dprintk(x...)   printk(x)
55 #else
56 #define dprintk(x...)
57 #endif
58
59 #ifdef AIC3262_TiLoad
60
61 /* Function prototypes */
62 #ifdef REG_DUMP_aic3262
63 static void aic3262_dump_page(struct i2c_client *i2c, u8 page);
64 #endif
65
66 /* externs */
67 /*extern int aic3262_change_page(struct snd_soc_codec *codec, u8 new_page);
68 extern int aic3262_change_book(struct snd_soc_codec *codec, u8 new_book);*/
69 extern int aic3262_write(struct snd_soc_codec *codec, unsigned int reg,
70                          unsigned int value);
71
72 int aic3262_driver_init(struct snd_soc_codec *codec);
73 /************** Dynamic aic3262 driver, TI LOAD support  ***************/
74
75 static struct cdev *aic3262_cdev;
76 static aic326x_reg_union aic_reg;
77 static int aic3262_major = 0;   /* Dynamic allocation of Mjr No. */
78 static int aic3262_opened = 0;  /* Dynamic allocation of Mjr No. */
79 static struct snd_soc_codec *aic3262_codec;
80 struct class *tiload_class;
81 static unsigned int magic_num = 0xE0;
82
83 /******************************** Debug section *****************************/
84
85 #ifdef REG_DUMP_aic3262
86 /*
87  *----------------------------------------------------------------------------
88  * Function : aic3262_dump_page
89  * Purpose  : Read and display one codec register page, for debugging purpose
90  *----------------------------------------------------------------------------
91  */
92 static void aic3262_dump_page(struct i2c_client *i2c, u8 page)
93 {
94         int i;
95         u8 data;
96         u8 test_page_array[8];
97
98         dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
99 //      aic3262_change_page(codec, page);
100
101         data = 0x0;
102
103         i2c_master_send(i2c, data, 1);
104         i2c_master_recv(i2c, test_page_array, 8);
105
106         dprintk("\n------- aic3262 PAGE %d DUMP --------\n", page);
107         for (i = 0; i < 8; i++) {
108                 printk(" [ %d ] = 0x%x\n", i, test_page_array[i]);
109         }
110 }
111 #endif
112
113 /*
114  *----------------------------------------------------------------------------
115  * Function : tiload_open
116  *
117  * Purpose  : open method for aic3262-tiload programming interface
118  *----------------------------------------------------------------------------
119  */
120 static int tiload_open(struct inode *in, struct file *filp)
121 {
122         dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
123         if (aic3262_opened) {
124                 dprintk("%s device is already opened\n", "aic3262");
125                 dprintk("%s: only one instance of driver is allowed\n",
126                        "aic3262");
127                 return -1;
128         }
129         aic3262_opened++;
130         return 0;
131 }
132
133 /*
134  *----------------------------------------------------------------------------
135  * Function : tiload_release
136  *
137  * Purpose  : close method for aic3262_tilaod programming interface
138  *----------------------------------------------------------------------------
139  */
140 static int tiload_release(struct inode *in, struct file *filp)
141 {
142         dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
143         aic3262_opened--;
144         return 0;
145 }
146
147 /*
148  *----------------------------------------------------------------------------
149  * Function : tiload_read
150  *
151  * Purpose  : read method for mini dsp programming interface
152  *----------------------------------------------------------------------------
153  */
154 static ssize_t tiload_read(struct file *file, char __user * buf,
155                            size_t count, loff_t * offset)
156 {
157         static char rd_data[8];
158         char reg_addr;
159         size_t size;
160         #ifdef DEBUG
161         int i;
162         #endif
163         struct aic3262 *control = aic3262_codec->control_data;
164
165         dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
166         if (count > 128) {
167                 printk("Max 128 bytes can be read\n");
168                 count = 128;
169         }
170
171         /* copy register address from user space  */
172         size = copy_from_user(&reg_addr, buf, 1);
173         if (size != 0) {
174                 printk("read: copy_from_user failure\n");
175                 return -1;
176         }
177         /* Send the address to device thats is to be read */
178         
179         aic_reg.aic326x_register.offset = reg_addr;
180         size = aic3262_bulk_read(control, aic_reg.aic326x_register_int, count, rd_data);
181 /*
182         if (i2c_master_send(i2c, &reg_addr, 1) != 1) {
183                 dprintk("Can not write register address\n");
184                 return -1;
185         }
186         size = i2c_master_recv(i2c, rd_data, count);
187 */
188 #ifdef DEBUG
189         printk(KERN_ERR "read size = %d, reg_addr= %x , count = %d\n",
190                (int)size, reg_addr, (int)count);
191         for (i = 0; i < (int)size; i++) {
192                 dprintk(KERN_ERR "rd_data[%d]=%x\n", i, rd_data[i]);
193         }
194 #endif
195         if (size != count) {
196                 dprintk("read %d registers from the codec\n", size);
197         }
198
199         if (copy_to_user(buf, rd_data, size) != 0) {
200                 dprintk("copy_to_user failed\n");
201                 return -1;
202         }
203
204         return size;
205 }
206
207 /*
208  *----------------------------------------------------------------------------
209  * Function : tiload_write
210  *
211  * Purpose  : write method for aic3262_tiload programming interface
212  *----------------------------------------------------------------------------
213  */
214 static ssize_t tiload_write(struct file *file, const char __user * buf,
215                             size_t count, loff_t * offset)
216 {
217         static char wr_data[8];
218         u8 pg_no;
219         unsigned int reg;
220         #ifdef DEBUG
221         int i;
222         #endif
223         struct aic3262 *control = aic3262_codec->control_data;
224
225         dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
226         /* copy buffer from user space  */
227         if (copy_from_user(wr_data, buf, count)) {
228                 printk("copy_from_user failure\n");
229                 return -1;
230         }
231 #ifdef DEBUG
232         dprintk(KERN_ERR "write size = %d\n", (int)count);
233         for (i = 0; i < (int)count; i++) {
234                 printk(KERN_INFO "\nwr_data[%d]=%x\n", i, wr_data[i]);
235         }
236 #endif
237         if(wr_data[0] == 0)
238         {
239                 //change of page seen, but will only be registered              
240                 aic_reg.aic326x_register.page = wr_data[1];
241                 return count;// trick
242                 
243         }       
244         else
245         if(wr_data[0] == 127 /* && aic_reg.aic326x_register.page == 0*/) 
246         {       
247                 //change of book seen, but will not be sent for I2C write
248                 aic_reg.aic326x_register.book = wr_data[1];
249                 return count; //trick
250                  
251         }
252         else
253         { 
254                 aic_reg.aic326x_register.offset = wr_data[0];   
255                 aic3262_bulk_write(control, aic_reg.aic326x_register_int, count - 1,&wr_data[1]); 
256                 return count;
257         }
258 /*      if (wr_data[0] == 0) {
259                 aic3262_change_page(aic3262_codec, wr_data[1]);
260                 return count;
261         }
262         pg_no = aic3262_private->page_no;
263
264         if ((wr_data[0] == 127) && (pg_no == 0)) {
265                 aic3262_change_book(aic3262_codec, wr_data[1]);
266                 return count;
267         }
268         return i2c_master_send(i2c, wr_data, count);*/
269         
270 }
271
272 static long tiload_ioctl(struct file *filp,
273                         unsigned int cmd, unsigned long arg)
274 {
275         long num = 0;
276         void __user *argp = (void __user *)arg;
277         if (_IOC_TYPE(cmd) != aic3262_IOC_MAGIC)
278                 return -ENOTTY;
279
280         dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
281         switch (cmd) {
282         case aic3262_IOMAGICNUM_GET:
283                 num = copy_to_user(argp, &magic_num, sizeof(int));
284                 break;
285         case aic3262_IOMAGICNUM_SET:
286                 num = copy_from_user(&magic_num, argp, sizeof(int));
287                 break;
288         }
289         return num;
290 }
291
292 /*********** File operations structure for aic3262-tiload programming *************/
293 static struct file_operations aic3262_fops = {
294         .owner = THIS_MODULE,
295         .open = tiload_open,
296         .release = tiload_release,
297         .read = tiload_read,
298         .write = tiload_write,
299         .unlocked_ioctl = tiload_ioctl,
300 };
301
302 /*
303  *----------------------------------------------------------------------------
304  * Function : aic3262_driver_init
305  *
306  * Purpose  : Register a char driver for dynamic aic3262-tiload programming
307  *----------------------------------------------------------------------------
308  */
309 int aic3262_driver_init(struct snd_soc_codec *codec)
310 {
311         int result;
312
313         dev_t dev = MKDEV(aic3262_major, 0);
314         dprintk("TiLoad DRIVER : %s\n", __FUNCTION__);
315         aic3262_codec = codec;
316
317         dprintk("allocating dynamic major number\n");
318
319         result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
320         if (result < 0) {
321                 dprintk("cannot allocate major number %d\n", aic3262_major);
322                 return result;
323         }
324
325         tiload_class = class_create(THIS_MODULE, DEVICE_NAME);
326         aic3262_major = MAJOR(dev);
327         dprintk("allocated Major Number: %d\n", aic3262_major);
328
329         aic3262_cdev = cdev_alloc();
330         cdev_init(aic3262_cdev, &aic3262_fops);
331         aic3262_cdev->owner = THIS_MODULE;
332         aic3262_cdev->ops = &aic3262_fops;
333
334         aic_reg.aic326x_register.page = 0;
335         aic_reg.aic326x_register.book = 0;
336
337         if (cdev_add(aic3262_cdev, dev, 1) < 0) {
338                 dprintk("aic3262_driver: cdev_add failed \n");
339                 unregister_chrdev_region(dev, 1);
340                 aic3262_cdev = NULL;
341                 return 1;
342         }
343         dprintk("Registered aic3262 TiLoad driver, Major number: %d \n",
344                aic3262_major);
345         //class_device_create(tiload_class, NULL, dev, NULL, DEVICE_NAME, 0);
346         return 0;
347 }
348
349 #endif