Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.19-rc8 232 lines 6.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * DRM driver for Ilitek ILI9341 panels 4 * 5 * Copyright 2018 David Lechner <david@lechnology.com> 6 * 7 * Based on mi0283qt.c: 8 * Copyright 2016 Noralf Trønnes 9 */ 10 11#include <linux/backlight.h> 12#include <linux/delay.h> 13#include <linux/gpio/consumer.h> 14#include <linux/module.h> 15#include <linux/property.h> 16#include <linux/spi/spi.h> 17 18#include <drm/drm_fb_helper.h> 19#include <drm/drm_gem_framebuffer_helper.h> 20#include <drm/drm_modeset_helper.h> 21#include <drm/tinydrm/mipi-dbi.h> 22#include <drm/tinydrm/tinydrm-helpers.h> 23#include <video/mipi_display.h> 24 25#define ILI9341_FRMCTR1 0xb1 26#define ILI9341_DISCTRL 0xb6 27#define ILI9341_ETMOD 0xb7 28 29#define ILI9341_PWCTRL1 0xc0 30#define ILI9341_PWCTRL2 0xc1 31#define ILI9341_VMCTRL1 0xc5 32#define ILI9341_VMCTRL2 0xc7 33#define ILI9341_PWCTRLA 0xcb 34#define ILI9341_PWCTRLB 0xcf 35 36#define ILI9341_PGAMCTRL 0xe0 37#define ILI9341_NGAMCTRL 0xe1 38#define ILI9341_DTCTRLA 0xe8 39#define ILI9341_DTCTRLB 0xea 40#define ILI9341_PWRSEQ 0xed 41 42#define ILI9341_EN3GAM 0xf2 43#define ILI9341_PUMPCTRL 0xf7 44 45#define ILI9341_MADCTL_BGR BIT(3) 46#define ILI9341_MADCTL_MV BIT(5) 47#define ILI9341_MADCTL_MX BIT(6) 48#define ILI9341_MADCTL_MY BIT(7) 49 50static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, 51 struct drm_crtc_state *crtc_state, 52 struct drm_plane_state *plane_state) 53{ 54 struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); 55 struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 56 u8 addr_mode; 57 int ret; 58 59 DRM_DEBUG_KMS("\n"); 60 61 ret = mipi_dbi_poweron_conditional_reset(mipi); 62 if (ret < 0) 63 return; 64 if (ret == 1) 65 goto out_enable; 66 67 mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF); 68 69 mipi_dbi_command(mipi, ILI9341_PWCTRLB, 0x00, 0xc1, 0x30); 70 mipi_dbi_command(mipi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81); 71 mipi_dbi_command(mipi, ILI9341_DTCTRLA, 0x85, 0x00, 0x78); 72 mipi_dbi_command(mipi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02); 73 mipi_dbi_command(mipi, ILI9341_PUMPCTRL, 0x20); 74 mipi_dbi_command(mipi, ILI9341_DTCTRLB, 0x00, 0x00); 75 76 /* Power Control */ 77 mipi_dbi_command(mipi, ILI9341_PWCTRL1, 0x23); 78 mipi_dbi_command(mipi, ILI9341_PWCTRL2, 0x10); 79 /* VCOM */ 80 mipi_dbi_command(mipi, ILI9341_VMCTRL1, 0x3e, 0x28); 81 mipi_dbi_command(mipi, ILI9341_VMCTRL2, 0x86); 82 83 /* Memory Access Control */ 84 mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); 85 86 /* Frame Rate */ 87 mipi_dbi_command(mipi, ILI9341_FRMCTR1, 0x00, 0x1b); 88 89 /* Gamma */ 90 mipi_dbi_command(mipi, ILI9341_EN3GAM, 0x00); 91 mipi_dbi_command(mipi, MIPI_DCS_SET_GAMMA_CURVE, 0x01); 92 mipi_dbi_command(mipi, ILI9341_PGAMCTRL, 93 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1, 94 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00); 95 mipi_dbi_command(mipi, ILI9341_NGAMCTRL, 96 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1, 97 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f); 98 99 /* DDRAM */ 100 mipi_dbi_command(mipi, ILI9341_ETMOD, 0x07); 101 102 /* Display */ 103 mipi_dbi_command(mipi, ILI9341_DISCTRL, 0x08, 0x82, 0x27, 0x00); 104 mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE); 105 msleep(100); 106 107 mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); 108 msleep(100); 109 110out_enable: 111 switch (mipi->rotation) { 112 default: 113 addr_mode = ILI9341_MADCTL_MX; 114 break; 115 case 90: 116 addr_mode = ILI9341_MADCTL_MV; 117 break; 118 case 180: 119 addr_mode = ILI9341_MADCTL_MY; 120 break; 121 case 270: 122 addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY | 123 ILI9341_MADCTL_MX; 124 break; 125 } 126 addr_mode |= ILI9341_MADCTL_BGR; 127 mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); 128 mipi_dbi_enable_flush(mipi, crtc_state, plane_state); 129} 130 131static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = { 132 .enable = yx240qv29_enable, 133 .disable = mipi_dbi_pipe_disable, 134 .update = tinydrm_display_pipe_update, 135 .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, 136}; 137 138static const struct drm_display_mode yx240qv29_mode = { 139 TINYDRM_MODE(240, 320, 37, 49), 140}; 141 142DEFINE_DRM_GEM_CMA_FOPS(ili9341_fops); 143 144static struct drm_driver ili9341_driver = { 145 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, 146 .fops = &ili9341_fops, 147 TINYDRM_GEM_DRIVER_OPS, 148 .debugfs_init = mipi_dbi_debugfs_init, 149 .name = "ili9341", 150 .desc = "Ilitek ILI9341", 151 .date = "20180514", 152 .major = 1, 153 .minor = 0, 154}; 155 156static const struct of_device_id ili9341_of_match[] = { 157 { .compatible = "adafruit,yx240qv29" }, 158 { } 159}; 160MODULE_DEVICE_TABLE(of, ili9341_of_match); 161 162static const struct spi_device_id ili9341_id[] = { 163 { "yx240qv29", 0 }, 164 { } 165}; 166MODULE_DEVICE_TABLE(spi, ili9341_id); 167 168static int ili9341_probe(struct spi_device *spi) 169{ 170 struct device *dev = &spi->dev; 171 struct mipi_dbi *mipi; 172 struct gpio_desc *dc; 173 u32 rotation = 0; 174 int ret; 175 176 mipi = devm_kzalloc(dev, sizeof(*mipi), GFP_KERNEL); 177 if (!mipi) 178 return -ENOMEM; 179 180 mipi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 181 if (IS_ERR(mipi->reset)) { 182 DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); 183 return PTR_ERR(mipi->reset); 184 } 185 186 dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW); 187 if (IS_ERR(dc)) { 188 DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n"); 189 return PTR_ERR(dc); 190 } 191 192 mipi->backlight = devm_of_find_backlight(dev); 193 if (IS_ERR(mipi->backlight)) 194 return PTR_ERR(mipi->backlight); 195 196 device_property_read_u32(dev, "rotation", &rotation); 197 198 ret = mipi_dbi_spi_init(spi, mipi, dc); 199 if (ret) 200 return ret; 201 202 ret = mipi_dbi_init(&spi->dev, mipi, &ili9341_pipe_funcs, 203 &ili9341_driver, &yx240qv29_mode, rotation); 204 if (ret) 205 return ret; 206 207 spi_set_drvdata(spi, mipi); 208 209 return devm_tinydrm_register(&mipi->tinydrm); 210} 211 212static void ili9341_shutdown(struct spi_device *spi) 213{ 214 struct mipi_dbi *mipi = spi_get_drvdata(spi); 215 216 tinydrm_shutdown(&mipi->tinydrm); 217} 218 219static struct spi_driver ili9341_spi_driver = { 220 .driver = { 221 .name = "ili9341", 222 .of_match_table = ili9341_of_match, 223 }, 224 .id_table = ili9341_id, 225 .probe = ili9341_probe, 226 .shutdown = ili9341_shutdown, 227}; 228module_spi_driver(ili9341_spi_driver); 229 230MODULE_DESCRIPTION("Ilitek ILI9341 DRM driver"); 231MODULE_AUTHOR("David Lechner <david@lechnology.com>"); 232MODULE_LICENSE("GPL");