Merge branch 'torvalds/master'
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / cxdebug.c
1 /*
2 * ALSA SoC CX20709 Channel codec driver
3 *
4 * Copyright:   (C) 2009/2010 Conexant Systems
5 *
6 *
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.
10 *
11
12 *      
13 *************************************************************************
14 *  Modified Date:  12/01/11
15 *  File Version:   2.26.35.11
16 *************************************************************************
17 */
18
19 #include <linux/module.h>
20 #include <linux/moduleparam.h>
21 #include <linux/module.h>       /* Specifically, a module */
22 #include <linux/fs.h>
23 #include <asm/uaccess.h>        /* for get_user and put_user */
24 //#include <sound/core.h>
25 //#include <sound/pcm.h>
26 //#include <sound/pcm_params.h>
27 #include <sound/soc.h>
28 //#include <sound/soc-dapm.h>
29 #include <linux/gpio.h>
30 #include <linux/slab.h>
31
32 //#define DEBUG 1
33
34 #include "cxdebug.h"
35
36 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
37 #include <linux/i2c.h>
38 #endif 
39
40 #if defined(CONFIG_SPI_MASTER)
41 #include <linux/spi/spi.h>
42 #endif 
43
44
45 /*
46
47  * Is the device open right now? Used to prevent
48  * concurent access into the same device 
49  */
50 static int Device_Open = 0;
51 extern int CX_AUDDRV_VERSION;
52 struct snd_soc_codec *g_codec = NULL;
53
54 /* 
55  * This is called whenever a process attempts to open the device file 
56  */
57 static int cxdbg_dev_open(struct inode *inode, struct file *file)
58 {
59 #ifdef DEBUG
60     printk(KERN_INFO "cxdbg_dev: device_open(%p)\n", file);
61 #endif
62
63     /* 
64     * We don't want to talk to two processes at the same time 
65     */
66     if (Device_Open)
67         return -EBUSY;
68
69     Device_Open++;
70     /*
71     * Initialize the message 
72     */
73
74    // try_module_get(THIS_MODULE);
75     return 0;
76 }
77
78 /* 
79  * This is called whenever a process attempts to open the device file 
80  */
81 static int cxdbg_dev_release(struct inode *inode, struct file *file)
82 {
83 #ifdef DEBUG
84     printk(KERN_INFO "cxdbg_dev: device_release(%p)\n", file);
85 #endif
86
87
88     Device_Open--;
89     /*
90     * Initialize the message 
91     */
92
93     return 0;
94 }
95 static int codec_reg_write(struct CXDBG_IODATA  *reg)
96 {
97     int errno = 0;
98
99     BUG_ON(!g_codec);
100     BUG_ON(!g_codec->hw_write);
101
102     if(g_codec&& g_codec->hw_write)
103     {
104         if( g_codec->hw_write(g_codec,(char*)reg->data,reg->len) 
105             !=reg->len)
106         {
107             errno =-EIO;
108             printk(KERN_ERR "cxdbg_dev: codec_reg_write failed\n");
109         }
110     }
111     else
112     {
113         errno = -EBUSY;
114         printk(KERN_ERR "cxdbg_dev: codec_reg_write failed, device is not ready.\n");
115     }
116     return errno;
117 }
118
119 static unsigned int codec_reg_read(struct CXDBG_IODATA  *reg)
120 {
121     int errno = 0;
122     unsigned int regaddr;
123     unsigned int data;
124
125
126     BUG_ON(!g_codec);
127     BUG_ON(!g_codec->hw_read);
128
129     if (reg-> len == 2)
130     {
131         regaddr = (((unsigned int)reg->data[0])<<8) + reg->data[1];
132     }
133     else if (reg->len == 1)
134     {
135         regaddr = (unsigned int)reg->data[0];
136     }
137     else 
138     {
139        printk(KERN_ERR "cxdbg_dev: codec_reg_read failed, invalid parameter.\n");
140        return -EINVAL;
141     }
142     memset(reg,0,sizeof(*reg));
143     if(g_codec && g_codec->hw_read)
144     {
145         data = g_codec->hw_read(g_codec,regaddr);
146         reg->data[0] = data & 0xFF;
147         reg->len     = 1;
148     }
149     else
150     {
151         errno = -EBUSY;
152         printk(KERN_ERR "cxdbg_dev: codec_reg_read failed, device is not ready.\n");
153     }
154     return errno;
155     return 0;
156 }
157
158 long cxdbg_dev_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
159 {
160     struct CXDBG_IODATA  *reg=NULL ;
161     int __user *ip = (int __user*) arg;
162     long err = -1;
163 #ifdef DEBUG
164     printk(KERN_INFO "cxdbg_dev: ioctl, cmd=0x%02x, arg=0x%02lx\n", cmd, arg);
165 #endif
166     
167     /* 
168     * Switch according to the ioctl called 
169     */
170     switch (cmd) {
171     case CXDBG_IOCTL_REG_SET:
172         reg = (struct CXDBG_IODATA*) kmalloc(sizeof(*reg),GFP_KERNEL);
173         err = copy_from_user((char*) reg, (char*)arg,sizeof(*reg));
174         if(err==0)
175         {
176             codec_reg_write(reg);
177         }
178         break;
179
180     case CXDBG_IOCTL_REG_GET:
181         reg = (struct CXDBG_IODATA*) kmalloc(sizeof(*reg),GFP_KERNEL);
182         err =copy_from_user((char*) reg, (char*)arg,sizeof(*reg));
183         if( err == 0)
184         {
185            codec_reg_read(reg);
186            err = copy_to_user((char*) arg, (char*)reg,sizeof(*reg));
187         }
188         break;
189     case CXDBG_IOCTL_PDRIVER_VERSION:
190         err = put_user(CX_AUDDRV_VERSION,ip);
191         break;  
192     default:
193         err =  -EINVAL;
194     }
195
196     if(reg)
197     {
198         kfree(reg);
199     }
200
201     return err;
202 }
203
204
205 #if defined(_MSC_VER)
206 static const struct file_operations cxdbg_dev_fops =
207 {
208     /*.owner =  */THIS_MODULE,
209     /*.llseek*/NULL,
210     /*.read =           */NULL,
211     /*.write*/ NULL,
212     /*.aio_read*/ NULL,
213     /*.aio_write*/NULL,
214     /*readdir*/NULL,
215     /*.poll*/NULL,
216     /*ioctl*/ NULL /*i2cdev_ioctl*/,
217     /*.unlocked_ioctl*/cxdbg_dev_ioctl,
218     /*.compat_ioctl*/NULL,
219     /*.mmap*/NULL,
220     /*.open*/cxdbg_dev_open,
221     /*.flush*/NULL,
222     /*.release*/NULL,
223     /*.fsync*/NULL,
224     /*.aio_fsync*/NULL,
225     /*.fasync*/NULL,
226     /*.lock*/NULL,
227     /*.sendpage*/NULL,
228 };
229 #else
230 static const struct file_operations cxdbg_dev_fops = {
231     .owner          = THIS_MODULE,
232     .unlocked_ioctl = cxdbg_dev_ioctl,
233     .open           = cxdbg_dev_open,
234     .release        = cxdbg_dev_release,
235 };
236 #endif
237
238
239 /* 
240 * Initialize the module - Register the character device 
241 */
242 int cxdbg_dev_init(struct snd_soc_codec *socdev)
243 {
244     int err;
245     printk(KERN_INFO "cxdbg_dev: entries driver\n");
246
247     g_codec = socdev;
248
249     err = register_chrdev(CXDBG_MAJOR, CXDBG_DEVICE_NAME, &cxdbg_dev_fops);
250     if (err)
251     {
252         printk(KERN_ERR "cxdbg_dev: Driver Initialisation failed\n");
253     }
254     return err;
255 }
256
257 void cxdbg_dev_exit(void)
258 {
259     unregister_chrdev(CXDBG_MAJOR,CXDBG_DEVICE_NAME);
260 }
261
262
263 MODULE_AUTHOR("Simon Ho<simon.ho@conexant.com");
264 MODULE_DESCRIPTION("debug driver");
265 MODULE_LICENSE("GPL");
266