From patchwork Tue Oct 16 12:34:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 148933 Delivered-To: patch@linaro.org Received: by 2002:a2e:8595:0:0:0:0:0 with SMTP id b21-v6csp5028573lji; Tue, 16 Oct 2018 05:34:55 -0700 (PDT) X-Google-Smtp-Source: ACcGV63CJtRkymuc6OcmNEmCBDI/aYN1nFqOg1e6qBKWmmtZlhnU5RQUO7KtY7inHKuPKguoKxxX X-Received: by 2002:a65:609a:: with SMTP id t26-v6mr19891939pgu.41.1539693295755; Tue, 16 Oct 2018 05:34:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1539693295; cv=none; d=google.com; s=arc-20160816; b=h67Ku2XBZU43DHyOeO2CPDCEWC9kL2kN0pVGEzQL1od8TyxCRP6jY0GFTwCDeznAe2 UB1NWhl6CkTFv2wKahWhjYFJbeQsEvqKqL5vSDZJ/xZs6MoyPauXCqynKKDlLVVjoW1O FVIYui3983mg2/WIQKUSu0iLY7LRcfOWDPkkcGh8/FKA6Qjl0XyArZyp5SCNsnSUf7/q gmYrEuewcgF0oBwBqLJvUrTJb06dcfksFGZ4KqjYnOXAchdN8v15TXGzHny6eonI+Xtp q+ziZJvgnwSwTRvV+E6ZiSRZaH+8hbDD0sqNgGNXbXgmxuoHnNM6MpRXN7blRZvXeuKJ csOg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:references:in-reply-to:message-id:date:subject :to:from:delivered-to; bh=SPJKeToXRpM8z9gCRbbVqIm7Hic4/kQLI+38CIJ0LpY=; b=MWSUgweEIrIy8FmhCNy5F2BfbhoNyW1dI7srguDmXmX3jlTDljjjxLwKJSrW7skV82 8Uw/cvrwT0vQlgHO+3q1m34/xnRtA99h0eAGJxuZZCnllPM3Q4OCwT4tEBypOv6InT4A ycqGbKrsZ/e8XX93W4U4pvffgAJ2GM5Ju+QeZNuyYkt0T7enIBGD0/8DY4IN0urWSNtj AzZV7WHazZopPZ2nOv2AcTGwDFLOOw/i13YXMtJ3pC75H2rDP/z2THkuwu11e2NJfxon h8QkJ4zuYbDcUHjRrpBzIHd8pRYjJ6LCqAIGdaPG0FJUdvc2BPJ4uhqmToBUlqQt9n+2 NfbA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from gabe.freedesktop.org (gabe.freedesktop.org. [131.252.210.177]) by mx.google.com with ESMTPS id c10-v6si10258393pla.251.2018.10.16.05.34.55 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 16 Oct 2018 05:34:55 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) client-ip=131.252.210.177; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of dri-devel-bounces@lists.freedesktop.org designates 131.252.210.177 as permitted sender) smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8FEB089CAA; Tue, 16 Oct 2018 12:34:24 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-lf1-x143.google.com (mail-lf1-x143.google.com [IPv6:2a00:1450:4864:20::143]) by gabe.freedesktop.org (Postfix) with ESMTPS id 34BD489CAA for ; Tue, 16 Oct 2018 12:34:22 +0000 (UTC) Received: by mail-lf1-x143.google.com with SMTP id y10-v6so16796539lfj.1 for ; Tue, 16 Oct 2018 05:34:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ZQejfeShWch6PuG0PH4hdmhmbAYtThwEry7BQMgEGIQ=; b=RISEM9Uw3gmM+/5/kw0Vej42btJi28HGkfmE8wRFEX+q6xGsUeLXBuiVUEeVGy4SKe MJdYcaiREUycQcJuOgLuCbrLAxxkpXvBDf4TQKaina04mJ4kjQougDDF9SaTIojsHXzo 2N/6sma1g7pvXHPjqWSnlvNSuzIRyziYk71jQVZNiyYJIMm5Nz4EyL3qHTQLWvRphggV MXpw5MAxJ8EDe1dCTcPY5uz6QAcYF+l7i/oht9DZsFaHqZHvYQWAauWdeqX3jjkTuO7A AGDJy0lgF6G7ZlNIjBDkuvslkP291ZsuQY/oxi70pWgks07BDyaz+nBtcxfS5ulWP9Xd drYA== X-Gm-Message-State: ABuFfohm9INemldhW6t2QS77npJvKxZAouEMz6eCTifREYUmzBdonRCK NAQAoXofkVXTUW53fjD4YZ4ydAS4v6c= X-Received: by 2002:a19:ab1a:: with SMTP id u26-v6mr13361752lfe.103.1539693260323; Tue, 16 Oct 2018 05:34:20 -0700 (PDT) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id h2-v6sm2989276lfb.27.2018.10.16.05.34.18 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 16 Oct 2018 05:34:19 -0700 (PDT) From: Linus Walleij To: Thierry Reding , dri-devel@lists.freedesktop.org Subject: [PATCH 2/2 v2] drm/panel: Add driver for Samsung S6D16D0 panel Date: Tue, 16 Oct 2018 14:34:09 +0200 Message-Id: <20181016123409.13275-2-linus.walleij@linaro.org> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20181016123409.13275-1-linus.walleij@linaro.org> References: <20181016123409.13275-1-linus.walleij@linaro.org> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Sam Ravnborg MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The Samsung S6D16D0 is a simple comman mode only DSI display that is used on the ST-Ericsson Ux500 reference design TVK1281618 user interface board (UIB). Cc: Sam Ravnborg Cc: Andrzej Hajda Signed-off-by: Linus Walleij Reviewed-by: Sam Ravnborg --- ChangeLog v1->v2: - Drop Backlight dependency from the Kconfig - this display has built-in backlight, I think. - Drop the big include and replace by more precise to-the-point includes. - Move display on/off to the enable/disable callbacks. - Use DRM_DEV_ERROR() instead of dev_err(). --- drivers/gpu/drm/panel/Kconfig | 6 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-samsung-s6d16d0.c | 255 ++++++++++++++++++ 3 files changed, 262 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6d16d0.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 6020c30a33b3..d3bb5b526015 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -126,6 +126,12 @@ config DRM_PANEL_RAYDIUM_RM68200 Say Y here if you want to enable support for Raydium RM68200 720x1280 DSI video mode panel. +config DRM_PANEL_SAMSUNG_S6D16D0 + tristate "Samsung S6D16D0 DSI video mode panel" + depends on OF + depends on DRM_MIPI_DSI + select VIDEOMODE_HELPERS + config DRM_PANEL_SAMSUNG_S6E3HA2 tristate "Samsung S6E3HA2 DSI video mode panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 5ccaaa9d13af..b52e5c5804ca 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o +obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c new file mode 100644 index 000000000000..a3bb4220681d --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * MIPI-DSI Samsung s6d16d0 panel driver. This is a 864x480 + * AMOLED panel with a command-only DSI interface. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct s6d16d0 { + struct device *dev; + struct drm_panel panel; + struct regulator *supply; + struct gpio_desc *reset_gpio; +}; + +/* + * The timings are not very helpful as the display is used in + * command mode. + */ +static const struct drm_display_mode samsung_s6d16d0_mode = { + .clock = 420160, /* HS 420160kHz, LP 19200kHz */ + .hdisplay = 864, + .hsync_start = 864 + 154, + .hsync_end = 864 + 154 + 16, + .htotal = 864 + 154 + 16 + 32, + .vdisplay = 480, + .vsync_start = 480 + 1, + .vsync_end = 480 + 1 + 1, + .vtotal = 480 + 1 + 1 + 1, + .vrefresh = 60, +}; + +static inline struct s6d16d0 *panel_to_s6d16d0(struct drm_panel *panel) +{ + return container_of(panel, struct s6d16d0, panel); +} + +static int s6d16d0_unprepare(struct drm_panel *panel) +{ + struct s6d16d0 *s6 = panel_to_s6d16d0(panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(s6->dev); + int ret; + + /* Enter sleep mode */ + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); + if (ret) { + DRM_DEV_ERROR(s6->dev, "failed to enter sleep mode (%d)\n", + ret); + return ret; + } + + /* Assert RESET */ + gpiod_set_value_cansleep(s6->reset_gpio, 1); + regulator_disable(s6->supply); + + return 0; +} + +static int s6d16d0_prepare(struct drm_panel *panel) +{ + struct s6d16d0 *s6 = panel_to_s6d16d0(panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(s6->dev); + int ret; + + ret = regulator_enable(s6->supply); + if (ret) { + DRM_DEV_ERROR(s6->dev, "failed to enable supply (%d)\n", ret); + return ret; + } + + /* Assert RESET */ + gpiod_set_value_cansleep(s6->reset_gpio, 1); + udelay(10); + /* De-assert RESET */ + gpiod_set_value_cansleep(s6->reset_gpio, 0); + msleep(120); + + /* Enabe tearing mode: send TE (tearing effect) at VBLANK */ + ret = mipi_dsi_dcs_set_tear_on(dsi, + MIPI_DSI_DCS_TEAR_MODE_VBLANK); + if (ret) { + DRM_DEV_ERROR(s6->dev, "failed to enble vblank TE (%d)\n", + ret); + return ret; + } + /* Exit sleep mode and power on */ + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret) { + DRM_DEV_ERROR(s6->dev, "failed to exit sleep mode (%d)\n", + ret); + return ret; + } + + return 0; +} + +static int s6d16d0_enable(struct drm_panel *panel) +{ + struct s6d16d0 *s6 = panel_to_s6d16d0(panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(s6->dev); + int ret; + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret) { + DRM_DEV_ERROR(s6->dev, "failed to turn display on (%d)\n", + ret); + return ret; + } + + return 0; +} + +static int s6d16d0_disable(struct drm_panel *panel) +{ + struct s6d16d0 *s6 = panel_to_s6d16d0(panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(s6->dev); + int ret; + + ret = mipi_dsi_dcs_set_display_off(dsi); + if (ret) { + DRM_DEV_ERROR(s6->dev, "failed to turn display off (%d)\n", + ret); + return ret; + } + + return 0; +} + +static int s6d16d0_get_modes(struct drm_panel *panel) +{ + struct drm_connector *connector = panel->connector; + struct drm_display_mode *mode; + + strncpy(connector->display_info.name, "Samsung S6D16D0\0", + DRM_DISPLAY_INFO_LEN); + + mode = drm_mode_duplicate(panel->drm, &samsung_s6d16d0_mode); + if (!mode) { + DRM_ERROR("bad mode or failed to add mode\n"); + return -EINVAL; + } + drm_mode_set_name(mode); + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + + mode->width_mm = 84; + mode->height_mm = 48; + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + + drm_mode_probed_add(connector, mode); + + return 1; /* Number of modes */ +} + +static const struct drm_panel_funcs s6d16d0_drm_funcs = { + .disable = s6d16d0_disable, + .unprepare = s6d16d0_unprepare, + .prepare = s6d16d0_prepare, + .enable = s6d16d0_enable, + .get_modes = s6d16d0_get_modes, +}; + +static int s6d16d0_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct s6d16d0 *s6; + int ret; + + s6 = devm_kzalloc(dev, sizeof(struct s6d16d0), GFP_KERNEL); + if (!s6) + return -ENOMEM; + mipi_dsi_set_drvdata(dsi, s6); + s6->dev = dev; + + dsi->lanes = 2; + dsi->format = MIPI_DSI_FMT_RGB888; + /* + * This display uses command mode so no MIPI_DSI_MODE_VIDEO + * or MIPI_DSI_MODE_VIDEO_SYNC_PULSE + * + * As we only send commands we do not need to be continously + * clocked. + */ + dsi->mode_flags = + MIPI_DSI_CLOCK_NON_CONTINUOUS | + MIPI_DSI_MODE_EOT_PACKET; + + s6->supply = devm_regulator_get(dev, "vdd1"); + if (IS_ERR(s6->supply)) + return PTR_ERR(s6->supply); + + /* This asserts RESET by default */ + s6->reset_gpio = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(s6->reset_gpio)) { + ret = PTR_ERR(s6->reset_gpio); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, "failed to request GPIO (%d)\n", + ret); + return ret; + } + + drm_panel_init(&s6->panel); + s6->panel.dev = dev; + s6->panel.funcs = &s6d16d0_drm_funcs; + + ret = drm_panel_add(&s6->panel); + if (ret < 0) + return ret; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) + drm_panel_remove(&s6->panel); + + return ret; +} + +static int s6d16d0_remove(struct mipi_dsi_device *dsi) +{ + struct s6d16d0 *s6 = mipi_dsi_get_drvdata(dsi); + + mipi_dsi_detach(dsi); + drm_panel_remove(&s6->panel); + + return 0; +} + +static const struct of_device_id s6d16d0_of_match[] = { + { .compatible = "samsung,s6d16d0" }, + { } +}; +MODULE_DEVICE_TABLE(of, s6d16d0_of_match); + +static struct mipi_dsi_driver s6d16d0_driver = { + .probe = s6d16d0_probe, + .remove = s6d16d0_remove, + .driver = { + .name = "panel-samsung-s6d16d0", + .of_match_table = s6d16d0_of_match, + }, +}; +module_mipi_dsi_driver(s6d16d0_driver); + +MODULE_AUTHOR("Linus Wallei "); +MODULE_DESCRIPTION("MIPI-DSI s6d16d0 Panel Driver"); +MODULE_LICENSE("GPL v2");