From patchwork Thu Jul 6 14:28:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 9828355 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 20B18602BD for ; Thu, 6 Jul 2017 14:28:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 88D2C27F8F for ; Thu, 6 Jul 2017 14:28:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7BA1A28552; Thu, 6 Jul 2017 14:28:44 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C08CC27F8F for ; Thu, 6 Jul 2017 14:28:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751861AbdGFO2n (ORCPT ); Thu, 6 Jul 2017 10:28:43 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43150 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751862AbdGFO2m (ORCPT ); Thu, 6 Jul 2017 10:28:42 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B68877CE12; Thu, 6 Jul 2017 14:28:41 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com B68877CE12 Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=hdegoede@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com B68877CE12 Received: from shalem.localdomain.com (ovpn-116-133.ams2.redhat.com [10.36.116.133]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8036D6C21A; Thu, 6 Jul 2017 14:28:40 +0000 (UTC) From: Hans de Goede To: Bartlomiej Zolnierkiewicz , Jean Delvare Cc: Hans de Goede , linux-fbdev@vger.kernel.org Subject: [PATCH v2] video/console: Add dmi quirk table for x86 systems which need fbcon rotation Date: Thu, 6 Jul 2017 16:28:39 +0200 Message-Id: <20170706142839.14659-1-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Thu, 06 Jul 2017 14:28:41 +0000 (UTC) Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Some x86 clamshell design devices use portrait tablet screens and a display engine which cannot rotate in hardware, so we need to rotate the fbcon to compensate. This commit adds a DMI based quirk table which is initially populated with 3 such devices: The GPD Win, the GPD Pocket and the I.T.Works TW891, so that the console comes up in the right orientation on this devices OOTB. Unfortunately these (cheap) devices also typically have quite generic DMI data, so we match on a combination of DMI data, screen resolution and a list of known BIOS dates to avoid false positives. Since we are now not just checking dmi-strings but also other variables we cannot use dmi_check_system. So this commit exports dmi_matches and we use our own loop over the table entries using dmi_matches to match the dmi strings. Signed-off-by: Hans de Goede --- Changes in v2: -Extend the commit message explaining why dmi_check_system does not work and this commit exports and uses dmi_matches instead --- drivers/firmware/dmi_scan.c | 3 +- drivers/video/console/Makefile | 3 + drivers/video/console/fbcon.c | 12 +++- drivers/video/console/fbcon.h | 7 ++- drivers/video/console/fbcon_dmi_quirks.c | 103 +++++++++++++++++++++++++++++++ include/linux/dmi.h | 1 + 6 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 drivers/video/console/fbcon_dmi_quirks.c diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 783041964439..bb1ad8b6939d 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -780,7 +780,7 @@ void __init dmi_set_dump_stack_arch_desc(void) * dmi_matches - check if dmi_system_id structure matches system DMI data * @dmi: pointer to the dmi_system_id structure to check */ -static bool dmi_matches(const struct dmi_system_id *dmi) +bool dmi_matches(const struct dmi_system_id *dmi) { int i; @@ -804,6 +804,7 @@ static bool dmi_matches(const struct dmi_system_id *dmi) } return true; } +EXPORT_SYMBOL(dmi_matches); /** * dmi_is_end_of_table - check for end-of-table marker diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 43bfa485db96..32ee2ad37369 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -15,5 +15,8 @@ ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION),y) obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \ fbcon_ccw.o endif +ifeq ($(CONFIG_DMI),y) +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_dmi_quirks.o +endif obj-$(CONFIG_FB_STI) += sticore.o diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 12ded23f1aaf..3db5ac2bfbb7 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -135,7 +135,7 @@ static char fontname[40]; static int info_idx = -1; /* console rotation */ -static int initial_rotation; +static int initial_rotation = -1; static int fbcon_has_sysfs; static const struct consw fb_con; @@ -954,7 +954,10 @@ static const char *fbcon_startup(void) ops->cur_rotate = -1; ops->cur_blink_jiffies = HZ / 5; info->fbcon_par = ops; - p->con_rotate = initial_rotation; + if (initial_rotation != -1) + p->con_rotate = initial_rotation; + else + p->con_rotate = fbcon_platform_get_rotate(info); set_blitting_type(vc, info); if (info->fix.type != FB_TYPE_TEXT) { @@ -1091,7 +1094,10 @@ static void fbcon_init(struct vc_data *vc, int init) ops = info->fbcon_par; ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms); - p->con_rotate = initial_rotation; + if (initial_rotation != -1) + p->con_rotate = initial_rotation; + else + p->con_rotate = fbcon_platform_get_rotate(info); set_blitting_type(vc, info); cols = vc->vc_cols; diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 7aaa4eabbba0..60e25e173fdb 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -261,5 +261,10 @@ extern void fbcon_set_rotate(struct fbcon_ops *ops); #define fbcon_set_rotate(x) do {} while(0) #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ -#endif /* _VIDEO_FBCON_H */ +#ifdef CONFIG_DMI +int fbcon_platform_get_rotate(struct fb_info *info); +#else +#define fbcon_platform_get_rotate(i) FB_ROTATE_UR +#endif /* CONFIG_DMI */ +#endif /* _VIDEO_FBCON_H */ diff --git a/drivers/video/console/fbcon_dmi_quirks.c b/drivers/video/console/fbcon_dmi_quirks.c new file mode 100644 index 000000000000..3267cab38717 --- /dev/null +++ b/drivers/video/console/fbcon_dmi_quirks.c @@ -0,0 +1,103 @@ +/* + * fbcon_dmi_quirks.c -- DMI based quirk detection for fbcon + * + * Copyright (C) 2017 Hans de Goede + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include +#include +#include +#include "fbcon.h" + +/* + * Some x86 clamshell design devices use portrait tablet screens and a display + * engine which cannot rotate in hardware, so we need to rotate the fbcon to + * compensate. Unfortunately these (cheap) devices also typically have quite + * generic DMI data, so we match on a combination of DMI data, screen resolution + * and a list of known BIOS dates to avoid false positives. + */ + +struct fbcon_dmi_rotate_data { + struct dmi_system_id dmi_id; + int width; + int height; + const char * const *bios_dates; + int rotate; +}; + +static const struct fbcon_dmi_rotate_data rotate_data[] = { + { /* + * GPD Win, note that the the DMI data is less generic then it + * seems, devices with a board_vendor of "AMI Corporation" are + * quite rare, as are devices which have both board- *and* + * product-id set to "Default String" + */ + .dmi_id = { .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Default string"), + DMI_MATCH(DMI_BOARD_SERIAL, "Default string"), + DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), + } }, + .width = 720, + .height = 1280, + .bios_dates = (const char * const []){ + "10/25/2016", "11/18/2016", "02/21/2017", + "03/20/2017", NULL }, + .rotate = FB_ROTATE_CW + }, { /* GPD Pocket (same note on DMI match as GPD Win) */ + .dmi_id = { .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Default string"), + DMI_MATCH(DMI_BOARD_SERIAL, "Default string"), + DMI_MATCH(DMI_PRODUCT_NAME, "Default string"), + } }, + .width = 1200, + .height = 1920, + .bios_dates = (const char * const []){ "05/26/2017", NULL }, + .rotate = FB_ROTATE_CW, + }, { /* I.T.Works TW891 */ + .dmi_id = { .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."), + DMI_MATCH(DMI_PRODUCT_NAME, "TW891"), + DMI_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."), + DMI_MATCH(DMI_BOARD_NAME, "TW891"), + } }, + .width = 800, + .height = 1280, + .bios_dates = (const char * const []){ "10/16/2015", NULL }, + .rotate = FB_ROTATE_CW, + } +}; + +int fbcon_platform_get_rotate(struct fb_info *info) +{ + const char *bios_date; + int i, j; + + for (i = 0; i < ARRAY_SIZE(rotate_data); i++) { + if (!dmi_matches(&rotate_data[i].dmi_id)) + continue; + + if (rotate_data[i].width != info->var.xres || + rotate_data[i].height != info->var.yres) + continue; + + if (!rotate_data[i].bios_dates) + return rotate_data->rotate; + + bios_date = dmi_get_system_info(DMI_BIOS_DATE); + if (!bios_date) + continue; + + for (j = 0; rotate_data[i].bios_dates[j]; j++) { + if (!strcmp(rotate_data[i].bios_dates[j], bios_date)) + return rotate_data->rotate; + } + } + + return FB_ROTATE_UR; +} diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 9bbf21a516e4..f1d28af7ed53 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -98,6 +98,7 @@ struct dmi_dev_onboard { extern struct kobject *dmi_kobj; extern int dmi_check_system(const struct dmi_system_id *list); const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list); +bool dmi_matches(const struct dmi_system_id *dmi); extern const char * dmi_get_system_info(int field); extern const struct dmi_device * dmi_find_device(int type, const char *name, const struct dmi_device *from);