267 lines
6.7 KiB
C
267 lines
6.7 KiB
C
|
/*
|
||
|
* sound/soc/sunxi/sunxi-aio/aio.c
|
||
|
* (C) Copyright 2016-2018
|
||
|
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
||
|
*
|
||
|
* zhangjingzhou <zhangjingzhou@allwinnertech.com>
|
||
|
* yumingfeng <yumingfeng@allwinnertech.com>
|
||
|
*
|
||
|
* Driver for embedded vision engine(AIO).
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License as
|
||
|
* published by the Free Software Foundation; either version 2 of
|
||
|
* the License, or (at your option) any later version.
|
||
|
*
|
||
|
*/
|
||
|
#include "mpp-aio.h"
|
||
|
#include <linux/init.h>
|
||
|
#include <linux/module.h>
|
||
|
#include <linux/kernel.h>
|
||
|
#include <linux/slab.h>
|
||
|
|
||
|
#include <linux/uaccess.h>
|
||
|
#include <linux/ctype.h>
|
||
|
#include <linux/signal.h>
|
||
|
#include <linux/mpp.h>
|
||
|
|
||
|
struct sunxi_audio_mpp_debugfs *mpp_audio_debugfs;
|
||
|
EXPORT_SYMBOL(mpp_audio_debugfs);
|
||
|
|
||
|
static int aio_write_to_usr(char __user *dst, char *src, size_t count, loff_t *ppos)
|
||
|
{
|
||
|
int len = strlen(src);
|
||
|
|
||
|
if (len) {
|
||
|
if (*ppos >= len)
|
||
|
return 0;
|
||
|
|
||
|
if (count >= len)
|
||
|
count = len;
|
||
|
|
||
|
if (count > (len - *ppos))
|
||
|
count = (len - *ppos);
|
||
|
|
||
|
if (copy_to_user(dst, src, count)) {
|
||
|
pr_warn("copy_to_user fail\n");
|
||
|
return 0;
|
||
|
}
|
||
|
*ppos += count;
|
||
|
} else {
|
||
|
count = 0;
|
||
|
}
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static int aio_info_get(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
|
||
|
{
|
||
|
int wr_cnt = 0;
|
||
|
char info[1024];
|
||
|
|
||
|
sprintf(info, "%s%s%s%s%s%s%s%s%s\n%s%s%s%s%s%s%s%s%s",
|
||
|
mpp_audio_debugfs->ai_info,
|
||
|
mpp_audio_debugfs->ai_devenable,
|
||
|
mpp_audio_debugfs->ai_channelcnt,
|
||
|
mpp_audio_debugfs->ai_cardtype,
|
||
|
mpp_audio_debugfs->ai_samplerate,
|
||
|
mpp_audio_debugfs->ai_bitwidth,
|
||
|
mpp_audio_debugfs->ai_trackcnt,
|
||
|
mpp_audio_debugfs->ai_bMute,
|
||
|
mpp_audio_debugfs->ai_volume,
|
||
|
mpp_audio_debugfs->ao_info,
|
||
|
mpp_audio_debugfs->ao_devenable,
|
||
|
mpp_audio_debugfs->ao_channelcnt,
|
||
|
mpp_audio_debugfs->ao_cardtype,
|
||
|
mpp_audio_debugfs->ao_samplerate,
|
||
|
mpp_audio_debugfs->ao_bitwidth,
|
||
|
mpp_audio_debugfs->ao_trackcnt,
|
||
|
mpp_audio_debugfs->ao_bMute,
|
||
|
mpp_audio_debugfs->ao_volume);
|
||
|
|
||
|
wr_cnt = aio_write_to_usr(buf, info, count, ppos);
|
||
|
|
||
|
return wr_cnt;
|
||
|
}
|
||
|
|
||
|
static int aio_info_set(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||
|
{
|
||
|
char info[64] = {0};
|
||
|
char *dst_ptr;
|
||
|
int match_flag = 1;
|
||
|
|
||
|
if (count > 64) {
|
||
|
pr_warn("copy_from_user fail, count:%d too big!\n", count);
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
if (copy_from_user(info, buf, count)) {
|
||
|
pr_warn("copy_from_user fail\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
switch (info[0]) {
|
||
|
case '0':
|
||
|
dst_ptr = mpp_audio_debugfs->ai_devenable;
|
||
|
break;
|
||
|
case '1':
|
||
|
dst_ptr = mpp_audio_debugfs->ai_channelcnt;
|
||
|
break;
|
||
|
case '2':
|
||
|
dst_ptr = mpp_audio_debugfs->ai_cardtype;
|
||
|
break;
|
||
|
case '3':
|
||
|
dst_ptr = mpp_audio_debugfs->ai_samplerate;
|
||
|
break;
|
||
|
case '4':
|
||
|
dst_ptr = mpp_audio_debugfs->ai_bitwidth;
|
||
|
break;
|
||
|
case '5':
|
||
|
dst_ptr = mpp_audio_debugfs->ai_trackcnt;
|
||
|
break;
|
||
|
case '6':
|
||
|
dst_ptr = mpp_audio_debugfs->ai_bMute;
|
||
|
break;
|
||
|
case '7':
|
||
|
dst_ptr = mpp_audio_debugfs->ai_volume;
|
||
|
break;
|
||
|
case '8':
|
||
|
dst_ptr = mpp_audio_debugfs->ao_devenable;
|
||
|
break;
|
||
|
case '9':
|
||
|
dst_ptr = mpp_audio_debugfs->ao_channelcnt;
|
||
|
break;
|
||
|
case 'a':
|
||
|
dst_ptr = mpp_audio_debugfs->ao_cardtype;
|
||
|
break;
|
||
|
case 'b':
|
||
|
dst_ptr = mpp_audio_debugfs->ao_samplerate;
|
||
|
break;
|
||
|
case 'c':
|
||
|
dst_ptr = mpp_audio_debugfs->ao_bitwidth;
|
||
|
break;
|
||
|
case 'd':
|
||
|
dst_ptr = mpp_audio_debugfs->ao_trackcnt;
|
||
|
break;
|
||
|
case 'e':
|
||
|
dst_ptr = mpp_audio_debugfs->ao_bMute;
|
||
|
break;
|
||
|
case 'f':
|
||
|
dst_ptr = mpp_audio_debugfs->ao_volume;
|
||
|
break;
|
||
|
default:
|
||
|
pr_warn("unknown aio debugfs setting[%s]!\n", info);
|
||
|
pr_warn("MUST be: echo x[0,f] yz > path!\n");
|
||
|
match_flag = 0;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
while ((*dst_ptr != '\0') && (*dst_ptr != ':'))
|
||
|
++dst_ptr;
|
||
|
|
||
|
if (match_flag && strlen(info) < 15)
|
||
|
snprintf(dst_ptr + 2, strlen(info), "%s", info + 2);
|
||
|
else
|
||
|
pr_warn("update fail! match_flag:%d, strlen: %d\n", match_flag, strlen(info));
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
int mpp_aio_info_set(char *dst_ptr, unsigned int size, unsigned int value)
|
||
|
{
|
||
|
unsigned int count = 0;
|
||
|
|
||
|
if (dst_ptr == NULL) {
|
||
|
pr_err("[%s] dst_ptr is NULL!\n", __func__);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
while ((*dst_ptr != '\0') && (*dst_ptr != ':')) {
|
||
|
count++;
|
||
|
++dst_ptr;
|
||
|
}
|
||
|
|
||
|
if (size <= 64)
|
||
|
snprintf(dst_ptr + 2, size-count, "%u\n", value);
|
||
|
else
|
||
|
pr_warn("update fail! [size-count]:%d, strlen(dst_ptr): %d\n",
|
||
|
size-count, strlen(dst_ptr));
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int aio_info_open(struct inode *inode, struct file *file)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int aio_info_release(struct inode *inode, struct file *file)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static const struct file_operations info_ops = {
|
||
|
.write = aio_info_set,
|
||
|
.read = aio_info_get,
|
||
|
.open = aio_info_open,
|
||
|
.release = aio_info_release,
|
||
|
};
|
||
|
|
||
|
static int __init debugfs_aio_init(void)
|
||
|
{
|
||
|
#ifdef CONFIG_SUNXI_MPP
|
||
|
mpp_audio_debugfs = kzalloc(sizeof(struct sunxi_audio_mpp_debugfs), GFP_KERNEL);
|
||
|
if (mpp_audio_debugfs)
|
||
|
mpp_audio_debugfs->debugfsP = debugfs_create_file("sunxi-aio", 0644, debugfs_mpp_root, NULL, &info_ops);
|
||
|
else {
|
||
|
mpp_audio_debugfs = NULL;
|
||
|
pr_err("[%s] can not malloc mpp_audio_debugfs", __func__);
|
||
|
}
|
||
|
|
||
|
if (mpp_audio_debugfs) {
|
||
|
/* ai dev attr */
|
||
|
mpp_audio_debugfs->ai_info = "-----------AI Dev ATTR(V1.0)---------------\n";
|
||
|
strcpy(mpp_audio_debugfs->ai_devenable, "ai_enable: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ai_channelcnt, "ai_chncnt: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ai_cardtype, "ai_cardtype[0-codec; 1-linein]: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ai_samplerate, "ai_samplerate: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ai_bitwidth, "ai_bitwidth: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ai_trackcnt, "ai_trackcnt: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ai_bMute, "ai_bMute: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ai_volume, "ai_volume: 0\n");
|
||
|
|
||
|
/* ao dev attr */
|
||
|
mpp_audio_debugfs->ao_info = "-----------AO Dev ATTR(V1.0)---------------\n";
|
||
|
strcpy(mpp_audio_debugfs->ao_devenable, "ao_enable: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ao_channelcnt, "ao_chncnt: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ao_cardtype, "ao_cardtype[0-codec; 1-hdmi]: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ao_samplerate, "ao_samplerate: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ao_bitwidth, "ao_bitwidth: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ao_trackcnt, "ao_trackcnt: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ao_bMute, "ao_bMute: 0\n");
|
||
|
strcpy(mpp_audio_debugfs->ao_volume, "ao_volume: 0\n");
|
||
|
}
|
||
|
#else
|
||
|
mpp_audio_debugfs = NULL;
|
||
|
#endif
|
||
|
return 0;
|
||
|
}
|
||
|
module_init(debugfs_aio_init);
|
||
|
|
||
|
static void __exit debugfs_aio_exit(void)
|
||
|
{
|
||
|
#ifdef CONFIG_SUNXI_MPP
|
||
|
if (mpp_audio_debugfs) {
|
||
|
if (mpp_audio_debugfs->debugfsP)
|
||
|
debugfs_remove_recursive(mpp_audio_debugfs->debugfsP);
|
||
|
kfree(mpp_audio_debugfs);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
module_exit(debugfs_aio_exit);
|
||
|
|
||
|
MODULE_LICENSE("Dual BSD/GPL");
|
||
|
MODULE_AUTHOR("zhangjingzhou<zhangjingzhou@allwinnertech.com>");
|
||
|
MODULE_DESCRIPTION("AIO debuginfo driver");
|
||
|
MODULE_VERSION("1.0");
|
||
|
MODULE_ALIAS("platform:AIO(AW1721)");
|