/* * sound/soc/sunxi/sunxi-aio/aio.c * (C) Copyright 2016-2018 * Allwinner Technology Co., Ltd. * * zhangjingzhou * yumingfeng * * 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 #include #include #include #include #include #include #include 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"); MODULE_DESCRIPTION("AIO debuginfo driver"); MODULE_VERSION("1.0"); MODULE_ALIAS("platform:AIO(AW1721)");