From nobody Wed Nov 27 16:50:45 2024 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A2FF1DFDB2 for ; Tue, 8 Oct 2024 14:18:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728397119; cv=none; b=g7L5+R6p7FLAl6ghr2zE3Je2R3yArs43tI9L1DaAt3ZIjMm2/KsEz1o0XcG0myroo56QXezradaULyZtNvm+KBn8NIpcoSUVVmAb0MYy2/uSsRSEa6BrhqmYEfDJFfRoQyRKt272p2x0iKH7+sO5CmlP7ziqvfbemDyR9U8guGo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728397119; c=relaxed/simple; bh=Twf9mm7xogNNeoBoUvQt5BEkK5aQyfHPm72uUfULHLI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=hK7A0LjH8NBFelNGWdn4cQ1IFt2Pqpwc5CLVcoitXsQsA5nvO+Xb0RVxFH5ULaPSIWm6CnTCUtl17WbyaK76qqqIWqaDGDMMGg6qbPfPTeHBNwUqudWzUdHYmEMkTbTJnJp3CuZjBAcIEW0hJMqZPUeLkH/GLBlOaRLvxmJjX+Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=pUyWPLeT; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="pUyWPLeT" Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 498DqX01010551; Tue, 8 Oct 2024 14:18:12 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= h7KtTqJFLwF8PTmHcsqsieXXCW211RyQKjuk7kT+TCw=; b=pUyWPLeT/4Tw011n qnw0RLpYF4UxAW9SnJkgNRj5ARrafMOlmfEiZmb9+xrcE6LnizDM6O29zHaoSoWa zWM2/ArN9Y542vmalE+OME5YSmpOD84cBNue/U2Q4HmCU/An/luL3ohfzTbP8wPo Z7ZAdj7KZ1FYlH44qDziXua1eomd6VYK8C0J3bDGq0wr+JTpQ/ZQ9RWc9n3fRVWk fxFD8Fo1CVCCBIZcQFX1X3wfB6W4TdOptjg7GHtGq2HMcCSlgmgJkoHlWoF68kKJ 5UvdFXeBb0z5ttu28/MxmEQS+cHuuif9uwLAO3fugMb50/BwSBIjXze+ZjD1Kz3v pTw/qg== Received: from nasanppmta05.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 424x7rsfrn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 08 Oct 2024 14:18:11 +0000 (GMT) Received: from nasanex01b.na.qualcomm.com (nasanex01b.na.qualcomm.com [10.46.141.250]) by NASANPPMTA05.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 498EIBrm016899 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 8 Oct 2024 14:18:11 GMT Received: from jesszhan-linux.qualcomm.com (10.80.80.8) by nasanex01b.na.qualcomm.com (10.46.141.250) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Tue, 8 Oct 2024 07:18:10 -0700 From: Jessica Zhang Date: Tue, 8 Oct 2024 07:17:38 -0700 Subject: [PATCH RFC v2 1/3] drm/panel: add driver for simulated panel Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20241008-jz-test-sim-panel-v2-1-d60046470e6c@quicinc.com> References: <20241008-jz-test-sim-panel-v2-0-d60046470e6c@quicinc.com> In-Reply-To: <20241008-jz-test-sim-panel-v2-0-d60046470e6c@quicinc.com> To: Neil Armstrong , Sam Ravnborg , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Jessica Zhang , Simona Vetter , Andrzej Hajda , Robert Foss , Laurent Pinchart , Jonas Karlman , "Jernej Skrabec" , Simona Vetter CC: , , X-Mailer: b4 0.15-dev-2a633 X-Developer-Signature: v=1; a=ed25519-sha256; t=1728397090; l=13166; i=quic_jesszhan@quicinc.com; s=20230329; h=from:subject:message-id; bh=Twf9mm7xogNNeoBoUvQt5BEkK5aQyfHPm72uUfULHLI=; b=wg0HTjqEbkwRUK2/Q1qhXNEiTjU22FDnaxELIiZRQH02uCh0lClrG+7kGTaYQfeFqEWDszIMx r8gimxIBbP2ACZuYWgbRpZunVzJSEq1egsJOwaNb/vtQdow69Za6f8h X-Developer-Key: i=quic_jesszhan@quicinc.com; a=ed25519; pk=gAUCgHZ6wTJOzQa3U0GfeCDH7iZLlqIEPo4rrjfDpWE= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01b.na.qualcomm.com (10.46.141.250) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: Ofn_klOyOcAbgE3uEJmokhHK83dxKWya X-Proofpoint-ORIG-GUID: Ofn_klOyOcAbgE3uEJmokhHK83dxKWya X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 suspectscore=0 phishscore=0 mlxlogscore=999 spamscore=0 clxscore=1011 malwarescore=0 lowpriorityscore=0 priorityscore=1501 mlxscore=0 adultscore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2410080091 Add a driver for simulating DSI panels. The DSI simulated panel can be configured via the sim_panel configfs. Currently, the simulated panel supports configuring a supported DRM mode (modes) and setting the DSI mode flags (mode_flags). To enable the simulated panel, the user must write the DSI host device name to the "enable" node. Signed-off-by: Jessica Zhang --- MAINTAINERS | 5 + drivers/gpu/drm/panel/Kconfig | 9 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-simulation.c | 371 +++++++++++++++++++++++++++= ++++ 4 files changed, 386 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c27f3190737f8b85779bde5489639c8b899f4fd8..cd7019cf3b492691059d897a739= dc746266e6ae8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7383,6 +7383,11 @@ S: Maintained F: Documentation/devicetree/bindings/display/panel/samsung,s6d7aa0.yaml F: drivers/gpu/drm/panel/panel-samsung-s6d7aa0.c =20 +DRM DRIVER FOR SIMULATED DSI PANELS +M: Jessica Zhang +S: Maintained +F: drivers/gpu/drm/panel/panel-simulation.c + DRM DRIVER FOR SITRONIX ST7586 PANELS M: David Lechner S: Maintained diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index d3a9a9fafe4ec7c276214871cc43be099f3a5534..d9aacb8c287371f072fe6652c7e= 884d5764be567 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -96,6 +96,15 @@ config DRM_PANEL_BOE_TV101WUM_LL2 Say Y here if you want to support for BOE TV101WUM-LL2 WUXGA PANEL DSI Video Mode panel =20 +config DRM_PANEL_SIMULATION + tristate "support for simulation panels" + depends on DRM_MIPI_DSI + help + Say Y here if you want to simulate a DSI panel. This module will allow + users to configure a simulated DSI panel driver via the configfs. + Enabling this config will cause the physical panel driver to not be + attached to its DSI host. + config DRM_PANEL_EBBG_FT8719 tristate "EBBG FT8719 panel driver" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 987a0870241035c6184a25c412c17caf03465dff..75038f6d93ba3d93c8274442904= 4e2ec8dfe51f8 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_DRM_PANEL_BOE_TV101WUM_NL6) +=3D panel-boe-t= v101wum-nl6.o obj-$(CONFIG_DRM_PANEL_DSI_CM) +=3D panel-dsi-cm.o obj-$(CONFIG_DRM_PANEL_LVDS) +=3D panel-lvds.o obj-$(CONFIG_DRM_PANEL_SIMPLE) +=3D panel-simple.o +obj-$(CONFIG_DRM_PANEL_SIMULATION) +=3D panel-simulation.o obj-$(CONFIG_DRM_PANEL_EDP) +=3D panel-edp.o obj-$(CONFIG_DRM_PANEL_EBBG_FT8719) +=3D panel-ebbg-ft8719.o obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) +=3D panel-elida-kd35t133.o diff --git a/drivers/gpu/drm/panel/panel-simulation.c b/drivers/gpu/drm/pan= el/panel-simulation.c new file mode 100644 index 0000000000000000000000000000000000000000..2f14bd36062ec876cf573637f9e= 4d6193a3a2864 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-simulation.c @@ -0,0 +1,371 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + +#include +#include + +#include +#include +#include +#include + +#define MAX_DSI_COUNT 2 + +static struct mipi_dsi_driver panel_simulation_driver; +struct panel_simulation; +struct panel_simulation_cfs { + struct config_group group; + struct panel_simulation *panel; + char *dev_name; + unsigned int num_modes; + struct drm_display_mode *display_modes; + u32 mode_flags; +}; + +struct panel_simulation { + struct drm_panel base; + unsigned int num_modes; + struct drm_display_mode *display_modes; + struct mipi_dsi_device *dsi; +}; + +static struct drm_display_mode sim_panel_default_mode =3D { + .clock =3D 345830, + .hdisplay =3D 1080, + .hsync_start =3D 1175, + .hsync_end =3D 1176, + .htotal =3D 1216, + .vdisplay =3D 2340, + .vsync_start =3D 2365, + .vsync_end =3D 2366, + .vtotal =3D 2370, + .width_mm =3D 0, + .height_mm =3D 0, + .type =3D DRM_MODE_TYPE_DRIVER, + .name =3D "FOO", +}; + +static inline struct panel_simulation *to_sim_panel(struct drm_panel *pane= l) +{ + return container_of(panel, struct panel_simulation, base); +} + +static int panel_simulation_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + struct panel_simulation *sim_panel =3D to_sim_panel(panel); + struct drm_display_mode *mode; + u32 num_modes =3D 0; + + for (int i =3D 0; i < sim_panel->num_modes; i++) { + mode =3D drm_mode_duplicate(connector->dev, + &sim_panel->display_modes[i]); + if (!mode) { + dev_err(panel->dev, "failed to add mode %s\n", + sim_panel->display_modes[i].name); + continue; + } + + drm_mode_set_name(mode); + num_modes++; + } + + mode->type =3D DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + connector->display_info.width_mm =3D mode->width_mm; + connector->display_info.height_mm =3D mode->height_mm; + drm_mode_probed_add(connector, mode); + + return num_modes; +} + +static const struct drm_panel_funcs panel_simulation_funcs =3D { + .get_modes =3D panel_simulation_get_modes, +}; + +static inline struct panel_simulation_cfs *get_sim_panel_config(struct con= fig_item *item) +{ + return container_of(to_config_group(item), + struct panel_simulation_cfs, group); +} + +static ssize_t sim_panel_cfs_item_enable_show(struct config_item *item, ch= ar *page) +{ + struct panel_simulation_cfs *config =3D get_sim_panel_config(item); + + return sprintf(page, "%s\n", config->dev_name); +} + +static ssize_t sim_panel_cfs_item_enable_store(struct config_item *item, + const char *page, size_t count) +{ + struct panel_simulation_cfs *config =3D get_sim_panel_config(item); + struct device *dev; + int ret; + char name[216]; + + if (config->dev_name) + return count; + + strscpy(name, page, strcspn(page, "\n")); + name[strcspn(page, "\n")] =3D '\0'; + + dev =3D bus_find_device_by_name(panel_simulation_driver.driver.bus, + NULL, name); + if (!dev) + return -EINVAL; + + config->dev_name =3D name; + + dev_set_drvdata(dev, config); + ret =3D device_reprobe(dev); + if (ret) + dev_warn(dev, "failed to reprobe: %d\n", ret); + + return count; +} +CONFIGFS_ATTR(sim_panel_cfs_item_, enable); + +static ssize_t sim_panel_cfs_item_modes_show(struct config_item *item, cha= r *page) +{ + struct panel_simulation_cfs *configfs =3D get_sim_panel_config(item); + int count =3D 0; + + for (int i =3D 0; i < configfs->num_modes; i++) { + count +=3D sprintf(page, DRM_MODE_FMT "\n", + DRM_MODE_ARG(&configfs->display_modes[i])); + } + + return count; +} + +static struct drm_display_mode *panel_simulation_parse_modes(const char *b= uf, + struct panel_simulation_cfs *config) +{ + int ret, num_modes; + struct drm_display_mode *modes =3D drm_mode_create(NULL); + + if (!modes) + return NULL; + + ret =3D sscanf(buf, "%d %hu %hu %hu %hu %hu %hu %hu %hu 0x%hhx 0x%x", + &modes->clock, &modes->hdisplay, &modes->hsync_start, + &modes->hsync_end, &modes->htotal, &modes->vdisplay, + &modes->vsync_start, &modes->vsync_end, &modes->vtotal, + &modes->type, &modes->flags); + if (ret !=3D 11) + return NULL; + + snprintf(modes->name, sizeof(modes->name), "custom%dx%d@%d", + modes->hdisplay, modes->vdisplay, + drm_mode_vrefresh(modes)); + num_modes =3D 1; + + config->num_modes =3D num_modes; + + return modes; +} + +static ssize_t sim_panel_cfs_item_modes_store(struct config_item *item, + const char *page, size_t count) +{ + struct panel_simulation_cfs *config =3D get_sim_panel_config(item); + struct drm_display_mode *new_modes =3D NULL; + + if (config->dev_name) + return count; + + new_modes =3D panel_simulation_parse_modes(page, config); + if (!new_modes) + return -EINVAL; + + config->display_modes =3D new_modes; + + return count; +} +CONFIGFS_ATTR(sim_panel_cfs_item_, modes); + +static ssize_t sim_panel_cfs_item_mode_flags_show(struct config_item *item, + char *page) +{ + struct panel_simulation_cfs *configfs =3D get_sim_panel_config(item); + + return sprintf(page, "%d\n", configfs->mode_flags); +} + +static ssize_t sim_panel_cfs_item_mode_flags_store(struct config_item *ite= m, + const char *page, size_t count) +{ + struct panel_simulation_cfs *configfs =3D get_sim_panel_config(item); + int ret, mode_flags; + + ret =3D kstrtoint(page, 0, &mode_flags); + if (ret < 0) + return ret; + + configfs->mode_flags =3D mode_flags; + + return 0; +} +CONFIGFS_ATTR(sim_panel_cfs_item_, mode_flags); + +static struct configfs_attribute *sim_panel_cfs_item_attrs[] =3D { + &sim_panel_cfs_item_attr_enable, + &sim_panel_cfs_item_attr_modes, + &sim_panel_cfs_item_attr_mode_flags, + NULL, +}; + +static void sim_panel_cfs_item_release(struct config_item *item) +{ + kfree(get_sim_panel_config(item)); +} + +static struct configfs_item_operations sim_panel_cfs_item_ops =3D { + .release =3D sim_panel_cfs_item_release, +}; + +static const struct config_item_type sim_panel_cfs_item_type =3D { + .ct_item_ops =3D &sim_panel_cfs_item_ops, + .ct_attrs =3D sim_panel_cfs_item_attrs, + .ct_owner =3D THIS_MODULE, +}; + +static struct config_group *sim_panel_cfs_make_group(struct config_group *= group, + const char *name) +{ + struct panel_simulation_cfs *sim_panel; + + sim_panel =3D kzalloc(sizeof(struct panel_simulation_cfs), GFP_KERNEL); + if (!sim_panel) + return ERR_PTR(-ENOMEM); + + sim_panel->num_modes =3D 1; + sim_panel->display_modes =3D &sim_panel_default_mode; + sim_panel->mode_flags =3D 0; + + config_group_init_type_name(&sim_panel->group, name, + &sim_panel_cfs_item_type); + + return &sim_panel->group; +} + +static struct configfs_attribute *sim_panel_cfs_attrs[] =3D { + NULL, +}; + +static struct configfs_group_operations sim_panel_cfs_group_ops =3D { + .make_group =3D sim_panel_cfs_make_group, +}; + +static const struct config_item_type sim_panel_cfs_group_type =3D { + .ct_group_ops =3D &sim_panel_cfs_group_ops, + .ct_attrs =3D sim_panel_cfs_attrs, + .ct_owner =3D THIS_MODULE, +}; + +static struct configfs_subsystem sim_panel_cfs_subsys =3D { + .su_group =3D { + .cg_item =3D { + .ci_namebuf =3D "sim_panel", + .ci_type =3D &sim_panel_cfs_group_type, + }, + }, +}; + +static int panel_simulation_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev =3D &dsi->dev; + struct panel_simulation *panel; + int ret =3D 0; + struct panel_simulation_cfs *configfs =3D mipi_dsi_get_drvdata(dsi); + + if (!configfs) + return dev_err_probe(dev, -EPROBE_DEFER, + "Cannot get configfs\n"); + + panel =3D devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); + if (!panel) + return -ENOMEM; + + panel->display_modes =3D configfs->display_modes; + panel->num_modes =3D configfs->num_modes; + + mipi_dsi_set_drvdata(dsi, panel); + + dsi->lanes =3D 4; + dsi->format =3D MIPI_DSI_FMT_RGB888; + dsi->mode_flags =3D configfs->mode_flags; + + drm_panel_init(&panel->base, dev, &panel_simulation_funcs, + DRM_MODE_CONNECTOR_DSI); + drm_panel_add(&panel->base); + + ret =3D mipi_dsi_attach(dsi); + if (ret) + drm_panel_remove(&panel->base); + + return ret; +} + +static void panel_simulation_remove(struct mipi_dsi_device *dsi) +{ + struct panel_simulation *panel =3D mipi_dsi_get_drvdata(dsi); + int err; + + err =3D mipi_dsi_detach(dsi); + if (err < 0) + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); + + drm_panel_remove(&panel->base); + drm_panel_disable(&panel->base); + drm_panel_unprepare(&panel->base); +} + +static void panel_simulation_shutdown(struct mipi_dsi_device *dsi) +{ + struct panel_simulation *panel =3D dev_get_drvdata(&dsi->dev); + + drm_panel_disable(&panel->base); + drm_panel_unprepare(&panel->base); +} + +static struct mipi_dsi_driver panel_simulation_driver =3D { + .driver =3D { + .name =3D "panel_simulation", + }, + .probe =3D panel_simulation_probe, + .remove =3D panel_simulation_remove, + .shutdown =3D panel_simulation_shutdown, +}; + +static int __init panel_simulation_init(void) +{ + int ret; + + ret =3D mipi_dsi_driver_register(&panel_simulation_driver); + if (ret < 0) + return ret; + + config_group_init(&sim_panel_cfs_subsys.su_group); + mutex_init(&sim_panel_cfs_subsys.su_mutex); + ret =3D configfs_register_subsystem(&sim_panel_cfs_subsys); + if (ret) { + mutex_destroy(&sim_panel_cfs_subsys.su_mutex); + mipi_dsi_driver_unregister(&panel_simulation_driver); + return ret; + } + + return 0; +} +module_init(panel_simulation_init); + +static void __exit panel_simulation_exit(void) +{ + configfs_unregister_subsystem(&sim_panel_cfs_subsys); + mipi_dsi_driver_unregister(&panel_simulation_driver); +} +module_exit(panel_simulation_exit); + +MODULE_AUTHOR("Jessica Zhang "); +MODULE_DESCRIPTION("DRM Driver for Simulated DSI Panels"); +MODULE_LICENSE("GPL"); --=20 2.34.1 From nobody Wed Nov 27 16:50:45 2024 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 65D1A1DF263 for ; Tue, 8 Oct 2024 14:18:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728397116; cv=none; b=C4ijKfrxrxBWonKSoMeFporQgDOktnZiUk7TH8KjzaAvPnaqP9++FSpvtUKSguIfJX4T5jB0sqTTmEVrEhLcUky7guJvVnq2erIMBA9eaAkDpuk3WHeVFR2dy7rSwxZaTo9htg2xCQblsLhKMYaLFh0qj9rYN/pLVY2OuAuljHc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728397116; c=relaxed/simple; bh=sm96UjPpbIF/phQCWE/RVSh5plSfPFMAnGA/yUzKtXw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=r/mADjIal/Fxv+tvHA7NkXNlONxo9G36EnkqHHbQubNL1x7wzyNJA65rclHxb5XyliW8qM9vBabOXKnnHnMVSvQhaznIMhR5bNxW7EhSXkUaqKEYe07UqBvja1v98XdbeZDDRfZ9zcCjAnqTqCNPKFwBGwIyWRn5fpqlKYwLV5A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=OlykCxfw; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="OlykCxfw" Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 498DcYNm000671; Tue, 8 Oct 2024 14:18:12 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= dLXUKvf19OCq2OCwG0iSsemRAtBC635XS9ZR1rdZt80=; b=OlykCxfw+8EcR55R 4HDMQ7edF1+due3lPNSYe+GVMZtB8INl1D936KYlGPLdcpbANvxdy9NPzZcjm4DC lC+k6STuQFIH61SL0u57glHnyajQM6VmGcShFfVXm8gYXnECn4AIkv8O69zSPCaq Oe383iM2ZGn7ZRXcy/Kh1PiVBvAva4D4TqSKC4r8MJfzLiJoIW4hGbcbuuURLuSv 4n9iswxed4rWycPfqe71doITF2TFk8UmCdTZ96OV7bqgZjC+wSE+xH+5y3N6Fiji f6ayo3Ar4qshAoNURor1maZtd5tYd33ou5zao65qokUGA2PkUMYVbjTMS5nN+jjr 489Q+Q== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 424wgs1k43-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 08 Oct 2024 14:18:12 +0000 (GMT) Received: from nasanex01b.na.qualcomm.com (nasanex01b.na.qualcomm.com [10.46.141.250]) by NASANPPMTA04.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 498EIBC9017948 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 8 Oct 2024 14:18:11 GMT Received: from jesszhan-linux.qualcomm.com (10.80.80.8) by nasanex01b.na.qualcomm.com (10.46.141.250) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Tue, 8 Oct 2024 07:18:11 -0700 From: Jessica Zhang Date: Tue, 8 Oct 2024 07:17:39 -0700 Subject: [PATCH RFC v2 2/3] drm/dsi: Add API to register simulated DSI panel Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20241008-jz-test-sim-panel-v2-2-d60046470e6c@quicinc.com> References: <20241008-jz-test-sim-panel-v2-0-d60046470e6c@quicinc.com> In-Reply-To: <20241008-jz-test-sim-panel-v2-0-d60046470e6c@quicinc.com> To: Neil Armstrong , Sam Ravnborg , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Jessica Zhang , Simona Vetter , Andrzej Hajda , Robert Foss , Laurent Pinchart , Jonas Karlman , "Jernej Skrabec" , Simona Vetter CC: , , X-Mailer: b4 0.15-dev-2a633 X-Developer-Signature: v=1; a=ed25519-sha256; t=1728397090; l=2166; i=quic_jesszhan@quicinc.com; s=20230329; h=from:subject:message-id; bh=sm96UjPpbIF/phQCWE/RVSh5plSfPFMAnGA/yUzKtXw=; b=H+w25gIqV43zYojzRDSIgEa2Zec+hgUoT8p1pH09KY8l5A80jd+eWdUs1i2zVNei0eXrBzs3O HAVrBC7lyCGCMd4vGjZK6OWpyR3AaOVejUJTfKpkwFu2/qqvYfSl/8U X-Developer-Key: i=quic_jesszhan@quicinc.com; a=ed25519; pk=gAUCgHZ6wTJOzQa3U0GfeCDH7iZLlqIEPo4rrjfDpWE= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01b.na.qualcomm.com (10.46.141.250) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: jK50yDp_27Oo2ONaGj8Wst4tL5dKI75Q X-Proofpoint-ORIG-GUID: jK50yDp_27Oo2ONaGj8Wst4tL5dKI75Q X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 suspectscore=0 impostorscore=0 bulkscore=0 clxscore=1015 adultscore=0 spamscore=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 phishscore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2410080091 Add new APIs to register a simulated DSI panel. If the panel_simulation module is enabled, the DSI host will register the sim panel instead of the physical panel. Signed-off-by: Jessica Zhang --- drivers/gpu/drm/drm_mipi_dsi.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 2bc3973d35a19fc7dff7d578636821a1059bb7f9..95498b9bb8953066b0b1e9cfaa9= 9d0b5b53e6cc8 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -153,6 +153,24 @@ static int mipi_dsi_device_add(struct mipi_dsi_device = *dsi) return device_add(&dsi->dev); } =20 +#if IS_ENABLED(CONFIG_DRM_PANEL_SIMULATION) +static struct mipi_dsi_device *mipi_dsi_device_add_sim_panel(struct mipi_d= si_host *host) +{ + struct mipi_dsi_device_info info =3D { }; + + info.channel =3D 0; + info.node =3D NULL; + strscpy(info.type, "panel_simulation", sizeof(info.type)); + + return mipi_dsi_device_register_full(host, &info); +} +#else +static struct mipi_dsi_device *mipi_dsi_device_add_sim_panel(struct mipi_d= si_host *host) +{ + return ERR_PTR(-ENODEV); +} +#endif + #if IS_ENABLED(CONFIG_OF) static struct mipi_dsi_device * of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *nod= e) @@ -324,10 +342,28 @@ struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(s= truct device_node *node) } EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node); =20 +static int mipi_dsi_host_register_sim_panel(struct mipi_dsi_host *host) +{ + struct mipi_dsi_device *ret; + + ret =3D mipi_dsi_device_add_sim_panel(host); + if (IS_ERR(ret)) + return -EPROBE_DEFER; + + mutex_lock(&host_lock); + list_add_tail(&host->list, &host_list); + mutex_unlock(&host_lock); + + return 0; +} + int mipi_dsi_host_register(struct mipi_dsi_host *host) { struct device_node *node; =20 + if (!mipi_dsi_host_register_sim_panel(host)) + return 0; + for_each_available_child_of_node(host->dev->of_node, node) { /* skip nodes without reg property */ if (!of_property_present(node, "reg")) --=20 2.34.1 From nobody Wed Nov 27 16:50:45 2024 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07BE614EC59 for ; Tue, 8 Oct 2024 14:18:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728397115; cv=none; b=OMZvvWb9mmo8CkkscTgpU9mxWNDqmqpDiH1/dFguRfdALYPpg/bs33ojkE263mTnehVsOEFqeEDcRQXgy+yubjpxBBMfTvE0BShHJJ9B7/0v080g2ew4lBkpIQdECvmZCznd4Bb/+ycjjVsqmhw332WzQKjzeqDd5baT6rO5OZQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728397115; c=relaxed/simple; bh=cIyPW9Z2jzZyEh86fXqhUa+MuKu+8xjoPEs+7ONDo2c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=OAkcIh47wIcLQPtEISFlweJR9Tbr1/t+5ECAMcjSo5Zs2n4wLnHsLzcRQT9o0jW82TfZSTgkQJX0FDhYvoKesAOG7gY4Rxehud1rKgbQ7hLwYyZsG1kcoORQTjnMJJYHNMhahBU9z0mFkaoiYKLsullWSa1qInQx/R+FdBRq3xs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=YvMth1VV; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="YvMth1VV" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4985vcou021306; Tue, 8 Oct 2024 14:18:12 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= gKsmCYkhXMlDqpGR7T5GsjFzXiEzCV3nk0wvpW6MLM8=; b=YvMth1VVfFQJaxvh hb1C+Ud0qunMaUXf1tZfB+I326jf2OPnRcqD6kcK1Fd+2cML3z/nyB6xoA0G38fb TR6iSTp1ABAratoWVofiVndYPpEj7qkaGfk2HUPC0yGX6/iAHSJXB/3ys6uCV7yR QZxN/62bcuvJDsnzjeTRGNU/GGpkSJfw5ezXbFoBugnklMOy1phiiqUupaCnX2yX Js9zsZaxP9Ruvg6ekMD0j6iBit0+zrB4ZPnpFVrSbMMgBD0g+uNqED388G04D4PN juTlXkrRgf/Bqy5EbPdn9gJCcGjzFejm5FFc3YDv3UYvdA0KkUCANKk0FrX0BTKq fB9qdQ== Received: from nasanppmta03.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 422xr5qkba-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 08 Oct 2024 14:18:12 +0000 (GMT) Received: from nasanex01b.na.qualcomm.com (nasanex01b.na.qualcomm.com [10.46.141.250]) by NASANPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id 498EIBH6021043 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 8 Oct 2024 14:18:11 GMT Received: from jesszhan-linux.qualcomm.com (10.80.80.8) by nasanex01b.na.qualcomm.com (10.46.141.250) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Tue, 8 Oct 2024 07:18:11 -0700 From: Jessica Zhang Date: Tue, 8 Oct 2024 07:17:40 -0700 Subject: [PATCH RFC v2 3/3] drm/panel: Introduce simulated panel bridge API Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20241008-jz-test-sim-panel-v2-3-d60046470e6c@quicinc.com> References: <20241008-jz-test-sim-panel-v2-0-d60046470e6c@quicinc.com> In-Reply-To: <20241008-jz-test-sim-panel-v2-0-d60046470e6c@quicinc.com> To: Neil Armstrong , Sam Ravnborg , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Jessica Zhang , Simona Vetter , Andrzej Hajda , Robert Foss , Laurent Pinchart , Jonas Karlman , "Jernej Skrabec" , Simona Vetter CC: , , X-Mailer: b4 0.15-dev-2a633 X-Developer-Signature: v=1; a=ed25519-sha256; t=1728397090; l=4528; i=quic_jesszhan@quicinc.com; s=20230329; h=from:subject:message-id; bh=cIyPW9Z2jzZyEh86fXqhUa+MuKu+8xjoPEs+7ONDo2c=; b=9tUmkgHjtKtmvNe7ODal7vwSpmLQH0saKzBK2c9oha69gDxYBzlN3/UOccd4vVRhqIJSwQm2R vK2kPXGbhOMDdRjRlBmrlSYGzZ93imkS1JXLtrBGqXkEzxiNmopDOJ/ X-Developer-Key: i=quic_jesszhan@quicinc.com; a=ed25519; pk=gAUCgHZ6wTJOzQa3U0GfeCDH7iZLlqIEPo4rrjfDpWE= X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To nasanex01b.na.qualcomm.com (10.46.141.250) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: era3619I07jwGVG3p2MzGq8wZtp3rjW5 X-Proofpoint-ORIG-GUID: era3619I07jwGVG3p2MzGq8wZtp3rjW5 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 clxscore=1015 mlxlogscore=999 priorityscore=1501 impostorscore=0 adultscore=0 mlxscore=0 phishscore=0 malwarescore=0 lowpriorityscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2410080091 Add separate bridge and drm_panel API for getting the simulated panel. If the panel_simulation kernel module is enabled, the DRM framework will get the sim panel bridge instead of the physical panel or bridge. Signed-off-by: Jessica Zhang --- drivers/gpu/drm/bridge/panel.c | 28 ++++++++++++++++++++++++++++ drivers/gpu/drm/drm_panel.c | 33 +++++++++++++++++++++++++++++++++ include/drm/drm_bridge.h | 1 + include/drm/drm_panel.h | 1 + 4 files changed, 63 insertions(+) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 6e88339dec0f5faee690b7c53e8dcd0f1ee2281c..e703a770a86e60887ecb669011f= 311210fac695e 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -482,6 +482,30 @@ struct drm_connector *drm_panel_bridge_connector(struc= t drm_bridge *bridge) } EXPORT_SYMBOL(drm_panel_bridge_connector); =20 +/** + * drm_get_sim_panel_bridge - return the simulated panel bridge + * @dev: device to tie the bridge lifetime to + * + * This function will return a bridge for the simulated panel. + * + * Returns a pointer to the bridge if successful, or an error pointer + * otherwise. + */ +struct drm_bridge *drm_get_sim_panel_bridge(struct device *dev) +{ + struct drm_bridge *bridge; + struct drm_panel *panel; + + panel =3D drm_find_sim_panel(); + if (IS_ERR(panel)) + return ERR_PTR(-EPROBE_DEFER); + + bridge =3D devm_drm_panel_bridge_add(dev, panel); + + return bridge; +} +EXPORT_SYMBOL(drm_get_sim_panel_bridge); + #ifdef CONFIG_OF /** * devm_drm_of_get_bridge - Return next bridge in the chain @@ -505,6 +529,10 @@ struct drm_bridge *devm_drm_of_get_bridge(struct devic= e *dev, struct drm_panel *panel; int ret; =20 + bridge =3D drm_get_sim_panel_bridge(dev); + if (!IS_ERR(bridge)) + return bridge; + ret =3D drm_of_find_panel_or_bridge(np, port, endpoint, &panel, &bridge); if (ret) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 19ab0a794add31f34275d53dfab0a7c0050476e3..1e532f8e5bff99467f058fe0a44= 1141c80ca95d6 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -313,6 +313,39 @@ int drm_panel_get_modes(struct drm_panel *panel, } EXPORT_SYMBOL(drm_panel_get_modes); =20 +/** + * drm_find_sim_panel - look up the simulated panel + * + * Searches for the simulated panel in the panel list. + * + * Return: A pointer to the simulated panel or an ERR_PTR() if the simulat= ed + * panel was not found in the panel list. + * + * Possible error codes returned by this function: + * - EPROBE_DEFER: the panel device has not been probed yet, and the caller + * should retry later + */ +struct drm_panel *drm_find_sim_panel(void) +{ + struct drm_panel *panel; + + mutex_lock(&panel_lock); + + list_for_each_entry(panel, &panel_list, list) { + bool is_sim_panel =3D !strncmp(panel->dev->driver->name, + "panel_simulation", + strlen("panel_simulation")); + if (is_sim_panel) { + mutex_unlock(&panel_lock); + return panel; + } + } + + mutex_unlock(&panel_lock); + return ERR_PTR(-EPROBE_DEFER); +} +EXPORT_SYMBOL(drm_find_sim_panel); + #ifdef CONFIG_OF /** * of_drm_find_panel - look up a panel using a device tree node diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 75019d16be643ae87f756e131a079feffd9b4d59..8c1ae06ecbcdb2e9d1fba6845bd= 85a54a9643502 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -1006,6 +1006,7 @@ static inline int drm_panel_bridge_set_orientation(st= ruct drm_connector *connect } #endif =20 +struct drm_bridge *drm_get_sim_panel_bridge(struct device *dev); #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL_BRIDGE) struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct devic= e_node *node, u32 port, u32 endpoint); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 10015891b056f816c7a992a2052b36fd26943c5b..c3a5944c35a911b809a6567040c= ea7bc7da07ba6 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -283,6 +283,7 @@ int drm_panel_enable(struct drm_panel *panel); int drm_panel_disable(struct drm_panel *panel); =20 int drm_panel_get_modes(struct drm_panel *panel, struct drm_connector *con= nector); +struct drm_panel *drm_find_sim_panel(void); =20 #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); --=20 2.34.1