1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2025-07-03 17:37:33 +00:00
Files
a155-U-u1/kernel-5.10/drivers/misc/mediatek/usb_boost/musb_boost_common.c
physwizz 99537be4e2 first
2024-03-11 06:53:12 +11:00

902 lines
20 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 MediaTek Inc.
*/
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/version.h>
#include <linux/workqueue.h>
#include <linux/kdev_t.h>
#include <linux/timekeeping.h>
#include <linux/usb/composite.h>
#include <trace/hooks/sound.h>
#include <linux/pm_wakeup.h>
#include "usb_boost.h"
#if IS_ENABLED(CONFIG_USB_MTK_HDRC)
#include "musb_core.h"
#include "musb_trace.h"
#endif
#define USB_BOOST_CLASS_NAME "usb_boost"
enum{
ATTR_ENABLE,
ATTR_TIMEOUT,
ATTR_POLLING_INTVAL,
ATTR_RAW,
_ATTR_PARA_RW_MAXID,
ATTR_CMD,
ATTR_RO_REF_TIME,
ATTR_RO_IS_RUNNING,
ATTR_RO_WORK_CNT,
_ATTR_PARA_MAXID
};
enum{
_ATTR_ARG_BEGIN = _ATTR_PARA_MAXID - 1,
ATTR_ARG1,
ATTR_ARG2,
ATTR_ARG3,
_ATTR_ARG_MAXID
};
#define _ATTR_MAXID _ATTR_ARG_MAXID
static char *attr_name[_ATTR_MAXID] = {
/* para part */
"enable",
"timeout",
"poll_intval",
"raw",
"para_rx_maxid",
"cmd",
"ro_ref_time",
"ro_is_running",
"ro_work_cnt",
/* arg part */
"arg1",
"arg2",
"arg3",
};
enum{
CMD_BOOST_TEST,
CMD_OVERHEAD_TEST,
CMD_OVERHEAD_TEST_BY_ID,
CMD_DUMP_INFO,
CMD_HOOK_NORMAL,
CMD_HOOK_EMPTY,
CMD_HOOK_CNT,
_CMD_MAXID
};
static char *type_name[_TYPE_MAXID] = {
"cpu_freq",
"cpu_core",
"dram_vcore",
};
enum {
USB_TYPE_UNKNOWN,
USB_TYPE_ADB,
USB_TYPE_MTP,
/* USB_TYPE_PTP, */
USB_TYPE_RNDIS,
};
#if IS_ENABLED(CONFIG_USB_MTK_HDRC)
#define MAX_EP_NUM 32
/* ep0 + in ep + out ep */
static int boost_ep[MAX_EP_NUM * 2 + 1];
#endif
#define MAX_LEN_WQ_NAME 32
static int trigger_cnt_disabled;
static int enabled;
static int inited;
static struct class *usb_boost_class;
static struct wakeup_source *usb_boost_ws;
static int cpu_freq_dft_para[_ATTR_PARA_RW_MAXID] = {1, 3, 300, 0};
static int cpu_core_dft_para[_ATTR_PARA_RW_MAXID] = {1, 3, 300, 0};
static int dram_vcore_dft_para[_ATTR_PARA_RW_MAXID] = {1, 3, 300, 0};
static void __usb_boost_empty(void) { return; }
static void __usb_boost_cnt(void) { trigger_cnt_disabled++; return; }
static void __usb_boost_id_empty(int id) { return; }
static void __request_empty(int id) { return; }
struct boost_ops {
void (*boost)(void);
void (*boost_by_id[_TYPE_MAXID])(int);
};
struct boost_ops __the_boost_ops = {
__usb_boost_empty,
{__usb_boost_id_empty,
__usb_boost_id_empty,
__usb_boost_id_empty} };
/* -1 denote not used*/
static struct act_arg_obj cpu_freq_dft_arg = {1000000000, -1, -1};
static struct act_arg_obj cpu_core_dft_arg = {2, -1, -1};
static struct act_arg_obj dram_vcore_dft_arg = {-1, -1, -1};
static int test_diff_sec, test_diff_usec;
struct control_ops {
int (*act[_ACT_MAXID]) (struct act_arg_obj *arg);
};
static struct mtk_usb_boost {
struct control_ops ops;
struct device_attribute attr[_ATTR_MAXID];
int para[_ATTR_PARA_RW_MAXID];
struct work_struct work;
struct workqueue_struct *wq;
int id;
struct device *dev;
int cmd;
int is_running;
struct timespec64 tv_ref_time;
int work_cnt;
struct act_arg_obj act_arg;
void (*request_func)(int id);
} boost_inst[_TYPE_MAXID];
static struct mtk_usb_audio_boost {
struct work_struct work;
struct workqueue_struct *wq;
struct timespec64 tv_ref_time;
void (*request_func)(int id);
} audio_boost_inst;
static int update_time(int id);
static bool check_timeout(int id);
static void __usb_boost_by_id(int id);
/* public to IP platform level */
void usb_boost_set_para_and_arg(int id, int *para, int para_range,
struct act_arg_obj *act_arg)
{
int i;
struct mtk_usb_boost *ptr_inst = &boost_inst[id];
int *ptr_para = ptr_inst->para;
USB_BOOST_NOTICE("para_range:<%d>\n", para_range);
if (para_range > _ATTR_PARA_RW_MAXID) {
USB_BOOST_NOTICE("ERROR, over range !!!!!\n");
USB_BOOST_NOTICE("para_range<%d>, _ATTR_PARA_RW_MAXID<%d>\n",
para_range, _ATTR_PARA_RW_MAXID);
return;
}
for (i = 0; i < para_range; i++, ptr_para++)
*ptr_para = para[i];
boost_inst[id].act_arg.arg1 = act_arg->arg1;
boost_inst[id].act_arg.arg2 = act_arg->arg2;
boost_inst[id].act_arg.arg3 = act_arg->arg3;
/* hook callback by enable flag */
if (para[0])
__the_boost_ops.boost_by_id[id] = __usb_boost_by_id;
else
__the_boost_ops.boost_by_id[id] = __usb_boost_id_empty;
}
void usb_boost(void)
{
__the_boost_ops.boost();
}
void usb_boost_by_id(int id)
{
__the_boost_ops.boost_by_id[id](id);
}
void register_usb_boost_act(int type_id, int action_id,
int (*func)(struct act_arg_obj *arg))
{
boost_inst[type_id].ops.act[action_id] = func;
}
static void __request_it(int id)
{
USB_BOOST_DBG("ID<%d>, WQ<%p>, WORK<%p>\n",
id, boost_inst[id].wq, &(boost_inst[id].work));
queue_work(boost_inst[id].wq, &(boost_inst[id].work));
USB_BOOST_DBG("\n");
}
static void __usb_boost_by_id(int id)
{
update_time(id);
boost_inst[id].request_func(id);
}
static void __usb_boost(void)
{
int id;
USB_BOOST_DBG("\n");
for (id = 0; id < _TYPE_MAXID; id++)
usb_boost_by_id(id);
}
static void __boost_act(int type_id, int action_id)
{
int (*func)(struct act_arg_obj *arg);
struct act_arg_obj *arg = &boost_inst[type_id].act_arg;
func = boost_inst[type_id].ops.act[action_id];
if (func)
func(arg);
}
static void dump_info(int id)
{
int n = 0;
struct mtk_usb_boost *ptr_inst = &boost_inst[id];
int *ptr_para = ptr_inst->para;
/* PARA */
for (n = 0; n < _ATTR_PARA_RW_MAXID; n++, ptr_para++) {
USB_BOOST_NOTICE("id<%d>, attr<%s>, val<%d>\n",
id, attr_name[n], *ptr_para);
}
/* RO */
USB_BOOST_NOTICE("id<%d>, attr<%s>, val<%d,%d>\n",
id, attr_name[ATTR_RO_REF_TIME],
(unsigned int)boost_inst[id].tv_ref_time.tv_sec,
(unsigned int)boost_inst[id].tv_ref_time.tv_nsec);
USB_BOOST_NOTICE("id<%d>, attr<%s>, val<%d>\n",
id, attr_name[ATTR_RO_IS_RUNNING], boost_inst[id].is_running);
USB_BOOST_NOTICE("id<%d>, attr<%s>, val<%d>\n",
id, attr_name[ATTR_RO_WORK_CNT], boost_inst[id].work_cnt);
/* ARG */
USB_BOOST_NOTICE("id<%d>, attr<%s>, val<%d>\n",
id, attr_name[ATTR_ARG1], boost_inst[id].act_arg.arg1);
USB_BOOST_NOTICE("id<%d>, attr<%s>, val<%d>\n",
id, attr_name[ATTR_ARG2], boost_inst[id].act_arg.arg2);
USB_BOOST_NOTICE("id<%d>, attr<%s>, val<%d>\n",
id, attr_name[ATTR_ARG3], boost_inst[id].act_arg.arg3);
}
static int update_time(int id)
{
ktime_get_ts64(&boost_inst[id].tv_ref_time);
USB_BOOST_DBG("id:%d, ref<%d,%d>\n", id,
(int)boost_inst[id].tv_ref_time.tv_sec,
(int)boost_inst[id].tv_ref_time.tv_nsec);
return 1;
}
static bool check_timeout(int id)
{
struct timespec64 tv, *ref;
int diff_sec;
ref = &boost_inst[id].tv_ref_time;
ktime_get_ts64(&tv);
diff_sec = tv.tv_sec - ref->tv_sec;
if (diff_sec >= boost_inst[id].para[ATTR_TIMEOUT]) {
USB_BOOST_DBG("id<%d>, cur<%d,%d>, ref<%d,%d>\n",
id, (int)tv.tv_sec, (int)tv.tv_nsec,
(int)ref->tv_sec, (int)ref->tv_nsec);
return true;
}
USB_BOOST_DBG("id<%d>, cur<%d,%d>, ref<%d,%d>\n",
id, (int)tv.tv_sec, (int)tv.tv_nsec,
(int)ref->tv_sec, (int)ref->tv_nsec);
return false;
}
static void boost_work(struct work_struct *work_struct)
{
struct mtk_usb_boost *ptr_inst =
container_of(work_struct, struct mtk_usb_boost, work);
int id = ptr_inst->id;
int raw = ptr_inst->para[ATTR_RAW];
int poll_intval = ptr_inst->para[ATTR_POLLING_INTVAL];
ptr_inst->is_running = true;
boost_inst[id].request_func = __request_empty;
ptr_inst->work_cnt++;
USB_BOOST_NOTICE("id:%d, begin of work\n", id);
/* dump_info(id); */
__boost_act(id, ACT_HOLD);
/* dump_info(id); */
while (1) {
int timeout;
USB_BOOST_DBG("id:%d, running of work\n", id);
if (!ptr_inst->para[ATTR_ENABLE]) {
/* dump_info(id); */
break;
}
timeout = check_timeout(id);
if (timeout) {
/* dump_info(id); */
break;
}
if (raw)
__boost_act(id, ACT_HOLD);
msleep(poll_intval);
}
/* dump_info(id); */
__boost_act(id, ACT_RELEASE);
boost_inst[id].request_func = __request_it;
ptr_inst->is_running = false;
USB_BOOST_NOTICE("id:%d, end of work\n", id);
/* dump_info(id); */
}
/* usb audio fine tune */
static void __request_audio(int id)
{
queue_work(audio_boost_inst.wq, &(audio_boost_inst.work));
}
static int update_time_audio(void)
{
ktime_get_ts64(&audio_boost_inst.tv_ref_time);
return 1;
}
static bool check_timeout_audio(void)
{
struct timespec64 tv, *ref;
int diff_sec;
ref = &audio_boost_inst.tv_ref_time;
ktime_get_ts64(&tv);
diff_sec = tv.tv_sec - ref->tv_sec;
/* 5 secs */
if (diff_sec >= 5) {
USB_BOOST_DBG("audio_boost, cur<%d,%d>, ref<%d,%d>\n",
(int)tv.tv_sec, (int)tv.tv_nsec,
(int)ref->tv_sec, (int)ref->tv_nsec);
return true;
}
return false;
}
static void audio_boost_work(struct work_struct *work_struct)
{
audio_boost_inst.request_func = __request_empty;
USB_BOOST_NOTICE("audio_boost, begin of work\n");
audio_core_hold();
audio_freq_hold();
while (1) {
int timeout;
USB_BOOST_DBG("audio_boost, running of work\n");
timeout = check_timeout_audio();
if (timeout) {
/* dump_info(id); */
break;
}
msleep(500);
}
audio_core_release();
audio_freq_release();
audio_boost_inst.request_func = __request_audio;
USB_BOOST_NOTICE("audio_boost, end of work\n");
}
static void vh_sound_usb_support_cpu_suspend(void *unused,
struct usb_device *udev, int direction, bool *is_support)
{
USB_BOOST_DBG("%s enter\n", __func__);
update_time_audio();
audio_boost_inst.request_func(0);
}
static void default_setting(void)
{
usb_boost_set_para_and_arg(TYPE_CPU_FREQ, cpu_freq_dft_para,
ARRAY_SIZE(cpu_freq_dft_para), &cpu_freq_dft_arg);
usb_boost_set_para_and_arg(TYPE_CPU_CORE, cpu_core_dft_para,
ARRAY_SIZE(cpu_core_dft_para), &cpu_core_dft_arg);
usb_boost_set_para_and_arg(TYPE_DRAM_VCORE, dram_vcore_dft_para,
ARRAY_SIZE(dram_vcore_dft_para), &dram_vcore_dft_arg);
}
static int which_attr(struct mtk_usb_boost *inst, struct device_attribute
*attr)
{
int i;
for (i = 0; i < _ATTR_MAXID; i++) {
if (attr == &inst->attr[i])
return i;
}
return -1;
}
static void test_loops(int id)
{
int n;
struct timespec64 tv_before, tv_after;
#define TEST_LOOP 100000
ktime_get_ts64(&tv_before);
if (id < 0) {
for (n = 0; n < TEST_LOOP; n++)
usb_boost();
} else {
for (n = 0; n < TEST_LOOP; n++)
usb_boost_by_id(id);
}
ktime_get_ts64(&tv_after);
test_diff_sec = tv_after.tv_sec - tv_before.tv_sec;
test_diff_usec = tv_after.tv_nsec - tv_before.tv_nsec;
USB_BOOST_NOTICE("id<%d>, loops:%d, spent %d sec, %d usec\n",
id, TEST_LOOP, test_diff_sec, test_diff_usec);
}
static ssize_t attr_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int i, ret, idx = -1;
long tmp;
for (i = 0; i < _TYPE_MAXID; i++) {
if (boost_inst[i].dev == dev) {
idx = which_attr(&boost_inst[i], attr);
break;
}
}
if (i == _TYPE_MAXID)
return 0;
if (idx < 0) {
USB_BOOST_NOTICE("sorry, I cannot find rawbulk fn '%s'\n",
attr->attr.name);
goto exit;
}
ret = kstrtol(buf, 0, &tmp);
switch (idx) {
/* normal usage */
case ATTR_ENABLE:
/* hook callback by enable flag */
if (tmp)
__the_boost_ops.boost_by_id[i] = __usb_boost_by_id;
else
__the_boost_ops.boost_by_id[i] = __usb_boost_id_empty;
boost_inst[i].para[idx] = (int)tmp;
break;
case ATTR_TIMEOUT:
case ATTR_POLLING_INTVAL:
case ATTR_RAW:
boost_inst[i].para[idx] = (int)tmp;
break;
/* command series */
case ATTR_CMD:
boost_inst[i].cmd = (int)tmp;
switch (tmp) {
case CMD_BOOST_TEST:
USB_BOOST_NOTICE("usb_boost_by_id <%d>\n", i);
usb_boost_by_id(i);
break;
case CMD_OVERHEAD_TEST:
test_loops(-1);
break;
case CMD_OVERHEAD_TEST_BY_ID:
test_loops(i);
break;
case CMD_DUMP_INFO:
dump_info(i);
break;
case CMD_HOOK_NORMAL:
__the_boost_ops.boost = __usb_boost;
enabled = 1;
break;
case CMD_HOOK_EMPTY:
__the_boost_ops.boost = __usb_boost_empty;
enabled = 0;
test_loops(-1);
break;
case CMD_HOOK_CNT:
__the_boost_ops.boost = __usb_boost_cnt;
enabled = 0;
test_loops(-1);
break;
default:
break;
}
break;
/* ARG usage */
case ATTR_ARG1:
boost_inst[i].act_arg.arg1 = (int)tmp;
break;
case ATTR_ARG2:
boost_inst[i].act_arg.arg2 = (int)tmp;
break;
case ATTR_ARG3:
boost_inst[i].act_arg.arg3 = (int)tmp;
break;
default:
break;
}
exit:
return count;
}
static ssize_t attr_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int i;
int idx;
ssize_t count = 0;
for (i = 0; i < _TYPE_MAXID; i++) {
if (boost_inst[i].dev == dev) {
idx = which_attr(&boost_inst[i], attr);
break;
}
}
if (i == _TYPE_MAXID)
return 0;
switch (idx) {
/* normal usage */
case ATTR_ENABLE:
case ATTR_TIMEOUT:
case ATTR_POLLING_INTVAL:
case ATTR_RAW:
count = sprintf(buf, "%d\n", boost_inst[i].para[idx]);
break;
case _ATTR_PARA_RW_MAXID:
count = sprintf(buf, "%d\n", _ATTR_PARA_RW_MAXID);
break;
/* command series */
case ATTR_CMD:
switch (boost_inst[i].cmd) {
case CMD_BOOST_TEST:
case CMD_DUMP_INFO:
count = sprintf(buf, "cmd<%d>\n", boost_inst[i].cmd);
break;
case CMD_OVERHEAD_TEST:
case CMD_OVERHEAD_TEST_BY_ID:
case CMD_HOOK_NORMAL:
case CMD_HOOK_EMPTY:
case CMD_HOOK_CNT:
count = sprintf(buf, "cmd<%d>, <%d, %d>\n",
boost_inst[i].cmd, test_diff_sec,
test_diff_usec);
break;
default:
break;
}
break;
/* RO usage */
case ATTR_RO_REF_TIME:
count = sprintf(buf, "<%d,%d>\n",
(int)boost_inst[i].tv_ref_time.tv_sec,
(int)boost_inst[i].tv_ref_time.tv_nsec);
break;
case ATTR_RO_IS_RUNNING:
count = sprintf(buf, "%s\n",
boost_inst[i].is_running ? "true" : "false");
break;
case ATTR_RO_WORK_CNT:
count = sprintf(buf, "%d\n", boost_inst[i].work_cnt);
break;
/* ARG usage */
case ATTR_ARG1:
count = sprintf(buf, "%d\n", boost_inst[i].act_arg.arg1);
break;
case ATTR_ARG2:
count = sprintf(buf, "%d\n", boost_inst[i].act_arg.arg2);
break;
case ATTR_ARG3:
count = sprintf(buf, "%d\n", boost_inst[i].act_arg.arg3);
break;
default:
break;
}
return count;
}
static int create_sys_fs(void)
{
int i;
int n, ret;
USB_BOOST_NOTICE("\n");
usb_boost_class = class_create(THIS_MODULE, USB_BOOST_CLASS_NAME);
if (IS_ERR(usb_boost_class))
return PTR_ERR(usb_boost_class);
for (i = 0 ; i < _TYPE_MAXID ; i++) {
boost_inst[i].dev = device_create(usb_boost_class,
NULL, MKDEV(0, i), NULL, type_name[i]);
for (n = 0; n < _ATTR_MAXID; n++) {
boost_inst[i].attr[n].attr.name = attr_name[n];
boost_inst[i].attr[n].attr.mode = 0400;
boost_inst[i].attr[n].show = attr_show;
boost_inst[i].attr[n].store = attr_store;
ret = device_create_file(boost_inst[i].dev,
&boost_inst[i].attr[n]);
if (ret < 0) {
while (--n >= 0) {
device_remove_file(boost_inst[i].dev,
&boost_inst[i].attr[n]);
}
return ret;
}
}
}
return 0;
}
#if IS_ENABLED(CONFIG_USB_MTK_HDRC)
static struct usb_descriptor_header **
get_function_descriptors(struct usb_function *f,
enum usb_device_speed speed)
{
struct usb_descriptor_header **descriptors;
switch (speed) {
case USB_SPEED_SUPER_PLUS:
descriptors = f->ssp_descriptors;
if (descriptors)
break;
fallthrough;
case USB_SPEED_SUPER:
descriptors = f->ss_descriptors;
if (descriptors)
break;
fallthrough;
case USB_SPEED_HIGH:
descriptors = f->hs_descriptors;
if (descriptors)
break;
fallthrough;
default:
descriptors = f->fs_descriptors;
}
return descriptors;
}
static int musb_get_ep_type(struct usb_descriptor_header **f_desc)
{
struct usb_interface_descriptor *int_desc;
u8 int_class, int_subclass, int_protocol;
for (; *f_desc; ++f_desc) {
if ((*f_desc)->bDescriptorType != USB_DT_INTERFACE)
continue;
int_desc = (struct usb_interface_descriptor *)*f_desc;
int_class = int_desc->bInterfaceClass;
int_subclass = int_desc->bInterfaceSubClass;
int_protocol = int_desc->bInterfaceProtocol;
if (int_class == 0x6 && int_subclass == 0x1
&& int_protocol == 0x1) {
return USB_TYPE_MTP;
} else if (int_class == 0xff && int_subclass == 0x42
&& int_protocol == 0x1) {
return USB_TYPE_ADB;
} else if (int_class == 0x2 && int_subclass == 0x2
&& int_protocol == 0xff) {
return USB_TYPE_RNDIS;
} else if (int_class == 0xe0 && int_subclass == 0x1
&& int_protocol == 0x3) {
return USB_TYPE_RNDIS;
}
}
return USB_TYPE_UNKNOWN;
}
static void boost_set_ep_type(int type, int num, int is_in)
{
if (num > MAX_EP_NUM)
return;
if (is_in)
boost_ep[num] = type;
else
boost_ep[num + MAX_EP_NUM] = type;
}
static int boost_get_ep_type(int num, int is_in)
{
int type;
if (num > MAX_EP_NUM)
return USB_TYPE_UNKNOWN;
if (is_in)
type = boost_ep[num];
else
type = boost_ep[num + MAX_EP_NUM];
return type;
}
static void boost_ep_enable(void *unused, struct musb_ep *musb_ep)
{
struct usb_ep *ep = &musb_ep->end_point;
struct usb_gadget *g = &musb_ep->musb->g;
struct usb_composite_dev *cdev;
struct usb_function *f = NULL;
struct usb_descriptor_header **f_desc;
int addr;
int type;
cdev = get_gadget_data(&musb_ep->musb->g);
if (!cdev || !cdev->config)
return;
if (!musb_ep->current_epnum)
return;
addr = ((ep->address & 0x80) >> 3)
| (ep->address & 0x0f);
list_for_each_entry(f, &cdev->config->functions, list) {
if (test_bit(addr, f->endpoints))
goto find_f;
}
return;
find_f:
f_desc = get_function_descriptors(f, g->speed);
if (f_desc) {
type = musb_get_ep_type(f_desc);
boost_set_ep_type(type, musb_ep->current_epnum, musb_ep->is_in);
}
}
static void boost_ep_disable(void *unused, struct musb_ep *musb_ep)
{
if (!musb_ep->current_epnum)
return;
boost_set_ep_type(USB_TYPE_UNKNOWN, musb_ep->current_epnum, musb_ep->is_in);
}
static void musb_g_giveback_boost(void *unused, struct musb_request *musb_req)
{
struct usb_request *req = &musb_req->request;
struct musb_ep *musb_ep = musb_req->ep;
int type = boost_get_ep_type(musb_ep->current_epnum, musb_ep->is_in);
switch (type) {
case USB_TYPE_MTP:
if (req->actual >= 8192)
usb_boost();
break;
case USB_TYPE_RNDIS:
if (musb_ep->is_in && musb_ep->type == USB_ENDPOINT_XFER_BULK)
usb_boost();
break;
default:
break;
}
}
void musb_host_urb_giveback_dbg(void *unused, struct urb *urb)
{
switch (usb_endpoint_type(&urb->ep->desc)) {
case USB_ENDPOINT_XFER_BULK:
if (urb->actual_length >= 8192) {
__pm_wakeup_event(usb_boost_ws, 10000);
usb_boost();
}
break;
case USB_ENDPOINT_XFER_ISOC:
update_time_audio();
break;
}
}
static int musb_trace_init(void)
{
WARN_ON(register_trace_musb_gadget_enable(
boost_ep_enable, NULL));
WARN_ON(register_trace_musb_gadget_disable(
boost_ep_disable, NULL));
WARN_ON(register_trace_musb_g_giveback(
musb_g_giveback_boost, NULL));
WARN_ON(register_trace_android_vh_sound_usb_support_cpu_suspend(
vh_sound_usb_support_cpu_suspend, NULL));
WARN_ON(register_trace_musb_host_urb_giveback(
musb_host_urb_giveback_dbg, NULL));
return 0;
}
#endif
int usb_boost_init(void)
{
int id;
for (id = 0; id < _TYPE_MAXID; id++) {
int count;
char wq_name[MAX_LEN_WQ_NAME];
count = sprintf(wq_name, "%s_wq", type_name[id]);
wq_name[count] = '\0';
boost_inst[id].id = id;
update_time(id);
boost_inst[id].wq = create_singlethread_workqueue(wq_name);
INIT_WORK(&boost_inst[id].work, boost_work);
USB_BOOST_DBG("ID<%d>, WQ<%p>, WORK<%p>\n",
id, boost_inst[id].wq, &(boost_inst[id].work));
boost_inst[id].request_func = __request_it;
}
/* hook workable interface */
__the_boost_ops.boost = __usb_boost;
enabled = 1;
/* usb audio fine tune */
audio_boost_inst.wq = create_singlethread_workqueue("usb_audio_wq");
INIT_WORK(&audio_boost_inst.work, audio_boost_work);
/* default off */
audio_boost_inst.request_func = __request_empty;
/* wakelock */
usb_boost_ws = wakeup_source_register(NULL, "usb_boost");
create_sys_fs();
default_setting();
inited = 1;
#if IS_ENABLED(CONFIG_USB_MTK_HDRC)
musb_trace_init();
#endif
return 0;
}
void usb_audio_boost(bool enable)
{
USB_BOOST_NOTICE("%s: enable:%d\n", __func__, enable);
if (enable) {
/* hook workable interface */
audio_boost_inst.request_func = __request_audio;
}
}
module_param(trigger_cnt_disabled, int, 0400);
module_param(enabled, int, 0400);
module_param(inited, int, 0400);
MODULE_LICENSE("GPL v2");