From patchwork Wed Jan 31 06:57:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Svyatoslav Ryhel X-Patchwork-Id: 1893244 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=EvmZmOjJ; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TPtCY6KSMz23fD for ; Wed, 31 Jan 2024 17:58:01 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2199B87BCB; Wed, 31 Jan 2024 07:57:47 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="EvmZmOjJ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 5CFA7879B0; Wed, 31 Jan 2024 07:57:46 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-lf1-x12f.google.com (mail-lf1-x12f.google.com [IPv6:2a00:1450:4864:20::12f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 41B70879B5 for ; Wed, 31 Jan 2024 07:57:43 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=clamor95@gmail.com Received: by mail-lf1-x12f.google.com with SMTP id 2adb3069b0e04-510faac8c57so563258e87.1 for ; Tue, 30 Jan 2024 22:57:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706684262; x=1707289062; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=HseZ4Amk00nzL0KGQLkpyxdV5KqbgCLiVbXogMuYcV8=; b=EvmZmOjJbnl9bsG1FfGMtmyyMNT0DiMG7nVu4e4OxW9Fsv4o0db2ug6IVnZEJLutOE jinnOYdni2XlNYr+sV618HNPwlTfaaN6NT2yfeWrarQ8zUw4AcWXUZxDI5okfgkGe+pV seTeyiNU2urWL9SqDZU1DM2hVO9OEBIiMZ58VyOVkLLiIujNlvxqa6rsGW/t8CO9b9Ca P8z9wJ+IE268Xd3ejnG+UbRgCrvrMQapC/5ffIhlyI4wvlLrPpRK+XPd9DW00qmHQuHv nTIe4dnsdt1vWgHWH3LwolieAbuGILaZVQ1N2ciZe6G3JEOkeSN9xw3gRtIPNfON9X2a 8u5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706684262; x=1707289062; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HseZ4Amk00nzL0KGQLkpyxdV5KqbgCLiVbXogMuYcV8=; b=CUzV08ObAKon7Ai5/9mo0ulQ2SWb5FcB5eh9wbQ/49+uO5n6CB9TRxQ/yLyRhDSj6M pz8mCIZmvkEzxT094SOj8epooFNuFrrGBm6w5eXnT7Ecam6oYgs0fb3loHGe9Pgr8kzf WvUYxH7MN+l07OMwCIr+NWfJ3sFTPZ0f+mLHZMvNOQRz+1qCY7XATcw4XI0vBEfgwVkN lbt8xmj9ZakQAnW0PrTeD5rXFjcIKR4j1e1xm1NnCIsoL3QnwBavSzYeabEDSpkBn5gF KKsXWWy8at8ZQ56rfjAvUh2iAfFCmH7tOFIB8OGoMGkzlpf0ydke5DaGpm+DWM2Vjn5j nT/g== X-Gm-Message-State: AOJu0Yy9Kyiu1AkSumw7cnLM+DdKUvY+afnB5FI0G6/rYSCubNozYO6Y S+g/KWCOOZXgybt3dGAIbtuMwIBtgZ5zira13pm2qyj0Axs5HuKg X-Google-Smtp-Source: AGHT+IEIrY0t15fGOVibHuQ3Eic3LR6t0YkFbEJpYh7G4WmqrI/j9wt7WmsiYaerowG4ldNNEFgh1g== X-Received: by 2002:a05:6512:1154:b0:510:9a2:1b6a with SMTP id m20-20020a056512115400b0051009a21b6amr242019lfg.29.1706684262364; Tue, 30 Jan 2024 22:57:42 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCULrm0RIstikoDiNrDSJAwgCwJw7ZaYw0wxUHsXP+hYyjqUTubYQChmFI8tXWV+Jp8R2FA2wsOnk0rFIfIQSzBFAr8Yu4+qCA0gMaS12Ldsff5G+wGcBZnV+y68pe7PgRqQmd4Tqlqxwvh4l93FTFpHWRtB95uyf9chHWM+KKO3ybOY3KRxhuiwgSgBSPw2K0Y/jCb1LQ== Received: from xeon.. ([188.163.112.73]) by smtp.gmail.com with ESMTPSA id s11-20020a19770b000000b0051023c2e95asm1760796lfc.209.2024.01.30.22.57.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 22:57:42 -0800 (PST) From: Svyatoslav Ryhel To: Tom Rini , Anatolij Gustschin , Simon Glass , Svyatoslav Ryhel , Anton Bambura , =?utf-8?q?Jonas_Schw=C3=B6bel?= Cc: u-boot@lists.denx.de Subject: [PATCH v2 1/7] video: panel: add LG LG070WX3 MIPI DSI panel driver Date: Wed, 31 Jan 2024 08:57:15 +0200 Message-Id: <20240131065721.4245-2-clamor95@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240131065721.4245-1-clamor95@gmail.com> References: <20240131065721.4245-1-clamor95@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean The LD070WX3 is a Color Active Matrix Liquid Crystal Display with an integral Light Emitting Diode (LED) backlight system. The matrix employs a-Si Thin Film Transistor as the active element. It is a transmissive type display operating in the normally Black mode. This TFT-LCD has 7.0 inches diagonally measured active display area with WXGA resolution (800 by 1280 pixel array). Signed-off-by: Svyatoslav Ryhel --- drivers/video/Kconfig | 8 ++ drivers/video/Makefile | 1 + drivers/video/lg-ld070wx3.c | 186 ++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 drivers/video/lg-ld070wx3.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e2016d73d1..05567a0095 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -522,6 +522,14 @@ config VIDEO_LCD_ORISETECH_OTM8009A Say Y here if you want to enable support for Orise Technology otm8009a 480x800 dsi 2dl panel. +config VIDEO_LCD_LG_LD070WX3 + bool "LD070WX3 DSI LCD panel support" + depends on PANEL && BACKLIGHT + select VIDEO_MIPI_DSI + help + Say Y here if you want to enable support for LG LD070WX3 + 800x1280 DSI video mode panel. + config VIDEO_LCD_RAYDIUM_RM68200 bool "RM68200 DSI LCD panel support" select VIDEO_MIPI_DSI diff --git a/drivers/video/Makefile b/drivers/video/Makefile index fdc2937632..bb6d9b74b9 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_VIDEO_LCD_ANX9804) += anx9804.o obj-$(CONFIG_VIDEO_LCD_ENDEAVORU) += endeavoru-panel.o obj-$(CONFIG_VIDEO_LCD_HIMAX_HX8394) += himax-hx8394.o obj-$(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM) += hitachi_tx18d42vm_lcd.o +obj-$(CONFIG_VIDEO_LCD_LG_LD070WX3) += lg-ld070wx3.o obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o diff --git a/drivers/video/lg-ld070wx3.c b/drivers/video/lg-ld070wx3.c new file mode 100644 index 0000000000..610a06ffe7 --- /dev/null +++ b/drivers/video/lg-ld070wx3.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * LG LD070WX3-SL01 DSI panel driver + * + * Copyright (c) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include +#include + +struct lg_ld070wx3_priv { + struct udevice *vdd; + struct udevice *vcc; + + struct udevice *backlight; +}; + +static struct display_timing default_timing = { + .pixelclock.typ = 70000000, + .hactive.typ = 800, + .hfront_porch.typ = 32, + .hback_porch.typ = 48, + .hsync_len.typ = 8, + .vactive.typ = 1280, + .vfront_porch.typ = 5, + .vback_porch.typ = 3, + .vsync_len.typ = 1, +}; + +static void dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data) +{ + mipi_dsi_dcs_write(dsi, cmd, &data, 1); +} + +static int lg_ld070wx3_enable_backlight(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *dsi = plat->device; + int ret; + + ret = mipi_dsi_dcs_soft_reset(dsi); + if (ret < 0) { + log_debug("%s: failed to soft reset panel: %d\n", + __func__, ret); + return ret; + } + + /* Delay before sending new command after soft reset */ + mdelay(20); + + /* Differential input impedance selection */ + dcs_write_one(dsi, 0xAE, 0x0B); + + /* Enter test mode 1 and 2*/ + dcs_write_one(dsi, 0xEE, 0xEA); + dcs_write_one(dsi, 0xEF, 0x5F); + + /* Increased MIPI CLK driving ability */ + dcs_write_one(dsi, 0xF2, 0x68); + + /* Exit test mode 1 and 2 */ + dcs_write_one(dsi, 0xEE, 0x00); + dcs_write_one(dsi, 0xEF, 0x00); + + return 0; +} + +static int lg_ld070wx3_set_backlight(struct udevice *dev, int percent) +{ + struct lg_ld070wx3_priv *priv = dev_get_priv(dev); + int ret; + + ret = backlight_enable(priv->backlight); + if (ret) + return ret; + + return backlight_set_brightness(priv->backlight, percent); +} + +static int lg_ld070wx3_timings(struct udevice *dev, + struct display_timing *timing) +{ + memcpy(timing, &default_timing, sizeof(*timing)); + return 0; +} + +static int lg_ld070wx3_of_to_plat(struct udevice *dev) +{ + struct lg_ld070wx3_priv *priv = dev_get_priv(dev); + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", &priv->backlight); + if (ret) { + log_debug("%s: cannot get backlight: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vdd-supply", &priv->vdd); + if (ret) { + log_debug("%s: cannot get vdd-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vcc-supply", &priv->vcc); + if (ret) { + log_debug("%s: cannot get vcc-supply: ret = %d\n", + __func__, ret); + return ret; + } + + return 0; +} + +static int lg_ld070wx3_hw_init(struct udevice *dev) +{ + struct lg_ld070wx3_priv *priv = dev_get_priv(dev); + int ret; + + ret = regulator_set_enable_if_allowed(priv->vcc, 1); + if (ret) { + log_debug("%s: enabling vcc-supply failed (%d)\n", + __func__, ret); + return ret; + } + + ret = regulator_set_enable_if_allowed(priv->vdd, 1); + if (ret) { + log_debug("%s: enabling vdd-supply failed (%d)\n", + __func__, ret); + return ret; + } + + /* + * According to spec delay between enabling supply is 0, + * for regulators to reach required voltage ~5ms needed. + * MIPI interface signal for setup requires additional + * 110ms which in total results in 115ms. + */ + mdelay(115); + + return 0; +} + +static int lg_ld070wx3_probe(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + + /* fill characteristics of DSI data link */ + plat->lanes = 4; + plat->format = MIPI_DSI_FMT_RGB888; + plat->mode_flags = MIPI_DSI_MODE_VIDEO; + + return lg_ld070wx3_hw_init(dev); +} + +static const struct panel_ops lg_ld070wx3_ops = { + .enable_backlight = lg_ld070wx3_enable_backlight, + .set_backlight = lg_ld070wx3_set_backlight, + .get_display_timing = lg_ld070wx3_timings, +}; + +static const struct udevice_id lg_ld070wx3_ids[] = { + { .compatible = "lg,ld070wx3-sl01" }, + { } +}; + +U_BOOT_DRIVER(lg_ld070wx3) = { + .name = "lg_ld070wx3", + .id = UCLASS_PANEL, + .of_match = lg_ld070wx3_ids, + .ops = &lg_ld070wx3_ops, + .of_to_plat = lg_ld070wx3_of_to_plat, + .probe = lg_ld070wx3_probe, + .plat_auto = sizeof(struct mipi_dsi_panel_plat), + .priv_auto = sizeof(struct lg_ld070wx3_priv), +}; From patchwork Wed Jan 31 06:57:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Svyatoslav Ryhel X-Patchwork-Id: 1893245 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=O616QFOr; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TPtCl1ydDz23fD for ; Wed, 31 Jan 2024 17:58:10 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3271D87A17; Wed, 31 Jan 2024 07:57:48 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="O616QFOr"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 6661F879B5; Wed, 31 Jan 2024 07:57:46 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-lf1-x12e.google.com (mail-lf1-x12e.google.com [IPv6:2a00:1450:4864:20::12e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 53AE987A23 for ; Wed, 31 Jan 2024 07:57:44 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=clamor95@gmail.com Received: by mail-lf1-x12e.google.com with SMTP id 2adb3069b0e04-51120e285f6so1218577e87.2 for ; Tue, 30 Jan 2024 22:57:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706684263; x=1707289063; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JGR8ictgxW5r/D8M2esRO7fnajcFEX/FnUfXIR2EzDo=; b=O616QFOrcAL1OL9m5OVCbvNVqVJlBJSQNE6oWWNqRbb+rP0h+nyRDpRkmxNin9LyLn J5SMz9XCZngnMdKytT+YD95c6O77L1fv+zp6PKSL+TuotYTqji8Yi3b2XrlhMNF9Xp3j ihdUdOMs82KJANZKaCSfOFKc9aja8CDykpPlNQndgqUYUzJ+/iKHmyeEtYqrvkthDxe9 41wM+w34sGtRYQqLcgMJBYEJ84J+0LLf6tCPw2TZXo4yd7w39YiIxb2qwPBYcOzJrDaP g+mtYwR0CxrpYu35TBh0PlH1TGEFaXQaOK1pKcC1ZbRAKXwpBYN+v+IcMId+UWYP3Ear 6CDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706684263; x=1707289063; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JGR8ictgxW5r/D8M2esRO7fnajcFEX/FnUfXIR2EzDo=; b=O2+FbnySVN2nd4xMDLf1LaqiICIpaYg15tfHsP3H9x6x0MkGFj3aEgGa0+bJ2lk8tB /uS5bMKPuJSfIx1FGKtnI/fDCXC6E0m4wnJkyJXx8JLKnsxZroCvQMZ5hk8Iis4S/FQ8 syizlraX+2gFcJcZVf7zIAaXHsx/9VUFD441kuBZ2Liu7Y0DvzJ/ebVQzlKY2Ad7i51V 6w92Vczm9k/FfBCXnyAM8UpFX2hQljkz8o6FVZ2Jstrx7+9p5uC+IjDWcNGP0kQCDv1N EIZZkex8Tm7NEa3g16IG3i2krWhn8l5YCXSw7OZk5PDtnT9Mv7xB26rqbySXt6NdJOqU hURg== X-Gm-Message-State: AOJu0Yy5LEsCa7VwNbd1FJsR0yNTPE22I1CBOIl1EnfHEg+RUFpvPqll Vkt1B9Gw1jr9SrD6nbH8PViNcB0p4aSyrXfhCuMSUxw+bx0HcZ+u X-Google-Smtp-Source: AGHT+IGDTrKp80O0lvhb8HZPLYmS6wyaoBeBlH9yQDZay7/bOoEB/uii6ZoHuGrx5Gj8NxlEHWZArA== X-Received: by 2002:a05:6512:3f28:b0:510:e08:c908 with SMTP id y40-20020a0565123f2800b005100e08c908mr642437lfa.57.1706684263400; Tue, 30 Jan 2024 22:57:43 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCVLGZAo4XCsw2TmQ/uYcmwgODsczieFrSHgblsN1XP38O1QBacqkUaL/qIEDsS+FEQ5FjjsOc3enAt1Nln+JPOYJzWFfq4utIujsjOwDJydukWebGt4p0t+HTZrEprbhBnXkJlxcFsgIp+4iQLP51adOENlDogHAFxSANIgVr/1fEs4iMHmBOg2VmuyvbPBcPvXLhQE1Q== Received: from xeon.. ([188.163.112.73]) by smtp.gmail.com with ESMTPSA id s11-20020a19770b000000b0051023c2e95asm1760796lfc.209.2024.01.30.22.57.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 22:57:43 -0800 (PST) From: Svyatoslav Ryhel To: Tom Rini , Anatolij Gustschin , Simon Glass , Svyatoslav Ryhel , Anton Bambura , =?utf-8?q?Jonas_Schw=C3=B6bel?= Cc: u-boot@lists.denx.de Subject: [PATCH v2 2/7] video: panel: add Samsung LTL106HL02 MIPI DSI panel driver Date: Wed, 31 Jan 2024 08:57:16 +0200 Message-Id: <20240131065721.4245-3-clamor95@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240131065721.4245-1-clamor95@gmail.com> References: <20240131065721.4245-1-clamor95@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Anton Bambura LTL106HL02 is a color active matrix TFT (Thin Film Transistor) liquid crystal display (LCD) that uses amorphous silicon TFT as switching devices. This model is composed of a TFT LCD panel, a driver circuit and a backlight unit. The resolution of a 10.6" contains 1920 x 1080 pixels and can display up to 16,8M color with wide viewing angle. Co-developed-by: Jonas Schwöbel Signed-off-by: Jonas Schwöbel Co-developed-by: Svyatoslav Ryhel Signed-off-by: Svyatoslav Ryhel Signed-off-by: Anton Bambura --- drivers/video/Kconfig | 9 ++ drivers/video/Makefile | 1 + drivers/video/samsung-ltl106hl02.c | 157 +++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 drivers/video/samsung-ltl106hl02.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 05567a0095..52b515197d 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -555,6 +555,15 @@ config VIDEO_LCD_RENESAS_R69328 IPS-LCD module with Renesas R69328 IC. The panel has a 720x1280 resolution and uses 24 bit RGB per pixel. +config VIDEO_LCD_SAMSUNG_LTL106HL02 + tristate "Samsung LTL106HL02 1920x1080 DSI video mode panel" + depends on PANEL && BACKLIGHT + select VIDEO_MIPI_DSI + help + Say Y here if you want to enable support for Samsung LTL106HL02 + LCD module found in Microsoft Surface 2. The panel has a FullHD + resolution (1920x1080). + config VIDEO_LCD_SSD2828 bool "SSD2828 bridge chip" ---help--- diff --git a/drivers/video/Makefile b/drivers/video/Makefile index bb6d9b74b9..f3f70cd04a 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_VIDEO_LCD_ORISETECH_OTM8009A) += orisetech_otm8009a.o obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R69328) += renesas-r69328.o +obj-$(CONFIG_VIDEO_LCD_SAMSUNG_LTL106HL02) += samsung-ltl106hl02.o obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o obj-$(CONFIG_VIDEO_MCDE_SIMPLE) += mcde_simple.o diff --git a/drivers/video/samsung-ltl106hl02.c b/drivers/video/samsung-ltl106hl02.c new file mode 100644 index 0000000000..5e6c11c4be --- /dev/null +++ b/drivers/video/samsung-ltl106hl02.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung LTL106HL02-001 DSI panel driver + * + * Copyright (c) 2020 Anton Bambura + * Copyright (c) 2023 Svyatoslav Ryhel + * Copyright (c) 2024 Jonas Schwöbel + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct samsung_ltl106hl02_priv { + struct udevice *vdd; + struct udevice *backlight; + + struct gpio_desc reset_gpio; +}; + +static struct display_timing default_timing = { + .pixelclock.typ = 137000000, + .hactive.typ = 1920, + .hfront_porch.typ = 32, + .hback_porch.typ = 64, + .hsync_len.typ = 32, + .vactive.typ = 1080, + .vfront_porch.typ = 2, + .vback_porch.typ = 26, + .vsync_len.typ = 3, +}; + +static int samsung_ltl106hl02_enable_backlight(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *dsi = plat->device; + int ret; + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + log_debug("%s: failed to exit sleep mode: %d\n", + __func__, ret); + return ret; + } + mdelay(70); + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret < 0) { + log_debug("%s: failed to enable display: %d\n", + __func__, ret); + return ret; + } + mdelay(5); + + return 0; +} + +static int samsung_ltl106hl02_set_backlight(struct udevice *dev, int percent) +{ + struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev); + int ret; + + ret = backlight_enable(priv->backlight); + if (ret) + return ret; + + return backlight_set_brightness(priv->backlight, percent); +} + +static int samsung_ltl106hl02_timings(struct udevice *dev, + struct display_timing *timing) +{ + memcpy(timing, &default_timing, sizeof(*timing)); + return 0; +} + +static int samsung_ltl106hl02_of_to_plat(struct udevice *dev) +{ + struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev); + int ret; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", &priv->backlight); + if (ret) { + log_debug("%s: cannot get backlight: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vdd-supply", &priv->vdd); + if (ret) + log_debug("%s: cannot get vdd-supply: error %d\n", + __func__, ret); + + ret = gpio_request_by_name(dev, "reset-gpios", 0, + &priv->reset_gpio, GPIOD_IS_OUT); + if (ret) + log_debug("%s: cannot get reset-gpios: error %d\n", + __func__, ret); + + return 0; +} + +static int samsung_ltl106hl02_hw_init(struct udevice *dev) +{ + struct samsung_ltl106hl02_priv *priv = dev_get_priv(dev); + + dm_gpio_set_value(&priv->reset_gpio, 1); + regulator_set_enable_if_allowed(priv->vdd, 1); + + /* Dataheets states at least 8.5 msec for vdd stabilization */ + mdelay(10); + + dm_gpio_set_value(&priv->reset_gpio, 0); + + return 0; +} + +static int samsung_ltl106hl02_probe(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + + /* fill characteristics of DSI data link */ + plat->lanes = 4; + plat->format = MIPI_DSI_FMT_RGB888; + plat->mode_flags = MIPI_DSI_MODE_VIDEO; + + return samsung_ltl106hl02_hw_init(dev); +} + +static const struct panel_ops samsung_ltl106hl02_ops = { + .enable_backlight = samsung_ltl106hl02_enable_backlight, + .set_backlight = samsung_ltl106hl02_set_backlight, + .get_display_timing = samsung_ltl106hl02_timings, +}; + +static const struct udevice_id samsung_ltl106hl02_ids[] = { + { .compatible = "samsung,ltl106hl02-001" }, + { } +}; + +U_BOOT_DRIVER(samsung_ltl106hl02) = { + .name = "samsung_ltl106hl02", + .id = UCLASS_PANEL, + .of_match = samsung_ltl106hl02_ids, + .ops = &samsung_ltl106hl02_ops, + .of_to_plat = samsung_ltl106hl02_of_to_plat, + .probe = samsung_ltl106hl02_probe, + .plat_auto = sizeof(struct mipi_dsi_panel_plat), + .priv_auto = sizeof(struct samsung_ltl106hl02_priv), +}; From patchwork Wed Jan 31 06:57:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Svyatoslav Ryhel X-Patchwork-Id: 1893247 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=la2Ri45A; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TPtD66kc2z23fD for ; Wed, 31 Jan 2024 17:58:30 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A4FAF879F0; Wed, 31 Jan 2024 07:57:51 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="la2Ri45A"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id F31D1879B5; Wed, 31 Jan 2024 07:57:48 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-lf1-x130.google.com (mail-lf1-x130.google.com [IPv6:2a00:1450:4864:20::130]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9ED2687B1D for ; Wed, 31 Jan 2024 07:57:45 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=clamor95@gmail.com Received: by mail-lf1-x130.google.com with SMTP id 2adb3069b0e04-51120e2864fso1172062e87.1 for ; Tue, 30 Jan 2024 22:57:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706684265; x=1707289065; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oov4idVeJrz8k9WCPK/zDpe7su7k+K84VHe4HOljud8=; b=la2Ri45AwQgv09hEXAUhRkLZDfJ6IJi7wPH/0D1ad4ya0YC1Nj71fSp3gLkN/jF/yA 8Pipz8Ua1ffx/5fH0DbDx1IfUqH1zSFoQNRKcbWZMyerH+2pyISVVlbowZWQGXVD0PVM EipIkh6R/TBTbTFz/UshOyX6/KEVLaJGf/l7AhpC1kT24/gzyx5XVUnUJ3KergZORw/5 wI9j7HKB2yFPmFxBI5FfRjjaThnUK/BqYkf1f/0OvQPc8+6yJepzVb0rzVRvEh7vfua6 YbZUGIhiDTQ0HTigx2qCfQL87h7+81l9NVLtw+q7OqNoa8FulJ3tpxqpYCS83xaTNVfV N5ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706684265; x=1707289065; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=oov4idVeJrz8k9WCPK/zDpe7su7k+K84VHe4HOljud8=; b=v3INyVHk5ttMhtT1tZl5czi9LHkQ2/Bg4tjOhgKwudWUDYyXc+4+LKywCr4ITaTRAX +xY4NXyrqhlSgzXRGqo5YClibOFbkzSUyq9gJzyXexfh0kHoe1Z+sWXv9iBWgxjePtOA PhhL2Fg8+R3KzhQ/Yuo1ldAQgHd1xFpxyo8aHtcWg1mCjELpcIGHok2XMTjyG3X0XlRj 7M2ycCLAdI/AXq0MNh0xbGaj7eaKK2ZYcZoDNSwkwIh8DkiaeG1OaDd041kEv/VZpDpd ysdudHbNkwoWTL1H9vAmFtLszVrwE/eQo9zdG92XDt0MTZ/mikrD5Usj/sskZC7jBoqQ HMCQ== X-Gm-Message-State: AOJu0YzgQsfkIWOdFqXlX6vVEZp5itGWW0zxLg3LwdOFYk3Xatq1+lFL CR64H/uFK4E4M7BbRZgPRz7/NLsNkRwG6bJ3O38QPdVjoXEzNEo3 X-Google-Smtp-Source: AGHT+IEKVc/lanlqpEY0woNKRxp+RN2+15DWJ+trAGPv6zyUUmIa/lTb5+5PrPcUZXPQsBaK8j9a6w== X-Received: by 2002:ac2:4d88:0:b0:511:1abb:3c8e with SMTP id g8-20020ac24d88000000b005111abb3c8emr536330lfe.31.1706684264631; Tue, 30 Jan 2024 22:57:44 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCVJV8udSsHsVEs9o1KJtDh1qP9P4i3DPG1zhM0mjQnQ2nKPN2O2U71tXcESkWlo0TSYneMP97EP/K/eTxlB9MmopU1HEE7wCr3RgFkp/rKK4rliaWqE8XuyoJlGd7JtuBZJfcA6epJ1tvtuUG21qGmyWYRkfFbvMo0qgyonyXbxygxms6DsMRYrmMjGbfkB84rd57xe6g== Received: from xeon.. ([188.163.112.73]) by smtp.gmail.com with ESMTPSA id s11-20020a19770b000000b0051023c2e95asm1760796lfc.209.2024.01.30.22.57.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 22:57:44 -0800 (PST) From: Svyatoslav Ryhel To: Tom Rini , Anatolij Gustschin , Simon Glass , Svyatoslav Ryhel , Anton Bambura , =?utf-8?q?Jonas_Schw=C3=B6bel?= Cc: u-boot@lists.denx.de Subject: [PATCH v2 3/7] video: bridge: add Toshiba TC358768 RGB to DSI bridge support Date: Wed, 31 Jan 2024 08:57:17 +0200 Message-Id: <20240131065721.4245-4-clamor95@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240131065721.4245-1-clamor95@gmail.com> References: <20240131065721.4245-1-clamor95@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Add initial support for the Toshiba TC358768 RGB to DSI bridge. The driver is based on the mainline Linux Toshiba TC358768 bridge driver and implements the same set of features. Tested-by: Andreas Westman Dorcsak # ASUS TF700T Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/Kconfig | 9 + drivers/video/bridge/Makefile | 1 + drivers/video/bridge/tc358768.c | 985 ++++++++++++++++++++++++++++++++ 3 files changed, 995 insertions(+) create mode 100644 drivers/video/bridge/tc358768.c diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index 2311ca2d1a..6a9e7c1454 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -40,3 +40,12 @@ config VIDEO_BRIDGE_SOLOMON_SSD2825 select VIDEO_MIPI_DSI help Solomon SSD2824 SPI RGB-DSI bridge driver wrapped into panel uClass. + +config VIDEO_BRIDGE_TOSHIBA_TC358768 + bool "Support Toshiba TC358768 MIPI DSI bridge" + depends on PANEL && DM_GPIO + select VIDEO_MIPI_DSI + select DM_I2C + help + Toshiba TC358768AXBG/TC358778XBG DSI bridge chip driver. + Found in Asus Transformer Infinity TF700T. diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile index 22625c8bc6..ed3e7e9ce1 100644 --- a/drivers/video/bridge/Makefile +++ b/drivers/video/bridge/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o +obj-$(CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768) += tc358768.o diff --git a/drivers/video/bridge/tc358768.c b/drivers/video/bridge/tc358768.c new file mode 100644 index 0000000000..19b6ca29d3 --- /dev/null +++ b/drivers/video/bridge/tc358768.c @@ -0,0 +1,985 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Texas Instruments Incorporated + * Copyright (C) 2022 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Global (16-bit addressable) */ +#define TC358768_CHIPID 0x0000 +#define TC358768_SYSCTL 0x0002 +#define TC358768_CONFCTL 0x0004 +#define TC358768_VSDLY 0x0006 +#define TC358768_DATAFMT 0x0008 +#define TC358768_GPIOEN 0x000E +#define TC358768_GPIODIR 0x0010 +#define TC358768_GPIOIN 0x0012 +#define TC358768_GPIOOUT 0x0014 +#define TC358768_PLLCTL0 0x0016 +#define TC358768_PLLCTL1 0x0018 +#define TC358768_CMDBYTE 0x0022 +#define TC358768_PP_MISC 0x0032 +#define TC358768_DSITX_DT 0x0050 +#define TC358768_FIFOSTATUS 0x00F8 + +/* Debug (16-bit addressable) */ +#define TC358768_VBUFCTRL 0x00E0 +#define TC358768_DBG_WIDTH 0x00E2 +#define TC358768_DBG_VBLANK 0x00E4 +#define TC358768_DBG_DATA 0x00E8 + +/* TX PHY (32-bit addressable) */ +#define TC358768_CLW_DPHYCONTTX 0x0100 +#define TC358768_D0W_DPHYCONTTX 0x0104 +#define TC358768_D1W_DPHYCONTTX 0x0108 +#define TC358768_D2W_DPHYCONTTX 0x010C +#define TC358768_D3W_DPHYCONTTX 0x0110 +#define TC358768_CLW_CNTRL 0x0140 +#define TC358768_D0W_CNTRL 0x0144 +#define TC358768_D1W_CNTRL 0x0148 +#define TC358768_D2W_CNTRL 0x014C +#define TC358768_D3W_CNTRL 0x0150 + +/* TX PPI (32-bit addressable) */ +#define TC358768_STARTCNTRL 0x0204 +#define TC358768_DSITXSTATUS 0x0208 +#define TC358768_LINEINITCNT 0x0210 +#define TC358768_LPTXTIMECNT 0x0214 +#define TC358768_TCLK_HEADERCNT 0x0218 +#define TC358768_TCLK_TRAILCNT 0x021C +#define TC358768_THS_HEADERCNT 0x0220 +#define TC358768_TWAKEUP 0x0224 +#define TC358768_TCLK_POSTCNT 0x0228 +#define TC358768_THS_TRAILCNT 0x022C +#define TC358768_HSTXVREGCNT 0x0230 +#define TC358768_HSTXVREGEN 0x0234 +#define TC358768_TXOPTIONCNTRL 0x0238 +#define TC358768_BTACNTRL1 0x023C + +/* TX CTRL (32-bit addressable) */ +#define TC358768_DSI_CONTROL 0x040C +#define TC358768_DSI_STATUS 0x0410 +#define TC358768_DSI_INT 0x0414 +#define TC358768_DSI_INT_ENA 0x0418 +#define TC358768_DSICMD_RDFIFO 0x0430 +#define TC358768_DSI_ACKERR 0x0434 +#define TC358768_DSI_ACKERR_INTENA 0x0438 +#define TC358768_DSI_ACKERR_HALT 0x043c +#define TC358768_DSI_RXERR 0x0440 +#define TC358768_DSI_RXERR_INTENA 0x0444 +#define TC358768_DSI_RXERR_HALT 0x0448 +#define TC358768_DSI_ERR 0x044C +#define TC358768_DSI_ERR_INTENA 0x0450 +#define TC358768_DSI_ERR_HALT 0x0454 +#define TC358768_DSI_CONFW 0x0500 +#define TC358768_DSI_LPCMD 0x0500 +#define TC358768_DSI_RESET 0x0504 +#define TC358768_DSI_INT_CLR 0x050C +#define TC358768_DSI_START 0x0518 + +/* DSITX CTRL (16-bit addressable) */ +#define TC358768_DSICMD_TX 0x0600 +#define TC358768_DSICMD_TYPE 0x0602 +#define TC358768_DSICMD_WC 0x0604 +#define TC358768_DSICMD_WD0 0x0610 +#define TC358768_DSICMD_WD1 0x0612 +#define TC358768_DSICMD_WD2 0x0614 +#define TC358768_DSICMD_WD3 0x0616 +#define TC358768_DSI_EVENT 0x0620 +#define TC358768_DSI_VSW 0x0622 +#define TC358768_DSI_VBPR 0x0624 +#define TC358768_DSI_VACT 0x0626 +#define TC358768_DSI_HSW 0x0628 +#define TC358768_DSI_HBPR 0x062A +#define TC358768_DSI_HACT 0x062C + +/* TC358768_DSI_CONTROL (0x040C) register */ +#define TC358768_DSI_CONTROL_DIS_MODE BIT(15) +#define TC358768_DSI_CONTROL_TXMD BIT(7) +#define TC358768_DSI_CONTROL_HSCKMD BIT(5) +#define TC358768_DSI_CONTROL_EOTDIS BIT(0) + +/* TC358768_DSI_CONFW (0x0500) register */ +#define TC358768_DSI_CONFW_MODE_SET (5 << 29) +#define TC358768_DSI_CONFW_MODE_CLR (6 << 29) +#define TC358768_DSI_CONFW_ADDR_DSI_CONTROL (3 << 24) + +#define NANO 1000000000UL +#define PICO 1000000000000ULL + +struct tc358768_priv { + struct mipi_dsi_host host; + struct mipi_dsi_device device; + + struct udevice *panel; + struct display_timing timing; + + struct udevice *vddc; + struct udevice *vddmipi; + struct udevice *vddio; + + struct clk *refclk; + + struct gpio_desc reset_gpio; + + u32 pd_lines; /* number of Parallel Port Input Data Lines */ + u32 dsi_lanes; /* number of DSI Lanes */ + + /* Parameters for PLL programming */ + u32 fbd; /* PLL feedback divider */ + u32 prd; /* PLL input divider */ + u32 frs; /* PLL Freqency range for HSCK (post divider) */ + + u32 dsiclk; /* pll_clk / 2 */ +}; + +static void tc358768_read(struct udevice *dev, u32 reg, u32 *val) +{ + int count; + u8 buf[4] = { 0, 0, 0, 0 }; + + /* 16-bit register? */ + if (reg < 0x100 || reg >= 0x600) + count = 2; + else + count = 4; + + dm_i2c_read(dev, reg, buf, count); + *val = (buf[0] << 8) | (buf[1] & 0xff) | + (buf[2] << 24) | (buf[3] << 16); + + log_debug("%s 0x%04x >> 0x%08x\n", + __func__, reg, *val); +} + +static void tc358768_write(struct udevice *dev, u32 reg, u32 val) +{ + int count; + u8 buf[4]; + + /* 16-bit register? */ + if (reg < 0x100 || reg >= 0x600) + count = 2; + else + count = 4; + + buf[0] = val >> 8; + buf[1] = val & 0xff; + buf[2] = val >> 24; + buf[3] = val >> 16; + + log_debug("%s 0x%04x << 0x%08x\n", + __func__, reg, val); + + dm_i2c_write(dev, reg, buf, count); +} + +static void tc358768_update_bits(struct udevice *dev, u32 reg, u32 mask, + u32 val) +{ + u32 tmp, orig; + + tc358768_read(dev, reg, &orig); + + tmp = orig & ~mask; + tmp |= val & mask; + if (tmp != orig) + tc358768_write(dev, reg, tmp); +} + +static ssize_t tc358768_dsi_host_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct udevice *dev = (struct udevice *)host->dev; + struct mipi_dsi_packet packet; + int ret; + + if (msg->rx_len) { + log_debug("%s: MIPI rx is not supported\n", __func__); + return -EOPNOTSUPP; + } + + if (msg->tx_len > 8) { + log_debug("%s: Maximum 8 byte MIPI tx is supported\n", __func__); + return -EOPNOTSUPP; + } + + ret = mipi_dsi_create_packet(&packet, msg); + if (ret) + return ret; + + if (mipi_dsi_packet_format_is_short(msg->type)) { + tc358768_write(dev, TC358768_DSICMD_TYPE, + (0x10 << 8) | (packet.header[0] & 0x3f)); + tc358768_write(dev, TC358768_DSICMD_WC, 0); + tc358768_write(dev, TC358768_DSICMD_WD0, + (packet.header[2] << 8) | packet.header[1]); + } else { + int i; + + tc358768_write(dev, TC358768_DSICMD_TYPE, + (0x40 << 8) | (packet.header[0] & 0x3f)); + tc358768_write(dev, TC358768_DSICMD_WC, packet.payload_length); + for (i = 0; i < packet.payload_length; i += 2) { + u16 val = packet.payload[i]; + + if (i + 1 < packet.payload_length) + val |= packet.payload[i + 1] << 8; + + tc358768_write(dev, TC358768_DSICMD_WD0 + i, val); + } + } + + /* start transfer */ + tc358768_write(dev, TC358768_DSICMD_TX, 1); + + return packet.size; +} + +static const struct mipi_dsi_host_ops tc358768_dsi_host_ops = { + .transfer = tc358768_dsi_host_transfer, +}; + +static void tc358768_sw_reset(struct udevice *dev) +{ + /* Assert Reset */ + tc358768_write(dev, TC358768_SYSCTL, 1); + mdelay(5); + + /* Release Reset, Exit Sleep */ + tc358768_write(dev, TC358768_SYSCTL, 0); +} + +static void tc358768_hw_enable(struct tc358768_priv *priv) +{ + int ret; + + ret = clk_prepare_enable(priv->refclk); + if (ret) + log_debug("%s: error enabling refclk (%d)\n", __func__, ret); + + ret = regulator_set_enable_if_allowed(priv->vddc, true); + if (ret) + log_debug("%s: error enabling vddc (%d)\n", __func__, ret); + + ret = regulator_set_enable_if_allowed(priv->vddmipi, true); + if (ret) + log_debug("%s: error enabling vddmipi (%d)\n", __func__, ret); + + mdelay(10); + + ret = regulator_set_enable_if_allowed(priv->vddio, true); + if (ret) + log_debug("%s: error enabling vddio (%d)\n", __func__, ret); + + mdelay(2); + + /* + * The RESX is active low (GPIO_ACTIVE_LOW). + * DEASSERT (value = 0) the reset_gpio to enable the chip + */ + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) + log_debug("%s: error changing reset-gpio (%d)\n", __func__, ret); + + /* wait for encoder clocks to stabilize */ + mdelay(2); +} + +static u32 tc358768_pclk_to_pll(struct tc358768_priv *priv, u32 pclk) +{ + return (u32)div_u64((u64)pclk * priv->pd_lines, priv->dsi_lanes); +} + +static int tc358768_calc_pll(struct tc358768_priv *priv, + struct display_timing *dt) +{ + static const u32 frs_limits[] = { + 1000000000, + 500000000, + 250000000, + 125000000, + 62500000 + }; + unsigned long refclk; + u32 prd, target_pll, i, max_pll, min_pll; + u32 frs, best_diff, best_pll, best_prd, best_fbd; + + target_pll = tc358768_pclk_to_pll(priv, dt->pixelclock.typ); + + /* pll_clk = RefClk * FBD / PRD * (1 / (2^FRS)) */ + + for (i = 0; i < ARRAY_SIZE(frs_limits); i++) + if (target_pll >= frs_limits[i]) + break; + + if (i == ARRAY_SIZE(frs_limits) || i == 0) + return -EINVAL; + + frs = i - 1; + max_pll = frs_limits[i - 1]; + min_pll = frs_limits[i]; + + refclk = clk_get_rate(priv->refclk); + + best_diff = UINT_MAX; + best_pll = 0; + best_prd = 0; + best_fbd = 0; + + for (prd = 1; prd <= 16; ++prd) { + u32 divisor = prd * (1 << frs); + u32 fbd; + + for (fbd = 1; fbd <= 512; ++fbd) { + u32 pll, diff, pll_in; + + pll = (u32)div_u64((u64)refclk * fbd, divisor); + + if (pll >= max_pll || pll < min_pll) + continue; + + pll_in = (u32)div_u64((u64)refclk, prd); + if (pll_in < 4000000) + continue; + + diff = max(pll, target_pll) - min(pll, target_pll); + + if (diff < best_diff) { + best_diff = diff; + best_pll = pll; + best_prd = prd; + best_fbd = fbd; + + if (best_diff == 0) + goto found; + } + } + } + + if (best_diff == UINT_MAX) { + log_debug("%s: could not find suitable PLL setup\n", __func__); + return -EINVAL; + } + +found: + priv->fbd = best_fbd; + priv->prd = best_prd; + priv->frs = frs; + priv->dsiclk = best_pll / 2; + + return 0; +} + +static void tc358768_setup_pll(struct udevice *dev) +{ + struct tc358768_priv *priv = dev_get_priv(dev); + u32 fbd, prd, frs; + int ret; + + ret = tc358768_calc_pll(priv, &priv->timing); + if (ret) + log_debug("%s: PLL calculation failed: %d\n", __func__, ret); + + fbd = priv->fbd; + prd = priv->prd; + frs = priv->frs; + + log_debug("%s: PLL: refclk %lu, fbd %u, prd %u, frs %u\n", __func__, + clk_get_rate(priv->refclk), fbd, prd, frs); + log_debug("%s: PLL: pll_clk: %u, DSIClk %u, HSByteClk %u\n", __func__, + priv->dsiclk * 2, priv->dsiclk, priv->dsiclk / 4); + + /* PRD[15:12] FBD[8:0] */ + tc358768_write(dev, TC358768_PLLCTL0, ((prd - 1) << 12) | (fbd - 1)); + + /* FRS[11:10] LBWS[9:8] CKEN[4] RESETB[1] EN[0] */ + tc358768_write(dev, TC358768_PLLCTL1, + (frs << 10) | (0x2 << 8) | BIT(1) | BIT(0)); + + /* wait for lock */ + mdelay(5); + + /* FRS[11:10] LBWS[9:8] CKEN[4] PLL_CKEN[4] RESETB[1] EN[0] */ + tc358768_write(dev, TC358768_PLLCTL1, + (frs << 10) | (0x2 << 8) | BIT(4) | BIT(1) | BIT(0)); +} + +static u32 tc358768_ns_to_cnt(u32 ns, u32 period_ps) +{ + return DIV_ROUND_UP(ns * 1000, period_ps); +} + +static u32 tc358768_ps_to_ns(u32 ps) +{ + return ps / 1000; +} + +static u32 tc358768_dpi_to_ns(u32 val, u32 pclk) +{ + return (u32)div_u64((u64)val * NANO, pclk); +} + +/* Convert value in DPI pixel clock units to DSI byte count */ +static u32 tc358768_dpi_to_dsi_bytes(struct tc358768_priv *priv, u32 val) +{ + u64 m = (u64)val * priv->dsiclk / 4 * priv->dsi_lanes; + u64 n = priv->timing.pixelclock.typ; + + return (u32)div_u64(m + n - 1, n); +} + +static u32 tc358768_dsi_bytes_to_ns(struct tc358768_priv *priv, u32 val) +{ + u64 m = (u64)val * NANO; + u64 n = priv->dsiclk / 4 * priv->dsi_lanes; + + return (u32)div_u64(m, n); +} + +static int tc358768_attach(struct udevice *dev) +{ + struct tc358768_priv *priv = dev_get_priv(dev); + struct mipi_dsi_device *device = &priv->device; + struct display_timing *dt = &priv->timing; + u32 val, val2, lptxcnt, hact, data_type; + s32 raw_val; + u32 hsbyteclk_ps, dsiclk_ps, ui_ps; + u32 dsiclk, hsbyteclk; + int i; + /* In pixelclock units */ + u32 dpi_htot, dpi_data_start; + /* In byte units */ + u32 dsi_dpi_htot, dsi_dpi_data_start; + u32 dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp; + const u32 dsi_hss = 4; /* HSS is a short packet (4 bytes) */ + /* In hsbyteclk units */ + u32 dsi_vsdly; + const u32 internal_dly = 40; + + if (device->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { + debug("%s: Non-continuous mode unimplemented, falling back to continuous\n", __func__); + device->mode_flags &= ~MIPI_DSI_CLOCK_NON_CONTINUOUS; + } + + tc358768_hw_enable(priv); + tc358768_sw_reset(dev); + + tc358768_setup_pll(dev); + + dsiclk = priv->dsiclk; + hsbyteclk = dsiclk / 4; + + /* Data Format Control Register */ + val = BIT(2) | BIT(1) | BIT(0); /* rdswap_en | dsitx_en | txdt_en */ + switch (device->format) { + case MIPI_DSI_FMT_RGB888: + val |= (0x3 << 4); + hact = dt->hactive.typ * 3; + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; + break; + case MIPI_DSI_FMT_RGB666: + val |= (0x4 << 4); + hact = dt->hactive.typ * 3; + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; + break; + case MIPI_DSI_FMT_RGB666_PACKED: + val |= (0x4 << 4) | BIT(3); + hact = dt->hactive.typ * 18 / 8; + data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; + break; + case MIPI_DSI_FMT_RGB565: + val |= (0x5 << 4); + hact = dt->hactive.typ * 2; + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; + break; + default: + log_debug("%s: Invalid data format (%u)\n", + __func__, device->format); + return -EINVAL; + } + + /* + * There are three important things to make TC358768 work correctly, + * which are not trivial to manage: + * + * 1. Keep the DPI line-time and the DSI line-time as close to each + * other as possible. + * 2. TC358768 goes to LP mode after each line's active area. The DSI + * HFP period has to be long enough for entering and exiting LP mode. + * But it is not clear how to calculate this. + * 3. VSDly (video start delay) has to be long enough to ensure that the + * DSI TX does not start transmitting until we have started receiving + * pixel data from the DPI input. It is not clear how to calculate + * this either. + */ + + dpi_htot = dt->hactive.typ + dt->hfront_porch.typ + + dt->hsync_len.typ + dt->hback_porch.typ; + dpi_data_start = dt->hsync_len.typ + dt->hback_porch.typ; + + log_debug("%s: dpi horiz timing (pclk): %u + %u + %u + %u = %u\n", __func__, + dt->hsync_len.typ, dt->hback_porch.typ, dt->hactive.typ, + dt->hfront_porch.typ, dpi_htot); + + log_debug("%s: dpi horiz timing (ns): %u + %u + %u + %u = %u\n", __func__, + tc358768_dpi_to_ns(dt->hsync_len.typ, dt->pixelclock.typ), + tc358768_dpi_to_ns(dt->hback_porch.typ, dt->pixelclock.typ), + tc358768_dpi_to_ns(dt->hactive.typ, dt->pixelclock.typ), + tc358768_dpi_to_ns(dt->hfront_porch.typ, dt->pixelclock.typ), + tc358768_dpi_to_ns(dpi_htot, dt->pixelclock.typ)); + + log_debug("%s: dpi data start (ns): %u + %u = %u\n", __func__, + tc358768_dpi_to_ns(dt->hsync_len.typ, dt->pixelclock.typ), + tc358768_dpi_to_ns(dt->hback_porch.typ, dt->pixelclock.typ), + tc358768_dpi_to_ns(dpi_data_start, dt->pixelclock.typ)); + + dsi_dpi_htot = tc358768_dpi_to_dsi_bytes(priv, dpi_htot); + dsi_dpi_data_start = tc358768_dpi_to_dsi_bytes(priv, dpi_data_start); + + if (device->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { + dsi_hsw = tc358768_dpi_to_dsi_bytes(priv, dt->hsync_len.typ); + dsi_hbp = tc358768_dpi_to_dsi_bytes(priv, dt->hback_porch.typ); + } else { + /* HBP is included in HSW in event mode */ + dsi_hbp = 0; + dsi_hsw = tc358768_dpi_to_dsi_bytes(priv, + dt->hsync_len.typ + + dt->hback_porch.typ); + + /* + * The pixel packet includes the actual pixel data, and: + * DSI packet header = 4 bytes + * DCS code = 1 byte + * DSI packet footer = 2 bytes + */ + dsi_hact = hact + 4 + 1 + 2; + + dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; + + /* + * Here we should check if HFP is long enough for entering LP + * and exiting LP, but it's not clear how to calculate that. + * Instead, this is a naive algorithm that just adjusts the HFP + * and HSW so that HFP is (at least) roughly 2/3 of the total + * blanking time. + */ + if (dsi_hfp < (dsi_hfp + dsi_hsw + dsi_hss) * 2 / 3) { + u32 old_hfp = dsi_hfp; + u32 old_hsw = dsi_hsw; + u32 tot = dsi_hfp + dsi_hsw + dsi_hss; + + dsi_hsw = tot / 3; + + /* + * Seems like sometimes HSW has to be divisible by num-lanes, but + * not always... + */ + dsi_hsw = roundup(dsi_hsw, priv->dsi_lanes); + + dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; + + log_debug("%s: hfp too short, adjusting dsi hfp and dsi hsw from %u, %u to %u, %u\n", + __func__, old_hfp, old_hsw, dsi_hfp, dsi_hsw); + } + + log_debug("%s: dsi horiz timing (bytes): %u, %u + %u + %u + %u = %u\n", __func__, + dsi_hss, dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp, + dsi_hss + dsi_hsw + dsi_hbp + dsi_hact + dsi_hfp); + + log_debug("%s: dsi horiz timing (ns): %u + %u + %u + %u + %u = %u\n", __func__, + tc358768_dsi_bytes_to_ns(priv, dsi_hss), + tc358768_dsi_bytes_to_ns(priv, dsi_hsw), + tc358768_dsi_bytes_to_ns(priv, dsi_hbp), + tc358768_dsi_bytes_to_ns(priv, dsi_hact), + tc358768_dsi_bytes_to_ns(priv, dsi_hfp), + tc358768_dsi_bytes_to_ns(priv, dsi_hss + dsi_hsw + + dsi_hbp + dsi_hact + dsi_hfp)); + } + + /* VSDly calculation */ + + /* Start with the HW internal delay */ + dsi_vsdly = internal_dly; + + /* Convert to byte units as the other variables are in byte units */ + dsi_vsdly *= priv->dsi_lanes; + + /* Do we need more delay, in addition to the internal? */ + if (dsi_dpi_data_start > dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp) { + dsi_vsdly = dsi_dpi_data_start - dsi_hss - dsi_hsw - dsi_hbp; + dsi_vsdly = roundup(dsi_vsdly, priv->dsi_lanes); + } + + log_debug("%s: dsi data start (bytes) %u + %u + %u + %u = %u\n", __func__, + dsi_vsdly, dsi_hss, dsi_hsw, dsi_hbp, + dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp); + + log_debug("%s: dsi data start (ns) %u + %u + %u + %u = %u\n", __func__, + tc358768_dsi_bytes_to_ns(priv, dsi_vsdly), + tc358768_dsi_bytes_to_ns(priv, dsi_hss), + tc358768_dsi_bytes_to_ns(priv, dsi_hsw), + tc358768_dsi_bytes_to_ns(priv, dsi_hbp), + tc358768_dsi_bytes_to_ns(priv, dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp)); + + /* Convert back to hsbyteclk */ + dsi_vsdly /= priv->dsi_lanes; + + /* + * The docs say that there is an internal delay of 40 cycles. + * However, we get underflows if we follow that rule. If we + * instead ignore the internal delay, things work. So either + * the docs are wrong or the calculations are wrong. + * + * As a temporary fix, add the internal delay here, to counter + * the subtraction when writing the register. + */ + dsi_vsdly += internal_dly; + + /* Clamp to the register max */ + if (dsi_vsdly - internal_dly > 0x3ff) { + log_warning("%s: VSDly too high, underflows likely\n", __func__); + dsi_vsdly = 0x3ff + internal_dly; + } + + /* VSDly[9:0] */ + tc358768_write(dev, TC358768_VSDLY, dsi_vsdly - internal_dly); + + tc358768_write(dev, TC358768_DATAFMT, val); + tc358768_write(dev, TC358768_DSITX_DT, data_type); + + /* Enable D-PHY (HiZ->LP11) */ + tc358768_write(dev, TC358768_CLW_CNTRL, 0x0000); + /* Enable lanes */ + for (i = 0; i < device->lanes; i++) + tc358768_write(dev, TC358768_D0W_CNTRL + i * 4, 0x0000); + + /* Set up D-PHY CONTTX */ + tc358768_write(dev, TC358768_CLW_DPHYCONTTX, 0x0203); + /* Adjust lanes */ + for (i = 0; i < device->lanes; i++) + tc358768_write(dev, TC358768_D0W_DPHYCONTTX + i * 4, 0x0203); + + /* DSI Timings */ + hsbyteclk_ps = (u32)div_u64(PICO, hsbyteclk); + dsiclk_ps = (u32)div_u64(PICO, dsiclk); + ui_ps = dsiclk_ps / 2; + log_debug("%s: dsiclk: %u ps, ui %u ps, hsbyteclk %u ps\n", + __func__, dsiclk_ps, ui_ps, hsbyteclk_ps); + + /* LP11 > 100us for D-PHY Rx Init */ + val = tc358768_ns_to_cnt(100 * 1000, hsbyteclk_ps) - 1; + log_debug("%s: LINEINITCNT: 0x%x\n", __func__, val); + tc358768_write(dev, TC358768_LINEINITCNT, val); + + /* LPTimeCnt > 50ns */ + val = tc358768_ns_to_cnt(50, hsbyteclk_ps) - 1; + lptxcnt = val; + log_debug("%s: LPTXTIMECNT: 0x%x\n", __func__, val); + tc358768_write(dev, TC358768_LPTXTIMECNT, val); + + /* 38ns < TCLK_PREPARE < 95ns */ + val = tc358768_ns_to_cnt(65, hsbyteclk_ps) - 1; + log_debug("%s: TCLK_PREPARECNT: 0x%x\n", __func__, val); + /* TCLK_PREPARE + TCLK_ZERO > 300ns */ + val2 = tc358768_ns_to_cnt(300 - tc358768_ps_to_ns(2 * ui_ps), + hsbyteclk_ps) - 2; + log_debug("%s: TCLK_ZEROCNT: 0x%x\n", __func__, val2); + val |= val2 << 8; + tc358768_write(dev, TC358768_TCLK_HEADERCNT, val); + + /* TCLK_TRAIL > 60ns AND TEOT <= 105 ns + 12*UI */ + raw_val = tc358768_ns_to_cnt(60 + tc358768_ps_to_ns(2 * ui_ps), + hsbyteclk_ps) - 5; + val = clamp(raw_val, 0, 127); + log_debug("%s: TCLK_TRAILCNT: 0x%x\n", __func__, val); + tc358768_write(dev, TC358768_TCLK_TRAILCNT, val); + + /* 40ns + 4*UI < THS_PREPARE < 85ns + 6*UI */ + val = 50 + tc358768_ps_to_ns(4 * ui_ps); + val = tc358768_ns_to_cnt(val, hsbyteclk_ps) - 1; + log_debug("%s: THS_PREPARECNT: 0x%x\n", __func__, val); + /* THS_PREPARE + THS_ZERO > 145ns + 10*UI */ + raw_val = tc358768_ns_to_cnt(145 - tc358768_ps_to_ns(3 * ui_ps), + hsbyteclk_ps) - 10; + val2 = clamp(raw_val, 0, 127); + log_debug("%s: THS_ZEROCNT: 0x%x\n", __func__, val2); + val |= val2 << 8; + tc358768_write(dev, TC358768_THS_HEADERCNT, val); + + /* TWAKEUP > 1ms in lptxcnt steps */ + val = tc358768_ns_to_cnt(1020000, hsbyteclk_ps); + val = val / (lptxcnt + 1) - 1; + log_debug("%s: TWAKEUP: 0x%x\n", __func__, val); + tc358768_write(dev, TC358768_TWAKEUP, val); + + /* TCLK_POSTCNT > 60ns + 52*UI */ + val = tc358768_ns_to_cnt(60 + tc358768_ps_to_ns(52 * ui_ps), + hsbyteclk_ps) - 3; + log_debug("%s: TCLK_POSTCNT: 0x%x\n", __func__, val); + tc358768_write(dev, TC358768_TCLK_POSTCNT, val); + + /* max(60ns + 4*UI, 8*UI) < THS_TRAILCNT < 105ns + 12*UI */ + raw_val = tc358768_ns_to_cnt(60 + tc358768_ps_to_ns(18 * ui_ps), + hsbyteclk_ps) - 4; + val = clamp(raw_val, 0, 15); + log_debug("%s: THS_TRAILCNT: 0x%x\n", __func__, val); + tc358768_write(dev, TC358768_THS_TRAILCNT, val); + + val = BIT(0); + for (i = 0; i < device->lanes; i++) + val |= BIT(i + 1); + tc358768_write(dev, TC358768_HSTXVREGEN, val); + + tc358768_write(dev, TC358768_TXOPTIONCNTRL, + (device->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) ? 0 : BIT(0)); + + /* TXTAGOCNT[26:16] RXTASURECNT[10:0] */ + val = tc358768_ps_to_ns((lptxcnt + 1) * hsbyteclk_ps * 4); + val = tc358768_ns_to_cnt(val, hsbyteclk_ps) / 4 - 1; + log_debug("%s: TXTAGOCNT: 0x%x\n", __func__, val); + val2 = tc358768_ns_to_cnt(tc358768_ps_to_ns((lptxcnt + 1) * hsbyteclk_ps), + hsbyteclk_ps) - 2; + log_debug("%s: RXTASURECNT: 0x%x\n", __func__, val2); + val = val << 16 | val2; + tc358768_write(dev, TC358768_BTACNTRL1, val); + + /* START[0] */ + tc358768_write(dev, TC358768_STARTCNTRL, 1); + + if (device->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { + /* Set pulse mode */ + tc358768_write(dev, TC358768_DSI_EVENT, 0); + + /* vact */ + tc358768_write(dev, TC358768_DSI_VACT, dt->vactive.typ); + /* vsw */ + tc358768_write(dev, TC358768_DSI_VSW, dt->vsync_len.typ); + /* vbp */ + tc358768_write(dev, TC358768_DSI_VBPR, dt->vback_porch.typ); + } else { + /* Set event mode */ + tc358768_write(dev, TC358768_DSI_EVENT, 1); + + /* vact */ + tc358768_write(dev, TC358768_DSI_VACT, dt->vactive.typ); + + /* vsw (+ vbp) */ + tc358768_write(dev, TC358768_DSI_VSW, + dt->vsync_len.typ + dt->vback_porch.typ); + /* vbp (not used in event mode) */ + tc358768_write(dev, TC358768_DSI_VBPR, 0); + } + + /* hsw (bytes) */ + tc358768_write(dev, TC358768_DSI_HSW, dsi_hsw); + + /* hbp (bytes) */ + tc358768_write(dev, TC358768_DSI_HBPR, dsi_hbp); + + /* hact (bytes) */ + tc358768_write(dev, TC358768_DSI_HACT, hact); + + /* VSYNC polarity */ + tc358768_update_bits(dev, TC358768_CONFCTL, BIT(5), + (dt->flags & DISPLAY_FLAGS_VSYNC_HIGH) ? BIT(5) : 0); + + /* HSYNC polarity */ + tc358768_update_bits(dev, TC358768_PP_MISC, BIT(0), + (dt->flags & DISPLAY_FLAGS_HSYNC_LOW) ? BIT(0) : 0); + + /* Start DSI Tx */ + tc358768_write(dev, TC358768_DSI_START, 0x1); + + /* Configure DSI_Control register */ + val = TC358768_DSI_CONFW_MODE_CLR | TC358768_DSI_CONFW_ADDR_DSI_CONTROL; + val |= TC358768_DSI_CONTROL_TXMD | TC358768_DSI_CONTROL_HSCKMD | + 0x3 << 1 | TC358768_DSI_CONTROL_EOTDIS; + tc358768_write(dev, TC358768_DSI_CONFW, val); + + val = TC358768_DSI_CONFW_MODE_SET | TC358768_DSI_CONFW_ADDR_DSI_CONTROL; + val |= (device->lanes - 1) << 1; + + val |= TC358768_DSI_CONTROL_TXMD; + + if (!(device->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)) + val |= TC358768_DSI_CONTROL_HSCKMD; + + /* + * TODO: Actually MIPI_DSI_MODE_NO_EOT_PACKET + * + * Many of the DSI flags have names opposite to their + * actual effects, e.g. MIPI_DSI_MODE_EOT_PACKET means + * that EoT packets will actually be disabled. + */ + if (device->mode_flags & MIPI_DSI_MODE_EOT_PACKET) + val |= TC358768_DSI_CONTROL_EOTDIS; + + tc358768_write(dev, TC358768_DSI_CONFW, val); + + val = TC358768_DSI_CONFW_MODE_CLR | + TC358768_DSI_CONFW_ADDR_DSI_CONTROL | + TC358768_DSI_CONTROL_DIS_MODE; /* DSI mode */ + tc358768_write(dev, TC358768_DSI_CONFW, val); + + /* clear FrmStop and RstPtr */ + tc358768_update_bits(dev, TC358768_PP_MISC, 0x3 << 14, 0); + + /* set PP_en */ + tc358768_update_bits(dev, TC358768_CONFCTL, BIT(6), BIT(6)); + + /* Set up panel configuration */ + return panel_enable_backlight(priv->panel); +} + +static int tc358768_set_backlight(struct udevice *dev, int percent) +{ + struct tc358768_priv *priv = dev_get_priv(dev); + + return panel_set_backlight(priv->panel, percent); +} + +static int tc358768_panel_timings(struct udevice *dev, + struct display_timing *timing) +{ + struct tc358768_priv *priv = dev_get_priv(dev); + + /* Default to positive sync */ + + if (!(priv->timing.flags & + (DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_HSYNC_HIGH))) + priv->timing.flags |= DISPLAY_FLAGS_HSYNC_HIGH; + + if (!(priv->timing.flags & + (DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH))) + priv->timing.flags |= DISPLAY_FLAGS_VSYNC_HIGH; + + memcpy(timing, &priv->timing, sizeof(*timing)); + + return 0; +} + +static int tc358768_setup(struct udevice *dev) +{ + struct tc358768_priv *priv = dev_get_priv(dev); + struct mipi_dsi_device *device = &priv->device; + struct mipi_dsi_panel_plat *mipi_plat; + int ret; + + /* The bridge uses 16 bit registers */ + ret = i2c_set_chip_offset_len(dev, 2); + if (ret) { + log_debug("%s: set_chip_offset_len failed: %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, + "panel", &priv->panel); + if (ret) { + log_debug("%s: Cannot get panel: ret=%d\n", __func__, ret); + return log_ret(ret); + } + + panel_get_display_timing(priv->panel, &priv->timing); + + mipi_plat = dev_get_plat(priv->panel); + mipi_plat->device = device; + + priv->host.dev = (struct device *)dev; + priv->host.ops = &tc358768_dsi_host_ops; + + device->host = &priv->host; + device->lanes = mipi_plat->lanes; + device->format = mipi_plat->format; + device->mode_flags = mipi_plat->mode_flags; + + priv->pd_lines = mipi_dsi_pixel_format_to_bpp(device->format); + priv->dsi_lanes = device->lanes; + + /* get regulators */ + ret = device_get_supply_regulator(dev, "vddc-supply", &priv->vddc); + if (ret) { + log_debug("%s: vddc regulator error: %d\n", __func__, ret); + if (ret != -ENOENT) + return log_ret(ret); + } + + ret = device_get_supply_regulator(dev, "vddmipi-supply", &priv->vddmipi); + if (ret) { + log_debug("%s: vddmipi regulator error: %d\n", __func__, ret); + if (ret != -ENOENT) + return log_ret(ret); + } + + ret = device_get_supply_regulator(dev, "vddio-supply", &priv->vddio); + if (ret) { + log_debug("%s: vddio regulator error: %d\n", __func__, ret); + if (ret != -ENOENT) + return log_ret(ret); + } + + /* get clk */ + priv->refclk = devm_clk_get(dev, "refclk"); + if (IS_ERR(priv->refclk)) { + log_debug("%s: Could not get refclk: %ld\n", + __func__, PTR_ERR(priv->refclk)); + return PTR_ERR(priv->refclk); + } + + /* get gpios */ + ret = gpio_request_by_name(dev, "reset-gpios", 0, + &priv->reset_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: Could not decode reset-gpios (%d)\n", __func__, ret); + return ret; + } + + dm_gpio_set_value(&priv->reset_gpio, 1); + + return 0; +} + +static int tc358768_probe(struct udevice *dev) +{ + if (device_get_uclass_id(dev->parent) != UCLASS_I2C) + return -EPROTONOSUPPORT; + + return tc358768_setup(dev); +} + +struct panel_ops tc358768_ops = { + .enable_backlight = tc358768_attach, + .set_backlight = tc358768_set_backlight, + .get_display_timing = tc358768_panel_timings, +}; + +static const struct udevice_id tc358768_ids[] = { + { .compatible = "toshiba,tc358768" }, + { .compatible = "toshiba,tc358778" }, + { } +}; + +U_BOOT_DRIVER(tc358768) = { + .name = "tc358768", + .id = UCLASS_PANEL, + .of_match = tc358768_ids, + .ops = &tc358768_ops, + .probe = tc358768_probe, + .priv_auto = sizeof(struct tc358768_priv), +}; From patchwork Wed Jan 31 06:57:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Svyatoslav Ryhel X-Patchwork-Id: 1893246 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=NghvwtDH; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TPtCw6xwkz23fD for ; Wed, 31 Jan 2024 17:58:20 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id ECBF287B71; Wed, 31 Jan 2024 07:57:50 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="NghvwtDH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D3D6187C46; Wed, 31 Jan 2024 07:57:48 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 7B5888799C for ; Wed, 31 Jan 2024 07:57:46 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=clamor95@gmail.com Received: by mail-lf1-x134.google.com with SMTP id 2adb3069b0e04-51109060d6aso4729821e87.2 for ; Tue, 30 Jan 2024 22:57:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706684266; x=1707289066; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ht6/Qe6+9/9PP9uR5Z+NET/sVf+lZbOIgbl2Townhjk=; b=NghvwtDHEiFaPLRLdJoSC8bBXTzy4+HocvT8RQnN8lEtDPF/OyG6mo24wZgf96YHYh 9cwQHuv2/nGqj7xSWF7dosvUhtS4j+t4A4944EY5kecD+x2SJtasaog7UuoWKCTU7A1i pWE8bhl0aPFcCLSkpIa90lZQESjwD8oD/WKGj2geULlZHefLBaZje2VHpti7Ea4mdiSd Cp2eL5jal+4qNSdfcTZr319oYwG6XgJX4T+bZL3749zY5BhDXvELKv+DEp3//Q7wMdAx jF87I6FPDzGyFF+LnqrQa+2OyFgk+Kdcl++Wqn43waRFJKqmPV/2bWHC5WqQlH8jMr+u PDyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706684266; x=1707289066; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ht6/Qe6+9/9PP9uR5Z+NET/sVf+lZbOIgbl2Townhjk=; b=MljcJwyo6APPHpdak7i7DTwd0+9dl624tMfQyJi881d2EcF1+skPnjs07Z8MgHV9uu GMfPpS4QB0MSl+f9b01YhsneYhqxM33qUh7Ixx5LqEia+M6PEZMoSdO32RE21yuDDdyC 3p5P4ZQIPtqrssLbdowJj+diiCf8eIxl+qqrwvzgWA7syOdSLcyfEUItBhCgWhVEhEN3 29AdkN9C+MTaDUzL2/EBkExNH4R7Uht1JCRcRQd0FYNVBu6/66lX1VeSGigQTYaOzjuY oh7XDFLaJnFFEUP5cu8kg6nJ31AUBseXOwi+iBk90U1oeYjlC2KfiMeDl6Yc+Jxh/fHF ocEQ== X-Gm-Message-State: AOJu0YyLM6G3cQqly6zqAqh8LVmb/NFPhFx22BZeQZnm+jQkc/UHE7fD 9j0oYurhExY1ewfaK7CmssboSGwIK/QL3Nja+d/pHPTDPEvfnZE0 X-Google-Smtp-Source: AGHT+IEJDQiD8MZjchIfrd3Dl5ZQuWuefxWobA+bHFSxMkzxM8o0i6woqlCOV5pCsvdQcUPb+a/fLA== X-Received: by 2002:ac2:428a:0:b0:511:e75:7fae with SMTP id m10-20020ac2428a000000b005110e757faemr521692lfh.66.1706684265689; Tue, 30 Jan 2024 22:57:45 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCX/R8lvFGK7M6bdaiovPCJNYZGxzaKvXpvxg6vIc3g1NRsd63KF9UjddO22KMZkU2WMpjeT7IoMRoV4mLXk8gS6OxxI3k5y2ElTN0Q6MpS6aahxYTUVIvTucvQlSKNXHZs6gvSyLB6p74Ix0gZLGdbWLFUxoa+cHsISbtqu130bVuxxqIrTGiXEPHBV/cUdcMGFRae51Q== Received: from xeon.. ([188.163.112.73]) by smtp.gmail.com with ESMTPSA id s11-20020a19770b000000b0051023c2e95asm1760796lfc.209.2024.01.30.22.57.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 22:57:45 -0800 (PST) From: Svyatoslav Ryhel To: Tom Rini , Anatolij Gustschin , Simon Glass , Svyatoslav Ryhel , Anton Bambura , =?utf-8?q?Jonas_Schw=C3=B6bel?= Cc: u-boot@lists.denx.de Subject: [PATCH v2 4/7] video: bridge: add basic support for the Parade DP501 transmitter Date: Wed, 31 Jan 2024 08:57:18 +0200 Message-Id: <20240131065721.4245-5-clamor95@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240131065721.4245-1-clamor95@gmail.com> References: <20240131065721.4245-1-clamor95@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean From: Jonas Schwöbel The Parade DP501 is a DP & DVI/HDMI dual-mode transmitter. It enables an RGB/Parallel SOC output to be converted, packed and serialized into either DP or TMDS output device. Only DisplayPort functionality of this transmitter has been implemented and tested. Signed-off-by: Jonas Schwöbel Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/Kconfig | 10 + drivers/video/bridge/Makefile | 1 + drivers/video/bridge/dp501.c | 579 ++++++++++++++++++++++++++++++++++ 3 files changed, 590 insertions(+) create mode 100644 drivers/video/bridge/dp501.c diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index 6a9e7c1454..ab91727372 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -7,6 +7,16 @@ config VIDEO_BRIDGE requires LVDS, an eDP->LVDS bridge chip can be used to provide the necessary conversion. This option enables support for these devices. +config VIDEO_BRIDGE_PARADE_DP501 + bool "Support Parade DP501 DP & DVI/HDMI dual mode transmitter" + depends on PANEL && DM_GPIO + select DM_I2C + help + The Parade DP501 is a DP & DVI/HDMI dual-mode transmitter. It + enables an RGB/Parallel SOC output to be converted, packed and + serialized into either DP or TMDS output device. Only DisplayPort + functionality of this transmitter has been implemented and tested. + config VIDEO_BRIDGE_PARADE_PS862X bool "Support Parade PS862X DP->LVDS bridge" depends on VIDEO_BRIDGE diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile index ed3e7e9ce1..58697e3cbe 100644 --- a/drivers/video/bridge/Makefile +++ b/drivers/video/bridge/Makefile @@ -4,6 +4,7 @@ # Written by Simon Glass obj-$(CONFIG_VIDEO_BRIDGE) += video-bridge-uclass.o +obj-$(CONFIG_VIDEO_BRIDGE_PARADE_DP501) += dp501.o obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o diff --git a/drivers/video/bridge/dp501.c b/drivers/video/bridge/dp501.c new file mode 100644 index 0000000000..095e3e71fe --- /dev/null +++ b/drivers/video/bridge/dp501.c @@ -0,0 +1,579 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Jonas Schwöbel + * Copyright (C) 2024 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* TOP */ +#define TOPCFG0 0x00 +#define ROMI2C_PRESCALE 0x01 +#define HDCPI2C_PRESCALE 0x02 +#define GPIO 0x03 +#define GPIO_OUT_ENB 0x04 +#define TESTI2C_CTL 0x05 +#define I2CMTIMEOUT 0x06 +#define TOPCFG1 0x07 +#define TOPCFG2 0x08 +#define TOPCFG3 0x09 +#define TOPCFG4 0x0A +#define CLKSWRST 0x0B +#define CADETB_CTL 0x0C + +/* Video Attribute */ +#define HTOTAL_L 0x10 +#define HTOTAL_H 0x11 +#define HSTART_L 0x12 +#define HSTART_H 0x13 +#define HWIDTH_L 0x14 +#define HWIDTH_H 0x15 +#define VTOTAL_L 0x16 +#define VTOTAL_H 0x17 +#define VSTART_L 0x18 +#define VSTART_H 0x19 +#define VHEIGHT_L 0x1A +#define VHEIGHT_H 0x1B +#define HSPHSW_L 0x1C +#define HSPHSW_H 0x1D +#define VSPVSW_L 0x1E +#define VSPVSW_H 0x1F +#define MISC0 0x20 +#define MISC1 0x21 + +/* Video Capture */ +#define VCAPCTRL0 0x24 +#define VCAPCTRL1 0x25 +#define VCAPCTRL2 0x26 +#define VCAPCTRL3 0x27 +#define VCAPCTRL4 0x28 +#define VCAP_MEASURE 0x29 + +/* Main Link Control */ +#define NVID_L 0x2C +#define NVID_M 0x2D +#define NVID_H 0x2E +#define LINK_CTRL0 0x2F +#define LINK_CTRL1 0x30 +#define LINK_DEBUG 0x31 +#define ERR_POS 0x32 +#define ERR_PAT 0x33 +#define LINK_DEB_SEL 0x34 +#define IDLE_PATTERN 0x35 +#define TU_SIZE 0x36 +#define CRC_CTRL 0x37 +#define CRC_OUT 0x38 + +/* AVI-2 InfoFrame */ +#define SD_CTRL0 0x3A +#define SD_CTRL1 0x3B +#define SD_HB0 0x3C +#define SD_HB1 0x3D +#define SD_HB2 0x3E +#define SD_HB3 0x3F +#define SD_DB0 0x40 +#define SD_DB1 0x41 +#define SD_DB2 0x42 +#define SD_DB3 0x43 +#define SD_DB4 0x44 +#define SD_DB5 0x45 +#define SD_DB6 0x46 +#define SD_DB7 0x47 +#define SD_DB8 0x48 +#define SD_DB9 0x49 +#define SD_DB10 0x4A +#define SD_DB11 0x4B +#define SD_DB12 0x4C +#define SD_DB13 0x4D +#define SD_DB14 0x4E +#define SD_DB15 0x4F + +/* Aux Channel and PCS */ +#define DPCD_REV 0X50 +#define MAX_LINK_RATE 0x51 +#define MAX_LANE_COUNT 0x52 +#define MAX_DOWNSPREAD 0x53 +#define NORP 0x54 +#define DOWNSTRMPORT_PRE 0x55 +#define MLINK_CH_CODING 0x56 +#define RCV_P0_CAP0 0x58 +#define RCV_P0_CAP1 0x59 +#define RCV_P1_CAP0 0x5A +#define RCV_P1_CAP1 0x5B +#define DOWNSPREAD_CTL 0x5C +#define LINK_BW 0x5D +#define LANE_CNT 0x5E +#define TRAINING_CTL 0x5F +#define QUALTEST_CTL 0x60 +#define SINK_COUNT 0x61 +#define DEV_SERVICE_IRQ 0x62 +#define LANE01_STATUS 0x63 +#define LANE23_STATUS 0x64 +#define LANE_STATUS_UPDATE 0x65 +#define SINK_STATUS 0x66 +#define AUX_NOISE 0x67 +#define TEST_MODE 0x69 +#define TEST_PATTERN0 0x6A +#define TEST_PATTERN1 0x6B +#define TEST_PATTERN2 0x6C +#define SIGNATURE 0x6D +#define PCSCFG 0x6E +#define AUXCTRL0 0x6f +#define AUXCTRL2 0x70 +#define AUXCTRL1 0x71 +#define HPDCTL0 0x72 +#define HPDCTL1 0x73 +#define LINK_STATE_CTRL 0x74 +#define SWRST 0x75 +#define LINK_IRQ 0x76 +#define AUXIRQ_CTRL 0x77 +#define HPD2_IRQ_CTRL 0x78 +#define SW_TRAIN_CTRL 0x79 +#define SW_DRV_SET 0x7A +#define SW_PRE_SET 0x7B +#define DPCD_ADDR_L 0x7D +#define DPCD_ADDR_M 0x7E +#define DPCD_ADDR_H 0x7F +#define DPCD_LENGTH 0x80 +#define DPCD_WDATA 0x81 +#define DPCD_RDATA 0x82 +#define DPCD_CTL 0x83 +#define DPCD_STATUS 0x84 +#define AUX_STATUS 0x85 +#define I2CTOAUX_RELENGTH 0x86 +#define AUX_RETRY_CTRL 0x87 +#define TIMEOUT_CTRL 0x88 +#define I2CCMD_OPT1 0x89 +#define AUXCMD_ERR_IRQ 0x8A +#define AUXCMD_OPT2 0x8B +#define HDCP_Reserved 0x8C + +/* Audio InfoFrame */ +#define TX_MVID0 0x90 +#define TX_MVID1 0x91 +#define TX_MVID2 0x92 +#define TX_MVID_OFF 0x93 +#define TX_MAUD0 0x94 +#define TX_MAUD1 0x95 +#define TX_MAUD2 0x96 +#define TX_MAUD_OFF 0x97 +#define MN_CTRL 0x98 +#define MOUT0 0x99 +#define MOUT1 0x9A +#define MOUT2 0x9B + +/* Audio Control */ +#define NAUD_L 0x9F +#define NAUD_M 0xA0 +#define NAUD_H 0xA1 +#define AUD_CTRL0 0xA2 +#define AUD_CTRL1 0xA3 +#define LANE_POL 0xAA +#define LANE_EN 0xAB +#define LANE_MAP 0xAC +#define SCR_POLY0 0xAD +#define SCR_POLY1 0xAE +#define PRBS7_POLY 0xAF + +/* Video Pre-process */ +#define MISC_SHDOW 0xB0 +#define VCAPCPCTL0 0xB1 +#define VCAPCPCTL1 0xB2 +#define VCAPCPCTL2 0xB3 +#define CSCPAR 0xB4 +#define I2CTODPCDSTATUS2 0xBA +#define AUXCTL_REG 0xBB + +/* Page 2 */ +#define SEL_PIO1 0x24 +#define SEL_PIO2 0x25 +#define SEL_PIO3 0x26 +#define CHIP_VER_L 0x82 + +struct dp501_priv { + struct udevice *panel; + struct display_timing timing; + + struct udevice *chip2; + + struct udevice *vdd; + struct gpio_desc reset_gpio; + struct gpio_desc enable_gpio; +}; + +static int dp501_sw_init(struct udevice *dev) +{ + struct dp501_priv *priv = dev_get_priv(dev); + int i; + u8 val; + + dm_i2c_reg_write(dev, TOPCFG4, 0x30); + udelay(200); + dm_i2c_reg_write(dev, TOPCFG4, 0x0c); + dm_i2c_reg_write(dev, 0x8f, 0x02); + + /* check for connected panel during 1 msec */ + for (i = 0; i < 5; i++) { + val = dm_i2c_reg_read(dev, 0x8d); + val &= BIT(2); + if (val) + break; + + udelay(200); + } + + if (!val) { + log_debug("%s: panel is not connected!\n", __func__); + return -ENODEV; + } + + dm_i2c_reg_write(priv->chip2, SEL_PIO1, 0x02); + dm_i2c_reg_write(priv->chip2, SEL_PIO2, 0x04); + dm_i2c_reg_write(priv->chip2, SEL_PIO3, 0x10); + + dm_i2c_reg_write(dev, LINK_STATE_CTRL, 0xa0); + dm_i2c_reg_write(dev, 0x8f, 0x02); + dm_i2c_reg_write(dev, TOPCFG1, 0x16); + dm_i2c_reg_write(dev, TOPCFG0, 0x24); + dm_i2c_reg_write(dev, HPD2_IRQ_CTRL, 0x30); + dm_i2c_reg_write(dev, AUXIRQ_CTRL, 0xff); + dm_i2c_reg_write(dev, LINK_IRQ, 0xff); + + /* auto detect DVO timing */ + dm_i2c_reg_write(dev, VCAPCTRL3, 0x30); + + /* reset tpfifo at v blank */ + dm_i2c_reg_write(dev, LINK_CTRL0, 0x82); + + dm_i2c_reg_write(dev, VCAPCTRL4, 0x07); + dm_i2c_reg_write(dev, AUX_RETRY_CTRL, 0x7f); + dm_i2c_reg_write(dev, TIMEOUT_CTRL, 0x1e); + dm_i2c_reg_write(dev, AUXCTL_REG, 0x06); + + /* DPCD readable */ + dm_i2c_reg_write(dev, HPDCTL0, 0xa9); + + /* Scramble on */ + dm_i2c_reg_write(dev, QUALTEST_CTL, 0x00); + + dm_i2c_reg_write(dev, 0x8f, 0x02); + + dm_i2c_reg_write(dev, VCAPCTRL0, 0xc4); + + /* set color depth 8bit (0x00: 6bit; 0x20: 8bit; 0x40: 10bit) */ + dm_i2c_reg_write(dev, MISC0, 0x20); + + dm_i2c_reg_write(dev, VCAPCPCTL2, 0x01); + + /* check if bridge returns ready status */ + for (i = 0; i < 5; i++) { + val = dm_i2c_reg_read(dev, LINK_IRQ); + val &= BIT(0); + if (val) + break; + + udelay(200); + } + + if (!val) { + log_debug("%s: bridge is not ready\n", __func__); + return -ENODEV; + } + + return 0; +} + +static void dpcd_configure(struct udevice *dev, u32 config, bool write) +{ + dm_i2c_reg_write(dev, DPCD_ADDR_L, (u8)(config >> 8)); + dm_i2c_reg_write(dev, DPCD_ADDR_M, (u8)(config >> 16)); + dm_i2c_reg_write(dev, DPCD_ADDR_H, (u8)((config >> 24) | BIT(7))); + dm_i2c_reg_write(dev, DPCD_LENGTH, 0x00); + dm_i2c_reg_write(dev, LINK_IRQ, 0x20); + + if (write) + dm_i2c_reg_write(dev, DPCD_WDATA, (u8)(config & 0xff)); + + dm_i2c_reg_write(dev, DPCD_CTL, 0x01); + + udelay(10); +} + +static int dump_dpcd_data(struct udevice *dev, u32 config, u8 *data) +{ + int i; + u8 value; + + dpcd_configure(dev, config, false); + + value = dm_i2c_reg_read(dev, DPCD_CTL); + if (value) + return -ENODATA; + + for (i = 0; i < 5; i++) { + value = dm_i2c_reg_read(dev, LINK_IRQ); + value &= BIT(5); + if (value) + break; + + udelay(100); + } + + if (!value) + return -ENODATA; + + value = dm_i2c_reg_read(dev, DPCD_STATUS); + if (!(value & 0xe0)) + *data = dm_i2c_reg_read(dev, DPCD_RDATA); + else + return -ENODATA; + + return 0; +} + +static int dp501_dpcd_dump(struct udevice *dev, u32 config, u8 *data) +{ + int i, ret; + + for (i = 0; i < 5; i++) { + ret = dump_dpcd_data(dev, config, data); + if (!ret) + break; + + udelay(100); + } + + return ret; +} + +static int dp501_reset_link(struct udevice *dev) +{ + dm_i2c_reg_write(dev, TRAINING_CTL, 0x00); + dm_i2c_reg_write(dev, SWRST, 0xf8); + dm_i2c_reg_write(dev, SWRST, 0x00); + + return -ENODEV; +} + +static int dp501_link_training(struct udevice *dev) +{ + int i, ret; + u8 lane, link, link_out; + u8 lane_cnt, lane01, lane23; + + dpcd_configure(dev, 0x030000, true); + dpcd_configure(dev, 0x03011c, true); + dpcd_configure(dev, 0x0301f8, true); + + ret = dp501_dpcd_dump(dev, 0x90000100, &link); + if (ret) { + log_debug("%s: link dump failed %d\n", __func__, ret); + return dp501_reset_link(dev); + } + + ret = dp501_dpcd_dump(dev, 0x90000200, &lane); + if (ret) { + log_debug("%s: lane dump failed %d\n", __func__, ret); + return dp501_reset_link(dev); + } + + /* Software trainig */ + for (i = 10; i > 0; i--) { + dm_i2c_reg_write(dev, LINK_BW, link); + dm_i2c_reg_write(dev, LANE_CNT, lane | BIT(7)); + + link_out = dm_i2c_reg_read(dev, LINK_BW); + lane_cnt = dm_i2c_reg_read(dev, LANE_CNT); + + if (link_out == link && + (lane_cnt == (lane | BIT(7)))) + break; + + udelay(500); + } + + if (!i) + return dp501_reset_link(dev); + + dm_i2c_reg_write(dev, LINK_STATE_CTRL, 0x00); + dm_i2c_reg_write(dev, TRAINING_CTL, 0x0d); + + /* check if bridge returns link ready status */ + for (i = 0; i < 100; i++) { + link_out = dm_i2c_reg_read(dev, LINK_IRQ); + link_out &= BIT(1); + if (link_out) { + dm_i2c_reg_write(dev, LINK_IRQ, 0xff); + break; + } + + udelay(100); + } + + if (!link_out) { + log_debug("%s: link prepare failed %d\n", + __func__, link_out); + return dp501_reset_link(dev); + } + + lane01 = dm_i2c_reg_read(dev, LANE01_STATUS); + lane23 = dm_i2c_reg_read(dev, LANE23_STATUS); + + switch (lane_cnt & 0xf) { + case 4: + if (lane01 == 0x77 && + lane23 == 0x77) + return 0; + break; + + case 2: + if (lane01 == 0x77) + return 0; + break; + + default: + if ((lane01 & 7) == 7) + return 0; + break; + } + + return dp501_reset_link(dev); +} + +static int dp501_attach(struct udevice *dev) +{ + struct dp501_priv *priv = dev_get_priv(dev); + int ret; + + ret = dp501_sw_init(dev); + if (ret) + return ret; + + mdelay(90); + + ret = dp501_link_training(dev); + if (ret) + return ret; + + /* Perform panel HW setup */ + return panel_enable_backlight(priv->panel); +} + +static int dp501_set_backlight(struct udevice *dev, int percent) +{ + struct dp501_priv *priv = dev_get_priv(dev); + + return panel_set_backlight(priv->panel, percent); +} + +static int dp501_panel_timings(struct udevice *dev, + struct display_timing *timing) +{ + struct dp501_priv *priv = dev_get_priv(dev); + + memcpy(timing, &priv->timing, sizeof(*timing)); + return 0; +} + +static void dp501_hw_init(struct dp501_priv *priv) +{ + dm_gpio_set_value(&priv->reset_gpio, 1); + + regulator_set_enable_if_allowed(priv->vdd, 1); + dm_gpio_set_value(&priv->enable_gpio, 1); + + udelay(100); + + dm_gpio_set_value(&priv->reset_gpio, 0); + mdelay(80); +} + +static int dp501_setup(struct udevice *dev) +{ + struct dm_i2c_chip *chip = dev_get_parent_plat(dev); + struct dp501_priv *priv = dev_get_priv(dev); + struct udevice *bus = dev_get_parent(dev); + int ret; + + /* get panel */ + ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, + "panel", &priv->panel); + if (ret) { + log_debug("%s: Cannot get panel: ret=%d\n", __func__, ret); + return log_ret(ret); + } + + /* get regulators */ + ret = device_get_supply_regulator(dev, "power-supply", &priv->vdd); + if (ret) { + log_debug("%s: vddc regulator error: %d\n", __func__, ret); + if (ret != -ENOENT) + return log_ret(ret); + } + + /* get gpios */ + ret = gpio_request_by_name(dev, "reset-gpios", 0, + &priv->reset_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: Could not decode reset-gpios (%d)\n", + __func__, ret); + return ret; + } + + ret = gpio_request_by_name(dev, "enable-gpios", 0, + &priv->enable_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: Could not decode enable-gpios (%d)\n", + __func__, ret); + return ret; + } + + ret = i2c_get_chip(bus, chip->chip_addr + 2, 1, &priv->chip2); + if (ret) { + log_debug("%s: cannot get second PMIC I2C chip (err %d)\n", + __func__, ret); + return ret; + } + + dp501_hw_init(priv); + + /* get EDID */ + return panel_get_display_timing(priv->panel, &priv->timing); +} + +static int dp501_probe(struct udevice *dev) +{ + if (device_get_uclass_id(dev->parent) != UCLASS_I2C) + return -EPROTONOSUPPORT; + + return dp501_setup(dev); +} + +struct panel_ops dp501_ops = { + .enable_backlight = dp501_attach, + .set_backlight = dp501_set_backlight, + .get_display_timing = dp501_panel_timings, +}; + +static const struct udevice_id dp501_ids[] = { + { .compatible = "parade,dp501" }, + { } +}; + +U_BOOT_DRIVER(dp501) = { + .name = "dp501", + .id = UCLASS_PANEL, + .of_match = dp501_ids, + .ops = &dp501_ops, + .probe = dp501_probe, + .priv_auto = sizeof(struct dp501_priv), +}; From patchwork Wed Jan 31 06:57:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Svyatoslav Ryhel X-Patchwork-Id: 1893248 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=W37KAtBd; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TPtDK299Sz23fD for ; Wed, 31 Jan 2024 17:58:41 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 386D787A00; Wed, 31 Jan 2024 07:57:54 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="W37KAtBd"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 85C0D87C5B; Wed, 31 Jan 2024 07:57:50 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-lf1-x12e.google.com (mail-lf1-x12e.google.com [IPv6:2a00:1450:4864:20::12e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 6864587C13 for ; Wed, 31 Jan 2024 07:57:47 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=clamor95@gmail.com Received: by mail-lf1-x12e.google.com with SMTP id 2adb3069b0e04-5110c166d70so5409566e87.1 for ; Tue, 30 Jan 2024 22:57:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706684267; x=1707289067; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LGHH6yNlGbogMbS3dM40GiMc+s0er55gxsmmSS+ffBE=; b=W37KAtBdZ7LUhbLcb4n6z7CeYnty8/3bhxZVzS6bMfRXcIvFtMP3d8SABrqnC7aMaM lhP/zboRRtwAMv/oHjVmeIo6WeVjAtnMBhwQVoJm01zk/fMY495IMCl/94AIiirNnwlp 6CY2DYNviJuxnZBZ2Ee5lMhsTgijDJpdHgbEbiulH/mrnfZmqTmDp5tnlXPA70kmFH/2 kH4D2ANAlFSIA67YL78t2J20Gx+gqHAsb1Sr67FoC7efJKhxAI9aglmGL3+9gMWritJQ 4em/2lgl2IdXsBhPTrdpHZig4TvWA203VPg7snUMJ6BGkPdkAq3+q0exyvt7VzBgbbs1 K3YQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706684267; x=1707289067; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LGHH6yNlGbogMbS3dM40GiMc+s0er55gxsmmSS+ffBE=; b=HpDKmU786M/T8M4ere9hAbtEjY29lqSCDMyhdd6ACPhWoWxB34KioPBpq4ABjibxW7 aMDfbtNm5QMtlSSS/pyWsEqjgrOSQTf19Jk6Hz1asKJnAPkp6SKUeqUIJ40ejSPnBaon f2Zh8AkKmdZk98Oxd8sppbmw3C2lAsdjbnRm0egr6N3DCrryvR1J44arFWwLOnnSZd8r axbWqi36UMI6xQqdCbRgccfljNlQayKFbD+ha8OKhu0H11NP5k9qiQuBKd9r+mEYMZ4H j52Rax1sWlZbORiHHJ2hJIMZL9ei9FIau7O+D1dvUo5UkN10wmQ9uLHNpGybwtDkDKaZ rRzw== X-Gm-Message-State: AOJu0Ywv06Zdvm9vYQVZcde16cJlX9t8jUds4BJWB3EHTClU841pPIIf 5ltymuR+8YB8E06evXTp1NJGgbhAYMVpw0g6iqcSBGYtrRt1SVp5 X-Google-Smtp-Source: AGHT+IH36CFnT//PcxpbM7aPhzyDJVqwSKkFIFveDkmfSaiWmj4XOb6a3WObpwZ+ZFW0cHAVzgbUXA== X-Received: by 2002:a19:6506:0:b0:511:171e:28a with SMTP id z6-20020a196506000000b00511171e028amr474121lfb.30.1706684266707; Tue, 30 Jan 2024 22:57:46 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCWFrGeZLtA7W6WlT9RZrUHiVSdOcBFrTYOQ8WNnIHYMcojcYRw9OB76P4S/0Dc5qC6ZYIjpLWZkMwlIl7rySnkKC1t6Hni8WnQ48gGKxuoi/q5O9KyhZydO095Jryu3m6jdONwECI2TcwwVw2zNP+Yg5JI/ywajiHMws/IwSEhLNJRyMMMoMIjmNsqSVhdSAm0JRttG4Q== Received: from xeon.. ([188.163.112.73]) by smtp.gmail.com with ESMTPSA id s11-20020a19770b000000b0051023c2e95asm1760796lfc.209.2024.01.30.22.57.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 22:57:46 -0800 (PST) From: Svyatoslav Ryhel To: Tom Rini , Anatolij Gustschin , Simon Glass , Svyatoslav Ryhel , Anton Bambura , =?utf-8?q?Jonas_Schw=C3=B6bel?= Cc: u-boot@lists.denx.de Subject: [PATCH v2 5/7] video: endeavoru-panel: shift the init sequence by one step earlier Date: Wed, 31 Jan 2024 08:57:19 +0200 Message-Id: <20240131065721.4245-6-clamor95@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240131065721.4245-1-clamor95@gmail.com> References: <20240131065721.4245-1-clamor95@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Shift all setup stages one step earlier to better fit the existing uclass. Signed-off-by: Svyatoslav Ryhel --- drivers/video/endeavoru-panel.c | 128 +++++++++++++++++--------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/drivers/video/endeavoru-panel.c b/drivers/video/endeavoru-panel.c index 79a272128b..1bff641434 100644 --- a/drivers/video/endeavoru-panel.c +++ b/drivers/video/endeavoru-panel.c @@ -57,61 +57,8 @@ static void dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data) static int endeavoru_panel_enable_backlight(struct udevice *dev) { - struct endeavoru_panel_priv *priv = dev_get_priv(dev); - int ret; - - ret = dm_gpio_set_value(&priv->reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = regulator_set_enable_if_allowed(priv->vddio, 1); - if (ret) { - log_err("error enabling iovcc-supply (%d)\n", ret); - return ret; - } - mdelay(1); - - ret = regulator_set_enable_if_allowed(priv->vdd, 1); - if (ret) { - log_err("error enabling vcc-supply (%d)\n", ret); - return ret; - } - mdelay(20); - - ret = dm_gpio_set_value(&priv->reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(2); - - /* Reset panel */ - ret = dm_gpio_set_value(&priv->reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(1); - - ret = dm_gpio_set_value(&priv->reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(25); - - return 0; -} - -static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) -{ - struct endeavoru_panel_priv *priv = dev_get_priv(dev); struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); struct mipi_dsi_device *dsi = plat->device; - int ret; dcs_write_one(dsi, 0xc2, 0x08); @@ -160,18 +107,22 @@ static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) dcs_write_one(dsi, 0x55, 0x80); dcs_write_one(dsi, 0x5e, 0x06); - ret = backlight_enable(priv->backlight); - if (ret) - return ret; - /* Set backlight */ dcs_write_one(dsi, 0x51, 0x96); - ret = backlight_set_brightness(priv->backlight, percent); + return 0; +} + +static int endeavoru_panel_set_backlight(struct udevice *dev, int percent) +{ + struct endeavoru_panel_priv *priv = dev_get_priv(dev); + int ret; + + ret = backlight_enable(priv->backlight); if (ret) return ret; - return 0; + return backlight_set_brightness(priv->backlight, percent); } static int endeavoru_panel_timings(struct udevice *dev, @@ -217,6 +168,63 @@ static int endeavoru_panel_of_to_plat(struct udevice *dev) return 0; } +static int endeavoru_panel_hw_init(struct udevice *dev) +{ + struct endeavoru_panel_priv *priv = dev_get_priv(dev); + int ret; + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = regulator_set_enable_if_allowed(priv->vddio, 1); + if (ret) { + log_debug("%s: error enabling iovcc-supply (%d)\n", + __func__, ret); + return ret; + } + mdelay(1); + + ret = regulator_set_enable_if_allowed(priv->vdd, 1); + if (ret) { + log_debug("%s: error enabling vcc-supply (%d)\n", + __func__, ret); + return ret; + } + mdelay(20); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(2); + + /* Reset panel */ + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(1); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(25); + + return 0; +} + static int endeavoru_panel_probe(struct udevice *dev) { struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); @@ -226,7 +234,7 @@ static int endeavoru_panel_probe(struct udevice *dev) plat->format = MIPI_DSI_FMT_RGB888; plat->mode_flags = MIPI_DSI_MODE_VIDEO; - return 0; + return endeavoru_panel_hw_init(dev); } static const struct panel_ops endeavoru_panel_ops = { From patchwork Wed Jan 31 06:57:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Svyatoslav Ryhel X-Patchwork-Id: 1893249 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=Hyi472PZ; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TPtDT6NLKz23fD for ; Wed, 31 Jan 2024 17:58:49 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B1EF987C13; Wed, 31 Jan 2024 07:57:54 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Hyi472PZ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B4AA287C87; Wed, 31 Jan 2024 07:57:51 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-lf1-x12a.google.com (mail-lf1-x12a.google.com [IPv6:2a00:1450:4864:20::12a]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B883287C39 for ; Wed, 31 Jan 2024 07:57:48 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=clamor95@gmail.com Received: by mail-lf1-x12a.google.com with SMTP id 2adb3069b0e04-51109060d6aso4729866e87.2 for ; Tue, 30 Jan 2024 22:57:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706684268; x=1707289068; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=alUXjltqlvZ70jNAItEMCT7cp0cEjOIxtwqPfa42pr4=; b=Hyi472PZiVITVhrqj57oi+r/5Wgm3/JNDqM/n6TMxiLy1Ha+jCu+1SpbP6Bj/7DuVC jBFcvi7h99Mqt6GH6C52pBRT+hg2j+7ikVHjq2YQGEim4G2uTavmAznFBtKo27QEIkRV JPcpRdzDCxZ9+Pq/7vYElQvK1ZtOkBx1RZY00E30+eWzA4JgyghyiIm7r1p3gqsDVZhH CnTwWTkuDIJmLBu/bFPAAffzXiRI13sIerl5v4N7k+XXKOqc4dkbYeAtIrI4NirRAKYd +nYLpHneqMW/MH9ANk0z/8lfdRAq9efP/3gOtGTJ4arv1IIB/qSK+nmrqQ8HWgZKfrjS LasA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706684268; x=1707289068; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=alUXjltqlvZ70jNAItEMCT7cp0cEjOIxtwqPfa42pr4=; b=b/6bQJ6J+WqFOKGNlg6kDPqXv7u99kkdR6bKSfr7uR/+SqCJPvMDpLiliUrqavGhQE OIQGXJ+Gw6TtKx5Wa+0nu+8KsVKUwN8Aa/aRskrMHN4mxgQVAdPWAbg8PI1FxwRPZE2L lSUoLrpSKdzYRsnGxLYZtEMaySPdpd1qBscWBoU+MHg/OPiuLG2LU/1vcZSvLgXhQiUX A54ub3Ha8TufJcaicy/pXEUmRNLzNZrvX2Ibpz8XTZv4hGN24jXzhcEeFhmEROY9AlwK 0uE294c1kSwlvi1WxuodSPB50E5gKvicYraziUaEK7KbNfa1QFt9GmftEedhdf+nv+Eg XSxg== X-Gm-Message-State: AOJu0Yw3cknx6nYNo4zRj9ykX1/Ln0/XAuHMbibbAapFqESTR89S26Ft PuHGNChBSPT6Sv2kjoLmSfnK6OnUnAb+XQl9KmgEtD0wsuLSLHfq X-Google-Smtp-Source: AGHT+IEZGHFxpXSfK+QnDyGCo60xn4GPOryvd7dE/A1PU+jLTjbs78LM4Ez5Vud1CSlwjbB8qHg7Xg== X-Received: by 2002:ac2:5f94:0:b0:510:544:78e with SMTP id r20-20020ac25f94000000b005100544078emr568823lfe.23.1706684267707; Tue, 30 Jan 2024 22:57:47 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCXxNyjpyA9/MngDTxmDAWI+hRSQQkuqXyIyPFmNazqkmu2ZH289vAZGAe4xD99RDrbJgdf+PBTJcCGEIAEJVq+daG50/Hqq/2L48laFa598xatw1r3znjZk0YOMcmGSbbpfoNZtfoLR9EWsZrp2Q65buY3eQks51HqYbY+b4VzKUWBxQm1Z+kTo1VGJc2vXmcn6bIqPYg== Received: from xeon.. ([188.163.112.73]) by smtp.gmail.com with ESMTPSA id s11-20020a19770b000000b0051023c2e95asm1760796lfc.209.2024.01.30.22.57.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 22:57:47 -0800 (PST) From: Svyatoslav Ryhel To: Tom Rini , Anatolij Gustschin , Simon Glass , Svyatoslav Ryhel , Anton Bambura , =?utf-8?q?Jonas_Schw=C3=B6bel?= Cc: u-boot@lists.denx.de Subject: [PATCH v2 6/7] video: bridge: ssd2825: shift the init sequence by one step earlier Date: Wed, 31 Jan 2024 08:57:20 +0200 Message-Id: <20240131065721.4245-7-clamor95@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240131065721.4245-1-clamor95@gmail.com> References: <20240131065721.4245-1-clamor95@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Shift all setup stages one step earlier to better fit the existing uclass. Signed-off-by: Svyatoslav Ryhel --- drivers/video/bridge/ssd2825.c | 86 ++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/drivers/video/bridge/ssd2825.c b/drivers/video/bridge/ssd2825.c index cea20dcffa..f0ef3dafb9 100644 --- a/drivers/video/bridge/ssd2825.c +++ b/drivers/video/bridge/ssd2825.c @@ -349,39 +349,6 @@ static int ssd2825_bridge_enable_panel(struct udevice *dev) struct ssd2825_bridge_priv *priv = dev_get_priv(dev); struct mipi_dsi_device *device = &priv->device; struct display_timing *dt = &priv->timing; - int ret; - - ret = clk_prepare_enable(priv->tx_clk); - if (ret) { - log_err("error enabling tx_clk (%d)\n", ret); - return ret; - } - - ret = dm_gpio_set_value(&priv->power_gpio, 1); - if (ret) { - log_err("error changing power-gpios (%d)\n", ret); - return ret; - } - mdelay(10); - - ret = dm_gpio_set_value(&priv->reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(10); - - ret = dm_gpio_set_value(&priv->reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(10); - - /* Perform panel HW setup */ - ret = panel_enable_backlight(priv->panel); - if (ret) - return ret; /* Perform SW reset */ ssd2825_write_register(dev, SSD2825_OPERATION_CTRL_REG, 0x0100); @@ -417,17 +384,15 @@ static int ssd2825_bridge_enable_panel(struct udevice *dev) SSD2825_CONF_REG_ECD | SSD2825_CONF_REG_EOT); ssd2825_write_register(dev, SSD2825_VC_CTRL_REG, 0x0000); - /* Set up SW panel configuration */ - ret = panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); - if (ret) - return ret; - - return 0; + /* Perform panel setup */ + return panel_enable_backlight(priv->panel); } static int ssd2825_bridge_set_panel(struct udevice *dev, int percent) { - return 0; + struct ssd2825_bridge_priv *priv = dev_get_priv(dev); + + return panel_set_backlight(priv->panel, percent); } static int ssd2825_bridge_panel_timings(struct udevice *dev, @@ -440,6 +405,45 @@ static int ssd2825_bridge_panel_timings(struct udevice *dev, return 0; } +static int ssd2825_bridge_hw_init(struct udevice *dev) +{ + struct ssd2825_bridge_priv *priv = dev_get_priv(dev); + int ret; + + ret = clk_prepare_enable(priv->tx_clk); + if (ret) { + log_debug("%s: error enabling tx_clk (%d)\n", + __func__, ret); + return ret; + } + + ret = dm_gpio_set_value(&priv->power_gpio, 1); + if (ret) { + log_debug("%s: error changing power-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(10); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(10); + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(10); + + return 0; +} + static int ssd2825_bridge_probe(struct udevice *dev) { struct ssd2825_bridge_priv *priv = dev_get_priv(dev); @@ -496,7 +500,7 @@ static int ssd2825_bridge_probe(struct udevice *dev) return PTR_ERR(priv->tx_clk); } - return 0; + return ssd2825_bridge_hw_init(dev); } static const struct panel_ops ssd2825_bridge_ops = { From patchwork Wed Jan 31 06:57:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Svyatoslav Ryhel X-Patchwork-Id: 1893250 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=Y3QxdhMG; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4TPtDg2DbHz23fD for ; Wed, 31 Jan 2024 17:58:59 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0808387C05; Wed, 31 Jan 2024 07:57:57 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Y3QxdhMG"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id E419687887; Wed, 31 Jan 2024 07:57:52 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-lf1-x130.google.com (mail-lf1-x130.google.com [IPv6:2a00:1450:4864:20::130]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 6803187B75 for ; Wed, 31 Jan 2024 07:57:49 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=clamor95@gmail.com Received: by mail-lf1-x130.google.com with SMTP id 2adb3069b0e04-511207d62b6so1548373e87.1 for ; Tue, 30 Jan 2024 22:57:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706684269; x=1707289069; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=C/k6Vt4YU3N+5KAJ3HIMs9S1WRPYjN8MzVYvWjaleh4=; b=Y3QxdhMGm+37FHbZZAvScH8xnyXLh0lOuSD88tyV4HIZ1rccAglNrySzmxphYPhvgW LCrl1mws0popql01smPpoE8ocficwJzBR7o8RHIUKeuVGX8L9saLziurubfuef34xz5x BvpFJPGAYWc02hguCGAn8UlYBZobp5HAIHvCYv7Kii5rFbItSG4/c/AFB5mQxq3uy+Mm lBmzoR7ofA132b6/T+unNwZ0zMY5D+3GzSWTrBDMbLy3l8Iz3nKx8AjbqQxInuqgH2Os O2c5A+Fo+09DUiRavSQ6ybzm00r2QvY8YC2x+NK9NUvxQnwC4roiZ0cHxDT3Q1NOqsWz pYNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706684269; x=1707289069; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=C/k6Vt4YU3N+5KAJ3HIMs9S1WRPYjN8MzVYvWjaleh4=; b=jGZIKZkVrP2LJbPMraErARHMdIBtv8U2mks1q68CZQk7H9IQPYaiwveYlUuoyT6aia 3qAD0F2uJvURenHpdFUJfEk7XLp3RB5QGe1oQmkkjcqPmbEgOxZlIX0L/0OY3MHU4Ilp yOXasSiBDbXaDjf78gVVL1MN/aJyWw8XodyjWIHE8xZpLaDsqLlFLrXUiLbzGAoW7FE4 BfKdiEOzz5rRzYCQ9L3oobmVXyKG2vtDBVqnHmu17uU9fc+H067EA/60nZwU7T1ZOfXO vR1M6N2aKn2UGkkyF3XEm4I2BOCKxf+4w4WjGzDee5/Yuok5abOsIopz4WpN2UGNuRWU 1NyA== X-Gm-Message-State: AOJu0YzvA8vXgjlwBzgobUCrHSFYKtUSBtseTem2rYdG8q9tPwVADeuj YHYMqPQ+99cAPi+GlFVnIGEuQiUU1EhPu25wNhyrajBKy8AltnOs X-Google-Smtp-Source: AGHT+IFJ0YDsmGKka2ySlkOGpz7/lUFvvZItw5rBGHsGmnAIWoaOTlMSuxSwZKzEO47FJ0kHYWlHXw== X-Received: by 2002:a19:7410:0:b0:50e:7aef:e9df with SMTP id v16-20020a197410000000b0050e7aefe9dfmr488472lfe.19.1706684268691; Tue, 30 Jan 2024 22:57:48 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCXPsSocexCpqZhB7FhgS4IkU3ZVOMDHQHJMAJCVi4Pqcfjco8W+ByxihwIqJvqsXxvZm5z0Uyse0KU8CrnOZbnvj5/U7+8KpCUvIbLWfAg6cj1sLuiCwleZFspTCyhibwoTAzPifnlmXvqkIcnYXh6X4qYiPLUvj5oApH54raF+7kOyKMJZmFfWgy6qyI89WtPXZfJtQA== Received: from xeon.. ([188.163.112.73]) by smtp.gmail.com with ESMTPSA id s11-20020a19770b000000b0051023c2e95asm1760796lfc.209.2024.01.30.22.57.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Jan 2024 22:57:48 -0800 (PST) From: Svyatoslav Ryhel To: Tom Rini , Anatolij Gustschin , Simon Glass , Svyatoslav Ryhel , Anton Bambura , =?utf-8?q?Jonas_Schw=C3=B6bel?= Cc: u-boot@lists.denx.de Subject: [PATCH v2 7/7] video: renesas: shift the init sequence by one step earlier Date: Wed, 31 Jan 2024 08:57:21 +0200 Message-Id: <20240131065721.4245-8-clamor95@gmail.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240131065721.4245-1-clamor95@gmail.com> References: <20240131065721.4245-1-clamor95@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Shift all setup stages one step earlier to better fit the existing uclass. Signed-off-by: Svyatoslav Ryhel --- drivers/video/renesas-r61307.c | 93 +++++++++++++++++++--------------- drivers/video/renesas-r69328.c | 81 +++++++++++++++-------------- 2 files changed, 95 insertions(+), 79 deletions(-) diff --git a/drivers/video/renesas-r61307.c b/drivers/video/renesas-r61307.c index 426fdc6224..1eccaf6b1b 100644 --- a/drivers/video/renesas-r61307.c +++ b/drivers/video/renesas-r61307.c @@ -118,42 +118,6 @@ static struct display_timing default_timing = { }; static int renesas_r61307_enable_backlight(struct udevice *dev) -{ - struct renesas_r61307_priv *priv = dev_get_priv(dev); - int ret; - - ret = regulator_set_enable_if_allowed(priv->vcc, 1); - if (ret) { - log_err("enabling vcc-supply failed (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = regulator_set_enable_if_allowed(priv->iovcc, 1); - if (ret) { - log_err("enabling iovcc-supply failed (%d)\n", ret); - return ret; - } - - ret = dm_gpio_set_value(&priv->reset_gpio, 0); - if (ret) { - log_err("changing reset-gpio failed (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = dm_gpio_set_value(&priv->reset_gpio, 1); - if (ret) { - log_err("changing reset-gpio failed (%d)\n", ret); - return ret; - } - - mdelay(5); - - return 0; -} - -static int renesas_r61307_set_backlight(struct udevice *dev, int percent) { struct renesas_r61307_priv *priv = dev_get_priv(dev); struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); @@ -205,18 +169,23 @@ static int renesas_r61307_set_backlight(struct udevice *dev, int percent) log_err("failed to set display on: %d\n", ret); return ret; } - mdelay(50); + return 0; +} + +static int renesas_r61307_set_backlight(struct udevice *dev, int percent) +{ + struct renesas_r61307_priv *priv = dev_get_priv(dev); + int ret; + ret = backlight_enable(priv->backlight); if (ret) return ret; - ret = backlight_set_brightness(priv->backlight, percent); - if (ret) - return ret; + mdelay(5); - return 0; + return backlight_set_brightness(priv->backlight, percent); } static int renesas_r61307_timings(struct udevice *dev, @@ -266,6 +235,46 @@ static int renesas_r61307_of_to_plat(struct udevice *dev) return 0; } +static int renesas_r61307_hw_init(struct udevice *dev) +{ + struct renesas_r61307_priv *priv = dev_get_priv(dev); + int ret; + + ret = regulator_set_enable_if_allowed(priv->vcc, 1); + if (ret) { + log_debug("%s: enabling vcc-supply failed (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = regulator_set_enable_if_allowed(priv->iovcc, 1); + if (ret) { + log_debug("%s: enabling iovcc-supply failed (%d)\n", + __func__, ret); + return ret; + } + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: changing reset-gpio failed (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + log_debug("%s: changing reset-gpio failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(5); + + return 0; +} + static int renesas_r61307_probe(struct udevice *dev) { struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); @@ -275,7 +284,7 @@ static int renesas_r61307_probe(struct udevice *dev) plat->format = MIPI_DSI_FMT_RGB888; plat->mode_flags = MIPI_DSI_MODE_VIDEO; - return 0; + return renesas_r61307_hw_init(dev); } static const struct panel_ops renesas_r61307_ops = { diff --git a/drivers/video/renesas-r69328.c b/drivers/video/renesas-r69328.c index d2f7169468..ecf89ec021 100644 --- a/drivers/video/renesas-r69328.c +++ b/drivers/video/renesas-r69328.c @@ -65,37 +65,6 @@ static struct display_timing default_timing = { static int renesas_r69328_enable_backlight(struct udevice *dev) { - struct renesas_r69328_priv *priv = dev_get_priv(dev); - int ret; - - ret = dm_gpio_set_value(&priv->enable_gpio, 1); - if (ret) { - log_err("error changing enable-gpios (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = dm_gpio_set_value(&priv->reset_gpio, 0); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - mdelay(5); - - ret = dm_gpio_set_value(&priv->reset_gpio, 1); - if (ret) { - log_err("error changing reset-gpios (%d)\n", ret); - return ret; - } - - mdelay(5); - - return 0; -} - -static int renesas_r69328_set_backlight(struct udevice *dev, int percent) -{ - struct renesas_r69328_priv *priv = dev_get_priv(dev); struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); struct mipi_dsi_device *dsi = plat->device; int ret; @@ -153,18 +122,23 @@ static int renesas_r69328_set_backlight(struct udevice *dev, int percent) log_err("failed to set display on: %d\n", ret); return ret; } - mdelay(50); + return 0; +} + +static int renesas_r69328_set_backlight(struct udevice *dev, int percent) +{ + struct renesas_r69328_priv *priv = dev_get_priv(dev); + int ret; + ret = backlight_enable(priv->backlight); if (ret) return ret; - ret = backlight_set_brightness(priv->backlight, percent); - if (ret) - return ret; + mdelay(5); - return 0; + return backlight_set_brightness(priv->backlight, percent); } static int renesas_r69328_timings(struct udevice *dev, @@ -203,6 +177,39 @@ static int renesas_r69328_of_to_plat(struct udevice *dev) return 0; } +static int renesas_r69328_hw_init(struct udevice *dev) +{ + struct renesas_r69328_priv *priv = dev_get_priv(dev); + int ret; + + ret = dm_gpio_set_value(&priv->enable_gpio, 1); + if (ret) { + log_debug("%s: error changing enable-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(5); + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + log_debug("%s: error changing reset-gpios (%d)\n", + __func__, ret); + return ret; + } + + mdelay(5); + + return 0; +} + static int renesas_r69328_probe(struct udevice *dev) { struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); @@ -212,7 +219,7 @@ static int renesas_r69328_probe(struct udevice *dev) plat->format = MIPI_DSI_FMT_RGB888; plat->mode_flags = MIPI_DSI_MODE_VIDEO; - return 0; + return renesas_r69328_hw_init(dev); } static const struct panel_ops renesas_r69328_ops = {