Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * DRM driver for Ilitek ILI9486 panels
0004  *
0005  * Copyright 2020 Kamlesh Gurudasani <kamlesh.gurudasani@gmail.com>
0006  */
0007 
0008 #include <linux/backlight.h>
0009 #include <linux/delay.h>
0010 #include <linux/gpio/consumer.h>
0011 #include <linux/module.h>
0012 #include <linux/property.h>
0013 #include <linux/spi/spi.h>
0014 
0015 #include <video/mipi_display.h>
0016 
0017 #include <drm/drm_atomic_helper.h>
0018 #include <drm/drm_drv.h>
0019 #include <drm/drm_fb_helper.h>
0020 #include <drm/drm_gem_atomic_helper.h>
0021 #include <drm/drm_gem_cma_helper.h>
0022 #include <drm/drm_managed.h>
0023 #include <drm/drm_mipi_dbi.h>
0024 #include <drm/drm_modeset_helper.h>
0025 
0026 #define ILI9486_ITFCTR1         0xb0
0027 #define ILI9486_PWCTRL1         0xc2
0028 #define ILI9486_VMCTRL1         0xc5
0029 #define ILI9486_PGAMCTRL        0xe0
0030 #define ILI9486_NGAMCTRL        0xe1
0031 #define ILI9486_DGAMCTRL        0xe2
0032 #define ILI9486_MADCTL_BGR      BIT(3)
0033 #define ILI9486_MADCTL_MV       BIT(5)
0034 #define ILI9486_MADCTL_MX       BIT(6)
0035 #define ILI9486_MADCTL_MY       BIT(7)
0036 
0037 /*
0038  * The PiScreen/waveshare rpi-lcd-35 has a SPI to 16-bit parallel bus converter
0039  * in front of the  display controller. This means that 8-bit values have to be
0040  * transferred as 16-bit.
0041  */
0042 static int waveshare_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par,
0043                  size_t num)
0044 {
0045     struct spi_device *spi = mipi->spi;
0046     void *data = par;
0047     u32 speed_hz;
0048     int i, ret;
0049     __be16 *buf;
0050 
0051     buf = kmalloc(32 * sizeof(u16), GFP_KERNEL);
0052     if (!buf)
0053         return -ENOMEM;
0054 
0055     /*
0056      * The displays are Raspberry Pi HATs and connected to the 8-bit only
0057      * SPI controller, so 16-bit command and parameters need byte swapping
0058      * before being transferred as 8-bit on the big endian SPI bus.
0059      * Pixel data bytes have already been swapped before this function is
0060      * called.
0061      */
0062     buf[0] = cpu_to_be16(*cmd);
0063     gpiod_set_value_cansleep(mipi->dc, 0);
0064     speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 2);
0065     ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, buf, 2);
0066     if (ret || !num)
0067         goto free;
0068 
0069     /* 8-bit configuration data, not 16-bit pixel data */
0070     if (num <= 32) {
0071         for (i = 0; i < num; i++)
0072             buf[i] = cpu_to_be16(par[i]);
0073         num *= 2;
0074         speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num);
0075         data = buf;
0076     }
0077 
0078     gpiod_set_value_cansleep(mipi->dc, 1);
0079     ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, data, num);
0080  free:
0081     kfree(buf);
0082 
0083     return ret;
0084 }
0085 
0086 static void waveshare_enable(struct drm_simple_display_pipe *pipe,
0087                  struct drm_crtc_state *crtc_state,
0088                  struct drm_plane_state *plane_state)
0089 {
0090     struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
0091     struct mipi_dbi *dbi = &dbidev->dbi;
0092     u8 addr_mode;
0093     int ret, idx;
0094 
0095     if (!drm_dev_enter(pipe->crtc.dev, &idx))
0096         return;
0097 
0098     DRM_DEBUG_KMS("\n");
0099 
0100     ret = mipi_dbi_poweron_conditional_reset(dbidev);
0101     if (ret < 0)
0102         goto out_exit;
0103     if (ret == 1)
0104         goto out_enable;
0105 
0106     mipi_dbi_command(dbi, ILI9486_ITFCTR1);
0107     mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
0108     msleep(250);
0109 
0110     mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
0111 
0112     mipi_dbi_command(dbi, ILI9486_PWCTRL1, 0x44);
0113 
0114     mipi_dbi_command(dbi, ILI9486_VMCTRL1, 0x00, 0x00, 0x00, 0x00);
0115 
0116     mipi_dbi_command(dbi, ILI9486_PGAMCTRL,
0117              0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98,
0118              0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x0);
0119     mipi_dbi_command(dbi, ILI9486_NGAMCTRL,
0120              0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75,
0121              0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00);
0122     mipi_dbi_command(dbi, ILI9486_DGAMCTRL,
0123              0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75,
0124              0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00);
0125 
0126     mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
0127     msleep(100);
0128 
0129  out_enable:
0130     switch (dbidev->rotation) {
0131     case 90:
0132         addr_mode = ILI9486_MADCTL_MY;
0133         break;
0134     case 180:
0135         addr_mode = ILI9486_MADCTL_MV;
0136         break;
0137     case 270:
0138         addr_mode = ILI9486_MADCTL_MX;
0139         break;
0140     default:
0141         addr_mode = ILI9486_MADCTL_MV | ILI9486_MADCTL_MY |
0142             ILI9486_MADCTL_MX;
0143         break;
0144     }
0145     addr_mode |= ILI9486_MADCTL_BGR;
0146     mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
0147     mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
0148  out_exit:
0149     drm_dev_exit(idx);
0150 }
0151 
0152 static const struct drm_simple_display_pipe_funcs waveshare_pipe_funcs = {
0153     .enable = waveshare_enable,
0154     .disable = mipi_dbi_pipe_disable,
0155     .update = mipi_dbi_pipe_update,
0156 };
0157 
0158 static const struct drm_display_mode waveshare_mode = {
0159     DRM_SIMPLE_MODE(480, 320, 73, 49),
0160 };
0161 
0162 DEFINE_DRM_GEM_CMA_FOPS(ili9486_fops);
0163 
0164 static const struct drm_driver ili9486_driver = {
0165     .driver_features    = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
0166     .fops           = &ili9486_fops,
0167     DRM_GEM_CMA_DRIVER_OPS_VMAP,
0168     .debugfs_init       = mipi_dbi_debugfs_init,
0169     .name           = "ili9486",
0170     .desc           = "Ilitek ILI9486",
0171     .date           = "20200118",
0172     .major          = 1,
0173     .minor          = 0,
0174 };
0175 
0176 static const struct of_device_id ili9486_of_match[] = {
0177     { .compatible = "waveshare,rpi-lcd-35" },
0178     { .compatible = "ozzmaker,piscreen" },
0179     {},
0180 };
0181 MODULE_DEVICE_TABLE(of, ili9486_of_match);
0182 
0183 static const struct spi_device_id ili9486_id[] = {
0184     { "ili9486", 0 },
0185     { }
0186 };
0187 MODULE_DEVICE_TABLE(spi, ili9486_id);
0188 
0189 static int ili9486_probe(struct spi_device *spi)
0190 {
0191     struct device *dev = &spi->dev;
0192     struct mipi_dbi_dev *dbidev;
0193     struct drm_device *drm;
0194     struct mipi_dbi *dbi;
0195     struct gpio_desc *dc;
0196     u32 rotation = 0;
0197     int ret;
0198 
0199     dbidev = devm_drm_dev_alloc(dev, &ili9486_driver,
0200                     struct mipi_dbi_dev, drm);
0201     if (IS_ERR(dbidev))
0202         return PTR_ERR(dbidev);
0203 
0204     dbi = &dbidev->dbi;
0205     drm = &dbidev->drm;
0206 
0207     dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
0208     if (IS_ERR(dbi->reset))
0209         return dev_err_probe(dev, PTR_ERR(dbi->reset), "Failed to get GPIO 'reset'\n");
0210 
0211     dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
0212     if (IS_ERR(dc))
0213         return dev_err_probe(dev, PTR_ERR(dc), "Failed to get GPIO 'dc'\n");
0214 
0215     dbidev->backlight = devm_of_find_backlight(dev);
0216     if (IS_ERR(dbidev->backlight))
0217         return PTR_ERR(dbidev->backlight);
0218 
0219     device_property_read_u32(dev, "rotation", &rotation);
0220 
0221     ret = mipi_dbi_spi_init(spi, dbi, dc);
0222     if (ret)
0223         return ret;
0224 
0225     dbi->command = waveshare_command;
0226     dbi->read_commands = NULL;
0227 
0228     ret = mipi_dbi_dev_init(dbidev, &waveshare_pipe_funcs,
0229                 &waveshare_mode, rotation);
0230     if (ret)
0231         return ret;
0232 
0233     drm_mode_config_reset(drm);
0234 
0235     ret = drm_dev_register(drm, 0);
0236     if (ret)
0237         return ret;
0238 
0239     spi_set_drvdata(spi, drm);
0240 
0241     drm_fbdev_generic_setup(drm, 0);
0242 
0243     return 0;
0244 }
0245 
0246 static void ili9486_remove(struct spi_device *spi)
0247 {
0248     struct drm_device *drm = spi_get_drvdata(spi);
0249 
0250     drm_dev_unplug(drm);
0251     drm_atomic_helper_shutdown(drm);
0252 }
0253 
0254 static void ili9486_shutdown(struct spi_device *spi)
0255 {
0256     drm_atomic_helper_shutdown(spi_get_drvdata(spi));
0257 }
0258 
0259 static struct spi_driver ili9486_spi_driver = {
0260     .driver = {
0261         .name = "ili9486",
0262         .of_match_table = ili9486_of_match,
0263     },
0264     .id_table = ili9486_id,
0265     .probe = ili9486_probe,
0266     .remove = ili9486_remove,
0267     .shutdown = ili9486_shutdown,
0268 };
0269 module_spi_driver(ili9486_spi_driver);
0270 
0271 MODULE_DESCRIPTION("Ilitek ILI9486 DRM driver");
0272 MODULE_AUTHOR("Kamlesh Gurudasani <kamlesh.gurudasani@gmail.com>");
0273 MODULE_LICENSE("GPL");