kernel_samsung_a53x/sound/soc/samsung/vts/vts_dump.c
2024-06-15 16:02:09 -03:00

187 lines
5.1 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0-or-later
/* sound/soc/samsung/vts/vts_dump.c
*
* ALSA SoC - Samsung VTS dump driver
*
* Copyright (c) 2017 Samsung Electronics Co. Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
//#define DEBUG
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include <sound/soc.h>
#include "vts_dump.h"
#include "vts_dbg.h"
#define S_IRWUG (0660)
struct vts_dump_info {
struct device *dev;
struct mutex audiolock;
struct mutex loglock;
u32 audioaddr_offset;
u32 audiodump_sz;
u32 logaddr_offset;
u32 logdump_sz;
};
static struct vts_dump_info gdump_info;
static void vts_audiodump_flush_work_func(struct work_struct *work)
{
struct device *dev = gdump_info.dev;
struct vts_dump_info *dump_info = &gdump_info;
struct vts_data *data = dev_get_drvdata(dev);
char filename[SZ_64];
/* struct file *filp; */
vts_dev_dbg(dev, "%s: SRAM Offset: 0x%x Size: %d\n", __func__,
dump_info->audioaddr_offset, dump_info->audiodump_sz);
mutex_lock(&gdump_info.audiolock);
sprintf(filename, "/data/vts_audiodump.raw");
/* filp = filp_open(filename, O_RDWR | O_APPEND | O_CREAT, S_IRWUG);
* vts_dev_info(dev, "AudioDump appended mode\n");
* if (!IS_ERR_OR_NULL(filp)) {
* void *area = (void *)(data->sram_base + dump_info->audioaddr_offset);
* size_t bytes = (size_t)dump_info->audiodump_sz;
* vts_dev_dbg(dev, " %p, %zx\n", area, bytes);
* kernel_write(filp, area, bytes, &filp->f_pos);
* dev_dbg(dev, "kernel_write %p, %zx\n", area, bytes);
* vfs_fsync(filp, 1);
* filp_close(filp, NULL);
* } else {
* vts_dev_err(dev, "VTS Audiodump file [%s] open
* error: %ld\n", filename, PTR_ERR(filp));
* }
*/
vts_send_ipc_ack(data, 1);
mutex_unlock(&gdump_info.audiolock);
}
static void vts_logdump_flush_work_func(struct work_struct *work)
{
struct device *dev = gdump_info.dev;
struct vts_dump_info *dump_info = &gdump_info;
struct vts_data *data = dev_get_drvdata(dev);
char filename[SZ_64];
/* struct file *filp; */
vts_dev_dbg(dev, "%s: SRAM Offset: 0x%x Size: %d\n", __func__,
dump_info->logaddr_offset, dump_info->logdump_sz);
mutex_lock(&gdump_info.loglock);
sprintf(filename, "/data/vts_logdump.txt");
/* filp = filp_open(filename, O_RDWR | O_APPEND | O_CREAT, S_IRWUG);
* vts_dev_info(dev, "LogDump appended mode\n");
* if (!IS_ERR_OR_NULL(filp)) {
* void *area = (void *)(data->sram_base + dump_info->logaddr_offset);
* size_t bytes = (size_t)dump_info->logdump_sz;
* vts_dev_dbg(dev, " %p, %zx\n", area, bytes);
* kernel_write(filp, area, bytes, &filp->f_pos);
* dev_dbg(dev, "kernel_write %p, %zx\n", area, bytes);
* vfs_fsync(filp, 1);
* filp_close(filp, NULL);
* } else {
* vts_dev_err(dev, "VTS Logdump file [%s] open error: %ld\n",
* filename, PTR_ERR(filp));
* }
*/
vts_send_ipc_ack(data, 1);
mutex_unlock(&gdump_info.loglock);
}
static DECLARE_WORK(vts_audiodump_work, vts_audiodump_flush_work_func);
static DECLARE_WORK(vts_logdump_work, vts_logdump_flush_work_func);
void vts_audiodump_schedule_flush(struct device *dev)
{
struct vts_data *data = dev_get_drvdata(dev);
if (gdump_info.audioaddr_offset) {
schedule_work(&vts_audiodump_work);
vts_dev_dbg(dev, "%s: AudioDump Scheduled\n", __func__);
} else {
vts_dev_warn(dev, "%s: AudioDump address not registered\n",
__func__);
/* send ipc ack to unblock vts firmware */
vts_send_ipc_ack(data, 1);
}
}
EXPORT_SYMBOL(vts_audiodump_schedule_flush);
void vts_logdump_schedule_flush(struct device *dev)
{
struct vts_data *data = dev_get_drvdata(dev);
if (gdump_info.logaddr_offset) {
schedule_work(&vts_logdump_work);
vts_dev_dbg(dev, "%s: LogDump Scheduled\n", __func__);
} else {
vts_dev_warn(dev, "%s: LogDump address not registered\n",
__func__);
/* send ipc ack to unblock vts firmware */
vts_send_ipc_ack(data, 1);
}
}
EXPORT_SYMBOL(vts_logdump_schedule_flush);
static int samsung_vts_dump_initcall(void)
{
static int has_run;
if (has_run)
return 0;
has_run = 1;
pr_info("%s\n", __func__);
mutex_init(&gdump_info.audiolock);
mutex_init(&gdump_info.loglock);
gdump_info.audioaddr_offset = 0;
gdump_info.audiodump_sz = 0;
gdump_info.logaddr_offset = 0;
gdump_info.logdump_sz = 0;
return 0;
}
void vts_dump_addr_register(
struct device *dev,
u32 addroffset,
u32 dumpsz,
u32 dump_mode)
{
struct vts_data *data = dev_get_drvdata(dev);
samsung_vts_dump_initcall();
gdump_info.dev = dev;
if ((addroffset + dumpsz) > data->sram_size) {
vts_dev_warn(dev, "%s: wrong offset[0x%x] or size[0x%x]\n",
__func__, addroffset, dumpsz);
return;
}
if (dump_mode == VTS_AUDIO_DUMP) {
gdump_info.audioaddr_offset = addroffset;
gdump_info.audiodump_sz = dumpsz;
} else if (dump_mode == VTS_LOG_DUMP) {
gdump_info.logaddr_offset = addroffset;
gdump_info.logdump_sz = dumpsz;
} else
vts_dev_warn(dev, "%s: Unknown dump mode\n", __func__);
vts_dev_info(dev, "%s: %sDump offset[0x%x] size [%d]Scheduled\n",
__func__, (dump_mode ? "Log" : "Audio"),
addroffset, dumpsz);
}
EXPORT_SYMBOL(vts_dump_addr_register);