From patchwork Thu Apr 5 09:49:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enric Balletbo i Serra X-Patchwork-Id: 10324323 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 91EAB600CB for ; Thu, 5 Apr 2018 10:11:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 800B929015 for ; Thu, 5 Apr 2018 10:11:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7461529146; Thu, 5 Apr 2018 10:11:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A737129015 for ; Thu, 5 Apr 2018 10:11:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Bif6ehnUx/m43s7dOlTMqJd/w0eaL/GJ0SNA1N9rXkI=; b=GNrnj5GGCkYQ4S5UlrrA0N6qkC v81vCbL5AJqZkF4bWAIDblmydMcwHR/5ptUlCK+yzKdHPgzMY2GSfPyLgGjGMim/XIxfoYwjGRb6L bGJ8nXJ6bZW0l8OMHKMhHKYoRz1DjLzcodvgZ1mD8qpeAweWEkB8yhUccVFKXKiC9BigfuglHOEh6 QNTDnGMvOmQ6Bep/cHTDSMv0zumqUDy5S0l0keP/WGsm/QogeCDdxa7h3vPOi4mViHhCTeB3nA46b 5xB0IO1nYOQWAgedSECqdabyXJiGV7dH0zQgfOFhef/EfRI0S3N/KLLpqK7oOQSnNSxmmcvpHLbzv pilaAOHg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1f41rc-0007bF-7i; Thu, 05 Apr 2018 10:11:28 +0000 Received: from bhuna.collabora.co.uk ([2a00:1098:0:82:1000:25:2eeb:e3e3]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1f41Y4-0007aY-EI; Thu, 05 Apr 2018 09:51:27 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: eballetbo) with ESMTPSA id 1D50C27A650 From: Enric Balletbo i Serra To: architt@codeaurora.org, inki.dae@samsung.com, thierry.reding@gmail.com, hjc@rock-chips.com, seanpaul@chromium.org, airlied@linux.ie, tfiga@chromium.org, heiko@sntech.de Subject: [PATCH v6 24/30] drm/rockchip: Disable PSR on input events Date: Thu, 5 Apr 2018 11:49:54 +0200 Message-Id: <20180405095000.9756-25-enric.balletbo@collabora.com> X-Mailer: git-send-email 2.16.3 In-Reply-To: <20180405095000.9756-1-enric.balletbo@collabora.com> References: <20180405095000.9756-1-enric.balletbo@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180405_025116_799297_AC9E6C24 X-CRM114-Status: GOOD ( 14.10 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, a.hajda@samsung.com, Laurent.pinchart@ideasonboard.com, ykk@rock-chips.com, kernel@collabora.com, m.szyprowski@samsung.com, linux-samsung-soc@vger.kernel.org, jy0922.shim@samsung.com, rydberg@bitmath.org, krzk@kernel.org, linux-rockchip@lists.infradead.org, kgene@kernel.org, linux-input@vger.kernel.org, orjan.eide@arm.com, wxt@rock-chips.com, jeffy.chen@rock-chips.com, linux-arm-kernel@lists.infradead.org, mark.yao@rock-chips.com, wzz@rock-chips.com, hl@rock-chips.com, jingoohan1@gmail.com, sw0312.kim@samsung.com, dianders@chromium.org, kyungmin.park@samsung.com, "Kristian H. Kristensen" , Enric Balletbo i Serra , kuankuan.y@gmail.com, hshi@chromium.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Kristian H. Kristensen" To improve PSR exit latency, we speculatively start exiting when we receive input events. Occasionally, this may lead to false positives, but most of the time we get a head start on coming out of PSR. Depending on how userspace takes to produce a new frame in response to the event, this can completely hide the exit latency. In case of Chrome OS, we typically get the input notifier 50ms or more before the dirty_fb triggered exit. Signed-off-by: Kristian H. Kristensen Signed-off-by: Thierry Escande Signed-off-by: Enric Balletbo i Serra Tested-by: Marek Szyprowski --- drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 134 ++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c index 9376f4396b6b..a107845ba97c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c @@ -12,6 +12,8 @@ * GNU General Public License for more details. */ +#include + #include #include @@ -35,6 +37,9 @@ struct psr_drv { enum psr_state state; struct delayed_work flush_work; + struct work_struct disable_work; + + struct input_handler input_handler; int (*set)(struct drm_encoder *encoder, bool enable); }; @@ -133,6 +138,18 @@ static void psr_flush_handler(struct work_struct *work) mutex_unlock(&psr->lock); } +static void psr_disable_handler(struct work_struct *work) +{ + struct psr_drv *psr = container_of(work, struct psr_drv, disable_work); + + /* If the state has changed since we initiated the flush, do nothing */ + mutex_lock(&psr->lock); + if (psr->state == PSR_ENABLE) + psr_set_state_locked(psr, PSR_FLUSH); + mutex_unlock(&psr->lock); + mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS); +} + /** * rockchip_drm_psr_activate - activate PSR on the given pipe * @encoder: encoder to obtain the PSR encoder @@ -173,6 +190,7 @@ int rockchip_drm_psr_deactivate(struct drm_encoder *encoder) psr->active = false; mutex_unlock(&psr->lock); cancel_delayed_work_sync(&psr->flush_work); + cancel_work_sync(&psr->disable_work); return 0; } @@ -226,6 +244,95 @@ void rockchip_drm_psr_flush_all(struct drm_device *dev) } EXPORT_SYMBOL(rockchip_drm_psr_flush_all); +static void psr_input_event(struct input_handle *handle, + unsigned int type, unsigned int code, + int value) +{ + struct psr_drv *psr = handle->handler->private; + + schedule_work(&psr->disable_work); +} + +static int psr_input_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "rockchip-psr"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + + return 0; + +err1: + input_unregister_handle(handle); +err2: + kfree(handle); + return error; +} + +static void psr_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +/* Same device ids as cpu-boost */ +static const struct input_device_id psr_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) }, + }, /* multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_X)] = BIT_MASK(ABS_X) } + + }, /* stylus or joystick device */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) }, + }, /* pointer (e.g. trackpad, mouse) */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(KEY_ESC)] = BIT_MASK(KEY_ESC) }, + }, /* keyboard */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = {[BIT_WORD(BTN_JOYSTICK)] = BIT_MASK(BTN_JOYSTICK) }, + }, /* joysticks not caught by ABS_X above */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(BTN_GAMEPAD)] = BIT_MASK(BTN_GAMEPAD) }, + }, /* gamepad */ + { }, +}; + /** * rockchip_drm_psr_register - register encoder to psr driver * @encoder: encoder that obtain the PSR function @@ -239,6 +346,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder, { struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; struct psr_drv *psr; + int error; if (!encoder || !psr_set) return -EINVAL; @@ -248,6 +356,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder, return -ENOMEM; INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler); + INIT_WORK(&psr->disable_work, psr_disable_handler); mutex_init(&psr->lock); psr->active = true; @@ -255,11 +364,33 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder, psr->encoder = encoder; psr->set = psr_set; + psr->input_handler.event = psr_input_event; + psr->input_handler.connect = psr_input_connect; + psr->input_handler.disconnect = psr_input_disconnect; + psr->input_handler.name = + kasprintf(GFP_KERNEL, "rockchip-psr-%s", encoder->name); + if (!psr->input_handler.name) { + error = -ENOMEM; + goto err2; + } + psr->input_handler.id_table = psr_ids; + psr->input_handler.private = psr; + + error = input_register_handler(&psr->input_handler); + if (error) + goto err1; + mutex_lock(&drm_drv->psr_list_lock); list_add_tail(&psr->list, &drm_drv->psr_list); mutex_unlock(&drm_drv->psr_list_lock); return 0; + + err1: + kfree(psr->input_handler.name); + err2: + kfree(psr); + return error; } EXPORT_SYMBOL(rockchip_drm_psr_register); @@ -279,8 +410,11 @@ void rockchip_drm_psr_unregister(struct drm_encoder *encoder) mutex_lock(&drm_drv->psr_list_lock); list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) { if (psr->encoder == encoder) { + input_unregister_handler(&psr->input_handler); cancel_delayed_work_sync(&psr->flush_work); + cancel_work_sync(&psr->disable_work); list_del(&psr->list); + kfree(psr->input_handler.name); kfree(psr); } }