summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/pl111/pl111_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/pl111/pl111_display.c')
-rw-r--r--drivers/gpu/drm/pl111/pl111_display.c52
1 files changed, 31 insertions, 21 deletions
diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c
index 15d2755fdba4..024771a4083e 100644
--- a/drivers/gpu/drm/pl111/pl111_display.c
+++ b/drivers/gpu/drm/pl111/pl111_display.c
@@ -11,14 +11,16 @@
#include <linux/amba/clcd-regs.h>
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/version.h>
#include <linux/dma-buf.h>
#include <linux/of_graph.h>
-#include <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_vblank.h>
#include "pl111_drm.h"
@@ -126,6 +128,7 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
struct drm_framebuffer *fb = plane->state->fb;
struct drm_connector *connector = priv->connector;
struct drm_bridge *bridge = priv->bridge;
+ bool grayscale = false;
u32 cntl;
u32 ppl, hsw, hfp, hbp;
u32 lpp, vsw, vfp, vbp;
@@ -185,6 +188,20 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
if (connector->display_info.bus_flags &
DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
tim2 |= TIM2_IPC;
+
+ if (connector->display_info.num_bus_formats == 1 &&
+ connector->display_info.bus_formats[0] ==
+ MEDIA_BUS_FMT_Y8_1X8)
+ grayscale = true;
+
+ /*
+ * The AC pin bias frequency is set to max count when using
+ * grayscale so at least once in a while we will reverse
+ * polarity and get rid of any DC built up that could
+ * damage the display.
+ */
+ if (grayscale)
+ tim2 |= TIM2_ACB_MASK;
}
if (bridge) {
@@ -216,8 +233,18 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
writel(0, priv->regs + CLCD_TIM3);
- /* Hard-code TFT panel */
- cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDVCOMP(1);
+ /*
+ * Detect grayscale bus format. We do not support a grayscale mode
+ * toward userspace, instead we expose an RGB24 buffer and then the
+ * hardware will activate its grayscaler to convert to the grayscale
+ * format.
+ */
+ if (grayscale)
+ cntl = CNTL_LCDEN | CNTL_LCDMONO8;
+ else
+ /* Else we assume TFT display */
+ cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDVCOMP(1);
+
/* On the ST Micro variant, assume all 24 bits are connected */
if (priv->variant->st_bitmux_control)
cntl |= CNTL_ST_CDWID_24;
@@ -546,25 +573,8 @@ pl111_init_clock_divider(struct drm_device *drm)
int pl111_display_init(struct drm_device *drm)
{
struct pl111_drm_dev_private *priv = drm->dev_private;
- struct device *dev = drm->dev;
- struct device_node *endpoint;
- u32 tft_r0b0g0[3];
int ret;
- endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
- if (!endpoint)
- return -ENODEV;
-
- if (of_property_read_u32_array(endpoint,
- "arm,pl11x,tft-r0g0b0-pads",
- tft_r0b0g0,
- ARRAY_SIZE(tft_r0b0g0)) != 0) {
- dev_err(dev, "arm,pl11x,tft-r0g0b0-pads should be 3 ints\n");
- of_node_put(endpoint);
- return -ENOENT;
- }
- of_node_put(endpoint);
-
ret = pl111_init_clock_divider(drm);
if (ret)
return ret;