Received: by 2002:a05:7412:a9a2:b0:e2:908c:2ebd with SMTP id o34csp2426270rdh; Sun, 29 Oct 2023 16:06:54 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHiEcyNmk+BXZoIj7N3br3spkL+M6lzvsPUvKmo8N4nJXFW82yatGVRaeNT3OEKqwXh1pQN X-Received: by 2002:a17:90b:3149:b0:27c:efcd:109a with SMTP id ip9-20020a17090b314900b0027cefcd109amr13996858pjb.18.1698620814568; Sun, 29 Oct 2023 16:06:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698620814; cv=none; d=google.com; s=arc-20160816; b=U+t/jS72HqBKM0S0Cn5jqd+CLxyzf5jwaZ2UUVA/DpK+Ad7wya0wkRlnwst0eI0cgl 8hXW82uAdZ8yx/1/IiR0d0ztqIFqvVJ/Zhi0ZdXHpCUAHF3GTdJp2w+v02VxPNl0RAyC F/ThwX6UD3QCFbxkc/3Fc3GWuAzn1DqHGU2JtCSAMqywrycz8lGShkhskHEFS/QF94I3 PXjMM8AJkTo1yRaVxMGlG3oOuEU9Vi511GOKBL90EStU9dAgnQgiWwaiI06ohY9lolQQ NBMcYktupWsghaYkSDhvIJLJhfmJMjiKzgtdBOpSYF1vZ57h4jX10z4RtPQBt7Y0dxk/ EQDQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=dcb7c04tPiDOafAHqnE+XyK7i4FW3WqnVq3MwHk1GMk=; fh=gs5Ca2Pm2HjjtfjDl5SRKddX4w6nlfz+7vN7wN7EBUI=; b=dXbn0sdWKWhesvpovnPYm3X0lCQRQQd780ZK48kvEDA+MD1ODw0k/HgkZKPMhacwxT OxRyFeQCl6e9q7mIG1Z7B8+ffjcsoaHUnfWgTcca6YjVvJ03IJckkmWRldt2R7uloS5p Jv5FwWQoFc8pwF2idio7KtxKnYBd4wGM6PWXx22cvniubk+m1yF34G07DOfQu7B6JD0X VO2Tw9IHaNutXVmnVlnjCpqDOfRGpBfHDFlEa4WHUAxVVWnOhvatDdITsuFcfBeCy8sc Aeowx5ysFXe2WT/KOgN7RChQuVwJzZrYpYZZDjjXVum1KlpZ+Ak7NIwuATJnhMIUWWQ/ KebQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kiRA14ql; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:5 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from groat.vger.email (groat.vger.email. [2620:137:e000::3:5]) by mx.google.com with ESMTPS id h22-20020a63c016000000b005657ba564bdsi4073388pgg.826.2023.10.29.16.06.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 29 Oct 2023 16:06:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:5 as permitted sender) client-ip=2620:137:e000::3:5; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kiRA14ql; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:5 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by groat.vger.email (Postfix) with ESMTP id EF3B18089E66; Sun, 29 Oct 2023 16:06:36 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at groat.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231979AbjJ2XFq (ORCPT + 99 others); Sun, 29 Oct 2023 19:05:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231972AbjJ2XFJ (ORCPT ); Sun, 29 Oct 2023 19:05:09 -0400 Received: from mail-yw1-x1133.google.com (mail-yw1-x1133.google.com [IPv6:2607:f8b0:4864:20::1133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A14F849E9 for ; Sun, 29 Oct 2023 15:59:41 -0700 (PDT) Received: by mail-yw1-x1133.google.com with SMTP id 00721157ae682-5a8628e54d4so33759597b3.0 for ; Sun, 29 Oct 2023 15:59:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698620374; x=1699225174; darn=vger.kernel.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=dcb7c04tPiDOafAHqnE+XyK7i4FW3WqnVq3MwHk1GMk=; b=kiRA14qloxuRNiC9I5F7T8Z8iQIMIeQGWtTdKjaw4PyU2fqRDVM5in0Eva4SFDwUF2 PfAQioyG5nNao3MmSQwFzd7bD28rgGnA5JIAdweDXXqUNMLyQBP35JOelZSeAoi0Pvqp PnZyVu27uK+i722rtP2KK6I6aTWdsvSfEwC/zyVDB00hcOrEzOLfV4DaZXrOeWU/N8Ei OH4tdA4brZilKK6AiPjMXYX+86nQqkj76Fj0nY7CD/cWGkoH+vqkvuouRsV9kziV+uh+ wvs8Q+Fu9J8l4LH9WUrQwgzKFdiOdoqp4Gf0wiyCJfJTIpbLt+CZ0a6ao1YPndjLureP SP5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698620374; x=1699225174; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=dcb7c04tPiDOafAHqnE+XyK7i4FW3WqnVq3MwHk1GMk=; b=tZuemgJBXuJxeYed1qWJ/UzGw62gQ14KZzU2G7qschG3Ax95IflPBbzGmRisPkPeWP p2X3rZ2zkYAbyM8GkzjDfp74Q2P6WztdM4MMxxk6ef8EpqPftIupWtFrFidfzAM+JQZT bWlqlm6L14Ijw+rI4pf3UTo9PzF0f5gSQ82r9oYQ+4AnWu8EtOehEPMtKgrV+zmuUd2r DPid/3faz7Vg4E17aW1dg+joN86peA9JK7J/nLFhOBKTf8WN0GfFw/tP4BdwMCKXvq0r U0aUCCvKH8t/tQoNJXQpySH5ndCPnmCYFubG3uTNEBHXajYuTxdJAnbQRLwRAKuVfr4o Vahw== X-Gm-Message-State: AOJu0YyFL45JbwZCcW+/xwYr6xvv7LXRVGblXfbqCfgVkx9lGS1e+hNo 826nZHcRim+NnGIja+4iX1sNznL9wtyFUytJTMojQDDtFja1gM3x7/cplA== X-Received: by 2002:a81:af1a:0:b0:5af:60ff:cfe6 with SMTP id n26-20020a81af1a000000b005af60ffcfe6mr11174060ywh.9.1698620373804; Sun, 29 Oct 2023 15:59:33 -0700 (PDT) MIME-Version: 1.0 References: <20231029194607.379459-1-suijingfeng@loongson.cn> <20231029194607.379459-2-suijingfeng@loongson.cn> In-Reply-To: <20231029194607.379459-2-suijingfeng@loongson.cn> From: Dmitry Baryshkov Date: Mon, 30 Oct 2023 00:59:22 +0200 Message-ID: Subject: Re: [PATCH 1/8] drm/loongson: Introduce a minimal support for Loongson VBIOS To: Sui Jingfeng Cc: Maxime Ripard , Thomas Zimmermann , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on groat.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (groat.vger.email [0.0.0.0]); Sun, 29 Oct 2023 16:06:37 -0700 (PDT) On Sun, 29 Oct 2023 at 21:46, Sui Jingfeng wrote: > > Because some boards are equipped with non-transparent display bridges, > which need the VBIOS to provided parameters. > > Signed-off-by: Sui Jingfeng > --- > drivers/gpu/drm/loongson/Makefile | 3 +- > drivers/gpu/drm/loongson/loongson_device.c | 4 + > drivers/gpu/drm/loongson/loongson_vbios.c | 420 +++++++++++++++++++++ > drivers/gpu/drm/loongson/loongson_vbios.h | 59 +++ > drivers/gpu/drm/loongson/lsdc_drv.c | 4 + > drivers/gpu/drm/loongson/lsdc_drv.h | 8 + > 6 files changed, 497 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/loongson/loongson_vbios.c > create mode 100644 drivers/gpu/drm/loongson/loongson_vbios.h > > diff --git a/drivers/gpu/drm/loongson/Makefile b/drivers/gpu/drm/loongson/Makefile > index 91e72bd900c1..bef00b2c5569 100644 > --- a/drivers/gpu/drm/loongson/Makefile > +++ b/drivers/gpu/drm/loongson/Makefile > @@ -17,6 +17,7 @@ loongson-y := \ > lsdc_ttm.o > > loongson-y += loongson_device.o \ > - loongson_module.o > + loongson_module.o \ > + loongson_vbios.o > > obj-$(CONFIG_DRM_LOONGSON) += loongson.o > diff --git a/drivers/gpu/drm/loongson/loongson_device.c b/drivers/gpu/drm/loongson/loongson_device.c > index 9986c8a2a255..64096ad5466e 100644 > --- a/drivers/gpu/drm/loongson/loongson_device.c > +++ b/drivers/gpu/drm/loongson/loongson_device.c > @@ -7,6 +7,8 @@ > > #include "lsdc_drv.h" > > +extern struct loongson_vbios __loongson_vbios; Usually names with two underscores in front of them are reserved for the compiler internals or low level stuff. > + > static const struct lsdc_kms_funcs ls7a1000_kms_funcs = { > .create_i2c = lsdc_create_i2c_chan, > .irq_handler = ls7a1000_dc_irq_handler, > @@ -53,6 +55,7 @@ static const struct loongson_gfx_desc ls7a1000_gfx = { > .reg_size = 8, > }, > }, > + .vbios = &__loongson_vbios, > .chip_id = CHIP_LS7A1000, > .model = "LS7A1000 bridge chipset", > }; > @@ -85,6 +88,7 @@ static const struct loongson_gfx_desc ls7a2000_gfx = { > .reg_size = 8, > }, > }, > + .vbios = &__loongson_vbios, > .chip_id = CHIP_LS7A2000, > .model = "LS7A2000 bridge chipset", > }; > diff --git a/drivers/gpu/drm/loongson/loongson_vbios.c b/drivers/gpu/drm/loongson/loongson_vbios.c > new file mode 100644 > index 000000000000..dc304018779e > --- /dev/null > +++ b/drivers/gpu/drm/loongson/loongson_vbios.c > @@ -0,0 +1,420 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright (C) 2023 Loongson Technology Corporation Limited > + */ > + > +#include > +#include > + > +#include "loongson_vbios.h" > +#include "lsdc_drv.h" > + > +#define LOONGSON_VBIOS_HEADER_STR "Loongson-VBIOS" > +/* Legacy VBIOS is stored at offset 0 */ > +#define LOONGSON_VBIOS_LEGACY_OFFSET 0 > +/* The size of legacy VBIOS is 1 KiB */ > +#define LOONGSON_VBIOS_LEGACY_SIZE 0x000400 > + > +/* Data Control Block of Newer version of the VBIOS started at here */ > +#define LOONGSON_VBIOS_DCB_OFFSET 0x006000 > +/* The last 1 MiB of the VRAM contains the raw VBIOS data */ > +#define LOONGSON_VBIOS_BLOCK_OFFSET 0x100000 > +/* Only 256KB of the 1 MiB are used for now */ > +#define LOONGSON_VBIOS_BLOCK_SIZE 0x040000 > + > +struct loongson_vbios __loongson_vbios; > + > +/* > + * vbios data control block is a kind of metadata, which is used to index > + * real hardware device data block. > + */ > +struct loongson_vbios_dcb { > + u16 type; /* what is it */ > + u8 version; /* version of it, useless */ > + u8 id; /* index (usually same with the display pipe) of the hardware */ > + u32 offset; /* the offset of the real data */ > + u32 size; /* the size of the real data */ > + u64 ext0; /* for extension purpose */ > + u64 ext1; /* extra space reserved for future use */ > +} __packed; > + > +/* > + * Loongson-VBIOS Data Block Layout > + * > + * > + * _____________________ 0x00000 > + * |_____________________| > + * | | [0x0000, 0x0400) : legacy vbios storage > + * | Not Used Yet | > + * | | > + * |---------------------|<------- 0x6000 > + * +----| DCB 0 | > + * | |---------------------| > + * | | DCB 1 | > + * | |---------------------| Format of Data Control Blocks > + * | | One by one, packed | +------------+ > + * | |---------------------| | u16 type | > + * | | DCB N |----+ | | > + * | |---------------------| | +------------+ > + * | | . | | | u8 version | > + * | | . | | | u8 index | > + * | | . | | +------------+ > + * | |---------------------| | | | > + * | | DCB end | | | u32 offset | > + * | |---------------------| | +------- | > + * | | | | | | | > + * | |_____________________| | | +------------+ > + * | |_____________________| | | | | > + * | | | | | | u32 size | > + * +--->| vbios header info | | | | -------+ > + * |_____________________| | | | | | > + * | . | | | +------------+ | > + * | . | | | | useless | | > + * | . | | | | members | | > + * |_____________________| | | +------------+ | > + * | | | | | > + * | encoders info |<---+ | | > + * |_____________________| | | > + * | | ___| | > + * |_____________________|____/ | > + * | | | > + * | Something | | > + * |_____________________|_________________ | > + * | | | | > + * | EDID | |<--------------+ > + * |_____________________|_____________|___ > + * | | > + * | | Contents of those device specific data > + * | GPU specific info | block are implement-defined and version > + * | | dependent :0 > + * |_____________________| > + * / . / > + * / . / > + * / . / > + * |_____________________| 0x040000 > + * > + */ > + > +enum loongson_vbios_dcb_type { > + LV_DCB_HEADER = 0, > + LV_DCB_CRTC = 1, > + LV_DCB_ENCODER = 2, > + LV_DCB_CONNECTOR = 3, > + LV_DCB_I2C = 4, > + LV_DCB_PWM = 5, > + LV_DCB_GPIO = 6, > + LV_DCB_BACKLIGHT = 7, > + LV_DCB_FAN = 8, > + LV_DCB_IRQ = 9, > + LV_DCB_ENCODER_CFG = 10, > + LV_DCB_ENCODER_RES = 11, > + LV_DCB_GPU = 12, > + LV_DCB_UNKNOWN = 13, > + LV_DCB_END = 0xffff, > +}; > + > +struct loongson_vbios_header { > + char header[16]; > + u32 version_major; Please specify whether this is BE or LE. (__be32 or __le32). Usually we use le32_to_cpu / be32_to_cpu helpers to access external data. > + u32 version_minor; > + char information[20]; > + u32 num_crtc; > + u32 crtc_offset; > + u32 num_connector; > + u32 connector_offset; > + u32 num_encoder; > + u32 encoder_offset; > +} __packed; > + > +struct loongson_vbios_encoder { > + u32 feature; > + u32 i2c_id; > + u32 connector_id; > + u32 type; > + u32 config_method; > + u32 chip_id; > + u8 chip_addr; > +} __packed; > + > +struct loongson_vbios_connector { > + u32 feature; > + u32 i2c_id; > + u8 edid[256]; > + u32 type; > + u32 hotplug_method; > + u32 edid_method; > + u32 hpd_int_gpio; > + u32 gpio_place; > +} __packed; > + > +/* > + * A list node which contains the information about the device specific data > + * block, the device here refer to the property or topology of hardware > + * configuration, such as external display bridges, HDP GPIO, connectors etc. > + */ > +struct loongson_vbios_node { > + struct list_head head; > + > + /* @type: the type of the data. For search */ > + u32 type; > + /* @id: the index(display pipe) of the data belong to. For search */ > + u32 id; > + /* > + * @data: point to the device specific data block, such as external > + * encoders name and it's i2c device address, hpd gpio resource etc. > + */ > + const void *data; > + /* > + * The size of the data. > + */ > + u32 size; > +}; > + > +/* > + * The returned pointer is actually point to &__loongson_vbios, but this > + * function is only intended to provide READ-ONLY access. As our vbios is > + * only be able to pass(provide) parameters, it is not executable and outside > + * should not modify it. > + */ > +const struct loongson_vbios *to_loongson_vbios(struct drm_device *ddev) > +{ > + struct lsdc_device *ldev = to_lsdc(ddev); > + const struct loongson_gfx_desc *gfx = to_loongson_gfx(ldev->descp); > + > + return gfx->vbios; > +} > + > +static bool loongson_vbios_is_valid(const struct loongson_vbios *vbios) > +{ > + char header[32]; > + > + memcpy(header, vbios->raw_data, sizeof(header)); > + > + if (strcmp(header, LOONGSON_VBIOS_HEADER_STR)) > + return false; > + > + return true; > +} > + > +/* > + * The VBIOS blob is stored at the last 1 MiB of the VRAM, no SPI flush or flash? > + * EEPROM is needed. Platform BIOS is responsible for store this VBIOS blob storing > + * data at right position on per boot time. > + */ > +static int loongson_vbios_construct(struct drm_device *ddev, > + struct loongson_vbios *vbios) > +{ > + struct lsdc_device *ldev = to_lsdc(ddev); > + u64 vram_end = ldev->vram_base + ldev->vram_size; > + u64 vbios_start = vram_end - LOONGSON_VBIOS_BLOCK_OFFSET; > + void __iomem *ptr; > + > + vbios->raw_data = kzalloc(LOONGSON_VBIOS_BLOCK_SIZE, GFP_KERNEL); > + if (!vbios->raw_data) > + return -ENOMEM; > + > + ptr = ioremap(vbios_start, LOONGSON_VBIOS_BLOCK_SIZE); > + if (!ptr) { > + drm_err(ddev, "Map VBIOS region failed\n"); > + return -ENOMEM; > + } > + > + memcpy_fromio(vbios->raw_data, ptr, LOONGSON_VBIOS_BLOCK_SIZE); > + > + iounmap(ptr); > + > + INIT_LIST_HEAD(&vbios->list); > + vbios->ddev = ddev; > + > + return 0; > +} > + > +static void loongson_vbios_destruct(struct drm_device *ddev, void *data) destroy or free. Also you can use drmm_ functions to make destructor unnecessary. > +{ > + struct loongson_vbios *vbios = (struct loongson_vbios *)data; > + struct loongson_vbios_node *node; > + struct loongson_vbios_node *tmp; > + > + list_for_each_entry_safe(node, tmp, &vbios->list, head) { > + list_del(&node->head); > + kfree(node); > + } > + > + kfree(vbios->raw_data); > + vbios->raw_data = NULL; > +} > + > +static void loongson_vbios_print_dcb(struct drm_device *ddev, > + struct loongson_vbios_dcb *dcb) > +{ > + drm_info(ddev, "type: %u, Offset: %u, Size: %u, version: %u, ID: %u\n", > + dcb->type, dcb->offset, dcb->size, dcb->version, dcb->id); > +} > + > +/* > + * Process the data control block, establish a list for later searching. > + * returns the number of data control block. Generally, loongson vbios > + * has only 10 DCB or so. > + */ > +static int loongson_vbios_process_dcb(struct loongson_vbios *vbios, > + bool verbose) > +{ > + struct drm_device *ddev = vbios->ddev; > + void *base = vbios->raw_data; > + int count = 0; > + struct loongson_vbios_dcb *dcb; > + > + dcb = (struct loongson_vbios_dcb *)(base + LOONGSON_VBIOS_DCB_OFFSET); > + > + while (dcb->type != LV_DCB_END) { > + struct loongson_vbios_node *node; > + > + node = kzalloc(sizeof(*node), GFP_KERNEL); > + if (!node) > + return -ENOMEM; > + > + node->type = dcb->type; > + node->id = dcb->id; > + node->data = base + dcb->offset; > + node->size = dcb->size; > + > + list_add_tail(&node->head, &vbios->list); > + > + if (verbose) > + loongson_vbios_print_dcb(ddev, dcb); > + > + ++dcb; > + > + if (++count > 1024) { > + drm_err(ddev, "Unlikely, DCB is too much\n"); > + break; > + } > + } > + > + return count; > +} > + > +static const struct loongson_vbios_node * > +loongson_vbios_get_node(struct drm_device *ddev, u32 type, u32 id) > +{ > + const struct loongson_vbios *vbios = to_loongson_vbios(ddev); > + struct loongson_vbios_node *np; > + > + if (!vbios) > + return NULL; > + > + list_for_each_entry(np, &vbios->list, head) { > + if (np->type == type && np->id == id) > + return np; > + } > + > + return NULL; > +} > + > +bool loongson_vbios_query_encoder_info(struct drm_device *ddev, > + u32 pipe, > + u32 *type, > + enum loongson_vbios_encoder_name *name, > + u8 *i2c_addr) > +{ > + const struct loongson_vbios_encoder *vencoder; > + const struct loongson_vbios_node *np; > + > + np = loongson_vbios_get_node(ddev, LV_DCB_ENCODER, pipe); > + if (!np) > + return false; > + > + if (np->size != sizeof(*vencoder)) > + WARN_ON(1); > + > + vencoder = (const struct loongson_vbios_encoder *)np->data; > + > + if (type) > + *type = vencoder->type; > + > + if (name) > + *name = vencoder->chip_id; > + > + /* i2c address, as a slave device */ > + if (i2c_addr) > + *i2c_addr = vencoder->chip_addr; > + > + return true; > +} > + > +bool loongson_vbios_query_connector_info(struct drm_device *ddev, > + u32 pipe, > + u32 *connector_type, > + u32 *hpd_method, > + u32 *int_gpio, > + u8 *edid_blob) > +{ > + const struct loongson_vbios_connector *vconnector; > + const struct loongson_vbios_node *np; > + > + np = loongson_vbios_get_node(ddev, LV_DCB_CONNECTOR, pipe); > + if (!np) > + return false; > + > + if (np->size != sizeof(*vconnector)) > + WARN_ON(1); > + > + vconnector = (const struct loongson_vbios_connector *)np->data; > + > + if (connector_type) > + *connector_type = vconnector->type; > + > + if (edid_blob) > + memcpy(edid_blob, vconnector->edid, 256); > + > + if (int_gpio) > + *int_gpio = vconnector->hpd_int_gpio; > + > + return true; > +} > + > +static void loongson_vbios_acquire_version(struct drm_device *ddev, > + struct loongson_vbios *vbios) > +{ > + struct loongson_vbios_header *vh; > + > + vh = (struct loongson_vbios_header *)vbios->raw_data; > + > + vbios->version_major = vh->version_major; > + vbios->version_minor = vh->version_minor; > + > + drm_info(ddev, "Loongson VBIOS version: %u.%u\n", > + vh->version_major, vh->version_minor); > +} > + > +int loongson_vbios_init(struct drm_device *ddev) > +{ > + struct loongson_vbios *vbios = &__loongson_vbios; > + int ret; > + int num; > + > + ret = loongson_vbios_construct(ddev, vbios); > + if (ret) > + return ret; > + > + ret = drmm_add_action_or_reset(ddev, loongson_vbios_destruct, vbios); > + if (ret) > + return ret; > + > + if (!loongson_vbios_is_valid(vbios)) { > + drm_err(ddev, "Loongson VBIOS: header is invalid\n"); > + return -EINVAL; > + } > + > + loongson_vbios_acquire_version(ddev, vbios); get_version. > + > + num = loongson_vbios_process_dcb(vbios, false); > + if (num <= 0) { > + drm_err(ddev, "Loongson VBIOS: Process DCB failed\n"); > + return -EINVAL; > + } > + > + drm_info(ddev, "Loongson VBIOS: has %d DCBs\n", num); > + > + return 0; > +} > diff --git a/drivers/gpu/drm/loongson/loongson_vbios.h b/drivers/gpu/drm/loongson/loongson_vbios.h > new file mode 100644 > index 000000000000..66fb43b3609e > --- /dev/null > +++ b/drivers/gpu/drm/loongson/loongson_vbios.h > @@ -0,0 +1,59 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * Copyright (C) 2023 Loongson Technology Corporation Limited > + */ > + > +#ifndef __LOONGSON_VBIOS_H__ > +#define __LOONGSON_VBIOS_H__ > + > +#include > + > +struct loongson_vbios { > + struct list_head list; > + void *raw_data; > + struct drm_device *ddev; > + u32 version_major; > + u32 version_minor; > +}; > + > +enum loongson_vbios_encoder_name { > + ENCODER_CHIP_UNKNOWN = 0x00, > + ENCODER_CHIP_INTERNAL_VGA = 0x01, > + ENCODER_CHIP_INTERNAL_HDMI = 0x02, > + ENCODER_CHIP_CH7055 = 0x10, > + ENCODER_CHIP_ADV7125 = 0x11, > + ENCODER_CHIP_TFP410 = 0x20, > + ENCODER_CHIP_IT66121 = 0x30, > + ENCODER_CHIP_SIL9022 = 0x31, > + ENCODER_CHIP_LT8618 = 0x32, > + ENCODER_CHIP_MS7210 = 0x33, > + ENCODER_CHIP_NCS8805 = 0x40, > + ENCODER_CHIP_LT9721 = 0x42, > + ENCODER_CHIP_LT6711 = 0x43, > + ENCODER_CHIP_LT8619 = 0x50, > +}; > + > +enum loongson_vbios_hotplug_method { > + LV_HPD_DISABLED = 0, > + LV_HPD_POLLING = 1, > + LV_HPD_IRQ = 2, > +}; > + > +const struct loongson_vbios *to_loongson_vbios(struct drm_device *ddev); > + > +bool loongson_vbios_query_encoder_info(struct drm_device *ddev, > + u32 pipe, > + u32 *type, > + enum loongson_vbios_encoder_name *name, > + u8 *i2c_addr); > + > +bool loongson_vbios_query_connector_info(struct drm_device *ddev, > + u32 pipe, > + u32 *connector_type, > + u32 *hpd_method, > + u32 *int_gpio, > + u8 *edid_blob); > + > +int loongson_vbios_init(struct drm_device *ddev); > + > +#endif > diff --git a/drivers/gpu/drm/loongson/lsdc_drv.c b/drivers/gpu/drm/loongson/lsdc_drv.c > index 89ccc0c43169..aebb200fa567 100644 > --- a/drivers/gpu/drm/loongson/lsdc_drv.c > +++ b/drivers/gpu/drm/loongson/lsdc_drv.c > @@ -213,6 +213,10 @@ lsdc_create_device(struct pci_dev *pdev, > return ERR_PTR(ret); > } > > + ret = loongson_vbios_init(ddev); > + if (ret) > + drm_info(ddev, "No VBIOS support\n"); > + > ret = drm_aperture_remove_conflicting_framebuffers(ldev->vram_base, > ldev->vram_size, > driver); > diff --git a/drivers/gpu/drm/loongson/lsdc_drv.h b/drivers/gpu/drm/loongson/lsdc_drv.h > index fbf2d760ef27..335953c988d1 100644 > --- a/drivers/gpu/drm/loongson/lsdc_drv.h > +++ b/drivers/gpu/drm/loongson/lsdc_drv.h > @@ -16,6 +16,7 @@ > #include > #include > > +#include "loongson_vbios.h" > #include "lsdc_i2c.h" > #include "lsdc_irq.h" > #include "lsdc_gfxpll.h" > @@ -85,6 +86,13 @@ struct loongson_gfx_desc { > u32 reg_size; > } pixpll[LSDC_NUM_CRTC]; > > + /* > + * @vbios: Provide information about the output configuration, > + * and provide information about dynamic features which cannot > + * be detected(determined) with the chip_id. > + */ > + const struct loongson_vbios *vbios; > + > enum loongson_chip_id chip_id; > char model[64]; > }; > -- > 2.34.1 > -- With best wishes Dmitry