linux/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2018 MediaTek Inc.
   4 * Author: Jitao Shi <jitao.shi@mediatek.com>
   5 */
   6
   7#include <linux/delay.h>
   8#include <linux/gpio/consumer.h>
   9#include <linux/module.h>
  10#include <linux/of.h>
  11#include <linux/of_device.h>
  12#include <linux/regulator/consumer.h>
  13
  14#include <drm/drm_connector.h>
  15#include <drm/drm_crtc.h>
  16#include <drm/drm_mipi_dsi.h>
  17#include <drm/drm_panel.h>
  18
  19#include <video/mipi_display.h>
  20
  21struct panel_desc {
  22        const struct drm_display_mode *modes;
  23        unsigned int bpc;
  24
  25        /**
  26         * @width_mm: width of the panel's active display area
  27         * @height_mm: height of the panel's active display area
  28         */
  29        struct {
  30                unsigned int width_mm;
  31                unsigned int height_mm;
  32        } size;
  33
  34        unsigned long mode_flags;
  35        enum mipi_dsi_pixel_format format;
  36        const struct panel_init_cmd *init_cmds;
  37        unsigned int lanes;
  38        bool discharge_on_disable;
  39};
  40
  41struct boe_panel {
  42        struct drm_panel base;
  43        struct mipi_dsi_device *dsi;
  44
  45        const struct panel_desc *desc;
  46
  47        enum drm_panel_orientation orientation;
  48        struct regulator *pp1800;
  49        struct regulator *avee;
  50        struct regulator *avdd;
  51        struct gpio_desc *enable_gpio;
  52
  53        bool prepared;
  54};
  55
  56enum dsi_cmd_type {
  57        INIT_DCS_CMD,
  58        DELAY_CMD,
  59};
  60
  61struct panel_init_cmd {
  62        enum dsi_cmd_type type;
  63        size_t len;
  64        const char *data;
  65};
  66
  67#define _INIT_DCS_CMD(...) { \
  68        .type = INIT_DCS_CMD, \
  69        .len = sizeof((char[]){__VA_ARGS__}), \
  70        .data = (char[]){__VA_ARGS__} }
  71
  72#define _INIT_DELAY_CMD(...) { \
  73        .type = DELAY_CMD,\
  74        .len = sizeof((char[]){__VA_ARGS__}), \
  75        .data = (char[]){__VA_ARGS__} }
  76
  77static const struct panel_init_cmd boe_init_cmd[] = {
  78        _INIT_DELAY_CMD(24),
  79        _INIT_DCS_CMD(0xB0, 0x05),
  80        _INIT_DCS_CMD(0xB1, 0xE5),
  81        _INIT_DCS_CMD(0xB3, 0x52),
  82        _INIT_DCS_CMD(0xB0, 0x00),
  83        _INIT_DCS_CMD(0xB3, 0x88),
  84        _INIT_DCS_CMD(0xB0, 0x04),
  85        _INIT_DCS_CMD(0xB8, 0x00),
  86        _INIT_DCS_CMD(0xB0, 0x00),
  87        _INIT_DCS_CMD(0xB6, 0x03),
  88        _INIT_DCS_CMD(0xBA, 0x8B),
  89        _INIT_DCS_CMD(0xBF, 0x1A),
  90        _INIT_DCS_CMD(0xC0, 0x0F),
  91        _INIT_DCS_CMD(0xC2, 0x0C),
  92        _INIT_DCS_CMD(0xC3, 0x02),
  93        _INIT_DCS_CMD(0xC4, 0x0C),
  94        _INIT_DCS_CMD(0xC5, 0x02),
  95        _INIT_DCS_CMD(0xB0, 0x01),
  96        _INIT_DCS_CMD(0xE0, 0x26),
  97        _INIT_DCS_CMD(0xE1, 0x26),
  98        _INIT_DCS_CMD(0xDC, 0x00),
  99        _INIT_DCS_CMD(0xDD, 0x00),
 100        _INIT_DCS_CMD(0xCC, 0x26),
 101        _INIT_DCS_CMD(0xCD, 0x26),
 102        _INIT_DCS_CMD(0xC8, 0x00),
 103        _INIT_DCS_CMD(0xC9, 0x00),
 104        _INIT_DCS_CMD(0xD2, 0x03),
 105        _INIT_DCS_CMD(0xD3, 0x03),
 106        _INIT_DCS_CMD(0xE6, 0x04),
 107        _INIT_DCS_CMD(0xE7, 0x04),
 108        _INIT_DCS_CMD(0xC4, 0x09),
 109        _INIT_DCS_CMD(0xC5, 0x09),
 110        _INIT_DCS_CMD(0xD8, 0x0A),
 111        _INIT_DCS_CMD(0xD9, 0x0A),
 112        _INIT_DCS_CMD(0xC2, 0x0B),
 113        _INIT_DCS_CMD(0xC3, 0x0B),
 114        _INIT_DCS_CMD(0xD6, 0x0C),
 115        _INIT_DCS_CMD(0xD7, 0x0C),
 116        _INIT_DCS_CMD(0xC0, 0x05),
 117        _INIT_DCS_CMD(0xC1, 0x05),
 118        _INIT_DCS_CMD(0xD4, 0x06),
 119        _INIT_DCS_CMD(0xD5, 0x06),
 120        _INIT_DCS_CMD(0xCA, 0x07),
 121        _INIT_DCS_CMD(0xCB, 0x07),
 122        _INIT_DCS_CMD(0xDE, 0x08),
 123        _INIT_DCS_CMD(0xDF, 0x08),
 124        _INIT_DCS_CMD(0xB0, 0x02),
 125        _INIT_DCS_CMD(0xC0, 0x00),
 126        _INIT_DCS_CMD(0xC1, 0x0D),
 127        _INIT_DCS_CMD(0xC2, 0x17),
 128        _INIT_DCS_CMD(0xC3, 0x26),
 129        _INIT_DCS_CMD(0xC4, 0x31),
 130        _INIT_DCS_CMD(0xC5, 0x1C),
 131        _INIT_DCS_CMD(0xC6, 0x2C),
 132        _INIT_DCS_CMD(0xC7, 0x33),
 133        _INIT_DCS_CMD(0xC8, 0x31),
 134        _INIT_DCS_CMD(0xC9, 0x37),
 135        _INIT_DCS_CMD(0xCA, 0x37),
 136        _INIT_DCS_CMD(0xCB, 0x37),
 137        _INIT_DCS_CMD(0xCC, 0x39),
 138        _INIT_DCS_CMD(0xCD, 0x2E),
 139        _INIT_DCS_CMD(0xCE, 0x2F),
 140        _INIT_DCS_CMD(0xCF, 0x2F),
 141        _INIT_DCS_CMD(0xD0, 0x07),
 142        _INIT_DCS_CMD(0xD2, 0x00),
 143        _INIT_DCS_CMD(0xD3, 0x0D),
 144        _INIT_DCS_CMD(0xD4, 0x17),
 145        _INIT_DCS_CMD(0xD5, 0x26),
 146        _INIT_DCS_CMD(0xD6, 0x31),
 147        _INIT_DCS_CMD(0xD7, 0x3F),
 148        _INIT_DCS_CMD(0xD8, 0x3F),
 149        _INIT_DCS_CMD(0xD9, 0x3F),
 150        _INIT_DCS_CMD(0xDA, 0x3F),
 151        _INIT_DCS_CMD(0xDB, 0x37),
 152        _INIT_DCS_CMD(0xDC, 0x37),
 153        _INIT_DCS_CMD(0xDD, 0x37),
 154        _INIT_DCS_CMD(0xDE, 0x39),
 155        _INIT_DCS_CMD(0xDF, 0x2E),
 156        _INIT_DCS_CMD(0xE0, 0x2F),
 157        _INIT_DCS_CMD(0xE1, 0x2F),
 158        _INIT_DCS_CMD(0xE2, 0x07),
 159        _INIT_DCS_CMD(0xB0, 0x03),
 160        _INIT_DCS_CMD(0xC8, 0x0B),
 161        _INIT_DCS_CMD(0xC9, 0x07),
 162        _INIT_DCS_CMD(0xC3, 0x00),
 163        _INIT_DCS_CMD(0xE7, 0x00),
 164        _INIT_DCS_CMD(0xC5, 0x2A),
 165        _INIT_DCS_CMD(0xDE, 0x2A),
 166        _INIT_DCS_CMD(0xCA, 0x43),
 167        _INIT_DCS_CMD(0xC9, 0x07),
 168        _INIT_DCS_CMD(0xE4, 0xC0),
 169        _INIT_DCS_CMD(0xE5, 0x0D),
 170        _INIT_DCS_CMD(0xCB, 0x00),
 171        _INIT_DCS_CMD(0xB0, 0x06),
 172        _INIT_DCS_CMD(0xB8, 0xA5),
 173        _INIT_DCS_CMD(0xC0, 0xA5),
 174        _INIT_DCS_CMD(0xC7, 0x0F),
 175        _INIT_DCS_CMD(0xD5, 0x32),
 176        _INIT_DCS_CMD(0xB8, 0x00),
 177        _INIT_DCS_CMD(0xC0, 0x00),
 178        _INIT_DCS_CMD(0xBC, 0x00),
 179        _INIT_DCS_CMD(0xB0, 0x07),
 180        _INIT_DCS_CMD(0xB1, 0x00),
 181        _INIT_DCS_CMD(0xB2, 0x02),
 182        _INIT_DCS_CMD(0xB3, 0x0F),
 183        _INIT_DCS_CMD(0xB4, 0x25),
 184        _INIT_DCS_CMD(0xB5, 0x39),
 185        _INIT_DCS_CMD(0xB6, 0x4E),
 186        _INIT_DCS_CMD(0xB7, 0x72),
 187        _INIT_DCS_CMD(0xB8, 0x97),
 188        _INIT_DCS_CMD(0xB9, 0xDC),
 189        _INIT_DCS_CMD(0xBA, 0x22),
 190        _INIT_DCS_CMD(0xBB, 0xA4),
 191        _INIT_DCS_CMD(0xBC, 0x2B),
 192        _INIT_DCS_CMD(0xBD, 0x2F),
 193        _INIT_DCS_CMD(0xBE, 0xA9),
 194        _INIT_DCS_CMD(0xBF, 0x25),
 195        _INIT_DCS_CMD(0xC0, 0x61),
 196        _INIT_DCS_CMD(0xC1, 0x97),
 197        _INIT_DCS_CMD(0xC2, 0xB2),
 198        _INIT_DCS_CMD(0xC3, 0xCD),
 199        _INIT_DCS_CMD(0xC4, 0xD9),
 200        _INIT_DCS_CMD(0xC5, 0xE7),
 201        _INIT_DCS_CMD(0xC6, 0xF4),
 202        _INIT_DCS_CMD(0xC7, 0xFA),
 203        _INIT_DCS_CMD(0xC8, 0xFC),
 204        _INIT_DCS_CMD(0xC9, 0x00),
 205        _INIT_DCS_CMD(0xCA, 0x00),
 206        _INIT_DCS_CMD(0xCB, 0x16),
 207        _INIT_DCS_CMD(0xCC, 0xAF),
 208        _INIT_DCS_CMD(0xCD, 0xFF),
 209        _INIT_DCS_CMD(0xCE, 0xFF),
 210        _INIT_DCS_CMD(0xB0, 0x08),
 211        _INIT_DCS_CMD(0xB1, 0x04),
 212        _INIT_DCS_CMD(0xB2, 0x05),
 213        _INIT_DCS_CMD(0xB3, 0x11),
 214        _INIT_DCS_CMD(0xB4, 0x24),
 215        _INIT_DCS_CMD(0xB5, 0x39),
 216        _INIT_DCS_CMD(0xB6, 0x4F),
 217        _INIT_DCS_CMD(0xB7, 0x72),
 218        _INIT_DCS_CMD(0xB8, 0x98),
 219        _INIT_DCS_CMD(0xB9, 0xDC),
 220        _INIT_DCS_CMD(0xBA, 0x23),
 221        _INIT_DCS_CMD(0xBB, 0xA6),
 222        _INIT_DCS_CMD(0xBC, 0x2C),
 223        _INIT_DCS_CMD(0xBD, 0x30),
 224        _INIT_DCS_CMD(0xBE, 0xAA),
 225        _INIT_DCS_CMD(0xBF, 0x26),
 226        _INIT_DCS_CMD(0xC0, 0x62),
 227        _INIT_DCS_CMD(0xC1, 0x9B),
 228        _INIT_DCS_CMD(0xC2, 0xB5),
 229        _INIT_DCS_CMD(0xC3, 0xCF),
 230        _INIT_DCS_CMD(0xC4, 0xDB),
 231        _INIT_DCS_CMD(0xC5, 0xE8),
 232        _INIT_DCS_CMD(0xC6, 0xF5),
 233        _INIT_DCS_CMD(0xC7, 0xFA),
 234        _INIT_DCS_CMD(0xC8, 0xFC),
 235        _INIT_DCS_CMD(0xC9, 0x00),
 236        _INIT_DCS_CMD(0xCA, 0x00),
 237        _INIT_DCS_CMD(0xCB, 0x16),
 238        _INIT_DCS_CMD(0xCC, 0xAF),
 239        _INIT_DCS_CMD(0xCD, 0xFF),
 240        _INIT_DCS_CMD(0xCE, 0xFF),
 241        _INIT_DCS_CMD(0xB0, 0x09),
 242        _INIT_DCS_CMD(0xB1, 0x04),
 243        _INIT_DCS_CMD(0xB2, 0x02),
 244        _INIT_DCS_CMD(0xB3, 0x16),
 245        _INIT_DCS_CMD(0xB4, 0x24),
 246        _INIT_DCS_CMD(0xB5, 0x3B),
 247        _INIT_DCS_CMD(0xB6, 0x4F),
 248        _INIT_DCS_CMD(0xB7, 0x73),
 249        _INIT_DCS_CMD(0xB8, 0x99),
 250        _INIT_DCS_CMD(0xB9, 0xE0),
 251        _INIT_DCS_CMD(0xBA, 0x26),
 252        _INIT_DCS_CMD(0xBB, 0xAD),
 253        _INIT_DCS_CMD(0xBC, 0x36),
 254        _INIT_DCS_CMD(0xBD, 0x3A),
 255        _INIT_DCS_CMD(0xBE, 0xAE),
 256        _INIT_DCS_CMD(0xBF, 0x2A),
 257        _INIT_DCS_CMD(0xC0, 0x66),
 258        _INIT_DCS_CMD(0xC1, 0x9E),
 259        _INIT_DCS_CMD(0xC2, 0xB8),
 260        _INIT_DCS_CMD(0xC3, 0xD1),
 261        _INIT_DCS_CMD(0xC4, 0xDD),
 262        _INIT_DCS_CMD(0xC5, 0xE9),
 263        _INIT_DCS_CMD(0xC6, 0xF6),
 264        _INIT_DCS_CMD(0xC7, 0xFA),
 265        _INIT_DCS_CMD(0xC8, 0xFC),
 266        _INIT_DCS_CMD(0xC9, 0x00),
 267        _INIT_DCS_CMD(0xCA, 0x00),
 268        _INIT_DCS_CMD(0xCB, 0x16),
 269        _INIT_DCS_CMD(0xCC, 0xAF),
 270        _INIT_DCS_CMD(0xCD, 0xFF),
 271        _INIT_DCS_CMD(0xCE, 0xFF),
 272        _INIT_DCS_CMD(0xB0, 0x0A),
 273        _INIT_DCS_CMD(0xB1, 0x00),
 274        _INIT_DCS_CMD(0xB2, 0x02),
 275        _INIT_DCS_CMD(0xB3, 0x0F),
 276        _INIT_DCS_CMD(0xB4, 0x25),
 277        _INIT_DCS_CMD(0xB5, 0x39),
 278        _INIT_DCS_CMD(0xB6, 0x4E),
 279        _INIT_DCS_CMD(0xB7, 0x72),
 280        _INIT_DCS_CMD(0xB8, 0x97),
 281        _INIT_DCS_CMD(0xB9, 0xDC),
 282        _INIT_DCS_CMD(0xBA, 0x22),
 283        _INIT_DCS_CMD(0xBB, 0xA4),
 284        _INIT_DCS_CMD(0xBC, 0x2B),
 285        _INIT_DCS_CMD(0xBD, 0x2F),
 286        _INIT_DCS_CMD(0xBE, 0xA9),
 287        _INIT_DCS_CMD(0xBF, 0x25),
 288        _INIT_DCS_CMD(0xC0, 0x61),
 289        _INIT_DCS_CMD(0xC1, 0x97),
 290        _INIT_DCS_CMD(0xC2, 0xB2),
 291        _INIT_DCS_CMD(0xC3, 0xCD),
 292        _INIT_DCS_CMD(0xC4, 0xD9),
 293        _INIT_DCS_CMD(0xC5, 0xE7),
 294        _INIT_DCS_CMD(0xC6, 0xF4),
 295        _INIT_DCS_CMD(0xC7, 0xFA),
 296        _INIT_DCS_CMD(0xC8, 0xFC),
 297        _INIT_DCS_CMD(0xC9, 0x00),
 298        _INIT_DCS_CMD(0xCA, 0x00),
 299        _INIT_DCS_CMD(0xCB, 0x16),
 300        _INIT_DCS_CMD(0xCC, 0xAF),
 301        _INIT_DCS_CMD(0xCD, 0xFF),
 302        _INIT_DCS_CMD(0xCE, 0xFF),
 303        _INIT_DCS_CMD(0xB0, 0x0B),
 304        _INIT_DCS_CMD(0xB1, 0x04),
 305        _INIT_DCS_CMD(0xB2, 0x05),
 306        _INIT_DCS_CMD(0xB3, 0x11),
 307        _INIT_DCS_CMD(0xB4, 0x24),
 308        _INIT_DCS_CMD(0xB5, 0x39),
 309        _INIT_DCS_CMD(0xB6, 0x4F),
 310        _INIT_DCS_CMD(0xB7, 0x72),
 311        _INIT_DCS_CMD(0xB8, 0x98),
 312        _INIT_DCS_CMD(0xB9, 0xDC),
 313        _INIT_DCS_CMD(0xBA, 0x23),
 314        _INIT_DCS_CMD(0xBB, 0xA6),
 315        _INIT_DCS_CMD(0xBC, 0x2C),
 316        _INIT_DCS_CMD(0xBD, 0x30),
 317        _INIT_DCS_CMD(0xBE, 0xAA),
 318        _INIT_DCS_CMD(0xBF, 0x26),
 319        _INIT_DCS_CMD(0xC0, 0x62),
 320        _INIT_DCS_CMD(0xC1, 0x9B),
 321        _INIT_DCS_CMD(0xC2, 0xB5),
 322        _INIT_DCS_CMD(0xC3, 0xCF),
 323        _INIT_DCS_CMD(0xC4, 0xDB),
 324        _INIT_DCS_CMD(0xC5, 0xE8),
 325        _INIT_DCS_CMD(0xC6, 0xF5),
 326        _INIT_DCS_CMD(0xC7, 0xFA),
 327        _INIT_DCS_CMD(0xC8, 0xFC),
 328        _INIT_DCS_CMD(0xC9, 0x00),
 329        _INIT_DCS_CMD(0xCA, 0x00),
 330        _INIT_DCS_CMD(0xCB, 0x16),
 331        _INIT_DCS_CMD(0xCC, 0xAF),
 332        _INIT_DCS_CMD(0xCD, 0xFF),
 333        _INIT_DCS_CMD(0xCE, 0xFF),
 334        _INIT_DCS_CMD(0xB0, 0x0C),
 335        _INIT_DCS_CMD(0xB1, 0x04),
 336        _INIT_DCS_CMD(0xB2, 0x02),
 337        _INIT_DCS_CMD(0xB3, 0x16),
 338        _INIT_DCS_CMD(0xB4, 0x24),
 339        _INIT_DCS_CMD(0xB5, 0x3B),
 340        _INIT_DCS_CMD(0xB6, 0x4F),
 341        _INIT_DCS_CMD(0xB7, 0x73),
 342        _INIT_DCS_CMD(0xB8, 0x99),
 343        _INIT_DCS_CMD(0xB9, 0xE0),
 344        _INIT_DCS_CMD(0xBA, 0x26),
 345        _INIT_DCS_CMD(0xBB, 0xAD),
 346        _INIT_DCS_CMD(0xBC, 0x36),
 347        _INIT_DCS_CMD(0xBD, 0x3A),
 348        _INIT_DCS_CMD(0xBE, 0xAE),
 349        _INIT_DCS_CMD(0xBF, 0x2A),
 350        _INIT_DCS_CMD(0xC0, 0x66),
 351        _INIT_DCS_CMD(0xC1, 0x9E),
 352        _INIT_DCS_CMD(0xC2, 0xB8),
 353        _INIT_DCS_CMD(0xC3, 0xD1),
 354        _INIT_DCS_CMD(0xC4, 0xDD),
 355        _INIT_DCS_CMD(0xC5, 0xE9),
 356        _INIT_DCS_CMD(0xC6, 0xF6),
 357        _INIT_DCS_CMD(0xC7, 0xFA),
 358        _INIT_DCS_CMD(0xC8, 0xFC),
 359        _INIT_DCS_CMD(0xC9, 0x00),
 360        _INIT_DCS_CMD(0xCA, 0x00),
 361        _INIT_DCS_CMD(0xCB, 0x16),
 362        _INIT_DCS_CMD(0xCC, 0xAF),
 363        _INIT_DCS_CMD(0xCD, 0xFF),
 364        _INIT_DCS_CMD(0xCE, 0xFF),
 365        _INIT_DCS_CMD(0xB0, 0x00),
 366        _INIT_DCS_CMD(0xB3, 0x08),
 367        _INIT_DCS_CMD(0xB0, 0x04),
 368        _INIT_DCS_CMD(0xB8, 0x68),
 369        _INIT_DELAY_CMD(150),
 370        {},
 371};
 372
 373static const struct panel_init_cmd auo_kd101n80_45na_init_cmd[] = {
 374        _INIT_DELAY_CMD(24),
 375        _INIT_DCS_CMD(0x11),
 376        _INIT_DELAY_CMD(120),
 377        _INIT_DCS_CMD(0x29),
 378        _INIT_DELAY_CMD(120),
 379        {},
 380};
 381
 382static const struct panel_init_cmd auo_b101uan08_3_init_cmd[] = {
 383        _INIT_DELAY_CMD(24),
 384        _INIT_DCS_CMD(0xB0, 0x01),
 385        _INIT_DCS_CMD(0xC0, 0x48),
 386        _INIT_DCS_CMD(0xC1, 0x48),
 387        _INIT_DCS_CMD(0xC2, 0x47),
 388        _INIT_DCS_CMD(0xC3, 0x47),
 389        _INIT_DCS_CMD(0xC4, 0x46),
 390        _INIT_DCS_CMD(0xC5, 0x46),
 391        _INIT_DCS_CMD(0xC6, 0x45),
 392        _INIT_DCS_CMD(0xC7, 0x45),
 393        _INIT_DCS_CMD(0xC8, 0x64),
 394        _INIT_DCS_CMD(0xC9, 0x64),
 395        _INIT_DCS_CMD(0xCA, 0x4F),
 396        _INIT_DCS_CMD(0xCB, 0x4F),
 397        _INIT_DCS_CMD(0xCC, 0x40),
 398        _INIT_DCS_CMD(0xCD, 0x40),
 399        _INIT_DCS_CMD(0xCE, 0x66),
 400        _INIT_DCS_CMD(0xCF, 0x66),
 401        _INIT_DCS_CMD(0xD0, 0x4F),
 402        _INIT_DCS_CMD(0xD1, 0x4F),
 403        _INIT_DCS_CMD(0xD2, 0x41),
 404        _INIT_DCS_CMD(0xD3, 0x41),
 405        _INIT_DCS_CMD(0xD4, 0x48),
 406        _INIT_DCS_CMD(0xD5, 0x48),
 407        _INIT_DCS_CMD(0xD6, 0x47),
 408        _INIT_DCS_CMD(0xD7, 0x47),
 409        _INIT_DCS_CMD(0xD8, 0x46),
 410        _INIT_DCS_CMD(0xD9, 0x46),
 411        _INIT_DCS_CMD(0xDA, 0x45),
 412        _INIT_DCS_CMD(0xDB, 0x45),
 413        _INIT_DCS_CMD(0xDC, 0x64),
 414        _INIT_DCS_CMD(0xDD, 0x64),
 415        _INIT_DCS_CMD(0xDE, 0x4F),
 416        _INIT_DCS_CMD(0xDF, 0x4F),
 417        _INIT_DCS_CMD(0xE0, 0x40),
 418        _INIT_DCS_CMD(0xE1, 0x40),
 419        _INIT_DCS_CMD(0xE2, 0x66),
 420        _INIT_DCS_CMD(0xE3, 0x66),
 421        _INIT_DCS_CMD(0xE4, 0x4F),
 422        _INIT_DCS_CMD(0xE5, 0x4F),
 423        _INIT_DCS_CMD(0xE6, 0x41),
 424        _INIT_DCS_CMD(0xE7, 0x41),
 425        _INIT_DELAY_CMD(150),
 426        {},
 427};
 428
 429static inline struct boe_panel *to_boe_panel(struct drm_panel *panel)
 430{
 431        return container_of(panel, struct boe_panel, base);
 432}
 433
 434static int boe_panel_init_dcs_cmd(struct boe_panel *boe)
 435{
 436        struct mipi_dsi_device *dsi = boe->dsi;
 437        struct drm_panel *panel = &boe->base;
 438        int i, err = 0;
 439
 440        if (boe->desc->init_cmds) {
 441                const struct panel_init_cmd *init_cmds = boe->desc->init_cmds;
 442
 443                for (i = 0; init_cmds[i].len != 0; i++) {
 444                        const struct panel_init_cmd *cmd = &init_cmds[i];
 445
 446                        switch (cmd->type) {
 447                        case DELAY_CMD:
 448                                msleep(cmd->data[0]);
 449                                err = 0;
 450                                break;
 451
 452                        case INIT_DCS_CMD:
 453                                err = mipi_dsi_dcs_write(dsi, cmd->data[0],
 454                                                         cmd->len <= 1 ? NULL :
 455                                                         &cmd->data[1],
 456                                                         cmd->len - 1);
 457                                break;
 458
 459                        default:
 460                                err = -EINVAL;
 461                        }
 462
 463                        if (err < 0) {
 464                                dev_err(panel->dev,
 465                                        "failed to write command %u\n", i);
 466                                return err;
 467                        }
 468                }
 469        }
 470        return 0;
 471}
 472
 473static int boe_panel_enter_sleep_mode(struct boe_panel *boe)
 474{
 475        struct mipi_dsi_device *dsi = boe->dsi;
 476        int ret;
 477
 478        dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
 479
 480        ret = mipi_dsi_dcs_set_display_off(dsi);
 481        if (ret < 0)
 482                return ret;
 483
 484        ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
 485        if (ret < 0)
 486                return ret;
 487
 488        return 0;
 489}
 490
 491static int boe_panel_unprepare(struct drm_panel *panel)
 492{
 493        struct boe_panel *boe = to_boe_panel(panel);
 494        int ret;
 495
 496        if (!boe->prepared)
 497                return 0;
 498
 499        ret = boe_panel_enter_sleep_mode(boe);
 500        if (ret < 0) {
 501                dev_err(panel->dev, "failed to set panel off: %d\n", ret);
 502                return ret;
 503        }
 504
 505        msleep(150);
 506
 507        if (boe->desc->discharge_on_disable) {
 508                regulator_disable(boe->avee);
 509                regulator_disable(boe->avdd);
 510                usleep_range(5000, 7000);
 511                gpiod_set_value(boe->enable_gpio, 0);
 512                usleep_range(5000, 7000);
 513                regulator_disable(boe->pp1800);
 514        } else {
 515                gpiod_set_value(boe->enable_gpio, 0);
 516                usleep_range(500, 1000);
 517                regulator_disable(boe->avee);
 518                regulator_disable(boe->avdd);
 519                usleep_range(5000, 7000);
 520                regulator_disable(boe->pp1800);
 521        }
 522
 523        boe->prepared = false;
 524
 525        return 0;
 526}
 527
 528static int boe_panel_prepare(struct drm_panel *panel)
 529{
 530        struct boe_panel *boe = to_boe_panel(panel);
 531        int ret;
 532
 533        if (boe->prepared)
 534                return 0;
 535
 536        gpiod_set_value(boe->enable_gpio, 0);
 537        usleep_range(1000, 1500);
 538
 539        ret = regulator_enable(boe->pp1800);
 540        if (ret < 0)
 541                return ret;
 542
 543        usleep_range(3000, 5000);
 544
 545        ret = regulator_enable(boe->avdd);
 546        if (ret < 0)
 547                goto poweroff1v8;
 548        ret = regulator_enable(boe->avee);
 549        if (ret < 0)
 550                goto poweroffavdd;
 551
 552        usleep_range(5000, 10000);
 553
 554        gpiod_set_value(boe->enable_gpio, 1);
 555        usleep_range(1000, 2000);
 556        gpiod_set_value(boe->enable_gpio, 0);
 557        usleep_range(1000, 2000);
 558        gpiod_set_value(boe->enable_gpio, 1);
 559        usleep_range(6000, 10000);
 560
 561        ret = boe_panel_init_dcs_cmd(boe);
 562        if (ret < 0) {
 563                dev_err(panel->dev, "failed to init panel: %d\n", ret);
 564                goto poweroff;
 565        }
 566
 567        boe->prepared = true;
 568
 569        return 0;
 570
 571poweroff:
 572        regulator_disable(boe->avee);
 573poweroffavdd:
 574        regulator_disable(boe->avdd);
 575poweroff1v8:
 576        usleep_range(5000, 7000);
 577        regulator_disable(boe->pp1800);
 578        gpiod_set_value(boe->enable_gpio, 0);
 579
 580        return ret;
 581}
 582
 583static int boe_panel_enable(struct drm_panel *panel)
 584{
 585        msleep(130);
 586        return 0;
 587}
 588
 589static const struct drm_display_mode boe_tv101wum_nl6_default_mode = {
 590        .clock = 159425,
 591        .hdisplay = 1200,
 592        .hsync_start = 1200 + 100,
 593        .hsync_end = 1200 + 100 + 40,
 594        .htotal = 1200 + 100 + 40 + 24,
 595        .vdisplay = 1920,
 596        .vsync_start = 1920 + 10,
 597        .vsync_end = 1920 + 10 + 14,
 598        .vtotal = 1920 + 10 + 14 + 4,
 599};
 600
 601static const struct panel_desc boe_tv101wum_nl6_desc = {
 602        .modes = &boe_tv101wum_nl6_default_mode,
 603        .bpc = 8,
 604        .size = {
 605                .width_mm = 135,
 606                .height_mm = 216,
 607        },
 608        .lanes = 4,
 609        .format = MIPI_DSI_FMT_RGB888,
 610        .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
 611                      MIPI_DSI_MODE_LPM,
 612        .init_cmds = boe_init_cmd,
 613        .discharge_on_disable = false,
 614};
 615
 616static const struct drm_display_mode auo_kd101n80_45na_default_mode = {
 617        .clock = 157000,
 618        .hdisplay = 1200,
 619        .hsync_start = 1200 + 60,
 620        .hsync_end = 1200 + 60 + 24,
 621        .htotal = 1200 + 60 + 24 + 56,
 622        .vdisplay = 1920,
 623        .vsync_start = 1920 + 16,
 624        .vsync_end = 1920 + 16 + 4,
 625        .vtotal = 1920 + 16 + 4 + 16,
 626};
 627
 628static const struct panel_desc auo_kd101n80_45na_desc = {
 629        .modes = &auo_kd101n80_45na_default_mode,
 630        .bpc = 8,
 631        .size = {
 632                .width_mm = 135,
 633                .height_mm = 216,
 634        },
 635        .lanes = 4,
 636        .format = MIPI_DSI_FMT_RGB888,
 637        .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
 638                      MIPI_DSI_MODE_LPM,
 639        .init_cmds = auo_kd101n80_45na_init_cmd,
 640        .discharge_on_disable = true,
 641};
 642
 643static const struct drm_display_mode boe_tv101wum_n53_default_mode = {
 644        .clock = 159916,
 645        .hdisplay = 1200,
 646        .hsync_start = 1200 + 80,
 647        .hsync_end = 1200 + 80 + 24,
 648        .htotal = 1200 + 80 + 24 + 60,
 649        .vdisplay = 1920,
 650        .vsync_start = 1920 + 20,
 651        .vsync_end = 1920 + 20 + 4,
 652        .vtotal = 1920 + 20 + 4 + 10,
 653        .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 654};
 655
 656static const struct panel_desc boe_tv101wum_n53_desc = {
 657        .modes = &boe_tv101wum_n53_default_mode,
 658        .bpc = 8,
 659        .size = {
 660                .width_mm = 135,
 661                .height_mm = 216,
 662        },
 663        .lanes = 4,
 664        .format = MIPI_DSI_FMT_RGB888,
 665        .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
 666                      MIPI_DSI_MODE_LPM,
 667        .init_cmds = boe_init_cmd,
 668};
 669
 670static const struct drm_display_mode auo_b101uan08_3_default_mode = {
 671        .clock = 159667,
 672        .hdisplay = 1200,
 673        .hsync_start = 1200 + 60,
 674        .hsync_end = 1200 + 60 + 4,
 675        .htotal = 1200 + 60 + 4 + 80,
 676        .vdisplay = 1920,
 677        .vsync_start = 1920 + 34,
 678        .vsync_end = 1920 + 34 + 2,
 679        .vtotal = 1920 + 34 + 2 + 24,
 680        .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 681};
 682
 683static const struct panel_desc auo_b101uan08_3_desc = {
 684        .modes = &auo_b101uan08_3_default_mode,
 685        .bpc = 8,
 686        .size = {
 687                .width_mm = 135,
 688                .height_mm = 216,
 689        },
 690        .lanes = 4,
 691        .format = MIPI_DSI_FMT_RGB888,
 692        .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
 693                      MIPI_DSI_MODE_LPM,
 694        .init_cmds = auo_b101uan08_3_init_cmd,
 695};
 696
 697static const struct drm_display_mode boe_tv105wum_nw0_default_mode = {
 698        .clock = 159916,
 699        .hdisplay = 1200,
 700        .hsync_start = 1200 + 80,
 701        .hsync_end = 1200 + 80 + 24,
 702        .htotal = 1200 + 80 + 24 + 60,
 703        .vdisplay = 1920,
 704        .vsync_start = 1920 + 20,
 705        .vsync_end = 1920 + 20 + 4,
 706        .vtotal = 1920 + 20 + 4 + 10,
 707        .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 708};
 709
 710static const struct panel_desc boe_tv105wum_nw0_desc = {
 711        .modes = &boe_tv105wum_nw0_default_mode,
 712        .bpc = 8,
 713        .size = {
 714                .width_mm = 141,
 715                .height_mm = 226,
 716        },
 717        .lanes = 4,
 718        .format = MIPI_DSI_FMT_RGB888,
 719        .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
 720                      MIPI_DSI_MODE_LPM,
 721        .init_cmds = boe_init_cmd,
 722};
 723
 724static int boe_panel_get_modes(struct drm_panel *panel,
 725                               struct drm_connector *connector)
 726{
 727        struct boe_panel *boe = to_boe_panel(panel);
 728        const struct drm_display_mode *m = boe->desc->modes;
 729        struct drm_display_mode *mode;
 730
 731        mode = drm_mode_duplicate(connector->dev, m);
 732        if (!mode) {
 733                dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
 734                        m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
 735                return -ENOMEM;
 736        }
 737
 738        mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 739        drm_mode_set_name(mode);
 740        drm_mode_probed_add(connector, mode);
 741
 742        connector->display_info.width_mm = boe->desc->size.width_mm;
 743        connector->display_info.height_mm = boe->desc->size.height_mm;
 744        connector->display_info.bpc = boe->desc->bpc;
 745        drm_connector_set_panel_orientation(connector, boe->orientation);
 746
 747        return 1;
 748}
 749
 750static const struct drm_panel_funcs boe_panel_funcs = {
 751        .unprepare = boe_panel_unprepare,
 752        .prepare = boe_panel_prepare,
 753        .enable = boe_panel_enable,
 754        .get_modes = boe_panel_get_modes,
 755};
 756
 757static int boe_panel_add(struct boe_panel *boe)
 758{
 759        struct device *dev = &boe->dsi->dev;
 760        int err;
 761
 762        boe->avdd = devm_regulator_get(dev, "avdd");
 763        if (IS_ERR(boe->avdd))
 764                return PTR_ERR(boe->avdd);
 765
 766        boe->avee = devm_regulator_get(dev, "avee");
 767        if (IS_ERR(boe->avee))
 768                return PTR_ERR(boe->avee);
 769
 770        boe->pp1800 = devm_regulator_get(dev, "pp1800");
 771        if (IS_ERR(boe->pp1800))
 772                return PTR_ERR(boe->pp1800);
 773
 774        boe->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
 775        if (IS_ERR(boe->enable_gpio)) {
 776                dev_err(dev, "cannot get reset-gpios %ld\n",
 777                        PTR_ERR(boe->enable_gpio));
 778                return PTR_ERR(boe->enable_gpio);
 779        }
 780
 781        gpiod_set_value(boe->enable_gpio, 0);
 782
 783        drm_panel_init(&boe->base, dev, &boe_panel_funcs,
 784                       DRM_MODE_CONNECTOR_DSI);
 785        err = of_drm_get_panel_orientation(dev->of_node, &boe->orientation);
 786        if (err < 0) {
 787                dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err);
 788                return err;
 789        }
 790
 791        err = drm_panel_of_backlight(&boe->base);
 792        if (err)
 793                return err;
 794
 795        boe->base.funcs = &boe_panel_funcs;
 796        boe->base.dev = &boe->dsi->dev;
 797
 798        drm_panel_add(&boe->base);
 799
 800        return 0;
 801}
 802
 803static int boe_panel_probe(struct mipi_dsi_device *dsi)
 804{
 805        struct boe_panel *boe;
 806        int ret;
 807        const struct panel_desc *desc;
 808
 809        boe = devm_kzalloc(&dsi->dev, sizeof(*boe), GFP_KERNEL);
 810        if (!boe)
 811                return -ENOMEM;
 812
 813        desc = of_device_get_match_data(&dsi->dev);
 814        dsi->lanes = desc->lanes;
 815        dsi->format = desc->format;
 816        dsi->mode_flags = desc->mode_flags;
 817        boe->desc = desc;
 818        boe->dsi = dsi;
 819        ret = boe_panel_add(boe);
 820        if (ret < 0)
 821                return ret;
 822
 823        mipi_dsi_set_drvdata(dsi, boe);
 824
 825        ret = mipi_dsi_attach(dsi);
 826        if (ret)
 827                drm_panel_remove(&boe->base);
 828
 829        return ret;
 830}
 831
 832static void boe_panel_shutdown(struct mipi_dsi_device *dsi)
 833{
 834        struct boe_panel *boe = mipi_dsi_get_drvdata(dsi);
 835
 836        drm_panel_disable(&boe->base);
 837        drm_panel_unprepare(&boe->base);
 838}
 839
 840static int boe_panel_remove(struct mipi_dsi_device *dsi)
 841{
 842        struct boe_panel *boe = mipi_dsi_get_drvdata(dsi);
 843        int ret;
 844
 845        boe_panel_shutdown(dsi);
 846
 847        ret = mipi_dsi_detach(dsi);
 848        if (ret < 0)
 849                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
 850
 851        if (boe->base.dev)
 852                drm_panel_remove(&boe->base);
 853
 854        return 0;
 855}
 856
 857static const struct of_device_id boe_of_match[] = {
 858        { .compatible = "boe,tv101wum-nl6",
 859          .data = &boe_tv101wum_nl6_desc
 860        },
 861        { .compatible = "auo,kd101n80-45na",
 862          .data = &auo_kd101n80_45na_desc
 863        },
 864        { .compatible = "boe,tv101wum-n53",
 865          .data = &boe_tv101wum_n53_desc
 866        },
 867        { .compatible = "auo,b101uan08.3",
 868          .data = &auo_b101uan08_3_desc
 869        },
 870        { .compatible = "boe,tv105wum-nw0",
 871          .data = &boe_tv105wum_nw0_desc
 872        },
 873        { /* sentinel */ }
 874};
 875MODULE_DEVICE_TABLE(of, boe_of_match);
 876
 877static struct mipi_dsi_driver boe_panel_driver = {
 878        .driver = {
 879                .name = "panel-boe-tv101wum-nl6",
 880                .of_match_table = boe_of_match,
 881        },
 882        .probe = boe_panel_probe,
 883        .remove = boe_panel_remove,
 884        .shutdown = boe_panel_shutdown,
 885};
 886module_mipi_dsi_driver(boe_panel_driver);
 887
 888MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>");
 889MODULE_DESCRIPTION("BOE tv101wum-nl6 1200x1920 video mode panel driver");
 890MODULE_LICENSE("GPL v2");
 891