Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * (C) COPYRIGHT 2012-2013 ARM Limited. All rights reserved.
0004  *
0005  * Parts of this file were based on sources as follows:
0006  *
0007  * Copyright (c) 2006-2008 Intel Corporation
0008  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
0009  * Copyright (C) 2011 Texas Instruments
0010  */
0011 
0012 /**
0013  * DOC: ARM PrimeCell PL110 and PL111 CLCD Driver
0014  *
0015  * The PL110/PL111 is a simple LCD controller that can support TFT
0016  * and STN displays. This driver exposes a standard KMS interface
0017  * for them.
0018  *
0019  * The driver currently doesn't expose the cursor.  The DRM API for
0020  * cursors requires support for 64x64 ARGB8888 cursor images, while
0021  * the hardware can only support 64x64 monochrome with masking
0022  * cursors.  While one could imagine trying to hack something together
0023  * to look at the ARGB8888 and program reasonable in monochrome, we
0024  * just don't expose the cursor at all instead, and leave cursor
0025  * support to the application software cursor layer.
0026  *
0027  * TODO:
0028  *
0029  * - Fix race between setting plane base address and getting IRQ for
0030  *   vsync firing the pageflip completion.
0031  *
0032  * - Read back hardware state at boot to skip reprogramming the
0033  *   hardware when doing a no-op modeset.
0034  *
0035  * - Use the CLKSEL bit to support switching between the two external
0036  *   clock parents.
0037  */
0038 
0039 #include <linux/amba/bus.h>
0040 #include <linux/dma-buf.h>
0041 #include <linux/module.h>
0042 #include <linux/of.h>
0043 #include <linux/of_graph.h>
0044 #include <linux/of_reserved_mem.h>
0045 #include <linux/shmem_fs.h>
0046 #include <linux/slab.h>
0047 
0048 #include <drm/drm_atomic_helper.h>
0049 #include <drm/drm_bridge.h>
0050 #include <drm/drm_drv.h>
0051 #include <drm/drm_fb_cma_helper.h>
0052 #include <drm/drm_fb_helper.h>
0053 #include <drm/drm_fourcc.h>
0054 #include <drm/drm_gem_cma_helper.h>
0055 #include <drm/drm_gem_framebuffer_helper.h>
0056 #include <drm/drm_of.h>
0057 #include <drm/drm_panel.h>
0058 #include <drm/drm_probe_helper.h>
0059 #include <drm/drm_vblank.h>
0060 
0061 #include "pl111_drm.h"
0062 #include "pl111_versatile.h"
0063 #include "pl111_nomadik.h"
0064 
0065 #define DRIVER_DESC      "DRM module for PL111"
0066 
0067 static const struct drm_mode_config_funcs mode_config_funcs = {
0068     .fb_create = drm_gem_fb_create,
0069     .atomic_check = drm_atomic_helper_check,
0070     .atomic_commit = drm_atomic_helper_commit,
0071 };
0072 
0073 static int pl111_modeset_init(struct drm_device *dev)
0074 {
0075     struct drm_mode_config *mode_config;
0076     struct pl111_drm_dev_private *priv = dev->dev_private;
0077     struct device_node *np = dev->dev->of_node;
0078     struct device_node *remote;
0079     struct drm_panel *panel = NULL;
0080     struct drm_bridge *bridge = NULL;
0081     bool defer = false;
0082     int ret;
0083     int i;
0084 
0085     ret = drmm_mode_config_init(dev);
0086     if (ret)
0087         return ret;
0088 
0089     mode_config = &dev->mode_config;
0090     mode_config->funcs = &mode_config_funcs;
0091     mode_config->min_width = 1;
0092     mode_config->max_width = 1024;
0093     mode_config->min_height = 1;
0094     mode_config->max_height = 768;
0095 
0096     i = 0;
0097     for_each_endpoint_of_node(np, remote) {
0098         struct drm_panel *tmp_panel;
0099         struct drm_bridge *tmp_bridge;
0100 
0101         dev_dbg(dev->dev, "checking endpoint %d\n", i);
0102 
0103         ret = drm_of_find_panel_or_bridge(dev->dev->of_node,
0104                           0, i,
0105                           &tmp_panel,
0106                           &tmp_bridge);
0107         if (ret) {
0108             if (ret == -EPROBE_DEFER) {
0109                 /*
0110                  * Something deferred, but that is often just
0111                  * another way of saying -ENODEV, but let's
0112                  * cast a vote for later deferral.
0113                  */
0114                 defer = true;
0115             } else if (ret != -ENODEV) {
0116                 /* Continue, maybe something else is working */
0117                 dev_err(dev->dev,
0118                     "endpoint %d returns %d\n", i, ret);
0119             }
0120         }
0121 
0122         if (tmp_panel) {
0123             dev_info(dev->dev,
0124                  "found panel on endpoint %d\n", i);
0125             panel = tmp_panel;
0126         }
0127         if (tmp_bridge) {
0128             dev_info(dev->dev,
0129                  "found bridge on endpoint %d\n", i);
0130             bridge = tmp_bridge;
0131         }
0132 
0133         i++;
0134     }
0135 
0136     /*
0137      * If we can't find neither panel nor bridge on any of the
0138      * endpoints, and any of them retured -EPROBE_DEFER, then
0139      * let's defer this driver too.
0140      */
0141     if ((!panel && !bridge) && defer)
0142         return -EPROBE_DEFER;
0143 
0144     if (panel) {
0145         bridge = drm_panel_bridge_add_typed(panel,
0146                             DRM_MODE_CONNECTOR_Unknown);
0147         if (IS_ERR(bridge)) {
0148             ret = PTR_ERR(bridge);
0149             goto finish;
0150         }
0151     } else if (bridge) {
0152         dev_info(dev->dev, "Using non-panel bridge\n");
0153     } else {
0154         dev_err(dev->dev, "No bridge, exiting\n");
0155         return -ENODEV;
0156     }
0157 
0158     priv->bridge = bridge;
0159     if (panel) {
0160         priv->panel = panel;
0161         priv->connector = drm_panel_bridge_connector(bridge);
0162     }
0163 
0164     ret = pl111_display_init(dev);
0165     if (ret != 0) {
0166         dev_err(dev->dev, "Failed to init display\n");
0167         goto out_bridge;
0168     }
0169 
0170     ret = drm_simple_display_pipe_attach_bridge(&priv->pipe,
0171                             bridge);
0172     if (ret)
0173         return ret;
0174 
0175     if (!priv->variant->broken_vblank) {
0176         ret = drm_vblank_init(dev, 1);
0177         if (ret != 0) {
0178             dev_err(dev->dev, "Failed to init vblank\n");
0179             goto out_bridge;
0180         }
0181     }
0182 
0183     drm_mode_config_reset(dev);
0184 
0185     drm_kms_helper_poll_init(dev);
0186 
0187     goto finish;
0188 
0189 out_bridge:
0190     if (panel)
0191         drm_panel_bridge_remove(bridge);
0192 finish:
0193     return ret;
0194 }
0195 
0196 static struct drm_gem_object *
0197 pl111_gem_import_sg_table(struct drm_device *dev,
0198               struct dma_buf_attachment *attach,
0199               struct sg_table *sgt)
0200 {
0201     struct pl111_drm_dev_private *priv = dev->dev_private;
0202 
0203     /*
0204      * When using device-specific reserved memory we can't import
0205      * DMA buffers: those are passed by reference in any global
0206      * memory and we can only handle a specific range of memory.
0207      */
0208     if (priv->use_device_memory)
0209         return ERR_PTR(-EINVAL);
0210 
0211     return drm_gem_cma_prime_import_sg_table(dev, attach, sgt);
0212 }
0213 
0214 DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
0215 
0216 static const struct drm_driver pl111_drm_driver = {
0217     .driver_features =
0218         DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
0219     .ioctls = NULL,
0220     .fops = &drm_fops,
0221     .name = "pl111",
0222     .desc = DRIVER_DESC,
0223     .date = "20170317",
0224     .major = 1,
0225     .minor = 0,
0226     .patchlevel = 0,
0227     .dumb_create = drm_gem_cma_dumb_create,
0228     .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
0229     .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
0230     .gem_prime_import_sg_table = pl111_gem_import_sg_table,
0231     .gem_prime_mmap = drm_gem_prime_mmap,
0232 
0233 #if defined(CONFIG_DEBUG_FS)
0234     .debugfs_init = pl111_debugfs_init,
0235 #endif
0236 };
0237 
0238 static int pl111_amba_probe(struct amba_device *amba_dev,
0239                 const struct amba_id *id)
0240 {
0241     struct device *dev = &amba_dev->dev;
0242     struct pl111_drm_dev_private *priv;
0243     const struct pl111_variant_data *variant = id->data;
0244     struct drm_device *drm;
0245     int ret;
0246 
0247     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0248     if (!priv)
0249         return -ENOMEM;
0250 
0251     drm = drm_dev_alloc(&pl111_drm_driver, dev);
0252     if (IS_ERR(drm))
0253         return PTR_ERR(drm);
0254     amba_set_drvdata(amba_dev, drm);
0255     priv->drm = drm;
0256     drm->dev_private = priv;
0257     priv->variant = variant;
0258 
0259     ret = of_reserved_mem_device_init(dev);
0260     if (!ret) {
0261         dev_info(dev, "using device-specific reserved memory\n");
0262         priv->use_device_memory = true;
0263     }
0264 
0265     if (of_property_read_u32(dev->of_node, "max-memory-bandwidth",
0266                  &priv->memory_bw)) {
0267         dev_info(dev, "no max memory bandwidth specified, assume unlimited\n");
0268         priv->memory_bw = 0;
0269     }
0270 
0271     /* The two main variants swap this register */
0272     if (variant->is_pl110 || variant->is_lcdc) {
0273         priv->ienb = CLCD_PL110_IENB;
0274         priv->ctrl = CLCD_PL110_CNTL;
0275     } else {
0276         priv->ienb = CLCD_PL111_IENB;
0277         priv->ctrl = CLCD_PL111_CNTL;
0278     }
0279 
0280     priv->regs = devm_ioremap_resource(dev, &amba_dev->res);
0281     if (IS_ERR(priv->regs)) {
0282         dev_err(dev, "%s failed mmio\n", __func__);
0283         ret = PTR_ERR(priv->regs);
0284         goto dev_put;
0285     }
0286 
0287     /* This may override some variant settings */
0288     ret = pl111_versatile_init(dev, priv);
0289     if (ret)
0290         goto dev_put;
0291 
0292     pl111_nomadik_init(dev);
0293 
0294     /* turn off interrupts before requesting the irq */
0295     writel(0, priv->regs + priv->ienb);
0296 
0297     ret = devm_request_irq(dev, amba_dev->irq[0], pl111_irq, 0,
0298                    variant->name, priv);
0299     if (ret != 0) {
0300         dev_err(dev, "%s failed irq %d\n", __func__, ret);
0301         return ret;
0302     }
0303 
0304     ret = pl111_modeset_init(drm);
0305     if (ret != 0)
0306         goto dev_put;
0307 
0308     ret = drm_dev_register(drm, 0);
0309     if (ret < 0)
0310         goto dev_put;
0311 
0312     drm_fbdev_generic_setup(drm, priv->variant->fb_bpp);
0313 
0314     return 0;
0315 
0316 dev_put:
0317     drm_dev_put(drm);
0318     of_reserved_mem_device_release(dev);
0319 
0320     return ret;
0321 }
0322 
0323 static void pl111_amba_remove(struct amba_device *amba_dev)
0324 {
0325     struct device *dev = &amba_dev->dev;
0326     struct drm_device *drm = amba_get_drvdata(amba_dev);
0327     struct pl111_drm_dev_private *priv = drm->dev_private;
0328 
0329     drm_dev_unregister(drm);
0330     if (priv->panel)
0331         drm_panel_bridge_remove(priv->bridge);
0332     drm_dev_put(drm);
0333     of_reserved_mem_device_release(dev);
0334 }
0335 
0336 /*
0337  * This early variant lacks the 565 and 444 pixel formats.
0338  */
0339 static const u32 pl110_pixel_formats[] = {
0340     DRM_FORMAT_ABGR8888,
0341     DRM_FORMAT_XBGR8888,
0342     DRM_FORMAT_ARGB8888,
0343     DRM_FORMAT_XRGB8888,
0344     DRM_FORMAT_ABGR1555,
0345     DRM_FORMAT_XBGR1555,
0346     DRM_FORMAT_ARGB1555,
0347     DRM_FORMAT_XRGB1555,
0348 };
0349 
0350 static const struct pl111_variant_data pl110_variant = {
0351     .name = "PL110",
0352     .is_pl110 = true,
0353     .formats = pl110_pixel_formats,
0354     .nformats = ARRAY_SIZE(pl110_pixel_formats),
0355     .fb_bpp = 16,
0356 };
0357 
0358 /* RealView, Versatile Express etc use this modern variant */
0359 static const u32 pl111_pixel_formats[] = {
0360     DRM_FORMAT_ABGR8888,
0361     DRM_FORMAT_XBGR8888,
0362     DRM_FORMAT_ARGB8888,
0363     DRM_FORMAT_XRGB8888,
0364     DRM_FORMAT_BGR565,
0365     DRM_FORMAT_RGB565,
0366     DRM_FORMAT_ABGR1555,
0367     DRM_FORMAT_XBGR1555,
0368     DRM_FORMAT_ARGB1555,
0369     DRM_FORMAT_XRGB1555,
0370     DRM_FORMAT_ABGR4444,
0371     DRM_FORMAT_XBGR4444,
0372     DRM_FORMAT_ARGB4444,
0373     DRM_FORMAT_XRGB4444,
0374 };
0375 
0376 static const struct pl111_variant_data pl111_variant = {
0377     .name = "PL111",
0378     .formats = pl111_pixel_formats,
0379     .nformats = ARRAY_SIZE(pl111_pixel_formats),
0380     .fb_bpp = 32,
0381 };
0382 
0383 static const u32 pl110_nomadik_pixel_formats[] = {
0384     DRM_FORMAT_RGB888,
0385     DRM_FORMAT_BGR888,
0386     DRM_FORMAT_ABGR8888,
0387     DRM_FORMAT_XBGR8888,
0388     DRM_FORMAT_ARGB8888,
0389     DRM_FORMAT_XRGB8888,
0390     DRM_FORMAT_BGR565,
0391     DRM_FORMAT_RGB565,
0392     DRM_FORMAT_ABGR1555,
0393     DRM_FORMAT_XBGR1555,
0394     DRM_FORMAT_ARGB1555,
0395     DRM_FORMAT_XRGB1555,
0396     DRM_FORMAT_ABGR4444,
0397     DRM_FORMAT_XBGR4444,
0398     DRM_FORMAT_ARGB4444,
0399     DRM_FORMAT_XRGB4444,
0400 };
0401 
0402 static const struct pl111_variant_data pl110_nomadik_variant = {
0403     .name = "LCDC (PL110 Nomadik)",
0404     .formats = pl110_nomadik_pixel_formats,
0405     .nformats = ARRAY_SIZE(pl110_nomadik_pixel_formats),
0406     .is_lcdc = true,
0407     .st_bitmux_control = true,
0408     .broken_vblank = true,
0409     .fb_bpp = 16,
0410 };
0411 
0412 static const struct amba_id pl111_id_table[] = {
0413     {
0414         .id = 0x00041110,
0415         .mask = 0x000fffff,
0416         .data = (void *)&pl110_variant,
0417     },
0418     {
0419         .id = 0x00180110,
0420         .mask = 0x00fffffe,
0421         .data = (void *)&pl110_nomadik_variant,
0422     },
0423     {
0424         .id = 0x00041111,
0425         .mask = 0x000fffff,
0426         .data = (void *)&pl111_variant,
0427     },
0428     {0, 0},
0429 };
0430 MODULE_DEVICE_TABLE(amba, pl111_id_table);
0431 
0432 static struct amba_driver pl111_amba_driver __maybe_unused = {
0433     .drv = {
0434         .name = "drm-clcd-pl111",
0435     },
0436     .probe = pl111_amba_probe,
0437     .remove = pl111_amba_remove,
0438     .id_table = pl111_id_table,
0439 };
0440 
0441 #ifdef CONFIG_ARM_AMBA
0442 module_amba_driver(pl111_amba_driver);
0443 #endif
0444 
0445 MODULE_DESCRIPTION(DRIVER_DESC);
0446 MODULE_AUTHOR("ARM Ltd.");
0447 MODULE_LICENSE("GPL");