blob: 4ab512ccbcee2d2bbf2f9cbed7ab7aca17e1b39a [file] [edit]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Google Corp.
*
* Author:
* Puma Hsu <[email protected]>
*/
#include <linux/usb.h>
#include <trace/hooks/sound.h>
#include <trace/hooks/usb.h>
#include "aoc_usb.h"
/*
* 1: enable AP suspend support
* 0: disable AP suspend support
*/
#define ap_suspend_enabled 1
/*
* Return true when the platform supports AP suspend with USB awake.
* Currently this will respond to Kernel alsa pcm driver.
*/
static void sound_vendor_support_suspend(void *unused, struct usb_device *udev,
int direction, bool *is_support)
{
if (!udev)
return;
*is_support = true;
return;
}
/*
* Set bypass = 1 will skip USB suspend.
*/
static void usb_vendor_dev_suspend(void *unused, struct usb_device *udev,
pm_message_t msg, int *bypass)
{
bool usb_playback = false;
bool usb_capture = false;
int usb_audio_count = xhci_get_usb_audio_count();
*bypass = 0;
/* If no USB audio device is connected, we won't skip suspend.*/
if (!udev || usb_audio_count < 1)
return;
usb_playback = aoc_alsa_usb_playback_enabled();
usb_capture = aoc_alsa_usb_capture_enabled();
if (usb_playback || usb_capture) {
dev_info(&udev->dev, "%s: skip suspend process (playback:%d,capture:%d)\n",
__func__, usb_playback, usb_capture);
*bypass = 1;
}
return;
}
/*
* Set bypass = 1 will skip USB resume.
*/
static void usb_vendor_dev_resume(void *unused, struct usb_device *udev,
pm_message_t msg, int *bypass)
{
if (!udev) {
*bypass = 0;
return;
}
if (udev->port_is_suspended || udev->state == USB_STATE_SUSPENDED) {
*bypass = 0;
} else {
dev_info(&udev->dev, "%s: skip resume process\n", __func__);
*bypass = 1;
}
return;
}
int usb_vendor_helper_init(void)
{
int ret = 0;
if (ap_suspend_enabled) {
pr_info("%s: AP suspend support is enabled\n", __func__);
} else {
pr_info("%s: AP suspend support is disabled\n", __func__);
return ret;
}
ret = register_trace_android_vh_sound_usb_support_cpu_suspend(sound_vendor_support_suspend,
NULL);
if (ret)
pr_err("register_trace_android_vh_sound_usb_support_cpu_suspend failed, ret:%d\n",
ret);
ret = register_trace_android_rvh_usb_dev_suspend(usb_vendor_dev_suspend, NULL);
if (ret)
pr_err("register_trace_android_rvh_usb_dev_suspend failed, ret:%d\n", ret);
ret = register_trace_android_vh_usb_dev_resume(usb_vendor_dev_resume, NULL);
if (ret)
pr_err("register_trace_android_vh_usb_dev_resume failed, ret:%d\n", ret);
return ret;
}