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.16-rc3 490 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * MIPI-DSI Sony ACX424AKP panel driver. This is a 480x864 4 * AMOLED panel with a command-only DSI interface. 5 * 6 * Copyright (C) Linaro Ltd. 2019 7 * Author: Linus Walleij 8 * Based on code and know-how from Marcus Lorentzon 9 * Copyright (C) ST-Ericsson SA 2010 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/of.h> 16#include <linux/regulator/consumer.h> 17 18#include <video/mipi_display.h> 19 20#include <drm/drm_mipi_dsi.h> 21#include <drm/drm_modes.h> 22#include <drm/drm_panel.h> 23 24#define ACX424_DCS_READ_ID1 0xDA 25#define ACX424_DCS_READ_ID2 0xDB 26#define ACX424_DCS_READ_ID3 0xDC 27#define ACX424_DCS_SET_MDDI 0xAE 28 29/* 30 * Sony seems to use vendor ID 0x81 31 */ 32#define DISPLAY_SONY_ACX424AKP_ID1 0x811b 33#define DISPLAY_SONY_ACX424AKP_ID2 0x811a 34/* 35 * The third ID looks like a bug, vendor IDs begin at 0x80 36 * and panel 00 ... seems like default values. 37 */ 38#define DISPLAY_SONY_ACX424AKP_ID3 0x8000 39 40struct acx424akp { 41 struct drm_panel panel; 42 struct device *dev; 43 struct regulator *supply; 44 struct gpio_desc *reset_gpio; 45 bool video_mode; 46}; 47 48static const struct drm_display_mode sony_acx424akp_vid_mode = { 49 .clock = 27234, 50 .hdisplay = 480, 51 .hsync_start = 480 + 15, 52 .hsync_end = 480 + 15 + 0, 53 .htotal = 480 + 15 + 0 + 15, 54 .vdisplay = 864, 55 .vsync_start = 864 + 14, 56 .vsync_end = 864 + 14 + 1, 57 .vtotal = 864 + 14 + 1 + 11, 58 .width_mm = 48, 59 .height_mm = 84, 60 .flags = DRM_MODE_FLAG_PVSYNC, 61}; 62 63/* 64 * The timings are not very helpful as the display is used in 65 * command mode using the maximum HS frequency. 66 */ 67static const struct drm_display_mode sony_acx424akp_cmd_mode = { 68 .clock = 35478, 69 .hdisplay = 480, 70 .hsync_start = 480 + 154, 71 .hsync_end = 480 + 154 + 16, 72 .htotal = 480 + 154 + 16 + 32, 73 .vdisplay = 864, 74 .vsync_start = 864 + 1, 75 .vsync_end = 864 + 1 + 1, 76 .vtotal = 864 + 1 + 1 + 1, 77 /* 78 * Some desired refresh rate, experiments at the maximum "pixel" 79 * clock speed (HS clock 420 MHz) yields around 117Hz. 80 */ 81 .width_mm = 48, 82 .height_mm = 84, 83}; 84 85static inline struct acx424akp *panel_to_acx424akp(struct drm_panel *panel) 86{ 87 return container_of(panel, struct acx424akp, panel); 88} 89 90#define FOSC 20 /* 20Mhz */ 91#define SCALE_FACTOR_NS_DIV_MHZ 1000 92 93static int acx424akp_set_brightness(struct backlight_device *bl) 94{ 95 struct acx424akp *acx = bl_get_data(bl); 96 struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev); 97 int period_ns = 1023; 98 int duty_ns = bl->props.brightness; 99 u8 pwm_ratio; 100 u8 pwm_div; 101 u8 par; 102 int ret; 103 104 if (backlight_is_blank(bl)) { 105 /* Disable backlight */ 106 par = 0x00; 107 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 108 &par, 1); 109 if (ret) { 110 dev_err(acx->dev, "failed to disable display backlight (%d)\n", ret); 111 return ret; 112 } 113 return 0; 114 } 115 116 /* Calculate the PWM duty cycle in n/256's */ 117 pwm_ratio = max(((duty_ns * 256) / period_ns) - 1, 1); 118 pwm_div = max(1, 119 ((FOSC * period_ns) / 256) / 120 SCALE_FACTOR_NS_DIV_MHZ); 121 122 /* Set up PWM dutycycle ONE byte (differs from the standard) */ 123 dev_dbg(acx->dev, "calculated duty cycle %02x\n", pwm_ratio); 124 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 125 &pwm_ratio, 1); 126 if (ret < 0) { 127 dev_err(acx->dev, "failed to set display PWM ratio (%d)\n", ret); 128 return ret; 129 } 130 131 /* 132 * Sequence to write PWMDIV: 133 * address data 134 * 0xF3 0xAA CMD2 Unlock 135 * 0x00 0x01 Enter CMD2 page 0 136 * 0X7D 0x01 No reload MTP of CMD2 P1 137 * 0x22 PWMDIV 138 * 0x7F 0xAA CMD2 page 1 lock 139 */ 140 par = 0xaa; 141 ret = mipi_dsi_dcs_write(dsi, 0xf3, &par, 1); 142 if (ret < 0) { 143 dev_err(acx->dev, "failed to unlock CMD 2 (%d)\n", ret); 144 return ret; 145 } 146 par = 0x01; 147 ret = mipi_dsi_dcs_write(dsi, 0x00, &par, 1); 148 if (ret < 0) { 149 dev_err(acx->dev, "failed to enter page 1 (%d)\n", ret); 150 return ret; 151 } 152 par = 0x01; 153 ret = mipi_dsi_dcs_write(dsi, 0x7d, &par, 1); 154 if (ret < 0) { 155 dev_err(acx->dev, "failed to disable MTP reload (%d)\n", ret); 156 return ret; 157 } 158 ret = mipi_dsi_dcs_write(dsi, 0x22, &pwm_div, 1); 159 if (ret < 0) { 160 dev_err(acx->dev, "failed to set PWM divisor (%d)\n", ret); 161 return ret; 162 } 163 par = 0xaa; 164 ret = mipi_dsi_dcs_write(dsi, 0x7f, &par, 1); 165 if (ret < 0) { 166 dev_err(acx->dev, "failed to lock CMD 2 (%d)\n", ret); 167 return ret; 168 } 169 170 /* Enable backlight */ 171 par = 0x24; 172 ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 173 &par, 1); 174 if (ret < 0) { 175 dev_err(acx->dev, "failed to enable display backlight (%d)\n", ret); 176 return ret; 177 } 178 179 return 0; 180} 181 182static const struct backlight_ops acx424akp_bl_ops = { 183 .update_status = acx424akp_set_brightness, 184}; 185 186static const struct backlight_properties acx424akp_bl_props = { 187 .type = BACKLIGHT_RAW, 188 .brightness = 512, 189 .max_brightness = 1023, 190}; 191 192static int acx424akp_read_id(struct acx424akp *acx) 193{ 194 struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev); 195 u8 vendor, version, panel; 196 u16 val; 197 int ret; 198 199 ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID1, &vendor, 1); 200 if (ret < 0) { 201 dev_err(acx->dev, "could not vendor ID byte\n"); 202 return ret; 203 } 204 ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID2, &version, 1); 205 if (ret < 0) { 206 dev_err(acx->dev, "could not read device version byte\n"); 207 return ret; 208 } 209 ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID3, &panel, 1); 210 if (ret < 0) { 211 dev_err(acx->dev, "could not read panel ID byte\n"); 212 return ret; 213 } 214 215 if (vendor == 0x00) { 216 dev_err(acx->dev, "device vendor ID is zero\n"); 217 return -ENODEV; 218 } 219 220 val = (vendor << 8) | panel; 221 switch (val) { 222 case DISPLAY_SONY_ACX424AKP_ID1: 223 case DISPLAY_SONY_ACX424AKP_ID2: 224 case DISPLAY_SONY_ACX424AKP_ID3: 225 dev_info(acx->dev, "MTP vendor: %02x, version: %02x, panel: %02x\n", 226 vendor, version, panel); 227 break; 228 default: 229 dev_info(acx->dev, "unknown vendor: %02x, version: %02x, panel: %02x\n", 230 vendor, version, panel); 231 break; 232 } 233 234 return 0; 235} 236 237static int acx424akp_power_on(struct acx424akp *acx) 238{ 239 int ret; 240 241 ret = regulator_enable(acx->supply); 242 if (ret) { 243 dev_err(acx->dev, "failed to enable supply (%d)\n", ret); 244 return ret; 245 } 246 247 /* Assert RESET */ 248 gpiod_set_value_cansleep(acx->reset_gpio, 1); 249 udelay(20); 250 /* De-assert RESET */ 251 gpiod_set_value_cansleep(acx->reset_gpio, 0); 252 usleep_range(11000, 20000); 253 254 return 0; 255} 256 257static void acx424akp_power_off(struct acx424akp *acx) 258{ 259 /* Assert RESET */ 260 gpiod_set_value_cansleep(acx->reset_gpio, 1); 261 usleep_range(11000, 20000); 262 263 regulator_disable(acx->supply); 264} 265 266static int acx424akp_prepare(struct drm_panel *panel) 267{ 268 struct acx424akp *acx = panel_to_acx424akp(panel); 269 struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev); 270 const u8 mddi = 3; 271 int ret; 272 273 ret = acx424akp_power_on(acx); 274 if (ret) 275 return ret; 276 277 ret = acx424akp_read_id(acx); 278 if (ret) { 279 dev_err(acx->dev, "failed to read panel ID (%d)\n", ret); 280 goto err_power_off; 281 } 282 283 /* Enabe tearing mode: send TE (tearing effect) at VBLANK */ 284 ret = mipi_dsi_dcs_set_tear_on(dsi, 285 MIPI_DSI_DCS_TEAR_MODE_VBLANK); 286 if (ret) { 287 dev_err(acx->dev, "failed to enable vblank TE (%d)\n", ret); 288 goto err_power_off; 289 } 290 291 /* 292 * Set MDDI 293 * 294 * This presumably deactivates the Qualcomm MDDI interface and 295 * selects DSI, similar code is found in other drivers such as the 296 * Sharp LS043T1LE01 which makes us suspect that this panel may be 297 * using a Novatek NT35565 or similar display driver chip that shares 298 * this command. Due to the lack of documentation we cannot know for 299 * sure. 300 */ 301 ret = mipi_dsi_dcs_write(dsi, ACX424_DCS_SET_MDDI, 302 &mddi, sizeof(mddi)); 303 if (ret < 0) { 304 dev_err(acx->dev, "failed to set MDDI (%d)\n", ret); 305 goto err_power_off; 306 } 307 308 /* Exit sleep mode */ 309 ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 310 if (ret) { 311 dev_err(acx->dev, "failed to exit sleep mode (%d)\n", ret); 312 goto err_power_off; 313 } 314 msleep(140); 315 316 ret = mipi_dsi_dcs_set_display_on(dsi); 317 if (ret) { 318 dev_err(acx->dev, "failed to turn display on (%d)\n", ret); 319 goto err_power_off; 320 } 321 if (acx->video_mode) { 322 /* In video mode turn peripheral on */ 323 ret = mipi_dsi_turn_on_peripheral(dsi); 324 if (ret) { 325 dev_err(acx->dev, "failed to turn on peripheral\n"); 326 goto err_power_off; 327 } 328 } 329 330 return 0; 331 332err_power_off: 333 acx424akp_power_off(acx); 334 return ret; 335} 336 337static int acx424akp_unprepare(struct drm_panel *panel) 338{ 339 struct acx424akp *acx = panel_to_acx424akp(panel); 340 struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev); 341 int ret; 342 343 ret = mipi_dsi_dcs_set_display_off(dsi); 344 if (ret) { 345 dev_err(acx->dev, "failed to turn display off (%d)\n", ret); 346 return ret; 347 } 348 349 /* Enter sleep mode */ 350 ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 351 if (ret) { 352 dev_err(acx->dev, "failed to enter sleep mode (%d)\n", ret); 353 return ret; 354 } 355 msleep(85); 356 357 acx424akp_power_off(acx); 358 359 return 0; 360} 361 362 363static int acx424akp_get_modes(struct drm_panel *panel, 364 struct drm_connector *connector) 365{ 366 struct acx424akp *acx = panel_to_acx424akp(panel); 367 struct drm_display_mode *mode; 368 369 if (acx->video_mode) 370 mode = drm_mode_duplicate(connector->dev, 371 &sony_acx424akp_vid_mode); 372 else 373 mode = drm_mode_duplicate(connector->dev, 374 &sony_acx424akp_cmd_mode); 375 if (!mode) { 376 dev_err(panel->dev, "bad mode or failed to add mode\n"); 377 return -EINVAL; 378 } 379 drm_mode_set_name(mode); 380 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 381 382 connector->display_info.width_mm = mode->width_mm; 383 connector->display_info.height_mm = mode->height_mm; 384 385 drm_mode_probed_add(connector, mode); 386 387 return 1; /* Number of modes */ 388} 389 390static const struct drm_panel_funcs acx424akp_drm_funcs = { 391 .unprepare = acx424akp_unprepare, 392 .prepare = acx424akp_prepare, 393 .get_modes = acx424akp_get_modes, 394}; 395 396static int acx424akp_probe(struct mipi_dsi_device *dsi) 397{ 398 struct device *dev = &dsi->dev; 399 struct acx424akp *acx; 400 int ret; 401 402 acx = devm_kzalloc(dev, sizeof(struct acx424akp), GFP_KERNEL); 403 if (!acx) 404 return -ENOMEM; 405 acx->video_mode = of_property_read_bool(dev->of_node, 406 "enforce-video-mode"); 407 408 mipi_dsi_set_drvdata(dsi, acx); 409 acx->dev = dev; 410 411 dsi->lanes = 2; 412 dsi->format = MIPI_DSI_FMT_RGB888; 413 /* 414 * FIXME: these come from the ST-Ericsson vendor driver for the 415 * HREF520 and seems to reflect limitations in the PLLs on that 416 * platform, if you have the datasheet, please cross-check the 417 * actual max rates. 418 */ 419 dsi->lp_rate = 19200000; 420 dsi->hs_rate = 420160000; 421 422 if (acx->video_mode) 423 /* Burst mode using event for sync */ 424 dsi->mode_flags = 425 MIPI_DSI_MODE_VIDEO | 426 MIPI_DSI_MODE_VIDEO_BURST; 427 else 428 dsi->mode_flags = 429 MIPI_DSI_CLOCK_NON_CONTINUOUS; 430 431 acx->supply = devm_regulator_get(dev, "vddi"); 432 if (IS_ERR(acx->supply)) 433 return PTR_ERR(acx->supply); 434 435 /* This asserts RESET by default */ 436 acx->reset_gpio = devm_gpiod_get_optional(dev, "reset", 437 GPIOD_OUT_HIGH); 438 if (IS_ERR(acx->reset_gpio)) 439 return dev_err_probe(dev, PTR_ERR(acx->reset_gpio), 440 "failed to request GPIO\n"); 441 442 drm_panel_init(&acx->panel, dev, &acx424akp_drm_funcs, 443 DRM_MODE_CONNECTOR_DSI); 444 445 acx->panel.backlight = devm_backlight_device_register(dev, "acx424akp", dev, acx, 446 &acx424akp_bl_ops, &acx424akp_bl_props); 447 if (IS_ERR(acx->panel.backlight)) 448 return dev_err_probe(dev, PTR_ERR(acx->panel.backlight), 449 "failed to register backlight device\n"); 450 451 drm_panel_add(&acx->panel); 452 453 ret = mipi_dsi_attach(dsi); 454 if (ret < 0) { 455 drm_panel_remove(&acx->panel); 456 return ret; 457 } 458 459 return 0; 460} 461 462static int acx424akp_remove(struct mipi_dsi_device *dsi) 463{ 464 struct acx424akp *acx = mipi_dsi_get_drvdata(dsi); 465 466 mipi_dsi_detach(dsi); 467 drm_panel_remove(&acx->panel); 468 469 return 0; 470} 471 472static const struct of_device_id acx424akp_of_match[] = { 473 { .compatible = "sony,acx424akp" }, 474 { /* sentinel */ } 475}; 476MODULE_DEVICE_TABLE(of, acx424akp_of_match); 477 478static struct mipi_dsi_driver acx424akp_driver = { 479 .probe = acx424akp_probe, 480 .remove = acx424akp_remove, 481 .driver = { 482 .name = "panel-sony-acx424akp", 483 .of_match_table = acx424akp_of_match, 484 }, 485}; 486module_mipi_dsi_driver(acx424akp_driver); 487 488MODULE_AUTHOR("Linus Wallei <linus.walleij@linaro.org>"); 489MODULE_DESCRIPTION("MIPI-DSI Sony acx424akp Panel Driver"); 490MODULE_LICENSE("GPL v2");