From d38a793e0efeb27e49b1ac0bad855f49f840684b Mon Sep 17 00:00:00 2001 From: Alexey Sheplyakov Date: Tue, 16 Mar 2021 12:45:43 +0400 Subject: [PATCH 625/625] baikal_vdu_drm: (LVDS) panel support --- drivers/gpu/drm/baikal/Makefile | 2 - drivers/gpu/drm/baikal/baikal_vdu_connector.c | 54 ++++++++++++------ drivers/gpu/drm/baikal/baikal_vdu_crtc.c | 55 ++++++++++++++----- drivers/gpu/drm/baikal/baikal_vdu_drm.h | 32 +++-------- drivers/gpu/drm/baikal/baikal_vdu_drv.c | 42 ++++++++------ drivers/gpu/drm/baikal/baikal_vdu_encoder.c | 51 ----------------- drivers/gpu/drm/baikal/baikal_vdu_gem.c | 37 ------------- drivers/gpu/drm/baikal/baikal_vdu_regs.h | 13 +---- 8 files changed, 113 insertions(+), 173 deletions(-) delete mode 100644 drivers/gpu/drm/baikal/baikal_vdu_encoder.c delete mode 100644 drivers/gpu/drm/baikal/baikal_vdu_gem.c diff --git a/drivers/gpu/drm/baikal/Makefile b/drivers/gpu/drm/baikal/Makefile index 4c3e9e67befb..eb029494e823 100644 --- a/drivers/gpu/drm/baikal/Makefile +++ b/drivers/gpu/drm/baikal/Makefile @@ -2,8 +2,6 @@ baikal_vdu_drm-y += baikal_vdu_connector.o \ baikal_vdu_crtc.o \ baikal_vdu_drv.o \ - baikal_vdu_encoder.o \ - baikal_vdu_gem.o \ baikal_vdu_plane.o baikal_vdu_drm-$(CONFIG_DEBUG_FS) += baikal_vdu_debugfs.o diff --git a/drivers/gpu/drm/baikal/baikal_vdu_connector.c b/drivers/gpu/drm/baikal/baikal_vdu_connector.c index ca48e230f174..2f20cf3da627 100644 --- a/drivers/gpu/drm/baikal/baikal_vdu_connector.c +++ b/drivers/gpu/drm/baikal/baikal_vdu_connector.c @@ -34,6 +34,9 @@ #include "baikal_vdu_drm.h" #include "baikal_vdu_regs.h" +#define to_baikal_vdu_private(x) \ + container_of(x, struct baikal_vdu_private, connector) + static void baikal_vdu_drm_connector_destroy(struct drm_connector *connector) { drm_connector_unregister(connector); @@ -43,10 +46,9 @@ static void baikal_vdu_drm_connector_destroy(struct drm_connector *connector) static enum drm_connector_status baikal_vdu_drm_connector_detect( struct drm_connector *connector, bool force) { - struct baikal_vdu_drm_connector *vdu_connector = - to_baikal_vdu_drm_connector(connector); + struct baikal_vdu_private *priv = to_baikal_vdu_private(connector); - return (vdu_connector->panel ? + return (priv->panel ? connector_status_connected : connector_status_disconnected); } @@ -54,24 +56,18 @@ static enum drm_connector_status baikal_vdu_drm_connector_detect( static int baikal_vdu_drm_connector_helper_get_modes( struct drm_connector *connector) { - struct baikal_vdu_drm_connector *vdu_connector = - to_baikal_vdu_drm_connector(connector); + struct baikal_vdu_private *priv = to_baikal_vdu_private(connector); - if (!vdu_connector) { - pr_err("%s: vdu_connector == NULL\n", __func__); - return 0; - } - if (!vdu_connector->panel) + if (!priv->panel) return 0; - return drm_panel_get_modes(vdu_connector->panel, connector); + return drm_panel_get_modes(priv->panel, connector); } const struct drm_connector_funcs connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .destroy = baikal_vdu_drm_connector_destroy, .detect = baikal_vdu_drm_connector_detect, - //.dpms = drm_atomic_helper_connector_dpms, // TODO enable it? .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, @@ -85,14 +81,38 @@ static const struct drm_encoder_funcs encoder_funcs = { .destroy = drm_encoder_cleanup, }; -int baikal_vdu_connector_create(struct drm_device *dev) +int baikal_vdu_lvds_connector_create(struct drm_device *dev) { struct baikal_vdu_private *priv = dev->dev_private; - struct baikal_vdu_drm_connector *vdu_connector = &priv->connector; - struct drm_connector *connector = &vdu_connector->connector; + struct drm_connector *connector = &priv->connector; + struct drm_encoder *encoder = &priv->encoder; + int ret = 0; - drm_connector_init(dev, connector, &connector_funcs, + ret = drm_connector_init(dev, connector, &connector_funcs, DRM_MODE_CONNECTOR_LVDS); + if (ret) { + dev_err(dev->dev, "drm_connector_init failed: %d\n", ret); + goto out; + } drm_connector_helper_add(connector, &connector_helper_funcs); - return 0; + ret = drm_encoder_init(dev, encoder, &encoder_funcs, + DRM_MODE_ENCODER_LVDS, NULL); + if (ret) { + dev_err(dev->dev, "drm_encoder_init failed: %d\n", ret); + goto out; + } + encoder->crtc = &priv->crtc; + encoder->possible_crtcs = drm_crtc_mask(encoder->crtc); + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) { + dev_err(dev->dev, "drm_connector_attach_encoder failed: %d\n", ret); + goto out; + } + ret = drm_connector_register(connector); + if (ret) { + dev_err(dev->dev, "drm_connector_register failed: %d\n", ret); + goto out; + } +out: + return ret; } diff --git a/drivers/gpu/drm/baikal/baikal_vdu_crtc.c b/drivers/gpu/drm/baikal/baikal_vdu_crtc.c index 6ef61791e299..d8bc1182bb77 100644 --- a/drivers/gpu/drm/baikal/baikal_vdu_crtc.c +++ b/drivers/gpu/drm/baikal/baikal_vdu_crtc.c @@ -134,8 +134,13 @@ static void baikal_vdu_crtc_helper_mode_set_nofb(struct drm_crtc *crtc) drm_mode_debug_printmodeline(mode); ppl = mode->hdisplay / 16; - hsw = mode->hsync_end - mode->hsync_start - 1; - hfp = mode->hsync_start - mode->hdisplay; + if (priv->panel) { + hsw = mode->hsync_end - mode->hsync_start; + hfp = mode->hsync_start - mode->hdisplay - 1; + } else { + hsw = mode->hsync_end - mode->hsync_start - 1; + hfp = mode->hsync_start - mode->hdisplay; + } hbp = mode->htotal - mode->hsync_end; lpp = mode->vdisplay; @@ -188,12 +193,15 @@ static void baikal_vdu_crtc_helper_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { struct baikal_vdu_private *priv = crtc->dev->dev_private; - u32 cntl; + struct drm_panel *panel = priv->panel; + struct device_node *panel_node; + const char *data_mapping; + u32 cntl, gpio; DRM_DEV_DEBUG_DRIVER(crtc->dev->dev, "enabling pixel clock\n"); clk_prepare_enable(priv->clk); - drm_panel_prepare(priv->connector.panel); + drm_panel_prepare(panel); writel(ISCR_VSC_VFP, priv->regs + ISCR); @@ -202,13 +210,37 @@ static void baikal_vdu_crtc_helper_enable(struct drm_crtc *crtc, cntl |= PCTR_PCR + PCTR_PCI; writel(cntl, priv->regs + PCTR); - /* Set 16-word input FIFO watermark and 24-bit LCD interface mode */ + /* Set 16-word input FIFO watermark */ /* Enable and Power Up */ cntl = readl(priv->regs + CR1); - cntl |= CR1_LCE + CR1_FDW_16_WORDS + CR1_OPS_LCD24; + cntl &= ~CR1_FDW_MASK; + cntl |= CR1_LCE + CR1_FDW_16_WORDS; + + if (priv->type == VDU_TYPE_LVDS) { + panel_node = panel->dev->of_node; + if (of_property_read_string(panel_node, "data-mapping", &data_mapping)) { + cntl |= CR1_OPS_LCD18; + } else if (strncmp(data_mapping, "vesa-24", 7)) + cntl |= CR1_OPS_LCD24; + else if (strncmp(data_mapping, "jeida-18", 8)) + cntl |= CR1_OPS_LCD18; + else { + dev_warn(crtc->dev->dev, "%s data mapping is not supported, vesa-24 is set\n", data_mapping); + cntl |= CR1_OPS_LCD24; + } + gpio = GPIOR_UHD_ENB; + if (priv->ep_count == 4) + gpio |= GPIOR_UHD_QUAD_PORT; + else if (priv->ep_count == 2) + gpio |= GPIOR_UHD_DUAL_PORT; + else + gpio |= GPIOR_UHD_SNGL_PORT; + writel(gpio, priv->regs + GPIOR); + } else + cntl |= CR1_OPS_LCD24; writel(cntl, priv->regs + CR1); - drm_panel_enable(priv->connector.panel); + drm_panel_enable(priv->panel); drm_crtc_vblank_on(crtc); } @@ -217,12 +249,9 @@ void baikal_vdu_crtc_helper_disable(struct drm_crtc *crtc) struct baikal_vdu_private *priv = crtc->dev->dev_private; drm_crtc_vblank_off(crtc); - drm_panel_disable(priv->connector.panel); + drm_panel_disable(priv->panel); - /* Disable and Power Down */ - //writel(0, priv->regs + CR1); - - drm_panel_unprepare(priv->connector.panel); + drm_panel_unprepare(priv->panel); /* Disable clock */ DRM_DEV_DEBUG_DRIVER(crtc->dev->dev, "disabling pixel clock\n"); @@ -250,8 +279,6 @@ static int baikal_vdu_enable_vblank(struct drm_crtc *crtc) { struct baikal_vdu_private *priv = crtc->dev->dev_private; - //clk_prepare_enable(priv->clk); - /* clear interrupt status */ writel(0x3ffff, priv->regs + ISR); diff --git a/drivers/gpu/drm/baikal/baikal_vdu_drm.h b/drivers/gpu/drm/baikal/baikal_vdu_drm.h index 2db3fb73c9e7..9ab6303a4195 100644 --- a/drivers/gpu/drm/baikal/baikal_vdu_drm.h +++ b/drivers/gpu/drm/baikal/baikal_vdu_drm.h @@ -23,22 +23,16 @@ #include #include -struct clk; -struct drm_device; -struct drm_fbdev_cma; -struct drm_panel; - -struct baikal_vdu_drm_connector { - struct drm_connector connector; - struct drm_panel *panel; -}; +#define VDU_TYPE_HDMI 0 +#define VDU_TYPE_LVDS 1 struct baikal_vdu_private { struct drm_device *drm; - struct baikal_vdu_drm_connector connector; + struct drm_connector connector; struct drm_crtc crtc; struct drm_encoder encoder; + struct drm_panel *panel; struct drm_bridge *bridge; struct drm_plane primary; @@ -47,16 +41,12 @@ struct baikal_vdu_private { spinlock_t lock; u32 counters[20]; int mode_fixup; - + int type; + u32 ep_count; u32 fb_addr; u32 fb_end; }; -#define to_baikal_vdu_drm_connector(x) \ - container_of(x, struct baikal_vdu_drm_connector, connector) - -extern const struct drm_encoder_funcs baikal_vdu_encoder_funcs; - /* CRTC Functions */ int baikal_vdu_crtc_create(struct drm_device *dev); irqreturn_t baikal_vdu_irq(int irq, void *data); @@ -64,15 +54,7 @@ irqreturn_t baikal_vdu_irq(int irq, void *data); int baikal_vdu_primary_plane_init(struct drm_device *dev); /* Connector Functions */ -int baikal_vdu_connector_create(struct drm_device *dev); - -/* Encoder Functions */ -int baikal_vdu_encoder_init(struct drm_device *dev); - -/* GEM Functions */ -int baikal_vdu_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args); +int baikal_vdu_lvds_connector_create(struct drm_device *dev); void baikal_vdu_debugfs_init(struct drm_minor *minor); diff --git a/drivers/gpu/drm/baikal/baikal_vdu_drv.c b/drivers/gpu/drm/baikal/baikal_vdu_drv.c index 5deab510ea57..8eb9dda7fa01 100644 --- a/drivers/gpu/drm/baikal/baikal_vdu_drv.c +++ b/drivers/gpu/drm/baikal/baikal_vdu_drv.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -63,6 +62,10 @@ static struct drm_mode_config_funcs mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; +static const struct drm_encoder_funcs baikal_vdu_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + static int vdu_modeset_init(struct drm_device *dev) { struct drm_mode_config *mode_config; @@ -94,38 +97,35 @@ static int vdu_modeset_init(struct drm_device *dev) } ret = drm_of_find_panel_or_bridge(dev->dev->of_node, -1, -1, - &priv->connector.panel, + &priv->panel, &priv->bridge); if (ret == -EPROBE_DEFER) { dev_info(dev->dev, "Bridge probe deferred\n"); goto out_config; } - ret = baikal_vdu_encoder_init(dev); - if (ret) { - dev_err(dev->dev, "Failed to create DRM encoder\n"); - goto out_config; - } - if (priv->bridge) { + struct drm_encoder *encoder = &priv->encoder; + ret = drm_encoder_init(dev, encoder, &baikal_vdu_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) { + dev_err(dev->dev, "failed to create DRM encoder\n"); + goto out_config; + } + encoder->crtc = &priv->crtc; + encoder->possible_crtcs = drm_crtc_mask(encoder->crtc); priv->bridge->encoder = &priv->encoder; ret = drm_bridge_attach(&priv->encoder, priv->bridge, NULL, 0); if (ret) { dev_err(dev->dev, "Failed to attach DRM bridge %d\n", ret); goto out_config; } - } else if (priv->connector.panel) { - ret = baikal_vdu_connector_create(dev); + } else if (priv->panel) { + ret = baikal_vdu_lvds_connector_create(dev); if (ret) { dev_err(dev->dev, "Failed to create DRM connector\n"); goto out_config; } - ret = drm_connector_attach_encoder(&priv->connector.connector, - &priv->encoder); - if (ret != 0) { - dev_err(dev->dev, "Failed to attach encoder\n"); - goto out_config; - } } else ret = -EINVAL; @@ -194,7 +194,7 @@ static struct drm_driver vdu_drm_driver = { .major = 1, .minor = 0, .patchlevel = 0, - .dumb_create = baikal_vdu_dumb_create, + .dumb_create = drm_gem_cma_dumb_create, .gem_create_object = drm_gem_cma_create_object_default_funcs, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, @@ -254,6 +254,14 @@ static int baikal_vdu_drm_probe(struct platform_device *pdev) return ret; } + if (pdev->dev.of_node && of_property_read_bool(pdev->dev.of_node, "lvds-out")) { + priv->type = VDU_TYPE_LVDS; + if (of_property_read_u32(pdev->dev.of_node, "num-lanes", &priv->ep_count)) + priv->ep_count = 1; + } + else + priv->type = VDU_TYPE_HDMI; + ret = vdu_modeset_init(drm); if (ret != 0) { dev_err(dev, "Failed to init modeset\n"); diff --git a/drivers/gpu/drm/baikal/baikal_vdu_encoder.c b/drivers/gpu/drm/baikal/baikal_vdu_encoder.c deleted file mode 100644 index 9081d196dac3..000000000000 --- a/drivers/gpu/drm/baikal/baikal_vdu_encoder.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2019-2020 Baikal Electronics JSC - * - * Author: Pavel Parkhomenko - * - * Parts of this file were based on sources as follows: - * - * Copyright (c) 2006-2008 Intel Corporation - * Copyright (c) 2007 Dave Airlie - * Copyright (C) 2011 Texas Instruments - * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms of - * such GNU licence. - * - */ - -/** - * baikal_vdu_encoder.c - * Implementation of the encoder functions for Baikal Electronics BE-M1000 VDU driver - */ -#include -#include -#include - -#include - -#include "baikal_vdu_drm.h" - -const struct drm_encoder_funcs baikal_vdu_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - -int baikal_vdu_encoder_init(struct drm_device *dev) -{ - struct baikal_vdu_private *priv = dev->dev_private; - struct drm_encoder *encoder = &priv->encoder; - int ret; - - ret = drm_encoder_init(dev, encoder, &baikal_vdu_encoder_funcs, - DRM_MODE_ENCODER_NONE, NULL); - if (ret) - return ret; - - encoder->crtc = &priv->crtc; - encoder->possible_crtcs = BIT(drm_crtc_index(encoder->crtc)); - - return 0; -} diff --git a/drivers/gpu/drm/baikal/baikal_vdu_gem.c b/drivers/gpu/drm/baikal/baikal_vdu_gem.c deleted file mode 100644 index b07566caf12c..000000000000 --- a/drivers/gpu/drm/baikal/baikal_vdu_gem.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2019-2020 Baikal Electronics JSC - * - * Author: Pavel Parkhomenko - * - * Parts of this file were based on sources as follows: - * - * Copyright (c) 2006-2008 Intel Corporation - * Copyright (c) 2007 Dave Airlie - * Copyright (C) 2011 Texas Instruments - * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the - * GNU General Public License version 2 as published by the Free Software - * Foundation, and any use by you of this program is subject to the terms of - * such GNU licence. - * - */ - -/** - * baikal_vdu_gem.c - * Implementation of the GEM functions for Baikal Electronics BE-M1000 VDU driver - */ -#include -#include -#include -#include -#include -#include "baikal_vdu_drm.h" - -int baikal_vdu_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, struct drm_mode_create_dumb *args) -{ - args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8); - - return drm_gem_cma_dumb_create_internal(file_priv, dev, args); -} diff --git a/drivers/gpu/drm/baikal/baikal_vdu_regs.h b/drivers/gpu/drm/baikal/baikal_vdu_regs.h index a0d8e69eb5e6..5553fcac5fec 100644 --- a/drivers/gpu/drm/baikal/baikal_vdu_regs.h +++ b/drivers/gpu/drm/baikal/baikal_vdu_regs.h @@ -1,5 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2019-2020 Baikal Electronics JSC + * Copyright (C) 2019-2021 Baikal Electronics JSC * * Author: Pavel Parkhomenko * @@ -7,10 +8,6 @@ * * David A Rusling * Copyright (C) 2001 ARM Limited - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. */ #ifndef __BAIKAL_VDU_REGS_H__ @@ -50,6 +47,7 @@ #define INTR_FER BIT(4) #define CR1_FBP BIT(19) +#define CR1_FDW_MASK GENMASK(17, 16) #define CR1_FDW_4_WORDS (0 << 16) #define CR1_FDW_8_WORDS (1 << 16) #define CR1_FDW_16_WORDS (2 << 16) @@ -129,15 +127,10 @@ #define HPPLOR_HPPLO(x) ((x) << 0) #define GPIOR_UHD_MASK GENMASK(23, 16) -#define GPIOR_UHD_FMT_LDI (0 << 20) -#define GPIOR_UHD_FMT_VESA (1 << 20) -#define GPIOR_UHD_FMT_JEIDA (2 << 20) #define GPIOR_UHD_SNGL_PORT (0 << 18) #define GPIOR_UHD_DUAL_PORT (1 << 18) #define GPIOR_UHD_QUAD_PORT (2 << 18) #define GPIOR_UHD_ENB BIT(17) -#define GPIOR_UHD_PIX_INTLV (0 << 16) -#define GPIOR_UHD_PIX_SQNTL (1 << 16) #define MRR_DEAR_MRR_MASK GENMASK(31, 3) #define MRR_OUTSTND_RQ_MASK GENMASK(2, 0) -- 2.31.1