1 #include <linux/module.h> 2 3 #include <linux/compat.h> 4 #include <linux/types.h> 5 #include <linux/errno.h> 6 #include <linux/kernel.h> 7 #include <linux/major.h> 8 #include <linux/slab.h> 9 #include <linux/mm.h> 10 #include <linux/mman.h> 11 #include <linux/vt.h> 12 #include <linux/init.h> 13 #include <linux/linux_logo.h> 14 #include <linux/proc_fs.h> 15 #include <linux/seq_file.h> 16 #include <linux/console.h> 17 #include <linux/kmod.h> 18 #include <linux/err.h> 19 #include <linux/device.h> 20 #include <linux/efi.h> 21 #include <linux/fb.h> 22 #include <linux/delay.h> 23 #include <linux/version.h> 24 #include <linux/kthread.h> 25 #include <linux/poll.h> 26 27 /*Proc based contron intertace*/ 28 #define AUDIO_DEBUG_PROC_DIR "audio" 29 #define AUDIO_DEBUG_PROC_INFO "debuginfo" 30 #define MAX_BUF_WT_LEN 200 //do not bigger than one page size 1024 bytes 31 #define MAX_BUF_RD_LEN 2048 32 33 static struct proc_dir_entry *audio_proc_dir = NULL; 34 static struct proc_dir_entry *audio_proc_dbginfo_file = NULL; 35 36 static struct deca_device *audio_deca_dev=NULL; 37 static struct snd_device *audio_snd_dev=NULL; 38 39 static char *audio_info_buffer = NULL; 40 static __u32 g_dbg_show_en = 0; 41 static __u32 g_dbg_show_interval = 1; 42 static struct mutex audio_dbg_mutex; 43 wait_queue_head_t audio_dbg_wq; 44 static struct task_struct *audio_dbg_show_thread_ptr; 45 46 static char *audio_state(unsigned long state) 47 { 48 char *ret = NULL; 49 switch(state) 50 { 51 case 0: 52 ret="DETACH"; 53 break; 54 case 1: 55 ret="ATTACH"; 56 break; 57 case 2: 58 ret="IDLE"; 59 break; 60 case 4: 61 ret="PLAY"; 62 break; 63 case 8: 64 ret="PAUSE"; 65 break; 66 default: 67 ret="UNKNOWN"; 68 break; 69 } 70 return ret; 71 } 72 static char *audio_sub_state(unsigned long state) 73 { 74 char *ret = NULL; 75 switch(state) 76 { 77 case 0: 78 ret="IDLE"; 79 break; 80 case 1: 81 ret="NORMAL"; 82 break; 83 case 2: 84 ret="NO DATA"; 85 break; 86 case 4: 87 ret="NO BUFF"; 88 break; 89 default: 90 ret="UNKNOWN"; 91 break; 92 } 93 return ret; 94 } 95 static int audio_read_debug_info(char * buffer) 96 { 97 int len = 0; 98 unsigned long len_max = MAX_BUF_RD_LEN - 100; 99 struct audio_dbg_info dbg_info; 100 101 if(!audio_deca_dev || !audio_snd_dev) 102 { 103 return -EUNATCH; 104 } 105 106 if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info))) 107 { 108 len += sprintf(&buffer[len]," desc enable : %s ", (1==dbg_info.snd.ad_en)?"yes":"no"); 109 if (len_max <= len) 110 goto out; 111 112 len += sprintf(&buffer[len],"deca state : %s(%d) ", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state); 113 if (len_max <= len) 114 goto out; 115 116 len += sprintf(&buffer[len],"deca sub state : %s(%d) ", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state); 117 if (len_max <= len) 118 goto out; 119 120 len += sprintf(&buffer[len],"snd state : %s(%d) ", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state); 121 if (len_max <= len) 122 goto out; 123 124 len += sprintf(&buffer[len],"snd sub state : %s(%d) ", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state); 125 if (len_max <= len) 126 goto out; 127 128 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+ "); 129 if (len_max <= len) 130 goto out; 131 len += sprintf(&buffer[len],"|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) | "); 132 if (len_max <= len) 133 goto out; 134 135 /* deca buff info */ 136 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+ "); 137 if (len_max <= len) 138 goto out; 139 len += sprintf(&buffer[len],"|BS |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | | ", 140 (int)((dbg_info.deca.prog_bs_buff_rm*100)/(dbg_info.deca.prog_bs_buff_len)), 141 (unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len, 142 (int)((dbg_info.deca.desc_bs_buff_rm*100)/(dbg_info.deca.desc_bs_buff_len)), 143 (unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len); 144 if (len_max <= len) 145 goto out; 146 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+ "); 147 if (len_max <= len) 148 goto out; 149 len += sprintf(&buffer[len],"|CB |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | | ", 150 (int)((dbg_info.deca.prog_cb_buff_rm*100)/(dbg_info.deca.prog_cb_buff_len)), 151 (unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len, 152 (int)((dbg_info.deca.desc_cb_buff_rm*100)/(dbg_info.deca.desc_cb_buff_len)), 153 (unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len); 154 if (len_max <= len) 155 goto out; 156 157 /* snd buff info */ 158 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+ "); 159 if (len_max <= len) 160 goto out; 161 len += sprintf(&buffer[len],"|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | ", 162 (int)((dbg_info.snd.sync_buff_pcm_rm*100)/(dbg_info.snd.sync_buff_pcm_len)), 163 (unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len, 164 (int)((dbg_info.snd.sync_buff_desc_pcm_rm*100)/(dbg_info.snd.sync_buff_desc_pcm_len)), 165 (unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len, 166 (int)((dbg_info.snd.sync_buff_dd_rm*100)/(dbg_info.snd.sync_buff_dd_len)), 167 (unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len, 168 (int)((dbg_info.snd.sync_buff_ddp_rm*100)/(dbg_info.snd.sync_buff_ddp_len)), 169 (unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len ); 170 if (len_max <= len) 171 goto out; 172 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+ "); 173 if (len_max <= len) 174 goto out; 175 len += sprintf(&buffer[len],"|DMA |%03d%%(%05x/%05x) | |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | ", 176 (int)((dbg_info.snd.dma_buff_pcm_rm*100)/(dbg_info.snd.dma_buff_pcm_len)), 177 (unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len, 178 (int)((dbg_info.snd.dma_buff_dd_rm*100)/(dbg_info.snd.dma_buff_dd_len)), 179 (unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len, 180 (int)((dbg_info.snd.dma_buff_ddp_rm*100)/(dbg_info.snd.dma_buff_ddp_len)), 181 (unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len ); 182 if (len_max <= len) 183 goto out; 184 185 len += sprintf(&buffer[len],"+-----+------------------+------------------+------------------+------------------+ "); 186 if (len_max <= len) 187 goto out; 188 } 189 190 out: 191 return len; 192 } 193 194 static int audio_show_debug_info(void) 195 { 196 struct audio_dbg_info dbg_info; 197 198 if(!audio_deca_dev || !audio_snd_dev) 199 { 200 return -EUNATCH; 201 } 202 203 if (RET_SUCCESS == deca_io_control(audio_deca_dev, DECA_GET_DBG_INFO, (UINT32)(&dbg_info))) 204 { 205 printk( " desc enable : %s ", (1==dbg_info.snd.ad_en)?"yes":"no"); 206 printk( "deca state : %s(%d) ", audio_state(dbg_info.deca.state), (int)dbg_info.deca.state); 207 printk( "deca sub state : %s(%d) ", audio_sub_state(dbg_info.deca.sub_state), (int)dbg_info.deca.sub_state); 208 printk( "snd state : %s(%d) ", audio_state(dbg_info.snd.state), (int)dbg_info.snd.state); 209 printk( "snd sub state : %s(%d) ", audio_sub_state(dbg_info.snd.sub_state), (int)dbg_info.snd.sub_state); 210 211 printk( "+-----+------------------+------------------+------------------+------------------+ "); 212 printk( "|BUFF |PCM(HEX BYTE) |DESC(HEX BYTE) |DD(HEX BYTE) |DDP(HEX BYTE) | "); 213 214 /* deca buff info */ 215 printk( "+-----+------------------+------------------+------------------+------------------+ "); 216 printk( "|BS |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | | ", 217 (int)((dbg_info.deca.prog_bs_buff_rm*100)/(dbg_info.deca.prog_bs_buff_len)), 218 (unsigned int)dbg_info.deca.prog_bs_buff_rm, (unsigned int)dbg_info.deca.prog_bs_buff_len, 219 (int)((dbg_info.deca.desc_bs_buff_rm*100)/(dbg_info.deca.desc_bs_buff_len)), 220 (unsigned int)dbg_info.deca.desc_bs_buff_rm, (unsigned int)dbg_info.deca.desc_bs_buff_len); 221 printk( "+-----+------------------+------------------+------------------+------------------+ "); 222 printk( "|CB |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | | | ", 223 (int)((dbg_info.deca.prog_cb_buff_rm*100)/(dbg_info.deca.prog_cb_buff_len)), 224 (unsigned int)dbg_info.deca.prog_cb_buff_rm, (unsigned int)dbg_info.deca.prog_cb_buff_len, 225 (int)((dbg_info.deca.desc_cb_buff_rm*100)/(dbg_info.deca.desc_cb_buff_len)), 226 (unsigned int)dbg_info.deca.desc_cb_buff_rm, (unsigned int)dbg_info.deca.desc_cb_buff_len); 227 228 /* snd buff info */ 229 printk( "+-----+------------------+------------------+------------------+------------------+ "); 230 printk( "|SYNC |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | ", 231 (int)((dbg_info.snd.sync_buff_pcm_rm*100)/(dbg_info.snd.sync_buff_pcm_len)), 232 (unsigned int)dbg_info.snd.sync_buff_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_pcm_len, 233 (int)((dbg_info.snd.sync_buff_desc_pcm_rm*100)/(dbg_info.snd.sync_buff_desc_pcm_len)), 234 (unsigned int)dbg_info.snd.sync_buff_desc_pcm_rm, (unsigned int)dbg_info.snd.sync_buff_desc_pcm_len, 235 (int)((dbg_info.snd.sync_buff_dd_rm*100)/(dbg_info.snd.sync_buff_dd_len)), 236 (unsigned int)dbg_info.snd.sync_buff_dd_rm, (unsigned int)dbg_info.snd.sync_buff_dd_len, 237 (int)((dbg_info.snd.sync_buff_ddp_rm*100)/(dbg_info.snd.sync_buff_ddp_len)), 238 (unsigned int)dbg_info.snd.sync_buff_ddp_rm, (unsigned int)dbg_info.snd.sync_buff_ddp_len ); 239 printk( "+-----+------------------+------------------+------------------+------------------+ "); 240 printk( "|DMA |%03d%%(%05x/%05x) | |%03d%%(%05x/%05x) |%03d%%(%05x/%05x) | ", 241 (int)((dbg_info.snd.dma_buff_pcm_rm*100)/(dbg_info.snd.dma_buff_pcm_len)), 242 (unsigned int)dbg_info.snd.dma_buff_pcm_rm, (unsigned int)dbg_info.snd.dma_buff_pcm_len, 243 (int)((dbg_info.snd.dma_buff_dd_rm*100)/(dbg_info.snd.dma_buff_dd_len)), 244 (unsigned int)dbg_info.snd.dma_buff_dd_rm, (unsigned int)dbg_info.snd.dma_buff_dd_len, 245 (int)((dbg_info.snd.dma_buff_ddp_rm*100)/(dbg_info.snd.dma_buff_ddp_len)), 246 (unsigned int)dbg_info.snd.dma_buff_ddp_rm, (unsigned int)dbg_info.snd.dma_buff_ddp_len ); 247 248 printk( "+-----+------------------+------------------+------------------+------------------+ "); 249 } 250 251 return 0; 252 } 253 254 /*Process debug info*/ 255 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) 256 static ssize_t audio_dbginfo_procfile_read(struct file *file, char __user *ubuf, size_t size, loff_t *ppos) 257 { 258 int len = 0; 259 ssize_t ret_len = 0; 260 261 if(audio_info_buffer) 262 { 263 memset(audio_info_buffer, 0, MAX_BUF_RD_LEN); 264 len = audio_read_debug_info(audio_info_buffer); 265 ret_len = simple_read_from_buffer(ubuf, size, ppos, audio_info_buffer, len); 266 } 267 268 return ret_len; 269 } 270 271 272 static ssize_t audio_dbginfo_procfile_write(struct file *file, const char __user * buffer, size_t count, loff_t *ppos) 273 { 274 char buf[MAX_BUF_WT_LEN] = {0}; 275 char *eq_ch = NULL; 276 char *endp = NULL; 277 unsigned long value = 0; 278 279 if ((0>=count) || (MAX_BUF_WT_LEN<count)) 280 return 0; 281 282 if (copy_from_user(buf, buffer, count)) 283 return -EFAULT; 284 285 eq_ch = strstr(buf, "="); 286 if (NULL == eq_ch) 287 { 288 printk(KERN_ERR "param error: incorrect value: "%s" ", buf); 289 return -EINVAL; 290 } 291 292 value = simple_strtoul((char *)(eq_ch+1), &endp, 0); 293 if ((eq_ch+1) == endp || value >= INT_MAX) 294 { 295 printk(KERN_ERR "param error: incorrect value: "%s" ", (eq_ch+1)); 296 return -EINVAL; 297 } 298 299 switch(*buf) 300 { 301 case 'a': 302 { 303 if (strstr(buf, "ad_en")) 304 { 305 if (0==value || 1==value) 306 { 307 if (RET_SUCCESS != snd_io_control(audio_snd_dev, SND_SET_AD_DYNAMIC_EN, (UINT32)value)) 308 { 309 printk("