From patchwork Mon Oct 24 08:43:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Golaszewski X-Patchwork-Id: 78905 Delivered-To: patch@linaro.org Received: by 10.140.97.247 with SMTP id m110csp2453783qge; Mon, 24 Oct 2016 01:43:11 -0700 (PDT) X-Received: by 10.98.34.218 with SMTP id p87mr26877030pfj.76.1477298591285; Mon, 24 Oct 2016 01:43:11 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id fc3si11947926pab.267.2016.10.24.01.43.11; Mon, 24 Oct 2016 01:43:11 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S936475AbcJXInI (ORCPT + 27 others); Mon, 24 Oct 2016 04:43:08 -0400 Received: from mail-wm0-f48.google.com ([74.125.82.48]:35164 "EHLO mail-wm0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935974AbcJXInF (ORCPT ); Mon, 24 Oct 2016 04:43:05 -0400 Received: by mail-wm0-f48.google.com with SMTP id c78so91231842wme.0 for ; Mon, 24 Oct 2016 01:43:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=5h+nrxOFGCaklbRE2jkQBi7NgLGhQjCxXSaDaaRazBo=; b=NIYco4luLA0yb2n+lakkaMOlLe+/eS9/LsUtD+49txzlKONWety89EqqVKF4XlBh+f 9uZZeIuWKv9aHmOkQ6hN/qglpH4Qc4Y1b5bVqmq3vDXTBIG0bBwb/9X+5wkFAYIkTIge p7sx1dMUIcdJtOEBp+LEow3kBEc4nVlWhix74/kZrlP/35lcRGym/go4RrOkOZ6DS0ng MiKmdlEo4iZL/W7zSFtd9RRCAkRZPCT4ZcRx0nT60lDUgmCPexKN3dqter7YKbdB6yn1 m07mi515XWSlvWlHy5e1coREyFGKUVwEokVdMWuHS2id281xj+48eHS3QQKudf09xby9 rrFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=5h+nrxOFGCaklbRE2jkQBi7NgLGhQjCxXSaDaaRazBo=; b=G0g2iLVwvI3dDCePu+jCt2Sa+SpBWax+1ohHI3kEg+XrA4PEnHT1J5qq053CG6kzUR 5+xw49KQm1CDhCbIh1fRfd3BI8F7NCpfZ0SmAU8d2zolsGbMOpvYFnHLvGedp7BYz/JM zdcUxZKSQe1wIMbIrOdqi6JZTvHnBxoCC3sMLMNjjHyWRHVArOwFrTeY6nmyhB2kc1oZ L7+6bt5M9Sg9YORitvCdNw2jisGN5LuLmruiMBuNauEtd6/2cO88/tqmC27CPNMBkctZ Q1uFvoaSQGEC+562Nq/Ohfz+Z9KsVvXgBGix0qmxGGBu6vIfYK62DEfDsdvTlixN+qCd Egqw== X-Gm-Message-State: ABUngvfUUoTbmYKUwoU4on+slwKME2APIxMkaO/bjRLUC7ImzXAcw8Jk203WT2mrgRCZIsWN X-Received: by 10.28.31.80 with SMTP id f77mr13405343wmf.104.1477298584256; Mon, 24 Oct 2016 01:43:04 -0700 (PDT) Received: from localhost.localdomain ([90.63.244.31]) by smtp.gmail.com with ESMTPSA id c7sm18059732wjk.19.2016.10.24.01.43.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 24 Oct 2016 01:43:03 -0700 (PDT) From: Bartosz Golaszewski To: Jyri Sarha , Tomi Valkeinen , David Airlie , Kevin Hilman , Michael Turquette , Sekhar Nori Cc: LKML , linux-drm , Laurent Pinchart , Peter Ujfalusi , Bartosz Golaszewski Subject: [PATCH v2] drm: tilcdc: implement palette loading for rev1 Date: Mon, 24 Oct 2016 10:43:01 +0200 Message-Id: <1477298581-31291-1-git-send-email-bgolaszewski@baylibre.com> X-Mailer: git-send-email 2.1.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Revision 1 of the IP doesn't work if we don't load the palette (even if it's not used, which is the case for the RGB565 format). Add a function called from tilcdc_crtc_enable() which performs all required actions if we're dealing with a rev1 chip. Signed-off-by: Bartosz Golaszewski --- v1 -> v2: - only allocate dma memory for revision 1 drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 86 +++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) -- 2.9.3 diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 87cfde9..92771c6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -21,11 +21,14 @@ #include #include #include +#include #include "tilcdc_drv.h" #include "tilcdc_regs.h" -#define TILCDC_VBLANK_SAFETY_THRESHOLD_US 1000 +#define TILCDC_VBLANK_SAFETY_THRESHOLD_US 1000 +#define TILCDC_REV1_PALETTE_SIZE 32 +#define TILCDC_REV1_PALETTE_FIRST_ENTRY 0x4000 struct tilcdc_crtc { struct drm_crtc base; @@ -53,6 +56,10 @@ struct tilcdc_crtc { int sync_lost_count; bool frame_intact; + + dma_addr_t palette_dma_handle; + void *palette_base; + struct completion palette_loaded; }; #define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base) @@ -100,6 +107,55 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) tilcdc_crtc->curr_fb = fb; } +/* + * The driver currently only supports the RGB565 format for revision 1. For + * 16 bits-per-pixel the palette block is bypassed, but the first 32 bytes of + * the framebuffer are still considered palette. The first 16-bit entry must + * be 0x4000 while all other entries must be zeroed. + */ +static void tilcdc_crtc_load_palette(struct drm_crtc *crtc) +{ + u32 dma_fb_base, dma_fb_ceiling, raster_ctl; + struct tilcdc_crtc *tilcdc_crtc; + struct drm_device *dev; + u16 *first_entry; + + dev = crtc->dev; + tilcdc_crtc = to_tilcdc_crtc(crtc); + first_entry = tilcdc_crtc->palette_base; + + *first_entry = TILCDC_REV1_PALETTE_FIRST_ENTRY; + + dma_fb_base = tilcdc_read(dev, LCDC_DMA_FB_BASE_ADDR_0_REG); + dma_fb_ceiling = tilcdc_read(dev, LCDC_DMA_FB_CEILING_ADDR_0_REG); + raster_ctl = tilcdc_read(dev, LCDC_RASTER_CTRL_REG); + + /* Tell the LCDC where the palette is located. */ + tilcdc_write(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, + tilcdc_crtc->palette_dma_handle); + tilcdc_write(dev, LCDC_DMA_FB_CEILING_ADDR_0_REG, + (u32)tilcdc_crtc->palette_dma_handle + + TILCDC_REV1_PALETTE_SIZE - 1); + + /* Load it. */ + tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, + LCDC_PALETTE_LOAD_MODE(DATA_ONLY)); + tilcdc_set(dev, LCDC_RASTER_CTRL_REG, + LCDC_PALETTE_LOAD_MODE(PALETTE_ONLY)); + + /* Enable the LCDC and wait for palette to be loaded. */ + tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_PL_INT_ENA); + tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); + + wait_for_completion(&tilcdc_crtc->palette_loaded); + + /* Restore the registers. */ + tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); + tilcdc_write(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, dma_fb_base); + tilcdc_write(dev, LCDC_DMA_FB_CEILING_ADDR_0_REG, dma_fb_ceiling); + tilcdc_write(dev, LCDC_RASTER_CTRL_REG, raster_ctl); +} + static void tilcdc_crtc_enable_irqs(struct drm_device *dev) { struct tilcdc_drm_private *priv = dev->dev_private; @@ -154,6 +210,7 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + struct tilcdc_drm_private *priv = dev->dev_private; WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); @@ -164,6 +221,9 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc) reset(crtc); + if (priv->rev == 1 && !completion_done(&tilcdc_crtc->palette_loaded)) + tilcdc_crtc_load_palette(crtc); + tilcdc_crtc_enable_irqs(dev); tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE); @@ -245,6 +305,12 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc) of_node_put(crtc->port); drm_crtc_cleanup(crtc); drm_flip_work_cleanup(&tilcdc_crtc->unref_work); + + if (priv->rev == 1) { + dma_free_coherent(crtc->dev->dev, TILCDC_REV1_PALETTE_SIZE, + tilcdc_crtc->palette_base, + tilcdc_crtc->palette_dma_handle); + } } int tilcdc_crtc_update_fb(struct drm_crtc *crtc, @@ -804,6 +870,14 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) dev_err_ratelimited(dev->dev, "%s(0x%08x): FIFO underfow", __func__, stat); + if (priv->rev == 1) { + if (stat & LCDC_PL_LOAD_DONE) { + complete(&tilcdc_crtc->palette_loaded); + tilcdc_clear(dev, + LCDC_RASTER_CTRL_REG, LCDC_V1_PL_INT_ENA); + } + } + /* For revision 2 only */ if (priv->rev == 2) { if (stat & LCDC_FRAME_DONE) { @@ -845,6 +919,16 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) return NULL; } + if (priv->rev == 1) { + init_completion(&tilcdc_crtc->palette_loaded); + tilcdc_crtc->palette_base = dma_zalloc_coherent(dev->dev, + TILCDC_REV1_PALETTE_SIZE, + &tilcdc_crtc->palette_dma_handle, + GFP_KERNEL); + if (!tilcdc_crtc->palette_base) + return ERR_PTR(-ENOMEM); + } + crtc = &tilcdc_crtc->base; ret = tilcdc_plane_init(dev, &tilcdc_crtc->primary);