Usb: Signal irq_hpd to drm stack
Monitor typec stack for irq_hpd events and signal irq_hpd when the irq_hpd counter value read is not the same as the previously cached value. Bug: 278307874 Change-Id: Id4a72afcf85550cabbc2f9469bb0ccb92cd02ad2
This commit is contained in:
parent
2d67d31e45
commit
412f31194c
3 changed files with 58 additions and 22 deletions
|
@ -17,6 +17,7 @@
|
||||||
#define LOG_TAG "android.hardware.usb.aidl-service"
|
#define LOG_TAG "android.hardware.usb.aidl-service"
|
||||||
|
|
||||||
#include <android-base/logging.h>
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/parseint.h>
|
||||||
#include <android-base/properties.h>
|
#include <android-base/properties.h>
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -81,6 +82,7 @@ constexpr char kThermalZoneForTempReadSecondary2[] = "qi_therm";
|
||||||
constexpr char kPogoUsbActive[] = "/sys/devices/platform/google,pogo/pogo_usb_active";
|
constexpr char kPogoUsbActive[] = "/sys/devices/platform/google,pogo/pogo_usb_active";
|
||||||
constexpr char kPogoEnableUsb[] = "/sys/devices/platform/google,pogo/enable_usb";
|
constexpr char kPogoEnableUsb[] = "/sys/devices/platform/google,pogo/enable_usb";
|
||||||
constexpr char kPowerSupplyUsbType[] = "/sys/class/power_supply/usb/usb_type";
|
constexpr char kPowerSupplyUsbType[] = "/sys/class/power_supply/usb/usb_type";
|
||||||
|
constexpr char kIrqHpdCounPath[] = "-0025/irq_hpd_count";
|
||||||
constexpr int kSamplingIntervalSec = 5;
|
constexpr int kSamplingIntervalSec = 5;
|
||||||
void queryVersionHelper(android::hardware::usb::Usb *usb,
|
void queryVersionHelper(android::hardware::usb::Usb *usb,
|
||||||
std::vector<PortStatus> *currentPortStatus);
|
std::vector<PortStatus> *currentPortStatus);
|
||||||
|
@ -420,9 +422,9 @@ Usb::Usb()
|
||||||
ALOGE("pthread_condattr_destroy failed: %s", strerror(errno));
|
ALOGE("pthread_condattr_destroy failed: %s", strerror(errno));
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
mDisplayPortShutdown = eventfd(0, EFD_NONBLOCK);
|
mDisplayPortEventPipe = eventfd(0, EFD_NONBLOCK);
|
||||||
if (mDisplayPortShutdown == -1) {
|
if (mDisplayPortEventPipe == -1) {
|
||||||
ALOGE("mDisplayPortShutdown eventfd failed: %s", strerror(errno));
|
ALOGE("mDisplayPortEventPipe eventfd failed: %s", strerror(errno));
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -921,9 +923,16 @@ static void uevent_event(uint32_t /*epevents*/, struct data *payload) {
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&payload->usb->mRoleSwitchLock);
|
pthread_mutex_unlock(&payload->usb->mRoleSwitchLock);
|
||||||
}
|
}
|
||||||
if (!!strncmp(cp, "DEVTYPE=typec_alternate_mode", strlen("DEVTYPE=typec_alternate_mode"))) {
|
if (!strncmp(cp, "DRIVER=max77759tcpc", strlen("DRIVER=max77759tcpc"))
|
||||||
break;
|
&& payload->usb->mDisplayPortPollRunning) {
|
||||||
|
uint64_t flag = DISPLAYPORT_IRQ_HPD_COUNT_CHECK;
|
||||||
|
|
||||||
|
ALOGI("usbdp: DISPLAYPORT_IRQ_HPD_COUNT_CHECK sent");
|
||||||
|
write(payload->usb->mDisplayPortEventPipe, &flag, sizeof(flag));
|
||||||
}
|
}
|
||||||
|
/*if (!!strncmp(cp, "DEVTYPE=typec_alternate_mode", strlen("DEVTYPE=typec_alternate_mode"))) {
|
||||||
|
break;
|
||||||
|
}*/
|
||||||
} else if (!strncmp(cp, kOverheatStatsDev, strlen(kOverheatStatsDev))) {
|
} else if (!strncmp(cp, kOverheatStatsDev, strlen(kOverheatStatsDev))) {
|
||||||
ALOGV("Overheat Cooling device suez update");
|
ALOGV("Overheat Cooling device suez update");
|
||||||
report_overheat_event(payload->usb);
|
report_overheat_event(payload->usb);
|
||||||
|
@ -1122,6 +1131,21 @@ Status Usb::writeDisplayPortAttribute(string attribute, string usb_path) {
|
||||||
return Status::SUCCESS;
|
return Status::SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!strncmp(attribute.c_str(), "irq_hpd_count", strlen("irq_hpd_count"))) {
|
||||||
|
uint32_t temp;
|
||||||
|
if (!::android::base::ParseUint(Trim(attrUsb), &temp)) {
|
||||||
|
ALOGE("usbdp: failed parsing irq_hpd_count:%s", attrUsb.c_str());
|
||||||
|
return Status::SUCCESS;
|
||||||
|
}
|
||||||
|
// Used to cache the values read from tcpci's irq_hpd_count.
|
||||||
|
// Update drm driver when cached value is not the same as the read value.
|
||||||
|
ALOGI("usbdp: mIrqHpdCountCache:%u irq_hpd_count:%u", mIrqHpdCountCache, temp);
|
||||||
|
if (mIrqHpdCountCache == temp) {
|
||||||
|
return Status::SUCCESS;
|
||||||
|
} else {
|
||||||
|
mIrqHpdCountCache = temp;
|
||||||
|
}
|
||||||
|
attrDrmPath = string(kDisplayPortDrmPath) + "irq_hpd";
|
||||||
} else if (!strncmp(attribute.c_str(), "pin_assignment", strlen("pin_assignment"))) {
|
} else if (!strncmp(attribute.c_str(), "pin_assignment", strlen("pin_assignment"))) {
|
||||||
size_t pos = attrUsb.find("[");
|
size_t pos = attrUsb.find("[");
|
||||||
if (pos != string::npos) {
|
if (pos != string::npos) {
|
||||||
|
@ -1168,26 +1192,32 @@ void *displayPortPollWork(void *param) {
|
||||||
int epoll_fd;
|
int epoll_fd;
|
||||||
struct epoll_event ev_hpd, ev_pin, ev_orientation, ev_eventfd, ev_link;
|
struct epoll_event ev_hpd, ev_pin, ev_orientation, ev_eventfd, ev_link;
|
||||||
int nevents = 0;
|
int nevents = 0;
|
||||||
int numRetries = 0;
|
|
||||||
int hpd_fd, pin_fd, orientation_fd, link_fd;
|
int hpd_fd, pin_fd, orientation_fd, link_fd;
|
||||||
int file_flags = O_RDONLY;
|
int file_flags = O_RDONLY;
|
||||||
int epoll_flags;
|
int epoll_flags;
|
||||||
bool orientationSet = false;
|
bool orientationSet = false;
|
||||||
bool pinSet = false;
|
bool pinSet = false;
|
||||||
string displayPortUsbPath;
|
string displayPortUsbPath, irqHpdCountPath, hpdPath, pinAssignmentPath, orientationPath;
|
||||||
string hpdPath, pinAssignmentPath, orientationPath, linkPath;
|
string tcpcI2cBus, linkPath;
|
||||||
::aidl::android::hardware::usb::Usb *usb = (::aidl::android::hardware::usb::Usb *)param;
|
::aidl::android::hardware::usb::Usb *usb = (::aidl::android::hardware::usb::Usb *)param;
|
||||||
|
|
||||||
if (usb->getDisplayPortUsbPathHelper(&displayPortUsbPath) == Status::ERROR) {
|
if (usb->getDisplayPortUsbPathHelper(&displayPortUsbPath) == Status::ERROR) {
|
||||||
ALOGE("usbdp: could not locate usb displayport directory");
|
ALOGE("usbdp: could not locate usb displayport directory");
|
||||||
goto usb_path_error;
|
goto usb_path_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usb->mDisplayPortPollRunning = true;
|
||||||
|
|
||||||
ALOGI("usbdp: displayport usb path located at %s", displayPortUsbPath.c_str());
|
ALOGI("usbdp: displayport usb path located at %s", displayPortUsbPath.c_str());
|
||||||
hpdPath = displayPortUsbPath + "hpd";
|
hpdPath = displayPortUsbPath + "hpd";
|
||||||
pinAssignmentPath = displayPortUsbPath + "pin_assignment";
|
pinAssignmentPath = displayPortUsbPath + "pin_assignment";
|
||||||
orientationPath = "/sys/class/typec/port0/orientation";
|
orientationPath = "/sys/class/typec/port0/orientation";
|
||||||
linkPath = string(kDisplayPortDrmPath) + "link_status";
|
linkPath = string(kDisplayPortDrmPath) + "link_status";
|
||||||
|
|
||||||
|
getI2cBusHelper(&tcpcI2cBus);
|
||||||
|
irqHpdCountPath = kI2CPath + tcpcI2cBus + "/" + tcpcI2cBus + kIrqHpdCounPath;
|
||||||
|
ALOGI("udbdp: irqHpdCountPath:%s", irqHpdCountPath.c_str());
|
||||||
|
|
||||||
epoll_fd = epoll_create(64);
|
epoll_fd = epoll_create(64);
|
||||||
if (epoll_fd == -1) {
|
if (epoll_fd == -1) {
|
||||||
ALOGE("usbdp: epoll_create failed; errno=%d", errno);
|
ALOGE("usbdp: epoll_create failed; errno=%d", errno);
|
||||||
|
@ -1218,7 +1248,7 @@ void *displayPortPollWork(void *param) {
|
||||||
ev_hpd.data.fd = hpd_fd;
|
ev_hpd.data.fd = hpd_fd;
|
||||||
ev_pin.data.fd = pin_fd;
|
ev_pin.data.fd = pin_fd;
|
||||||
ev_orientation.data.fd = orientation_fd;
|
ev_orientation.data.fd = orientation_fd;
|
||||||
ev_eventfd.data.fd = usb->mDisplayPortShutdown;
|
ev_eventfd.data.fd = usb->mDisplayPortEventPipe;
|
||||||
ev_link.data.fd = link_fd;
|
ev_link.data.fd = link_fd;
|
||||||
|
|
||||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, hpd_fd, &ev_hpd) == -1) {
|
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, hpd_fd, &ev_hpd) == -1) {
|
||||||
|
@ -1237,7 +1267,7 @@ void *displayPortPollWork(void *param) {
|
||||||
ALOGE("usbdp: epoll_ctl failed to add link status; errno=%d", errno);
|
ALOGE("usbdp: epoll_ctl failed to add link status; errno=%d", errno);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortShutdown, &ev_eventfd) == -1) {
|
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortEventPipe, &ev_eventfd) == -1) {
|
||||||
ALOGE("usbdp: epoll_ctl failed to add orientation; errno=%d", errno);
|
ALOGE("usbdp: epoll_ctl failed to add orientation; errno=%d", errno);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1265,15 +1295,9 @@ void *displayPortPollWork(void *param) {
|
||||||
} else if (events[n].data.fd == orientation_fd) {
|
} else if (events[n].data.fd == orientation_fd) {
|
||||||
usb->writeDisplayPortAttribute("orientation", orientationPath);
|
usb->writeDisplayPortAttribute("orientation", orientationPath);
|
||||||
orientationSet = true;
|
orientationSet = true;
|
||||||
} else if (events[n].data.fd == link_fd) {
|
} else if (events[n].data.fd == usb->mDisplayPortEventPipe) {
|
||||||
if (usb->determineDisplayPortRetry(linkPath, hpdPath) && numRetries < 3) {
|
|
||||||
ALOGW("usbdp: Link Training Failed, rewriting hpd to trigger retry.");
|
|
||||||
usb->writeDisplayPortAttributeOverride("hpd", "1");
|
|
||||||
numRetries++;
|
|
||||||
}
|
|
||||||
} else if (events[n].data.fd == usb->mDisplayPortShutdown) {
|
|
||||||
uint64_t flag = 0;
|
uint64_t flag = 0;
|
||||||
if (!read(usb->mDisplayPortShutdown, &flag, sizeof(flag))) {
|
if (!read(usb->mDisplayPortEventPipe, &flag, sizeof(flag))) {
|
||||||
if (errno == EAGAIN)
|
if (errno == EAGAIN)
|
||||||
continue;
|
continue;
|
||||||
ALOGI("usbdp: Shutdown eventfd read error");
|
ALOGI("usbdp: Shutdown eventfd read error");
|
||||||
|
@ -1283,6 +1307,9 @@ void *displayPortPollWork(void *param) {
|
||||||
ALOGI("usbdp: Shutdown eventfd triggered");
|
ALOGI("usbdp: Shutdown eventfd triggered");
|
||||||
destroyDisplayPortThread = true;
|
destroyDisplayPortThread = true;
|
||||||
break;
|
break;
|
||||||
|
} else if (flag == DISPLAYPORT_IRQ_HPD_COUNT_CHECK) {
|
||||||
|
ALOGI("usbdp: IRQ_HPD event through DISPLAYPORT_IRQ_HPD_COUNT_CHECK");
|
||||||
|
usb->writeDisplayPortAttribute("irq_hpd_count", irqHpdCountPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1297,10 +1324,11 @@ orientation_fd_error:
|
||||||
pin_fd_error:
|
pin_fd_error:
|
||||||
close(hpd_fd);
|
close(hpd_fd);
|
||||||
hpd_fd_error:
|
hpd_fd_error:
|
||||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortShutdown, &ev_eventfd);
|
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortEventPipe, &ev_eventfd);
|
||||||
close(epoll_fd);
|
close(epoll_fd);
|
||||||
epoll_fd_error:
|
epoll_fd_error:
|
||||||
usb_path_error:
|
usb_path_error:
|
||||||
|
usb->mDisplayPortPollRunning = false;
|
||||||
ALOGI("usbdp: Exiting worker thread");
|
ALOGI("usbdp: Exiting worker thread");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1308,7 +1336,7 @@ usb_path_error:
|
||||||
void Usb::setupDisplayPortPoll() {
|
void Usb::setupDisplayPortPoll() {
|
||||||
uint64_t flag = DISPLAYPORT_SHUTDOWN_CLEAR;
|
uint64_t flag = DISPLAYPORT_SHUTDOWN_CLEAR;
|
||||||
|
|
||||||
write(mDisplayPortShutdown, &flag, sizeof(flag));
|
write(mDisplayPortEventPipe, &flag, sizeof(flag));
|
||||||
destroyDisplayPortThread = false;
|
destroyDisplayPortThread = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1345,7 +1373,7 @@ void Usb::shutdownDisplayPortPoll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown thread, make sure to rewrite hpd because file no longer exists.
|
// Shutdown thread, make sure to rewrite hpd because file no longer exists.
|
||||||
write(mDisplayPortShutdown, &flag, sizeof(flag));
|
write(mDisplayPortEventPipe, &flag, sizeof(flag));
|
||||||
if (pthread_create(&mDisplayPortShutdownHelper, NULL, shutdownDisplayPortPollWork, this)) {
|
if (pthread_create(&mDisplayPortShutdownHelper, NULL, shutdownDisplayPortPollWork, this)) {
|
||||||
ALOGE("pthread creation failed %d", errno);
|
ALOGE("pthread creation failed %d", errno);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ constexpr char kGadgetName[] = "11210000.dwc3";
|
||||||
|
|
||||||
#define DISPLAYPORT_SHUTDOWN_CLEAR 0
|
#define DISPLAYPORT_SHUTDOWN_CLEAR 0
|
||||||
#define DISPLAYPORT_SHUTDOWN_SET 1
|
#define DISPLAYPORT_SHUTDOWN_SET 1
|
||||||
|
#define DISPLAYPORT_IRQ_HPD_COUNT_CHECK 3
|
||||||
|
|
||||||
struct Usb : public BnUsb {
|
struct Usb : public BnUsb {
|
||||||
Usb();
|
Usb();
|
||||||
|
@ -103,12 +104,17 @@ struct Usb : public BnUsb {
|
||||||
float mPluggedTemperatureCelsius;
|
float mPluggedTemperatureCelsius;
|
||||||
// Usb Data status
|
// Usb Data status
|
||||||
bool mUsbDataEnabled;
|
bool mUsbDataEnabled;
|
||||||
|
// True when mDisplayPortPoll pthread is running
|
||||||
|
volatile bool mDisplayPortPollRunning;
|
||||||
|
// Used to cache the values read from tcpci's irq_hpd_count.
|
||||||
|
// Update drm driver when cached value is not the same as the read value.
|
||||||
|
uint32_t mIrqHpdCountCache;
|
||||||
|
|
||||||
// Protects writeDisplayPortToExynos(), setupDisplayPortPoll(), and
|
// Protects writeDisplayPortToExynos(), setupDisplayPortPoll(), and
|
||||||
// shutdownDisplayPortPoll()
|
// shutdownDisplayPortPoll()
|
||||||
pthread_mutex_t mDisplayPortLock;
|
pthread_mutex_t mDisplayPortLock;
|
||||||
// eventfd to signal DisplayPort thread
|
// eventfd to signal DisplayPort thread
|
||||||
int mDisplayPortShutdown;
|
int mDisplayPortEventPipe;
|
||||||
private:
|
private:
|
||||||
pthread_t mPoll;
|
pthread_t mPoll;
|
||||||
pthread_t mDisplayPortPoll;
|
pthread_t mDisplayPortPoll;
|
||||||
|
|
|
@ -69,6 +69,7 @@ on post-fs
|
||||||
chown root system /sys/devices/platform/10cb0000.hsi2c/i2c-8/8-0025/usb_limit_source_enable
|
chown root system /sys/devices/platform/10cb0000.hsi2c/i2c-8/8-0025/usb_limit_source_enable
|
||||||
chown root system /sys/devices/platform/10cb0000.hsi2c/i2c-9/9-0025/usb_limit_source_enable
|
chown root system /sys/devices/platform/10cb0000.hsi2c/i2c-9/9-0025/usb_limit_source_enable
|
||||||
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd
|
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd
|
||||||
|
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/irq_hpd
|
||||||
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation
|
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation
|
||||||
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment
|
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment
|
||||||
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status
|
chown root system /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status
|
||||||
|
@ -143,6 +144,7 @@ on post-fs
|
||||||
chmod 664 /sys/devices/platform/10cb0000.hsi2c/i2c-8/8-0025/usb_limit_source_enable
|
chmod 664 /sys/devices/platform/10cb0000.hsi2c/i2c-8/8-0025/usb_limit_source_enable
|
||||||
chmod 664 /sys/devices/platform/10cb0000.hsi2c/i2c-9/9-0025/usb_limit_source_enable
|
chmod 664 /sys/devices/platform/10cb0000.hsi2c/i2c-9/9-0025/usb_limit_source_enable
|
||||||
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd
|
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/hpd
|
||||||
|
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/irq_hpd
|
||||||
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation
|
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/orientation
|
||||||
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment
|
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/pin_assignment
|
||||||
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status
|
chmod 664 /sys/devices/platform/110f0000.drmdp/drm-displayport/link_status
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue