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 v5.5-rc4 449 lines 14 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2017 Free Electrons 4 */ 5 6#include <linux/backlight.h> 7#include <linux/delay.h> 8#include <linux/gpio/consumer.h> 9#include <linux/module.h> 10#include <linux/regulator/consumer.h> 11#include <linux/spi/spi.h> 12 13#include <video/mipi_display.h> 14 15#include <drm/drm_device.h> 16#include <drm/drm_modes.h> 17#include <drm/drm_panel.h> 18 19#define ST7789V_COLMOD_RGB_FMT_18BITS (6 << 4) 20#define ST7789V_COLMOD_CTRL_FMT_18BITS (6 << 0) 21 22#define ST7789V_RAMCTRL_CMD 0xb0 23#define ST7789V_RAMCTRL_RM_RGB BIT(4) 24#define ST7789V_RAMCTRL_DM_RGB BIT(0) 25#define ST7789V_RAMCTRL_MAGIC (3 << 6) 26#define ST7789V_RAMCTRL_EPF(n) (((n) & 3) << 4) 27 28#define ST7789V_RGBCTRL_CMD 0xb1 29#define ST7789V_RGBCTRL_WO BIT(7) 30#define ST7789V_RGBCTRL_RCM(n) (((n) & 3) << 5) 31#define ST7789V_RGBCTRL_VSYNC_HIGH BIT(3) 32#define ST7789V_RGBCTRL_HSYNC_HIGH BIT(2) 33#define ST7789V_RGBCTRL_PCLK_HIGH BIT(1) 34#define ST7789V_RGBCTRL_VBP(n) ((n) & 0x7f) 35#define ST7789V_RGBCTRL_HBP(n) ((n) & 0x1f) 36 37#define ST7789V_PORCTRL_CMD 0xb2 38#define ST7789V_PORCTRL_IDLE_BP(n) (((n) & 0xf) << 4) 39#define ST7789V_PORCTRL_IDLE_FP(n) ((n) & 0xf) 40#define ST7789V_PORCTRL_PARTIAL_BP(n) (((n) & 0xf) << 4) 41#define ST7789V_PORCTRL_PARTIAL_FP(n) ((n) & 0xf) 42 43#define ST7789V_GCTRL_CMD 0xb7 44#define ST7789V_GCTRL_VGHS(n) (((n) & 7) << 4) 45#define ST7789V_GCTRL_VGLS(n) ((n) & 7) 46 47#define ST7789V_VCOMS_CMD 0xbb 48 49#define ST7789V_LCMCTRL_CMD 0xc0 50#define ST7789V_LCMCTRL_XBGR BIT(5) 51#define ST7789V_LCMCTRL_XMX BIT(3) 52#define ST7789V_LCMCTRL_XMH BIT(2) 53 54#define ST7789V_VDVVRHEN_CMD 0xc2 55#define ST7789V_VDVVRHEN_CMDEN BIT(0) 56 57#define ST7789V_VRHS_CMD 0xc3 58 59#define ST7789V_VDVS_CMD 0xc4 60 61#define ST7789V_FRCTRL2_CMD 0xc6 62 63#define ST7789V_PWCTRL1_CMD 0xd0 64#define ST7789V_PWCTRL1_MAGIC 0xa4 65#define ST7789V_PWCTRL1_AVDD(n) (((n) & 3) << 6) 66#define ST7789V_PWCTRL1_AVCL(n) (((n) & 3) << 4) 67#define ST7789V_PWCTRL1_VDS(n) ((n) & 3) 68 69#define ST7789V_PVGAMCTRL_CMD 0xe0 70#define ST7789V_PVGAMCTRL_JP0(n) (((n) & 3) << 4) 71#define ST7789V_PVGAMCTRL_JP1(n) (((n) & 3) << 4) 72#define ST7789V_PVGAMCTRL_VP0(n) ((n) & 0xf) 73#define ST7789V_PVGAMCTRL_VP1(n) ((n) & 0x3f) 74#define ST7789V_PVGAMCTRL_VP2(n) ((n) & 0x3f) 75#define ST7789V_PVGAMCTRL_VP4(n) ((n) & 0x1f) 76#define ST7789V_PVGAMCTRL_VP6(n) ((n) & 0x1f) 77#define ST7789V_PVGAMCTRL_VP13(n) ((n) & 0xf) 78#define ST7789V_PVGAMCTRL_VP20(n) ((n) & 0x7f) 79#define ST7789V_PVGAMCTRL_VP27(n) ((n) & 7) 80#define ST7789V_PVGAMCTRL_VP36(n) (((n) & 7) << 4) 81#define ST7789V_PVGAMCTRL_VP43(n) ((n) & 0x7f) 82#define ST7789V_PVGAMCTRL_VP50(n) ((n) & 0xf) 83#define ST7789V_PVGAMCTRL_VP57(n) ((n) & 0x1f) 84#define ST7789V_PVGAMCTRL_VP59(n) ((n) & 0x1f) 85#define ST7789V_PVGAMCTRL_VP61(n) ((n) & 0x3f) 86#define ST7789V_PVGAMCTRL_VP62(n) ((n) & 0x3f) 87#define ST7789V_PVGAMCTRL_VP63(n) (((n) & 0xf) << 4) 88 89#define ST7789V_NVGAMCTRL_CMD 0xe1 90#define ST7789V_NVGAMCTRL_JN0(n) (((n) & 3) << 4) 91#define ST7789V_NVGAMCTRL_JN1(n) (((n) & 3) << 4) 92#define ST7789V_NVGAMCTRL_VN0(n) ((n) & 0xf) 93#define ST7789V_NVGAMCTRL_VN1(n) ((n) & 0x3f) 94#define ST7789V_NVGAMCTRL_VN2(n) ((n) & 0x3f) 95#define ST7789V_NVGAMCTRL_VN4(n) ((n) & 0x1f) 96#define ST7789V_NVGAMCTRL_VN6(n) ((n) & 0x1f) 97#define ST7789V_NVGAMCTRL_VN13(n) ((n) & 0xf) 98#define ST7789V_NVGAMCTRL_VN20(n) ((n) & 0x7f) 99#define ST7789V_NVGAMCTRL_VN27(n) ((n) & 7) 100#define ST7789V_NVGAMCTRL_VN36(n) (((n) & 7) << 4) 101#define ST7789V_NVGAMCTRL_VN43(n) ((n) & 0x7f) 102#define ST7789V_NVGAMCTRL_VN50(n) ((n) & 0xf) 103#define ST7789V_NVGAMCTRL_VN57(n) ((n) & 0x1f) 104#define ST7789V_NVGAMCTRL_VN59(n) ((n) & 0x1f) 105#define ST7789V_NVGAMCTRL_VN61(n) ((n) & 0x3f) 106#define ST7789V_NVGAMCTRL_VN62(n) ((n) & 0x3f) 107#define ST7789V_NVGAMCTRL_VN63(n) (((n) & 0xf) << 4) 108 109#define ST7789V_TEST(val, func) \ 110 do { \ 111 if ((val = (func))) \ 112 return val; \ 113 } while (0) 114 115struct st7789v { 116 struct drm_panel panel; 117 struct spi_device *spi; 118 struct gpio_desc *reset; 119 struct backlight_device *backlight; 120 struct regulator *power; 121}; 122 123enum st7789v_prefix { 124 ST7789V_COMMAND = 0, 125 ST7789V_DATA = 1, 126}; 127 128static inline struct st7789v *panel_to_st7789v(struct drm_panel *panel) 129{ 130 return container_of(panel, struct st7789v, panel); 131} 132 133static int st7789v_spi_write(struct st7789v *ctx, enum st7789v_prefix prefix, 134 u8 data) 135{ 136 struct spi_transfer xfer = { }; 137 struct spi_message msg; 138 u16 txbuf = ((prefix & 1) << 8) | data; 139 140 spi_message_init(&msg); 141 142 xfer.tx_buf = &txbuf; 143 xfer.bits_per_word = 9; 144 xfer.len = sizeof(txbuf); 145 146 spi_message_add_tail(&xfer, &msg); 147 return spi_sync(ctx->spi, &msg); 148} 149 150static int st7789v_write_command(struct st7789v *ctx, u8 cmd) 151{ 152 return st7789v_spi_write(ctx, ST7789V_COMMAND, cmd); 153} 154 155static int st7789v_write_data(struct st7789v *ctx, u8 cmd) 156{ 157 return st7789v_spi_write(ctx, ST7789V_DATA, cmd); 158} 159 160static const struct drm_display_mode default_mode = { 161 .clock = 7000, 162 .hdisplay = 240, 163 .hsync_start = 240 + 38, 164 .hsync_end = 240 + 38 + 10, 165 .htotal = 240 + 38 + 10 + 10, 166 .vdisplay = 320, 167 .vsync_start = 320 + 8, 168 .vsync_end = 320 + 8 + 4, 169 .vtotal = 320 + 8 + 4 + 4, 170 .vrefresh = 60, 171}; 172 173static int st7789v_get_modes(struct drm_panel *panel) 174{ 175 struct drm_connector *connector = panel->connector; 176 struct drm_display_mode *mode; 177 178 mode = drm_mode_duplicate(panel->drm, &default_mode); 179 if (!mode) { 180 dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n", 181 default_mode.hdisplay, default_mode.vdisplay, 182 default_mode.vrefresh); 183 return -ENOMEM; 184 } 185 186 drm_mode_set_name(mode); 187 188 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 189 drm_mode_probed_add(connector, mode); 190 191 panel->connector->display_info.width_mm = 61; 192 panel->connector->display_info.height_mm = 103; 193 194 return 1; 195} 196 197static int st7789v_prepare(struct drm_panel *panel) 198{ 199 struct st7789v *ctx = panel_to_st7789v(panel); 200 int ret; 201 202 ret = regulator_enable(ctx->power); 203 if (ret) 204 return ret; 205 206 gpiod_set_value(ctx->reset, 1); 207 msleep(30); 208 gpiod_set_value(ctx->reset, 0); 209 msleep(120); 210 211 ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_EXIT_SLEEP_MODE)); 212 213 /* We need to wait 120ms after a sleep out command */ 214 msleep(120); 215 216 ST7789V_TEST(ret, st7789v_write_command(ctx, 217 MIPI_DCS_SET_ADDRESS_MODE)); 218 ST7789V_TEST(ret, st7789v_write_data(ctx, 0)); 219 220 ST7789V_TEST(ret, st7789v_write_command(ctx, 221 MIPI_DCS_SET_PIXEL_FORMAT)); 222 ST7789V_TEST(ret, st7789v_write_data(ctx, 223 (MIPI_DCS_PIXEL_FMT_18BIT << 4) | 224 (MIPI_DCS_PIXEL_FMT_18BIT))); 225 226 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_PORCTRL_CMD)); 227 ST7789V_TEST(ret, st7789v_write_data(ctx, 0xc)); 228 ST7789V_TEST(ret, st7789v_write_data(ctx, 0xc)); 229 ST7789V_TEST(ret, st7789v_write_data(ctx, 0)); 230 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PORCTRL_IDLE_BP(3) | 231 ST7789V_PORCTRL_IDLE_FP(3))); 232 ST7789V_TEST(ret, st7789v_write_data(ctx, 233 ST7789V_PORCTRL_PARTIAL_BP(3) | 234 ST7789V_PORCTRL_PARTIAL_FP(3))); 235 236 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_GCTRL_CMD)); 237 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_GCTRL_VGLS(5) | 238 ST7789V_GCTRL_VGHS(3))); 239 240 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VCOMS_CMD)); 241 ST7789V_TEST(ret, st7789v_write_data(ctx, 0x2b)); 242 243 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_LCMCTRL_CMD)); 244 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_LCMCTRL_XMH | 245 ST7789V_LCMCTRL_XMX | 246 ST7789V_LCMCTRL_XBGR)); 247 248 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VDVVRHEN_CMD)); 249 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_VDVVRHEN_CMDEN)); 250 251 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VRHS_CMD)); 252 ST7789V_TEST(ret, st7789v_write_data(ctx, 0xf)); 253 254 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_VDVS_CMD)); 255 ST7789V_TEST(ret, st7789v_write_data(ctx, 0x20)); 256 257 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_FRCTRL2_CMD)); 258 ST7789V_TEST(ret, st7789v_write_data(ctx, 0xf)); 259 260 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_PWCTRL1_CMD)); 261 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PWCTRL1_MAGIC)); 262 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PWCTRL1_AVDD(2) | 263 ST7789V_PWCTRL1_AVCL(2) | 264 ST7789V_PWCTRL1_VDS(1))); 265 266 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_PVGAMCTRL_CMD)); 267 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP63(0xd))); 268 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP1(0xca))); 269 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP2(0xe))); 270 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP4(8))); 271 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP6(9))); 272 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP13(7))); 273 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP20(0x2d))); 274 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP27(0xb) | 275 ST7789V_PVGAMCTRL_VP36(3))); 276 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP43(0x3d))); 277 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_JP1(3) | 278 ST7789V_PVGAMCTRL_VP50(4))); 279 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP57(0xa))); 280 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP59(0xa))); 281 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP61(0x1b))); 282 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_PVGAMCTRL_VP62(0x28))); 283 284 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_NVGAMCTRL_CMD)); 285 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN63(0xd))); 286 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN1(0xca))); 287 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN2(0xf))); 288 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN4(8))); 289 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN6(8))); 290 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN13(7))); 291 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN20(0x2e))); 292 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN27(0xc) | 293 ST7789V_NVGAMCTRL_VN36(5))); 294 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN43(0x40))); 295 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_JN1(3) | 296 ST7789V_NVGAMCTRL_VN50(4))); 297 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN57(9))); 298 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN59(0xb))); 299 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN61(0x1b))); 300 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_NVGAMCTRL_VN62(0x28))); 301 302 ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_ENTER_INVERT_MODE)); 303 304 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_RAMCTRL_CMD)); 305 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RAMCTRL_DM_RGB | 306 ST7789V_RAMCTRL_RM_RGB)); 307 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RAMCTRL_EPF(3) | 308 ST7789V_RAMCTRL_MAGIC)); 309 310 ST7789V_TEST(ret, st7789v_write_command(ctx, ST7789V_RGBCTRL_CMD)); 311 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RGBCTRL_WO | 312 ST7789V_RGBCTRL_RCM(2) | 313 ST7789V_RGBCTRL_VSYNC_HIGH | 314 ST7789V_RGBCTRL_HSYNC_HIGH | 315 ST7789V_RGBCTRL_PCLK_HIGH)); 316 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RGBCTRL_VBP(8))); 317 ST7789V_TEST(ret, st7789v_write_data(ctx, ST7789V_RGBCTRL_HBP(20))); 318 319 return 0; 320} 321 322static int st7789v_enable(struct drm_panel *panel) 323{ 324 struct st7789v *ctx = panel_to_st7789v(panel); 325 326 if (ctx->backlight) { 327 ctx->backlight->props.state &= ~BL_CORE_FBBLANK; 328 ctx->backlight->props.power = FB_BLANK_UNBLANK; 329 backlight_update_status(ctx->backlight); 330 } 331 332 return st7789v_write_command(ctx, MIPI_DCS_SET_DISPLAY_ON); 333} 334 335static int st7789v_disable(struct drm_panel *panel) 336{ 337 struct st7789v *ctx = panel_to_st7789v(panel); 338 int ret; 339 340 ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_SET_DISPLAY_OFF)); 341 342 if (ctx->backlight) { 343 ctx->backlight->props.power = FB_BLANK_POWERDOWN; 344 ctx->backlight->props.state |= BL_CORE_FBBLANK; 345 backlight_update_status(ctx->backlight); 346 } 347 348 return 0; 349} 350 351static int st7789v_unprepare(struct drm_panel *panel) 352{ 353 struct st7789v *ctx = panel_to_st7789v(panel); 354 int ret; 355 356 ST7789V_TEST(ret, st7789v_write_command(ctx, MIPI_DCS_ENTER_SLEEP_MODE)); 357 358 regulator_disable(ctx->power); 359 360 return 0; 361} 362 363static const struct drm_panel_funcs st7789v_drm_funcs = { 364 .disable = st7789v_disable, 365 .enable = st7789v_enable, 366 .get_modes = st7789v_get_modes, 367 .prepare = st7789v_prepare, 368 .unprepare = st7789v_unprepare, 369}; 370 371static int st7789v_probe(struct spi_device *spi) 372{ 373 struct device_node *backlight; 374 struct st7789v *ctx; 375 int ret; 376 377 ctx = devm_kzalloc(&spi->dev, sizeof(*ctx), GFP_KERNEL); 378 if (!ctx) 379 return -ENOMEM; 380 381 spi_set_drvdata(spi, ctx); 382 ctx->spi = spi; 383 384 drm_panel_init(&ctx->panel, &spi->dev, &st7789v_drm_funcs, 385 DRM_MODE_CONNECTOR_DPI); 386 387 ctx->power = devm_regulator_get(&spi->dev, "power"); 388 if (IS_ERR(ctx->power)) 389 return PTR_ERR(ctx->power); 390 391 ctx->reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW); 392 if (IS_ERR(ctx->reset)) { 393 dev_err(&spi->dev, "Couldn't get our reset line\n"); 394 return PTR_ERR(ctx->reset); 395 } 396 397 backlight = of_parse_phandle(spi->dev.of_node, "backlight", 0); 398 if (backlight) { 399 ctx->backlight = of_find_backlight_by_node(backlight); 400 of_node_put(backlight); 401 402 if (!ctx->backlight) 403 return -EPROBE_DEFER; 404 } 405 406 ret = drm_panel_add(&ctx->panel); 407 if (ret < 0) 408 goto err_free_backlight; 409 410 return 0; 411 412err_free_backlight: 413 if (ctx->backlight) 414 put_device(&ctx->backlight->dev); 415 416 return ret; 417} 418 419static int st7789v_remove(struct spi_device *spi) 420{ 421 struct st7789v *ctx = spi_get_drvdata(spi); 422 423 drm_panel_remove(&ctx->panel); 424 425 if (ctx->backlight) 426 put_device(&ctx->backlight->dev); 427 428 return 0; 429} 430 431static const struct of_device_id st7789v_of_match[] = { 432 { .compatible = "sitronix,st7789v" }, 433 { } 434}; 435MODULE_DEVICE_TABLE(of, st7789v_of_match); 436 437static struct spi_driver st7789v_driver = { 438 .probe = st7789v_probe, 439 .remove = st7789v_remove, 440 .driver = { 441 .name = "st7789v", 442 .of_match_table = st7789v_of_match, 443 }, 444}; 445module_spi_driver(st7789v_driver); 446 447MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); 448MODULE_DESCRIPTION("Sitronix st7789v LCD Driver"); 449MODULE_LICENSE("GPL v2");