| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * Copyright (c) 2006-2008 Intel Corporation |
|---|
| 7 | 8 | * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> |
|---|
| 8 | 9 | * Copyright (C) 2011 Texas Instruments |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software and is provided to you under the terms of the |
|---|
| 11 | | - * GNU General Public License version 2 as published by the Free Software |
|---|
| 12 | | - * Foundation, and any use by you of this program is subject to the terms of |
|---|
| 13 | | - * such GNU licence. |
|---|
| 14 | | - * |
|---|
| 15 | 10 | */ |
|---|
| 16 | 11 | |
|---|
| 17 | | -#include <linux/amba/clcd-regs.h> |
|---|
| 18 | 12 | #include <linux/clk.h> |
|---|
| 13 | +#include <linux/delay.h> |
|---|
| 19 | 14 | #include <linux/version.h> |
|---|
| 20 | 15 | #include <linux/dma-buf.h> |
|---|
| 21 | 16 | #include <linux/of_graph.h> |
|---|
| 22 | 17 | |
|---|
| 23 | | -#include <drm/drmP.h> |
|---|
| 18 | +#include <drm/drm_fb_cma_helper.h> |
|---|
| 19 | +#include <drm/drm_fourcc.h> |
|---|
| 24 | 20 | #include <drm/drm_gem_cma_helper.h> |
|---|
| 25 | 21 | #include <drm/drm_gem_framebuffer_helper.h> |
|---|
| 26 | | -#include <drm/drm_fb_cma_helper.h> |
|---|
| 22 | +#include <drm/drm_vblank.h> |
|---|
| 27 | 23 | |
|---|
| 28 | 24 | #include "pl111_drm.h" |
|---|
| 29 | 25 | |
|---|
| .. | .. |
|---|
| 51 | 47 | } |
|---|
| 52 | 48 | |
|---|
| 53 | 49 | static enum drm_mode_status |
|---|
| 54 | | -pl111_mode_valid(struct drm_crtc *crtc, |
|---|
| 50 | +pl111_mode_valid(struct drm_simple_display_pipe *pipe, |
|---|
| 55 | 51 | const struct drm_display_mode *mode) |
|---|
| 56 | 52 | { |
|---|
| 57 | | - struct drm_device *drm = crtc->dev; |
|---|
| 53 | + struct drm_device *drm = pipe->crtc.dev; |
|---|
| 58 | 54 | struct pl111_drm_dev_private *priv = drm->dev_private; |
|---|
| 59 | 55 | u32 cpp = priv->variant->fb_bpp / 8; |
|---|
| 60 | 56 | u64 bw; |
|---|
| .. | .. |
|---|
| 131 | 127 | struct drm_framebuffer *fb = plane->state->fb; |
|---|
| 132 | 128 | struct drm_connector *connector = priv->connector; |
|---|
| 133 | 129 | struct drm_bridge *bridge = priv->bridge; |
|---|
| 130 | + bool grayscale = false; |
|---|
| 134 | 131 | u32 cntl; |
|---|
| 135 | 132 | u32 ppl, hsw, hfp, hbp; |
|---|
| 136 | 133 | u32 lpp, vsw, vfp, vbp; |
|---|
| .. | .. |
|---|
| 188 | 185 | tim2 |= TIM2_IOE; |
|---|
| 189 | 186 | |
|---|
| 190 | 187 | if (connector->display_info.bus_flags & |
|---|
| 191 | | - DRM_BUS_FLAG_PIXDATA_NEGEDGE) |
|---|
| 188 | + DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) |
|---|
| 192 | 189 | tim2 |= TIM2_IPC; |
|---|
| 190 | + |
|---|
| 191 | + if (connector->display_info.num_bus_formats == 1 && |
|---|
| 192 | + connector->display_info.bus_formats[0] == |
|---|
| 193 | + MEDIA_BUS_FMT_Y8_1X8) |
|---|
| 194 | + grayscale = true; |
|---|
| 195 | + |
|---|
| 196 | + /* |
|---|
| 197 | + * The AC pin bias frequency is set to max count when using |
|---|
| 198 | + * grayscale so at least once in a while we will reverse |
|---|
| 199 | + * polarity and get rid of any DC built up that could |
|---|
| 200 | + * damage the display. |
|---|
| 201 | + */ |
|---|
| 202 | + if (grayscale) |
|---|
| 203 | + tim2 |= TIM2_ACB_MASK; |
|---|
| 193 | 204 | } |
|---|
| 194 | 205 | |
|---|
| 195 | 206 | if (bridge) { |
|---|
| .. | .. |
|---|
| 221 | 232 | |
|---|
| 222 | 233 | writel(0, priv->regs + CLCD_TIM3); |
|---|
| 223 | 234 | |
|---|
| 224 | | - /* Hard-code TFT panel */ |
|---|
| 225 | | - cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDVCOMP(1); |
|---|
| 235 | + /* |
|---|
| 236 | + * Detect grayscale bus format. We do not support a grayscale mode |
|---|
| 237 | + * toward userspace, instead we expose an RGB24 buffer and then the |
|---|
| 238 | + * hardware will activate its grayscaler to convert to the grayscale |
|---|
| 239 | + * format. |
|---|
| 240 | + */ |
|---|
| 241 | + if (grayscale) |
|---|
| 242 | + cntl = CNTL_LCDEN | CNTL_LCDMONO8; |
|---|
| 243 | + else |
|---|
| 244 | + /* Else we assume TFT display */ |
|---|
| 245 | + cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDVCOMP(1); |
|---|
| 246 | + |
|---|
| 226 | 247 | /* On the ST Micro variant, assume all 24 bits are connected */ |
|---|
| 227 | 248 | if (priv->variant->st_bitmux_control) |
|---|
| 228 | 249 | cntl |= CNTL_ST_CDWID_24; |
|---|
| .. | .. |
|---|
| 551 | 572 | int pl111_display_init(struct drm_device *drm) |
|---|
| 552 | 573 | { |
|---|
| 553 | 574 | struct pl111_drm_dev_private *priv = drm->dev_private; |
|---|
| 554 | | - struct device *dev = drm->dev; |
|---|
| 555 | | - struct device_node *endpoint; |
|---|
| 556 | | - u32 tft_r0b0g0[3]; |
|---|
| 557 | 575 | int ret; |
|---|
| 558 | | - |
|---|
| 559 | | - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); |
|---|
| 560 | | - if (!endpoint) |
|---|
| 561 | | - return -ENODEV; |
|---|
| 562 | | - |
|---|
| 563 | | - if (of_property_read_u32_array(endpoint, |
|---|
| 564 | | - "arm,pl11x,tft-r0g0b0-pads", |
|---|
| 565 | | - tft_r0b0g0, |
|---|
| 566 | | - ARRAY_SIZE(tft_r0b0g0)) != 0) { |
|---|
| 567 | | - dev_err(dev, "arm,pl11x,tft-r0g0b0-pads should be 3 ints\n"); |
|---|
| 568 | | - of_node_put(endpoint); |
|---|
| 569 | | - return -ENOENT; |
|---|
| 570 | | - } |
|---|
| 571 | | - of_node_put(endpoint); |
|---|
| 572 | 576 | |
|---|
| 573 | 577 | ret = pl111_init_clock_divider(drm); |
|---|
| 574 | 578 | if (ret) |
|---|