Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 737ba109 authored by Haixia Shi's avatar Haixia Shi Committed by Sean Paul
Browse files

drm/udl: implement usb_driver suspend/resume.



The usb_driver suspend and resume function pointers must be populated
to prevent forced unbinding of USB interface driver. See usb/core/driver.c:
unbind_no_pm_drivers_interfaces().

Restore mode and damage the entire frame buffer upon resume.

TEST=suspend and resume with the same UDL device connected
TEST=suspend with UDL, unplug UDL and resume
TEST=suspend with UDL, unplug and connect another UDL device then resume

Signed-off-by: default avatarHaixia Shi <hshi@chromium.org>
Reviewed-by: default avatarStéphane Marchesin <marcheu@chromium.org>
[seanpaul fixed checkpatch warnings and gave marcheu his é back]
Signed-off-by: default avatarSean Paul <seanpaul@chromium.org>
Link: http://patchwork.freedesktop.org/patch/msgid/1472593821-38429-2-git-send-email-hshi@chromium.org
parent ae0119f5
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -16,6 +16,20 @@ static int udl_driver_set_busid(struct drm_device *d, struct drm_master *m)
	return 0;
}

static int udl_usb_suspend(struct usb_interface *interface,
			   pm_message_t message)
{
	return 0;
}

static int udl_usb_resume(struct usb_interface *interface)
{
	struct drm_device *dev = usb_get_intfdata(interface);

	udl_modeset_restore(dev);
	return 0;
}

static const struct vm_operations_struct udl_gem_vm_ops = {
	.fault = udl_gem_fault,
	.open = drm_gem_vm_open,
@@ -122,6 +136,8 @@ static struct usb_driver udl_driver = {
	.name = "udl",
	.probe = udl_usb_probe,
	.disconnect = udl_usb_disconnect,
	.suspend = udl_usb_suspend,
	.resume = udl_usb_resume,
	.id_table = id_table,
};
module_usb_driver(udl_driver);
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ struct udl_device {
	struct device *dev;
	struct drm_device *ddev;
	struct usb_device *udev;
	struct drm_crtc *crtc;

	int sku_pixel_limit;

@@ -87,6 +88,7 @@ struct udl_framebuffer {

/* modeset */
int udl_modeset_init(struct drm_device *dev);
void udl_modeset_restore(struct drm_device *dev);
void udl_modeset_cleanup(struct drm_device *dev);
int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder);

+14 −0
Original line number Diff line number Diff line
@@ -309,6 +309,8 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc,
	char *wrptr;
	int color_depth = 0;

	udl->crtc = crtc;

	buf = (char *)udl->mode_buf;

	/* for now we just clip 24 -> 16 - if we fix that fix this */
@@ -450,6 +452,18 @@ int udl_modeset_init(struct drm_device *dev)
	return 0;
}

void udl_modeset_restore(struct drm_device *dev)
{
	struct udl_device *udl = dev->dev_private;
	struct udl_framebuffer *ufb;

	if (!udl->crtc || !udl->crtc->primary->fb)
		return;
	udl_crtc_commit(udl->crtc);
	ufb = to_udl_fb(udl->crtc->primary->fb);
	udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height);
}

void udl_modeset_cleanup(struct drm_device *dev)
{
	drm_mode_config_cleanup(dev);