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

drm/tinydrm: Add MIPI DBI support

Add support for MIPI DBI compatible controllers.
Interface type C option 1 and 3 are supported (SPI).

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Acked-by: Thierry Reding <treding@nvidia.com>

+1130
+12
Documentation/gpu/tinydrm.rst
··· 28 28 29 29 .. kernel-doc:: drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c 30 30 :export: 31 + 32 + MIPI DBI Compatible Controllers 33 + =============================== 34 + 35 + .. kernel-doc:: drivers/gpu/drm/tinydrm/mipi-dbi.c 36 + :doc: overview 37 + 38 + .. kernel-doc:: include/drm/tinydrm/mipi-dbi.h 39 + :internal: 40 + 41 + .. kernel-doc:: drivers/gpu/drm/tinydrm/mipi-dbi.c 42 + :export:
+3
drivers/gpu/drm/tinydrm/Kconfig
··· 8 8 help 9 9 Choose this option if you have a tinydrm supported display. 10 10 If M is selected the module will be called tinydrm. 11 + 12 + config TINYDRM_MIPI_DBI 13 + tristate
+3
drivers/gpu/drm/tinydrm/Makefile
··· 1 1 obj-$(CONFIG_DRM_TINYDRM) += core/ 2 + 3 + # Controllers 4 + obj-$(CONFIG_TINYDRM_MIPI_DBI) += mipi-dbi.o
+1005
drivers/gpu/drm/tinydrm/mipi-dbi.c
··· 1 + /* 2 + * MIPI Display Bus Interface (DBI) LCD controller support 3 + * 4 + * Copyright 2016 Noralf Trønnes 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + */ 11 + 12 + #include <drm/tinydrm/mipi-dbi.h> 13 + #include <drm/tinydrm/tinydrm-helpers.h> 14 + #include <linux/debugfs.h> 15 + #include <linux/dma-buf.h> 16 + #include <linux/gpio/consumer.h> 17 + #include <linux/module.h> 18 + #include <linux/regulator/consumer.h> 19 + #include <linux/spi/spi.h> 20 + #include <video/mipi_display.h> 21 + 22 + #define MIPI_DBI_MAX_SPI_READ_SPEED 2000000 /* 2MHz */ 23 + 24 + #define DCS_POWER_MODE_DISPLAY BIT(2) 25 + #define DCS_POWER_MODE_DISPLAY_NORMAL_MODE BIT(3) 26 + #define DCS_POWER_MODE_SLEEP_MODE BIT(4) 27 + #define DCS_POWER_MODE_PARTIAL_MODE BIT(5) 28 + #define DCS_POWER_MODE_IDLE_MODE BIT(6) 29 + #define DCS_POWER_MODE_RESERVED_MASK (BIT(0) | BIT(1) | BIT(7)) 30 + 31 + /** 32 + * DOC: overview 33 + * 34 + * This library provides helpers for MIPI Display Bus Interface (DBI) 35 + * compatible display controllers. 36 + * 37 + * Many controllers for tiny lcd displays are MIPI compliant and can use this 38 + * library. If a controller uses registers 0x2A and 0x2B to set the area to 39 + * update and uses register 0x2C to write to frame memory, it is most likely 40 + * MIPI compliant. 41 + * 42 + * Only MIPI Type 1 displays are supported since a full frame memory is needed. 43 + * 44 + * There are 3 MIPI DBI implementation types: 45 + * 46 + * A. Motorola 6800 type parallel bus 47 + * 48 + * B. Intel 8080 type parallel bus 49 + * 50 + * C. SPI type with 3 options: 51 + * 52 + * 1. 9-bit with the Data/Command signal as the ninth bit 53 + * 2. Same as above except it's sent as 16 bits 54 + * 3. 8-bit with the Data/Command signal as a separate D/CX pin 55 + * 56 + * Currently mipi_dbi only supports Type C options 1 and 3 with 57 + * mipi_dbi_spi_init(). 58 + */ 59 + 60 + #define MIPI_DBI_DEBUG_COMMAND(cmd, data, len) \ 61 + ({ \ 62 + if (!len) \ 63 + DRM_DEBUG_DRIVER("cmd=%02x\n", cmd); \ 64 + else if (len <= 32) \ 65 + DRM_DEBUG_DRIVER("cmd=%02x, par=%*ph\n", cmd, len, data); \ 66 + else \ 67 + DRM_DEBUG_DRIVER("cmd=%02x, len=%zu\n", cmd, len); \ 68 + }) 69 + 70 + static const u8 mipi_dbi_dcs_read_commands[] = { 71 + MIPI_DCS_GET_DISPLAY_ID, 72 + MIPI_DCS_GET_RED_CHANNEL, 73 + MIPI_DCS_GET_GREEN_CHANNEL, 74 + MIPI_DCS_GET_BLUE_CHANNEL, 75 + MIPI_DCS_GET_DISPLAY_STATUS, 76 + MIPI_DCS_GET_POWER_MODE, 77 + MIPI_DCS_GET_ADDRESS_MODE, 78 + MIPI_DCS_GET_PIXEL_FORMAT, 79 + MIPI_DCS_GET_DISPLAY_MODE, 80 + MIPI_DCS_GET_SIGNAL_MODE, 81 + MIPI_DCS_GET_DIAGNOSTIC_RESULT, 82 + MIPI_DCS_READ_MEMORY_START, 83 + MIPI_DCS_READ_MEMORY_CONTINUE, 84 + MIPI_DCS_GET_SCANLINE, 85 + MIPI_DCS_GET_DISPLAY_BRIGHTNESS, 86 + MIPI_DCS_GET_CONTROL_DISPLAY, 87 + MIPI_DCS_GET_POWER_SAVE, 88 + MIPI_DCS_GET_CABC_MIN_BRIGHTNESS, 89 + MIPI_DCS_READ_DDB_START, 90 + MIPI_DCS_READ_DDB_CONTINUE, 91 + 0, /* sentinel */ 92 + }; 93 + 94 + static bool mipi_dbi_command_is_read(struct mipi_dbi *mipi, u8 cmd) 95 + { 96 + unsigned int i; 97 + 98 + if (!mipi->read_commands) 99 + return false; 100 + 101 + for (i = 0; i < 0xff; i++) { 102 + if (!mipi->read_commands[i]) 103 + return false; 104 + if (cmd == mipi->read_commands[i]) 105 + return true; 106 + } 107 + 108 + return false; 109 + } 110 + 111 + /** 112 + * mipi_dbi_command_read - MIPI DCS read command 113 + * @mipi: MIPI structure 114 + * @cmd: Command 115 + * @val: Value read 116 + * 117 + * Send MIPI DCS read command to the controller. 118 + * 119 + * Returns: 120 + * Zero on success, negative error code on failure. 121 + */ 122 + int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val) 123 + { 124 + if (!mipi->read_commands) 125 + return -EACCES; 126 + 127 + if (!mipi_dbi_command_is_read(mipi, cmd)) 128 + return -EINVAL; 129 + 130 + return mipi_dbi_command_buf(mipi, cmd, val, 1); 131 + } 132 + EXPORT_SYMBOL(mipi_dbi_command_read); 133 + 134 + /** 135 + * mipi_dbi_command_buf - MIPI DCS command with parameter(s) in an array 136 + * @mipi: MIPI structure 137 + * @cmd: Command 138 + * @data: Parameter buffer 139 + * @len: Buffer length 140 + * 141 + * Returns: 142 + * Zero on success, negative error code on failure. 143 + */ 144 + int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len) 145 + { 146 + int ret; 147 + 148 + mutex_lock(&mipi->cmdlock); 149 + ret = mipi->command(mipi, cmd, data, len); 150 + mutex_unlock(&mipi->cmdlock); 151 + 152 + return ret; 153 + } 154 + EXPORT_SYMBOL(mipi_dbi_command_buf); 155 + 156 + static int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, 157 + struct drm_clip_rect *clip, bool swap) 158 + { 159 + struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 160 + struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; 161 + struct drm_format_name_buf format_name; 162 + void *src = cma_obj->vaddr; 163 + int ret = 0; 164 + 165 + if (import_attach) { 166 + ret = dma_buf_begin_cpu_access(import_attach->dmabuf, 167 + DMA_FROM_DEVICE); 168 + if (ret) 169 + return ret; 170 + } 171 + 172 + switch (fb->format->format) { 173 + case DRM_FORMAT_RGB565: 174 + if (swap) 175 + tinydrm_swab16(dst, src, fb, clip); 176 + else 177 + tinydrm_memcpy(dst, src, fb, clip); 178 + break; 179 + case DRM_FORMAT_XRGB8888: 180 + tinydrm_xrgb8888_to_rgb565(dst, src, fb, clip, swap); 181 + break; 182 + default: 183 + dev_err_once(fb->dev->dev, "Format is not supported: %s\n", 184 + drm_get_format_name(fb->format->format, 185 + &format_name)); 186 + return -EINVAL; 187 + } 188 + 189 + if (import_attach) 190 + ret = dma_buf_end_cpu_access(import_attach->dmabuf, 191 + DMA_FROM_DEVICE); 192 + return ret; 193 + } 194 + 195 + static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, 196 + struct drm_file *file_priv, 197 + unsigned int flags, unsigned int color, 198 + struct drm_clip_rect *clips, 199 + unsigned int num_clips) 200 + { 201 + struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 202 + struct tinydrm_device *tdev = fb->dev->dev_private; 203 + struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 204 + bool swap = mipi->swap_bytes; 205 + struct drm_clip_rect clip; 206 + int ret = 0; 207 + bool full; 208 + void *tr; 209 + 210 + mutex_lock(&tdev->dirty_lock); 211 + 212 + if (!mipi->enabled) 213 + goto out_unlock; 214 + 215 + /* fbdev can flush even when we're not interested */ 216 + if (tdev->pipe.plane.fb != fb) 217 + goto out_unlock; 218 + 219 + full = tinydrm_merge_clips(&clip, clips, num_clips, flags, 220 + fb->width, fb->height); 221 + 222 + DRM_DEBUG("Flushing [FB:%d] x1=%u, x2=%u, y1=%u, y2=%u\n", fb->base.id, 223 + clip.x1, clip.x2, clip.y1, clip.y2); 224 + 225 + if (!mipi->dc || !full || swap || 226 + fb->format->format == DRM_FORMAT_XRGB8888) { 227 + tr = mipi->tx_buf; 228 + ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, &clip, swap); 229 + if (ret) 230 + goto out_unlock; 231 + } else { 232 + tr = cma_obj->vaddr; 233 + } 234 + 235 + mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, 236 + (clip.x1 >> 8) & 0xFF, clip.x1 & 0xFF, 237 + (clip.x2 >> 8) & 0xFF, (clip.x2 - 1) & 0xFF); 238 + mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS, 239 + (clip.y1 >> 8) & 0xFF, clip.y1 & 0xFF, 240 + (clip.y2 >> 8) & 0xFF, (clip.y2 - 1) & 0xFF); 241 + 242 + ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, tr, 243 + (clip.x2 - clip.x1) * (clip.y2 - clip.y1) * 2); 244 + 245 + out_unlock: 246 + mutex_unlock(&tdev->dirty_lock); 247 + 248 + if (ret) 249 + dev_err_once(fb->dev->dev, "Failed to update display %d\n", 250 + ret); 251 + 252 + return ret; 253 + } 254 + 255 + static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = { 256 + .destroy = drm_fb_cma_destroy, 257 + .create_handle = drm_fb_cma_create_handle, 258 + .dirty = mipi_dbi_fb_dirty, 259 + }; 260 + 261 + /** 262 + * mipi_dbi_pipe_enable - MIPI DBI pipe enable helper 263 + * @pipe: Display pipe 264 + * @crtc_state: CRTC state 265 + * 266 + * This function enables backlight. Drivers can use this as their 267 + * &drm_simple_display_pipe_funcs->enable callback. 268 + */ 269 + void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe, 270 + struct drm_crtc_state *crtc_state) 271 + { 272 + struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); 273 + struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 274 + struct drm_framebuffer *fb = pipe->plane.fb; 275 + 276 + DRM_DEBUG_KMS("\n"); 277 + 278 + mipi->enabled = true; 279 + if (fb) 280 + fb->funcs->dirty(fb, NULL, 0, 0, NULL, 0); 281 + 282 + tinydrm_enable_backlight(mipi->backlight); 283 + } 284 + EXPORT_SYMBOL(mipi_dbi_pipe_enable); 285 + 286 + static void mipi_dbi_blank(struct mipi_dbi *mipi) 287 + { 288 + struct drm_device *drm = mipi->tinydrm.drm; 289 + u16 height = drm->mode_config.min_height; 290 + u16 width = drm->mode_config.min_width; 291 + size_t len = width * height * 2; 292 + 293 + memset(mipi->tx_buf, 0, len); 294 + 295 + mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, 0, 0, 296 + (width >> 8) & 0xFF, (width - 1) & 0xFF); 297 + mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS, 0, 0, 298 + (height >> 8) & 0xFF, (height - 1) & 0xFF); 299 + mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, 300 + (u8 *)mipi->tx_buf, len); 301 + } 302 + 303 + /** 304 + * mipi_dbi_pipe_disable - MIPI DBI pipe disable helper 305 + * @pipe: Display pipe 306 + * 307 + * This function disables backlight if present or if not the 308 + * display memory is blanked. Drivers can use this as their 309 + * &drm_simple_display_pipe_funcs->disable callback. 310 + */ 311 + void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) 312 + { 313 + struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); 314 + struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 315 + 316 + DRM_DEBUG_KMS("\n"); 317 + 318 + mipi->enabled = false; 319 + 320 + if (mipi->backlight) 321 + tinydrm_disable_backlight(mipi->backlight); 322 + else 323 + mipi_dbi_blank(mipi); 324 + } 325 + EXPORT_SYMBOL(mipi_dbi_pipe_disable); 326 + 327 + static const uint32_t mipi_dbi_formats[] = { 328 + DRM_FORMAT_RGB565, 329 + DRM_FORMAT_XRGB8888, 330 + }; 331 + 332 + /** 333 + * mipi_dbi_init - MIPI DBI initialization 334 + * @dev: Parent device 335 + * @mipi: &mipi_dbi structure to initialize 336 + * @pipe_funcs: Display pipe functions 337 + * @driver: DRM driver 338 + * @mode: Display mode 339 + * @rotation: Initial rotation in degrees Counter Clock Wise 340 + * 341 + * This function initializes a &mipi_dbi structure and it's underlying 342 + * @tinydrm_device. It also sets up the display pipeline. 343 + * 344 + * Supported formats: Native RGB565 and emulated XRGB8888. 345 + * 346 + * Objects created by this function will be automatically freed on driver 347 + * detach (devres). 348 + * 349 + * Returns: 350 + * Zero on success, negative error code on failure. 351 + */ 352 + int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi, 353 + const struct drm_simple_display_pipe_funcs *pipe_funcs, 354 + struct drm_driver *driver, 355 + const struct drm_display_mode *mode, unsigned int rotation) 356 + { 357 + size_t bufsize = mode->vdisplay * mode->hdisplay * sizeof(u16); 358 + struct tinydrm_device *tdev = &mipi->tinydrm; 359 + int ret; 360 + 361 + if (!mipi->command) 362 + return -EINVAL; 363 + 364 + mutex_init(&mipi->cmdlock); 365 + 366 + mipi->tx_buf = devm_kmalloc(dev, bufsize, GFP_KERNEL); 367 + if (!mipi->tx_buf) 368 + return -ENOMEM; 369 + 370 + ret = devm_tinydrm_init(dev, tdev, &mipi_dbi_fb_funcs, driver); 371 + if (ret) 372 + return ret; 373 + 374 + /* TODO: Maybe add DRM_MODE_CONNECTOR_SPI */ 375 + ret = tinydrm_display_pipe_init(tdev, pipe_funcs, 376 + DRM_MODE_CONNECTOR_VIRTUAL, 377 + mipi_dbi_formats, 378 + ARRAY_SIZE(mipi_dbi_formats), mode, 379 + rotation); 380 + if (ret) 381 + return ret; 382 + 383 + tdev->drm->mode_config.preferred_depth = 16; 384 + mipi->rotation = rotation; 385 + 386 + drm_mode_config_reset(tdev->drm); 387 + 388 + DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n", 389 + tdev->drm->mode_config.preferred_depth, rotation); 390 + 391 + return 0; 392 + } 393 + EXPORT_SYMBOL(mipi_dbi_init); 394 + 395 + /** 396 + * mipi_dbi_hw_reset - Hardware reset of controller 397 + * @mipi: MIPI DBI structure 398 + * 399 + * Reset controller if the &mipi_dbi->reset gpio is set. 400 + */ 401 + void mipi_dbi_hw_reset(struct mipi_dbi *mipi) 402 + { 403 + if (!mipi->reset) 404 + return; 405 + 406 + gpiod_set_value_cansleep(mipi->reset, 0); 407 + msleep(20); 408 + gpiod_set_value_cansleep(mipi->reset, 1); 409 + msleep(120); 410 + } 411 + EXPORT_SYMBOL(mipi_dbi_hw_reset); 412 + 413 + /** 414 + * mipi_dbi_display_is_on - Check if display is on 415 + * @mipi: MIPI DBI structure 416 + * 417 + * This function checks the Power Mode register (if readable) to see if 418 + * display output is turned on. This can be used to see if the bootloader 419 + * has already turned on the display avoiding flicker when the pipeline is 420 + * enabled. 421 + * 422 + * Returns: 423 + * true if the display can be verified to be on, false otherwise. 424 + */ 425 + bool mipi_dbi_display_is_on(struct mipi_dbi *mipi) 426 + { 427 + u8 val; 428 + 429 + if (mipi_dbi_command_read(mipi, MIPI_DCS_GET_POWER_MODE, &val)) 430 + return false; 431 + 432 + val &= ~DCS_POWER_MODE_RESERVED_MASK; 433 + 434 + if (val != (DCS_POWER_MODE_DISPLAY | 435 + DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE)) 436 + return false; 437 + 438 + DRM_DEBUG_DRIVER("Display is ON\n"); 439 + 440 + return true; 441 + } 442 + EXPORT_SYMBOL(mipi_dbi_display_is_on); 443 + 444 + #if IS_ENABLED(CONFIG_SPI) 445 + 446 + /* 447 + * Many controllers have a max speed of 10MHz, but can be pushed way beyond 448 + * that. Increase reliability by running pixel data at max speed and the rest 449 + * at 10MHz, preventing transfer glitches from messing up the init settings. 450 + */ 451 + static u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len) 452 + { 453 + if (len > 64) 454 + return 0; /* use default */ 455 + 456 + return min_t(u32, 10000000, spi->max_speed_hz); 457 + } 458 + 459 + /* 460 + * MIPI DBI Type C Option 1 461 + * 462 + * If the SPI controller doesn't have 9 bits per word support, 463 + * use blocks of 9 bytes to send 8x 9-bit words using a 8-bit SPI transfer. 464 + * Pad partial blocks with MIPI_DCS_NOP (zero). 465 + * This is how the D/C bit (x) is added: 466 + * x7654321 467 + * 0x765432 468 + * 10x76543 469 + * 210x7654 470 + * 3210x765 471 + * 43210x76 472 + * 543210x7 473 + * 6543210x 474 + * 76543210 475 + */ 476 + 477 + static int mipi_dbi_spi1e_transfer(struct mipi_dbi *mipi, int dc, 478 + const void *buf, size_t len, 479 + unsigned int bpw) 480 + { 481 + bool swap_bytes = (bpw == 16 && tinydrm_machine_little_endian()); 482 + size_t chunk, max_chunk = mipi->tx_buf9_len; 483 + struct spi_device *spi = mipi->spi; 484 + struct spi_transfer tr = { 485 + .tx_buf = mipi->tx_buf9, 486 + .bits_per_word = 8, 487 + }; 488 + struct spi_message m; 489 + const u8 *src = buf; 490 + int i, ret; 491 + u8 *dst; 492 + 493 + if (drm_debug & DRM_UT_DRIVER) 494 + pr_debug("[drm:%s] dc=%d, max_chunk=%zu, transfers:\n", 495 + __func__, dc, max_chunk); 496 + 497 + tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len); 498 + spi_message_init_with_transfers(&m, &tr, 1); 499 + 500 + if (!dc) { 501 + if (WARN_ON_ONCE(len != 1)) 502 + return -EINVAL; 503 + 504 + /* Command: pad no-op's (zeroes) at beginning of block */ 505 + dst = mipi->tx_buf9; 506 + memset(dst, 0, 9); 507 + dst[8] = *src; 508 + tr.len = 9; 509 + 510 + tinydrm_dbg_spi_message(spi, &m); 511 + 512 + return spi_sync(spi, &m); 513 + } 514 + 515 + /* max with room for adding one bit per byte */ 516 + max_chunk = max_chunk / 9 * 8; 517 + /* but no bigger than len */ 518 + max_chunk = min(max_chunk, len); 519 + /* 8 byte blocks */ 520 + max_chunk = max_t(size_t, 8, max_chunk & ~0x7); 521 + 522 + while (len) { 523 + size_t added = 0; 524 + 525 + chunk = min(len, max_chunk); 526 + len -= chunk; 527 + dst = mipi->tx_buf9; 528 + 529 + if (chunk < 8) { 530 + u8 val, carry = 0; 531 + 532 + /* Data: pad no-op's (zeroes) at end of block */ 533 + memset(dst, 0, 9); 534 + 535 + if (swap_bytes) { 536 + for (i = 1; i < (chunk + 1); i++) { 537 + val = src[1]; 538 + *dst++ = carry | BIT(8 - i) | (val >> i); 539 + carry = val << (8 - i); 540 + i++; 541 + val = src[0]; 542 + *dst++ = carry | BIT(8 - i) | (val >> i); 543 + carry = val << (8 - i); 544 + src += 2; 545 + } 546 + *dst++ = carry; 547 + } else { 548 + for (i = 1; i < (chunk + 1); i++) { 549 + val = *src++; 550 + *dst++ = carry | BIT(8 - i) | (val >> i); 551 + carry = val << (8 - i); 552 + } 553 + *dst++ = carry; 554 + } 555 + 556 + chunk = 8; 557 + added = 1; 558 + } else { 559 + for (i = 0; i < chunk; i += 8) { 560 + if (swap_bytes) { 561 + *dst++ = BIT(7) | (src[1] >> 1); 562 + *dst++ = (src[1] << 7) | BIT(6) | (src[0] >> 2); 563 + *dst++ = (src[0] << 6) | BIT(5) | (src[3] >> 3); 564 + *dst++ = (src[3] << 5) | BIT(4) | (src[2] >> 4); 565 + *dst++ = (src[2] << 4) | BIT(3) | (src[5] >> 5); 566 + *dst++ = (src[5] << 3) | BIT(2) | (src[4] >> 6); 567 + *dst++ = (src[4] << 2) | BIT(1) | (src[7] >> 7); 568 + *dst++ = (src[7] << 1) | BIT(0); 569 + *dst++ = src[6]; 570 + } else { 571 + *dst++ = BIT(7) | (src[0] >> 1); 572 + *dst++ = (src[0] << 7) | BIT(6) | (src[1] >> 2); 573 + *dst++ = (src[1] << 6) | BIT(5) | (src[2] >> 3); 574 + *dst++ = (src[2] << 5) | BIT(4) | (src[3] >> 4); 575 + *dst++ = (src[3] << 4) | BIT(3) | (src[4] >> 5); 576 + *dst++ = (src[4] << 3) | BIT(2) | (src[5] >> 6); 577 + *dst++ = (src[5] << 2) | BIT(1) | (src[6] >> 7); 578 + *dst++ = (src[6] << 1) | BIT(0); 579 + *dst++ = src[7]; 580 + } 581 + 582 + src += 8; 583 + added++; 584 + } 585 + } 586 + 587 + tr.len = chunk + added; 588 + 589 + tinydrm_dbg_spi_message(spi, &m); 590 + ret = spi_sync(spi, &m); 591 + if (ret) 592 + return ret; 593 + }; 594 + 595 + return 0; 596 + } 597 + 598 + static int mipi_dbi_spi1_transfer(struct mipi_dbi *mipi, int dc, 599 + const void *buf, size_t len, 600 + unsigned int bpw) 601 + { 602 + struct spi_device *spi = mipi->spi; 603 + struct spi_transfer tr = { 604 + .bits_per_word = 9, 605 + }; 606 + const u16 *src16 = buf; 607 + const u8 *src8 = buf; 608 + struct spi_message m; 609 + size_t max_chunk; 610 + u16 *dst16; 611 + int ret; 612 + 613 + if (!tinydrm_spi_bpw_supported(spi, 9)) 614 + return mipi_dbi_spi1e_transfer(mipi, dc, buf, len, bpw); 615 + 616 + tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len); 617 + max_chunk = mipi->tx_buf9_len; 618 + dst16 = mipi->tx_buf9; 619 + 620 + if (drm_debug & DRM_UT_DRIVER) 621 + pr_debug("[drm:%s] dc=%d, max_chunk=%zu, transfers:\n", 622 + __func__, dc, max_chunk); 623 + 624 + max_chunk = min(max_chunk / 2, len); 625 + 626 + spi_message_init_with_transfers(&m, &tr, 1); 627 + tr.tx_buf = dst16; 628 + 629 + while (len) { 630 + size_t chunk = min(len, max_chunk); 631 + unsigned int i; 632 + 633 + if (bpw == 16 && tinydrm_machine_little_endian()) { 634 + for (i = 0; i < (chunk * 2); i += 2) { 635 + dst16[i] = *src16 >> 8; 636 + dst16[i + 1] = *src16++ & 0xFF; 637 + if (dc) { 638 + dst16[i] |= 0x0100; 639 + dst16[i + 1] |= 0x0100; 640 + } 641 + } 642 + } else { 643 + for (i = 0; i < chunk; i++) { 644 + dst16[i] = *src8++; 645 + if (dc) 646 + dst16[i] |= 0x0100; 647 + } 648 + } 649 + 650 + tr.len = chunk; 651 + len -= chunk; 652 + 653 + tinydrm_dbg_spi_message(spi, &m); 654 + ret = spi_sync(spi, &m); 655 + if (ret) 656 + return ret; 657 + }; 658 + 659 + return 0; 660 + } 661 + 662 + static int mipi_dbi_typec1_command(struct mipi_dbi *mipi, u8 cmd, 663 + u8 *parameters, size_t num) 664 + { 665 + unsigned int bpw = (cmd == MIPI_DCS_WRITE_MEMORY_START) ? 16 : 8; 666 + int ret; 667 + 668 + if (mipi_dbi_command_is_read(mipi, cmd)) 669 + return -ENOTSUPP; 670 + 671 + MIPI_DBI_DEBUG_COMMAND(cmd, parameters, num); 672 + 673 + ret = mipi_dbi_spi1_transfer(mipi, 0, &cmd, 1, 8); 674 + if (ret || !num) 675 + return ret; 676 + 677 + return mipi_dbi_spi1_transfer(mipi, 1, parameters, num, bpw); 678 + } 679 + 680 + /* MIPI DBI Type C Option 3 */ 681 + 682 + static int mipi_dbi_typec3_command_read(struct mipi_dbi *mipi, u8 cmd, 683 + u8 *data, size_t len) 684 + { 685 + struct spi_device *spi = mipi->spi; 686 + u32 speed_hz = min_t(u32, MIPI_DBI_MAX_SPI_READ_SPEED, 687 + spi->max_speed_hz / 2); 688 + struct spi_transfer tr[2] = { 689 + { 690 + .speed_hz = speed_hz, 691 + .tx_buf = &cmd, 692 + .len = 1, 693 + }, { 694 + .speed_hz = speed_hz, 695 + .len = len, 696 + }, 697 + }; 698 + struct spi_message m; 699 + u8 *buf; 700 + int ret; 701 + 702 + if (!len) 703 + return -EINVAL; 704 + 705 + /* 706 + * Support non-standard 24-bit and 32-bit Nokia read commands which 707 + * start with a dummy clock, so we need to read an extra byte. 708 + */ 709 + if (cmd == MIPI_DCS_GET_DISPLAY_ID || 710 + cmd == MIPI_DCS_GET_DISPLAY_STATUS) { 711 + if (!(len == 3 || len == 4)) 712 + return -EINVAL; 713 + 714 + tr[1].len = len + 1; 715 + } 716 + 717 + buf = kmalloc(tr[1].len, GFP_KERNEL); 718 + if (!buf) 719 + return -ENOMEM; 720 + 721 + tr[1].rx_buf = buf; 722 + gpiod_set_value_cansleep(mipi->dc, 0); 723 + 724 + spi_message_init_with_transfers(&m, tr, ARRAY_SIZE(tr)); 725 + ret = spi_sync(spi, &m); 726 + if (ret) 727 + goto err_free; 728 + 729 + tinydrm_dbg_spi_message(spi, &m); 730 + 731 + if (tr[1].len == len) { 732 + memcpy(data, buf, len); 733 + } else { 734 + unsigned int i; 735 + 736 + for (i = 0; i < len; i++) 737 + data[i] = (buf[i] << 1) | !!(buf[i + 1] & BIT(7)); 738 + } 739 + 740 + MIPI_DBI_DEBUG_COMMAND(cmd, data, len); 741 + 742 + err_free: 743 + kfree(buf); 744 + 745 + return ret; 746 + } 747 + 748 + static int mipi_dbi_typec3_command(struct mipi_dbi *mipi, u8 cmd, 749 + u8 *par, size_t num) 750 + { 751 + struct spi_device *spi = mipi->spi; 752 + unsigned int bpw = 8; 753 + u32 speed_hz; 754 + int ret; 755 + 756 + if (mipi_dbi_command_is_read(mipi, cmd)) 757 + return mipi_dbi_typec3_command_read(mipi, cmd, par, num); 758 + 759 + MIPI_DBI_DEBUG_COMMAND(cmd, par, num); 760 + 761 + gpiod_set_value_cansleep(mipi->dc, 0); 762 + speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1); 763 + ret = tinydrm_spi_transfer(spi, speed_hz, NULL, 8, &cmd, 1); 764 + if (ret || !num) 765 + return ret; 766 + 767 + if (cmd == MIPI_DCS_WRITE_MEMORY_START && !mipi->swap_bytes) 768 + bpw = 16; 769 + 770 + gpiod_set_value_cansleep(mipi->dc, 1); 771 + speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num); 772 + 773 + return tinydrm_spi_transfer(spi, speed_hz, NULL, bpw, par, num); 774 + } 775 + 776 + /** 777 + * mipi_dbi_spi_init - Initialize MIPI DBI SPI interfaced controller 778 + * @spi: SPI device 779 + * @dc: D/C gpio (optional) 780 + * @mipi: &mipi_dbi structure to initialize 781 + * @pipe_funcs: Display pipe functions 782 + * @driver: DRM driver 783 + * @mode: Display mode 784 + * @rotation: Initial rotation in degrees Counter Clock Wise 785 + * 786 + * This function sets &mipi_dbi->command, enables &mipi->read_commands for the 787 + * usual read commands and initializes @mipi using mipi_dbi_init(). 788 + * 789 + * If @dc is set, a Type C Option 3 interface is assumed, if not 790 + * Type C Option 1. 791 + * 792 + * If the SPI master driver doesn't support the necessary bits per word, 793 + * the following transformation is used: 794 + * 795 + * - 9-bit: reorder buffer as 9x 8-bit words, padded with no-op command. 796 + * - 16-bit: if big endian send as 8-bit, if little endian swap bytes 797 + * 798 + * Returns: 799 + * Zero on success, negative error code on failure. 800 + */ 801 + int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi, 802 + struct gpio_desc *dc, 803 + const struct drm_simple_display_pipe_funcs *pipe_funcs, 804 + struct drm_driver *driver, 805 + const struct drm_display_mode *mode, 806 + unsigned int rotation) 807 + { 808 + size_t tx_size = tinydrm_spi_max_transfer_size(spi, 0); 809 + struct device *dev = &spi->dev; 810 + int ret; 811 + 812 + if (tx_size < 16) { 813 + DRM_ERROR("SPI transmit buffer too small: %zu\n", tx_size); 814 + return -EINVAL; 815 + } 816 + 817 + /* 818 + * Even though it's not the SPI device that does DMA (the master does), 819 + * the dma mask is necessary for the dma_alloc_wc() in 820 + * drm_gem_cma_create(). The dma_addr returned will be a physical 821 + * adddress which might be different from the bus address, but this is 822 + * not a problem since the address will not be used. 823 + * The virtual address is used in the transfer and the SPI core 824 + * re-maps it on the SPI master device using the DMA streaming API 825 + * (spi_map_buf()). 826 + */ 827 + if (!dev->coherent_dma_mask) { 828 + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); 829 + if (ret) { 830 + dev_warn(dev, "Failed to set dma mask %d\n", ret); 831 + return ret; 832 + } 833 + } 834 + 835 + mipi->spi = spi; 836 + mipi->read_commands = mipi_dbi_dcs_read_commands; 837 + 838 + if (dc) { 839 + mipi->command = mipi_dbi_typec3_command; 840 + mipi->dc = dc; 841 + if (tinydrm_machine_little_endian() && 842 + !tinydrm_spi_bpw_supported(spi, 16)) 843 + mipi->swap_bytes = true; 844 + } else { 845 + mipi->command = mipi_dbi_typec1_command; 846 + mipi->tx_buf9_len = tx_size; 847 + mipi->tx_buf9 = devm_kmalloc(dev, tx_size, GFP_KERNEL); 848 + if (!mipi->tx_buf9) 849 + return -ENOMEM; 850 + } 851 + 852 + return mipi_dbi_init(dev, mipi, pipe_funcs, driver, mode, rotation); 853 + } 854 + EXPORT_SYMBOL(mipi_dbi_spi_init); 855 + 856 + #endif /* CONFIG_SPI */ 857 + 858 + #ifdef CONFIG_DEBUG_FS 859 + 860 + static ssize_t mipi_dbi_debugfs_command_write(struct file *file, 861 + const char __user *ubuf, 862 + size_t count, loff_t *ppos) 863 + { 864 + struct seq_file *m = file->private_data; 865 + struct mipi_dbi *mipi = m->private; 866 + u8 val, cmd, parameters[64]; 867 + char *buf, *pos, *token; 868 + unsigned int i; 869 + int ret; 870 + 871 + buf = memdup_user_nul(ubuf, count); 872 + if (IS_ERR(buf)) 873 + return PTR_ERR(buf); 874 + 875 + /* strip trailing whitespace */ 876 + for (i = count - 1; i > 0; i--) 877 + if (isspace(buf[i])) 878 + buf[i] = '\0'; 879 + else 880 + break; 881 + i = 0; 882 + pos = buf; 883 + while (pos) { 884 + token = strsep(&pos, " "); 885 + if (!token) { 886 + ret = -EINVAL; 887 + goto err_free; 888 + } 889 + 890 + ret = kstrtou8(token, 16, &val); 891 + if (ret < 0) 892 + goto err_free; 893 + 894 + if (token == buf) 895 + cmd = val; 896 + else 897 + parameters[i++] = val; 898 + 899 + if (i == 64) { 900 + ret = -E2BIG; 901 + goto err_free; 902 + } 903 + } 904 + 905 + ret = mipi_dbi_command_buf(mipi, cmd, parameters, i); 906 + 907 + err_free: 908 + kfree(buf); 909 + 910 + return ret < 0 ? ret : count; 911 + } 912 + 913 + static int mipi_dbi_debugfs_command_show(struct seq_file *m, void *unused) 914 + { 915 + struct mipi_dbi *mipi = m->private; 916 + u8 cmd, val[4]; 917 + size_t len, i; 918 + int ret; 919 + 920 + for (cmd = 0; cmd < 255; cmd++) { 921 + if (!mipi_dbi_command_is_read(mipi, cmd)) 922 + continue; 923 + 924 + switch (cmd) { 925 + case MIPI_DCS_READ_MEMORY_START: 926 + case MIPI_DCS_READ_MEMORY_CONTINUE: 927 + len = 2; 928 + break; 929 + case MIPI_DCS_GET_DISPLAY_ID: 930 + len = 3; 931 + break; 932 + case MIPI_DCS_GET_DISPLAY_STATUS: 933 + len = 4; 934 + break; 935 + default: 936 + len = 1; 937 + break; 938 + } 939 + 940 + seq_printf(m, "%02x: ", cmd); 941 + ret = mipi_dbi_command_buf(mipi, cmd, val, len); 942 + if (ret) { 943 + seq_puts(m, "XX\n"); 944 + continue; 945 + } 946 + 947 + for (i = 0; i < len; i++) 948 + seq_printf(m, "%02x", val[i]); 949 + seq_puts(m, "\n"); 950 + } 951 + 952 + return 0; 953 + } 954 + 955 + static int mipi_dbi_debugfs_command_open(struct inode *inode, 956 + struct file *file) 957 + { 958 + return single_open(file, mipi_dbi_debugfs_command_show, 959 + inode->i_private); 960 + } 961 + 962 + static const struct file_operations mipi_dbi_debugfs_command_fops = { 963 + .owner = THIS_MODULE, 964 + .open = mipi_dbi_debugfs_command_open, 965 + .read = seq_read, 966 + .llseek = seq_lseek, 967 + .release = single_release, 968 + .write = mipi_dbi_debugfs_command_write, 969 + }; 970 + 971 + static const struct drm_info_list mipi_dbi_debugfs_list[] = { 972 + { "fb", drm_fb_cma_debugfs_show, 0 }, 973 + }; 974 + 975 + /** 976 + * mipi_dbi_debugfs_init - Create debugfs entries 977 + * @minor: DRM minor 978 + * 979 + * This function creates a 'command' debugfs file for sending commands to the 980 + * controller or getting the read command values. 981 + * Drivers can use this as their &drm_driver->debugfs_init callback. 982 + * 983 + * Returns: 984 + * Zero on success, negative error code on failure. 985 + */ 986 + int mipi_dbi_debugfs_init(struct drm_minor *minor) 987 + { 988 + struct tinydrm_device *tdev = minor->dev->dev_private; 989 + struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); 990 + umode_t mode = S_IFREG | S_IWUSR; 991 + 992 + if (mipi->read_commands) 993 + mode |= S_IRUGO; 994 + debugfs_create_file("command", mode, minor->debugfs_root, mipi, 995 + &mipi_dbi_debugfs_command_fops); 996 + 997 + return drm_debugfs_create_files(mipi_dbi_debugfs_list, 998 + ARRAY_SIZE(mipi_dbi_debugfs_list), 999 + minor->debugfs_root, minor); 1000 + } 1001 + EXPORT_SYMBOL(mipi_dbi_debugfs_init); 1002 + 1003 + #endif 1004 + 1005 + MODULE_LICENSE("GPL");
+107
include/drm/tinydrm/mipi-dbi.h
··· 1 + /* 2 + * MIPI Display Bus Interface (DBI) LCD controller support 3 + * 4 + * Copyright 2016 Noralf Trønnes 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + */ 11 + 12 + #ifndef __LINUX_MIPI_DBI_H 13 + #define __LINUX_MIPI_DBI_H 14 + 15 + #include <drm/tinydrm/tinydrm.h> 16 + 17 + struct spi_device; 18 + struct gpio_desc; 19 + struct regulator; 20 + 21 + /** 22 + * struct mipi_dbi - MIPI DBI controller 23 + * @tinydrm: tinydrm base 24 + * @spi: SPI device 25 + * @enabled: Pipeline is enabled 26 + * @cmdlock: Command lock 27 + * @command: Bus specific callback executing commands. 28 + * @read_commands: Array of read commands terminated by a zero entry. 29 + * Reading is disabled if this is NULL. 30 + * @dc: Optional D/C gpio. 31 + * @tx_buf: Buffer used for transfer (copy clip rect area) 32 + * @tx_buf9: Buffer used for Option 1 9-bit conversion 33 + * @tx_buf9_len: Size of tx_buf9. 34 + * @swap_bytes: Swap bytes in buffer before transfer 35 + * @reset: Optional reset gpio 36 + * @rotation: initial rotation in degrees Counter Clock Wise 37 + * @backlight: backlight device (optional) 38 + * @regulator: power regulator (optional) 39 + */ 40 + struct mipi_dbi { 41 + struct tinydrm_device tinydrm; 42 + struct spi_device *spi; 43 + bool enabled; 44 + struct mutex cmdlock; 45 + int (*command)(struct mipi_dbi *mipi, u8 cmd, u8 *param, size_t num); 46 + const u8 *read_commands; 47 + struct gpio_desc *dc; 48 + u16 *tx_buf; 49 + void *tx_buf9; 50 + size_t tx_buf9_len; 51 + bool swap_bytes; 52 + struct gpio_desc *reset; 53 + unsigned int rotation; 54 + struct backlight_device *backlight; 55 + struct regulator *regulator; 56 + }; 57 + 58 + static inline struct mipi_dbi * 59 + mipi_dbi_from_tinydrm(struct tinydrm_device *tdev) 60 + { 61 + return container_of(tdev, struct mipi_dbi, tinydrm); 62 + } 63 + 64 + int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi, 65 + struct gpio_desc *dc, 66 + const struct drm_simple_display_pipe_funcs *pipe_funcs, 67 + struct drm_driver *driver, 68 + const struct drm_display_mode *mode, 69 + unsigned int rotation); 70 + int mipi_dbi_init(struct device *dev, struct mipi_dbi *mipi, 71 + const struct drm_simple_display_pipe_funcs *pipe_funcs, 72 + struct drm_driver *driver, 73 + const struct drm_display_mode *mode, unsigned int rotation); 74 + void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe, 75 + struct drm_crtc_state *crtc_state); 76 + void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe); 77 + void mipi_dbi_hw_reset(struct mipi_dbi *mipi); 78 + bool mipi_dbi_display_is_on(struct mipi_dbi *mipi); 79 + 80 + int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val); 81 + int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len); 82 + 83 + /** 84 + * mipi_dbi_command - MIPI DCS command with optional parameter(s) 85 + * @mipi: MIPI structure 86 + * @cmd: Command 87 + * @seq...: Optional parameter(s) 88 + * 89 + * Send MIPI DCS command to the controller. Use mipi_dbi_command_read() for 90 + * get/read. 91 + * 92 + * Returns: 93 + * Zero on success, negative error code on failure. 94 + */ 95 + #define mipi_dbi_command(mipi, cmd, seq...) \ 96 + ({ \ 97 + u8 d[] = { seq }; \ 98 + mipi_dbi_command_buf(mipi, cmd, d, ARRAY_SIZE(d)); \ 99 + }) 100 + 101 + #ifdef CONFIG_DEBUG_FS 102 + int mipi_dbi_debugfs_init(struct drm_minor *minor); 103 + #else 104 + #define mipi_dbi_debugfs_init NULL 105 + #endif 106 + 107 + #endif /* __LINUX_MIPI_DBI_H */