projects/linux·blob master · refs

393 lines · 10.2 KiB

1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * DRM driver for Ilitek ILI9486 panels
4 *
5 * Copyright 2020 Kamlesh Gurudasani <[email protected]>
6 */
7
8#include <linux/backlight.h>
9#include <linux/delay.h>
10#include <linux/gpio/consumer.h>
11#include <linux/module.h>
12#include <linux/property.h>
13#include <linux/spi/spi.h>
14
15#include <video/mipi_display.h>
16
17#include <drm/clients/drm_client_setup.h>
18#include <drm/drm_atomic_helper.h>
19#include <drm/drm_drv.h>
20#include <drm/drm_fbdev_dma.h>
21#include <drm/drm_gem_atomic_helper.h>
22#include <drm/drm_gem_dma_helper.h>
23#include <drm/drm_managed.h>
24#include <drm/drm_mipi_dbi.h>
25#include <drm/drm_modeset_helper.h>
26#include <drm/drm_print.h>
27
28#define ILI9486_ITFCTR1 0xb0
29#define ILI9486_PWCTRL1 0xc2
30#define ILI9486_VMCTRL1 0xc5
31#define ILI9486_PGAMCTRL 0xe0
32#define ILI9486_NGAMCTRL 0xe1
33#define ILI9486_DGAMCTRL 0xe2
34#define ILI9486_MADCTL_BGR BIT(3)
35#define ILI9486_MADCTL_MV BIT(5)
36#define ILI9486_MADCTL_MX BIT(6)
37#define ILI9486_MADCTL_MY BIT(7)
38
39struct ili9486_device {
40 struct mipi_dbi_dev dbidev;
41
42 struct drm_plane plane;
43 struct drm_crtc crtc;
44 struct drm_encoder encoder;
45 struct drm_connector connector;
46};
47
48static struct ili9486_device *to_ili9486_device(struct drm_device *dev)
49{
50 return container_of(drm_to_mipi_dbi_dev(dev), struct ili9486_device, dbidev);
51}
52
53/*
54 * The PiScreen/waveshare rpi-lcd-35 has a SPI to 16-bit parallel bus converter
55 * in front of the display controller. This means that 8-bit values have to be
56 * transferred as 16-bit.
57 */
58static int waveshare_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par,
59 size_t num)
60{
61 struct spi_device *spi = mipi->spi;
62 unsigned int bpw = 8;
63 void *data = par;
64 u32 speed_hz;
65 int i, ret;
66 __be16 *buf;
67
68 buf = kmalloc(32 * sizeof(u16), GFP_KERNEL);
69 if (!buf)
70 return -ENOMEM;
71
72 /*
73 * The displays are Raspberry Pi HATs and connected to the 8-bit only
74 * SPI controller, so 16-bit command and parameters need byte swapping
75 * before being transferred as 8-bit on the big endian SPI bus.
76 */
77 buf[0] = cpu_to_be16(*cmd);
78 spi_bus_lock(spi->controller);
79 gpiod_set_value_cansleep(mipi->dc, 0);
80 speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 2);
81 ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, buf, 2);
82 spi_bus_unlock(spi->controller);
83 if (ret || !num)
84 goto free;
85
86 /* 8-bit configuration data, not 16-bit pixel data */
87 if (num <= 32) {
88 for (i = 0; i < num; i++)
89 buf[i] = cpu_to_be16(par[i]);
90 num *= 2;
91 data = buf;
92 }
93
94 /*
95 * Check whether pixel data bytes needs to be swapped or not
96 */
97 if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !mipi->swap_bytes)
98 bpw = 16;
99
100 spi_bus_lock(spi->controller);
101 gpiod_set_value_cansleep(mipi->dc, 1);
102 speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num);
103 ret = mipi_dbi_spi_transfer(spi, speed_hz, bpw, data, num);
104 spi_bus_unlock(spi->controller);
105 free:
106 kfree(buf);
107
108 return ret;
109}
110
111static const u32 ili9486_plane_formats[] = {
112 DRM_MIPI_DBI_PLANE_FORMATS,
113};
114
115static const u64 ili9486_plane_format_modifiers[] = {
116 DRM_MIPI_DBI_PLANE_FORMAT_MODIFIERS,
117};
118
119static const struct drm_plane_helper_funcs ili9486_plane_helper_funcs = {
120 DRM_MIPI_DBI_PLANE_HELPER_FUNCS,
121};
122
123static const struct drm_plane_funcs ili9486_plane_funcs = {
124 DRM_MIPI_DBI_PLANE_FUNCS,
125 .destroy = drm_plane_cleanup,
126};
127
128static void ili9486_crtc_helper_atomic_enable(struct drm_crtc *crtc,
129 struct drm_atomic_commit *state)
130{
131 struct drm_device *drm = crtc->dev;
132 struct ili9486_device *ili9486 = to_ili9486_device(drm);
133 struct mipi_dbi_dev *dbidev = &ili9486->dbidev;
134 struct mipi_dbi *dbi = &dbidev->dbi;
135 u8 addr_mode;
136 int ret, idx;
137
138 if (!drm_dev_enter(drm, &idx))
139 return;
140
141 DRM_DEBUG_KMS("\n");
142
143 ret = mipi_dbi_poweron_conditional_reset(dbidev);
144 if (ret < 0)
145 goto out_exit;
146 if (ret == 1)
147 goto out_enable;
148
149 mipi_dbi_command(dbi, ILI9486_ITFCTR1);
150 mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
151 msleep(250);
152
153 mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
154
155 mipi_dbi_command(dbi, ILI9486_PWCTRL1, 0x44);
156
157 mipi_dbi_command(dbi, ILI9486_VMCTRL1, 0x00, 0x00, 0x00, 0x00);
158
159 mipi_dbi_command(dbi, ILI9486_PGAMCTRL,
160 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98,
161 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x0);
162 mipi_dbi_command(dbi, ILI9486_NGAMCTRL,
163 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75,
164 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00);
165 mipi_dbi_command(dbi, ILI9486_DGAMCTRL,
166 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75,
167 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00);
168
169 mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
170 msleep(100);
171
172 out_enable:
173 switch (dbidev->rotation) {
174 case 90:
175 addr_mode = ILI9486_MADCTL_MY;
176 break;
177 case 180:
178 addr_mode = ILI9486_MADCTL_MV;
179 break;
180 case 270:
181 addr_mode = ILI9486_MADCTL_MX;
182 break;
183 default:
184 addr_mode = ILI9486_MADCTL_MV | ILI9486_MADCTL_MY |
185 ILI9486_MADCTL_MX;
186 break;
187 }
188 addr_mode |= ILI9486_MADCTL_BGR;
189 mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
190
191 backlight_enable(dbidev->backlight);
192 out_exit:
193 drm_dev_exit(idx);
194}
195
196static const struct drm_crtc_helper_funcs ili9486_crtc_helper_funcs = {
197 DRM_MIPI_DBI_CRTC_HELPER_FUNCS,
198 .atomic_enable = ili9486_crtc_helper_atomic_enable,
199};
200
201static const struct drm_crtc_funcs ili9486_crtc_funcs = {
202 DRM_MIPI_DBI_CRTC_FUNCS,
203 .destroy = drm_crtc_cleanup,
204};
205
206static const struct drm_encoder_funcs ili9486_encoder_funcs = {
207 .destroy = drm_encoder_cleanup,
208};
209
210static const struct drm_connector_helper_funcs ili9486_connector_helper_funcs = {
211 DRM_MIPI_DBI_CONNECTOR_HELPER_FUNCS,
212};
213
214static const struct drm_connector_funcs ili9486_connector_funcs = {
215 DRM_MIPI_DBI_CONNECTOR_FUNCS,
216 .destroy = drm_connector_cleanup,
217};
218
219static const struct drm_mode_config_helper_funcs ili9486_mode_config_helper_funcs = {
220 DRM_MIPI_DBI_MODE_CONFIG_HELPER_FUNCS,
221};
222
223static const struct drm_mode_config_funcs ili9486_mode_config_funcs = {
224 DRM_MIPI_DBI_MODE_CONFIG_FUNCS,
225};
226
227static const struct drm_display_mode waveshare_mode = {
228 DRM_SIMPLE_MODE(480, 320, 73, 49),
229};
230
231DEFINE_DRM_GEM_DMA_FOPS(ili9486_fops);
232
233static const struct drm_driver ili9486_driver = {
234 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
235 .fops = &ili9486_fops,
236 DRM_GEM_DMA_DRIVER_OPS_VMAP,
237 DRM_FBDEV_DMA_DRIVER_OPS,
238 .debugfs_init = mipi_dbi_debugfs_init,
239 .name = "ili9486",
240 .desc = "Ilitek ILI9486",
241 .major = 1,
242 .minor = 0,
243};
244
245static const struct of_device_id ili9486_of_match[] = {
246 { .compatible = "waveshare,rpi-lcd-35" },
247 { .compatible = "ozzmaker,piscreen" },
248 {},
249};
250MODULE_DEVICE_TABLE(of, ili9486_of_match);
251
252static const struct spi_device_id ili9486_id[] = {
253 { "ili9486", 0 },
254 { "rpi-lcd-35", 0 },
255 { "piscreen", 0 },
256 { }
257};
258MODULE_DEVICE_TABLE(spi, ili9486_id);
259
260static int ili9486_probe(struct spi_device *spi)
261{
262 struct device *dev = &spi->dev;
263 struct ili9486_device *ili9486;
264 struct mipi_dbi_dev *dbidev;
265 struct drm_device *drm;
266 struct mipi_dbi *dbi;
267 struct gpio_desc *dc;
268 struct drm_plane *plane;
269 struct drm_crtc *crtc;
270 struct drm_encoder *encoder;
271 struct drm_connector *connector;
272 u32 rotation = 0;
273 int ret;
274
275 ili9486 = devm_drm_dev_alloc(dev, &ili9486_driver, struct ili9486_device, dbidev.drm);
276 if (IS_ERR(ili9486))
277 return PTR_ERR(ili9486);
278 dbidev = &ili9486->dbidev;
279 dbi = &dbidev->dbi;
280 drm = &dbidev->drm;
281
282 dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
283 if (IS_ERR(dbi->reset))
284 return dev_err_probe(dev, PTR_ERR(dbi->reset), "Failed to get GPIO 'reset'\n");
285
286 dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
287 if (IS_ERR(dc))
288 return dev_err_probe(dev, PTR_ERR(dc), "Failed to get GPIO 'dc'\n");
289
290 dbidev->backlight = devm_of_find_backlight(dev);
291 if (IS_ERR(dbidev->backlight))
292 return PTR_ERR(dbidev->backlight);
293
294 device_property_read_u32(dev, "rotation", &rotation);
295
296 ret = mipi_dbi_spi_init(spi, dbi, dc);
297 if (ret)
298 return ret;
299
300 dbi->command = waveshare_command;
301 dbi->read_commands = NULL;
302
303 ret = drm_mipi_dbi_dev_init(dbidev, &waveshare_mode, ili9486_plane_formats[0],
304 rotation, 0);
305 if (ret)
306 return ret;
307
308 ret = drmm_mode_config_init(drm);
309 if (ret)
310 return ret;
311
312 drm->mode_config.min_width = dbidev->mode.hdisplay;
313 drm->mode_config.max_width = dbidev->mode.hdisplay;
314 drm->mode_config.min_height = dbidev->mode.vdisplay;
315 drm->mode_config.max_height = dbidev->mode.vdisplay;
316 drm->mode_config.funcs = &ili9486_mode_config_funcs;
317 drm->mode_config.preferred_depth = 16;
318 drm->mode_config.helper_private = &ili9486_mode_config_helper_funcs;
319
320 plane = &ili9486->plane;
321 ret = drm_universal_plane_init(drm, plane, 0, &ili9486_plane_funcs,
322 ili9486_plane_formats, ARRAY_SIZE(ili9486_plane_formats),
323 ili9486_plane_format_modifiers,
324 DRM_PLANE_TYPE_PRIMARY, NULL);
325 if (ret)
326 return ret;
327 drm_plane_helper_add(plane, &ili9486_plane_helper_funcs);
328 drm_plane_enable_fb_damage_clips(plane);
329
330 crtc = &ili9486->crtc;
331 ret = drm_crtc_init_with_planes(drm, crtc, plane, NULL, &ili9486_crtc_funcs, NULL);
332 if (ret)
333 return ret;
334 drm_crtc_helper_add(crtc, &ili9486_crtc_helper_funcs);
335
336 encoder = &ili9486->encoder;
337 ret = drm_encoder_init(drm, encoder, &ili9486_encoder_funcs, DRM_MODE_ENCODER_NONE, NULL);
338 if (ret)
339 return ret;
340 encoder->possible_crtcs = drm_crtc_mask(crtc);
341
342 connector = &ili9486->connector;
343 ret = drm_connector_init(drm, connector, &ili9486_connector_funcs,
344 DRM_MODE_CONNECTOR_SPI);
345 if (ret)
346 return ret;
347 drm_connector_helper_add(connector, &ili9486_connector_helper_funcs);
348
349 ret = drm_connector_attach_encoder(connector, encoder);
350 if (ret)
351 return ret;
352
353 drm_mode_config_reset(drm);
354
355 ret = drm_dev_register(drm, 0);
356 if (ret)
357 return ret;
358
359 spi_set_drvdata(spi, drm);
360
361 drm_client_setup(drm, NULL);
362
363 return 0;
364}
365
366static void ili9486_remove(struct spi_device *spi)
367{
368 struct drm_device *drm = spi_get_drvdata(spi);
369
370 drm_dev_unplug(drm);
371 drm_atomic_helper_shutdown(drm);
372}
373
374static void ili9486_shutdown(struct spi_device *spi)
375{
376 drm_atomic_helper_shutdown(spi_get_drvdata(spi));
377}
378
379static struct spi_driver ili9486_spi_driver = {
380 .driver = {
381 .name = "ili9486",
382 .of_match_table = ili9486_of_match,
383 },
384 .id_table = ili9486_id,
385 .probe = ili9486_probe,
386 .remove = ili9486_remove,
387 .shutdown = ili9486_shutdown,
388};
389module_spi_driver(ili9486_spi_driver);
390
391MODULE_DESCRIPTION("Ilitek ILI9486 DRM driver");
392MODULE_AUTHOR("Kamlesh Gurudasani <[email protected]>");
393MODULE_LICENSE("GPL");