cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

panel-samsung-s6e3ha2.c (25633B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver.
      4 *
      5 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
      6 * Donghwa Lee <dh09.lee@samsung.com>
      7 * Hyungwon Hwang <human.hwang@samsung.com>
      8 * Hoegeun Kwon <hoegeun.kwon@samsung.com>
      9 */
     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_device.h>
     16#include <linux/regulator/consumer.h>
     17
     18#include <drm/drm_mipi_dsi.h>
     19#include <drm/drm_modes.h>
     20#include <drm/drm_panel.h>
     21
     22#define S6E3HA2_MIN_BRIGHTNESS		0
     23#define S6E3HA2_MAX_BRIGHTNESS		100
     24#define S6E3HA2_DEFAULT_BRIGHTNESS	80
     25
     26#define S6E3HA2_NUM_GAMMA_STEPS		46
     27#define S6E3HA2_GAMMA_CMD_CNT		35
     28#define S6E3HA2_VINT_STATUS_MAX		10
     29
     30static const u8 gamma_tbl[S6E3HA2_NUM_GAMMA_STEPS][S6E3HA2_GAMMA_CMD_CNT] = {
     31	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x82, 0x83,
     32	  0x85, 0x88, 0x8b, 0x8b, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8c,
     33	  0x94, 0x84, 0xb1, 0xaf, 0x8e, 0xcf, 0xad, 0xc9, 0x00, 0x00, 0x00,
     34	  0x00, 0x00 },
     35	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x84, 0x84,
     36	  0x85, 0x87, 0x8b, 0x8a, 0x84, 0x88, 0x82, 0x82, 0x89, 0x86, 0x8a,
     37	  0x93, 0x84, 0xb0, 0xae, 0x8e, 0xc9, 0xa8, 0xc5, 0x00, 0x00, 0x00,
     38	  0x00, 0x00 },
     39	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
     40	  0x85, 0x86, 0x8a, 0x8a, 0x84, 0x88, 0x81, 0x84, 0x8a, 0x88, 0x8a,
     41	  0x91, 0x84, 0xb1, 0xae, 0x8b, 0xd5, 0xb2, 0xcc, 0x00, 0x00, 0x00,
     42	  0x00, 0x00 },
     43	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
     44	  0x85, 0x86, 0x8a, 0x8a, 0x84, 0x87, 0x81, 0x84, 0x8a, 0x87, 0x8a,
     45	  0x91, 0x85, 0xae, 0xac, 0x8a, 0xc3, 0xa3, 0xc0, 0x00, 0x00, 0x00,
     46	  0x00, 0x00 },
     47	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x85, 0x85,
     48	  0x86, 0x85, 0x88, 0x89, 0x84, 0x89, 0x82, 0x84, 0x87, 0x85, 0x8b,
     49	  0x91, 0x88, 0xad, 0xab, 0x8a, 0xb7, 0x9b, 0xb6, 0x00, 0x00, 0x00,
     50	  0x00, 0x00 },
     51	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
     52	  0x85, 0x86, 0x89, 0x8a, 0x84, 0x89, 0x83, 0x83, 0x86, 0x84, 0x8b,
     53	  0x90, 0x84, 0xb0, 0xae, 0x8b, 0xce, 0xad, 0xc8, 0x00, 0x00, 0x00,
     54	  0x00, 0x00 },
     55	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
     56	  0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x89,
     57	  0x8f, 0x84, 0xac, 0xaa, 0x89, 0xb1, 0x98, 0xaf, 0x00, 0x00, 0x00,
     58	  0x00, 0x00 },
     59	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
     60	  0x85, 0x86, 0x88, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8c,
     61	  0x91, 0x86, 0xac, 0xaa, 0x89, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00,
     62	  0x00, 0x00 },
     63	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
     64	  0x85, 0x87, 0x89, 0x8a, 0x83, 0x87, 0x82, 0x85, 0x88, 0x87, 0x88,
     65	  0x8b, 0x82, 0xad, 0xaa, 0x8a, 0xc2, 0xa5, 0xbd, 0x00, 0x00, 0x00,
     66	  0x00, 0x00 },
     67	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x89, 0x87, 0x87, 0x83, 0x83,
     68	  0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x82, 0x85, 0x84, 0x8a,
     69	  0x8e, 0x84, 0xae, 0xac, 0x89, 0xda, 0xb7, 0xd0, 0x00, 0x00, 0x00,
     70	  0x00, 0x00 },
     71	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
     72	  0x85, 0x86, 0x87, 0x89, 0x84, 0x88, 0x83, 0x80, 0x83, 0x82, 0x8b,
     73	  0x8e, 0x85, 0xac, 0xaa, 0x89, 0xc8, 0xaa, 0xc1, 0x00, 0x00, 0x00,
     74	  0x00, 0x00 },
     75	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
     76	  0x85, 0x86, 0x87, 0x89, 0x81, 0x85, 0x81, 0x84, 0x86, 0x84, 0x8c,
     77	  0x8c, 0x84, 0xa9, 0xa8, 0x87, 0xa3, 0x92, 0xa1, 0x00, 0x00, 0x00,
     78	  0x00, 0x00 },
     79	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
     80	  0x85, 0x86, 0x87, 0x89, 0x84, 0x86, 0x83, 0x80, 0x83, 0x81, 0x8c,
     81	  0x8d, 0x84, 0xaa, 0xaa, 0x89, 0xce, 0xaf, 0xc5, 0x00, 0x00, 0x00,
     82	  0x00, 0x00 },
     83	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
     84	  0x85, 0x86, 0x87, 0x89, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c,
     85	  0x8c, 0x84, 0xa8, 0xa8, 0x88, 0xb5, 0x9f, 0xb0, 0x00, 0x00, 0x00,
     86	  0x00, 0x00 },
     87	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
     88	  0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x83, 0x85, 0x85, 0x8c,
     89	  0x8b, 0x84, 0xab, 0xa8, 0x86, 0xd4, 0xb4, 0xc9, 0x00, 0x00, 0x00,
     90	  0x00, 0x00 },
     91	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
     92	  0x86, 0x86, 0x87, 0x88, 0x81, 0x83, 0x80, 0x84, 0x84, 0x85, 0x8b,
     93	  0x8a, 0x83, 0xa6, 0xa5, 0x84, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00,
     94	  0x00, 0x00 },
     95	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x84, 0x84,
     96	  0x86, 0x85, 0x86, 0x86, 0x82, 0x85, 0x81, 0x82, 0x83, 0x84, 0x8e,
     97	  0x8b, 0x83, 0xa4, 0xa3, 0x8a, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00,
     98	  0x00, 0x00 },
     99	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
    100	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8e,
    101	  0x8b, 0x83, 0xa4, 0xa2, 0x86, 0xc1, 0xa9, 0xb7, 0x00, 0x00, 0x00,
    102	  0x00, 0x00 },
    103	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
    104	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x82, 0x82, 0x84, 0x8d,
    105	  0x89, 0x82, 0xa2, 0xa1, 0x84, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
    106	  0x00, 0x00 },
    107	{ 0x00, 0xb8, 0x00, 0xc3, 0x00, 0xb1, 0x88, 0x86, 0x87, 0x83, 0x83,
    108	  0x85, 0x86, 0x87, 0x87, 0x82, 0x85, 0x81, 0x83, 0x83, 0x85, 0x8c,
    109	  0x87, 0x7f, 0xa2, 0x9d, 0x88, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
    110	  0x00, 0x00 },
    111	{ 0x00, 0xbb, 0x00, 0xc5, 0x00, 0xb4, 0x87, 0x86, 0x86, 0x84, 0x83,
    112	  0x86, 0x87, 0x87, 0x87, 0x80, 0x82, 0x7f, 0x86, 0x86, 0x88, 0x8a,
    113	  0x84, 0x7e, 0x9d, 0x9c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
    114	  0x00, 0x00 },
    115	{ 0x00, 0xbd, 0x00, 0xc7, 0x00, 0xb7, 0x87, 0x85, 0x85, 0x84, 0x83,
    116	  0x86, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x83, 0x84, 0x85, 0x8a,
    117	  0x85, 0x7e, 0x9c, 0x9b, 0x85, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    118	  0x00, 0x00 },
    119	{ 0x00, 0xc0, 0x00, 0xca, 0x00, 0xbb, 0x87, 0x86, 0x85, 0x83, 0x83,
    120	  0x85, 0x86, 0x86, 0x88, 0x81, 0x83, 0x80, 0x84, 0x85, 0x86, 0x89,
    121	  0x83, 0x7d, 0x9c, 0x99, 0x87, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
    122	  0x00, 0x00 },
    123	{ 0x00, 0xc4, 0x00, 0xcd, 0x00, 0xbe, 0x87, 0x86, 0x85, 0x83, 0x83,
    124	  0x86, 0x85, 0x85, 0x87, 0x81, 0x82, 0x80, 0x82, 0x82, 0x83, 0x8a,
    125	  0x85, 0x7f, 0x9f, 0x9b, 0x86, 0xb4, 0xa1, 0xac, 0x00, 0x00, 0x00,
    126	  0x00, 0x00 },
    127	{ 0x00, 0xc7, 0x00, 0xd0, 0x00, 0xc2, 0x87, 0x85, 0x85, 0x83, 0x82,
    128	  0x85, 0x85, 0x85, 0x86, 0x82, 0x83, 0x80, 0x82, 0x82, 0x84, 0x87,
    129	  0x86, 0x80, 0x9e, 0x9a, 0x87, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
    130	  0x00, 0x00 },
    131	{ 0x00, 0xca, 0x00, 0xd2, 0x00, 0xc5, 0x87, 0x85, 0x84, 0x82, 0x82,
    132	  0x84, 0x85, 0x85, 0x86, 0x81, 0x82, 0x7f, 0x82, 0x82, 0x84, 0x88,
    133	  0x86, 0x81, 0x9d, 0x98, 0x86, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
    134	  0x00, 0x00 },
    135	{ 0x00, 0xce, 0x00, 0xd6, 0x00, 0xca, 0x86, 0x85, 0x84, 0x83, 0x83,
    136	  0x85, 0x84, 0x84, 0x85, 0x81, 0x82, 0x80, 0x81, 0x81, 0x82, 0x89,
    137	  0x86, 0x81, 0x9c, 0x97, 0x86, 0xa7, 0x98, 0xa1, 0x00, 0x00, 0x00,
    138	  0x00, 0x00 },
    139	{ 0x00, 0xd1, 0x00, 0xd9, 0x00, 0xce, 0x86, 0x84, 0x83, 0x83, 0x82,
    140	  0x85, 0x85, 0x85, 0x86, 0x81, 0x83, 0x81, 0x82, 0x82, 0x83, 0x86,
    141	  0x83, 0x7f, 0x99, 0x95, 0x86, 0xbb, 0xa4, 0xb3, 0x00, 0x00, 0x00,
    142	  0x00, 0x00 },
    143	{ 0x00, 0xd4, 0x00, 0xdb, 0x00, 0xd1, 0x86, 0x85, 0x83, 0x83, 0x82,
    144	  0x85, 0x84, 0x84, 0x85, 0x80, 0x83, 0x82, 0x80, 0x80, 0x81, 0x87,
    145	  0x84, 0x81, 0x98, 0x93, 0x85, 0xae, 0x9c, 0xa8, 0x00, 0x00, 0x00,
    146	  0x00, 0x00 },
    147	{ 0x00, 0xd8, 0x00, 0xde, 0x00, 0xd6, 0x86, 0x84, 0x83, 0x81, 0x81,
    148	  0x83, 0x85, 0x85, 0x85, 0x82, 0x83, 0x81, 0x81, 0x81, 0x83, 0x86,
    149	  0x84, 0x80, 0x98, 0x91, 0x85, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
    150	  0x00, 0x00 },
    151	{ 0x00, 0xdc, 0x00, 0xe2, 0x00, 0xda, 0x85, 0x84, 0x83, 0x82, 0x82,
    152	  0x84, 0x84, 0x84, 0x85, 0x81, 0x82, 0x82, 0x80, 0x80, 0x81, 0x83,
    153	  0x82, 0x7f, 0x99, 0x93, 0x86, 0x94, 0x8b, 0x92, 0x00, 0x00, 0x00,
    154	  0x00, 0x00 },
    155	{ 0x00, 0xdf, 0x00, 0xe5, 0x00, 0xde, 0x85, 0x84, 0x82, 0x82, 0x82,
    156	  0x84, 0x83, 0x83, 0x84, 0x81, 0x81, 0x80, 0x83, 0x82, 0x84, 0x82,
    157	  0x81, 0x7f, 0x99, 0x92, 0x86, 0x7b, 0x7b, 0x7c, 0x00, 0x00, 0x00,
    158	  0x00, 0x00 },
    159	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
    160	  0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x83, 0x83, 0x84, 0x80,
    161	  0x81, 0x7c, 0x99, 0x92, 0x87, 0xa1, 0x93, 0x9d, 0x00, 0x00, 0x00,
    162	  0x00, 0x00 },
    163	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x85, 0x84, 0x83, 0x81, 0x81,
    164	  0x82, 0x82, 0x82, 0x83, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83,
    165	  0x82, 0x80, 0x91, 0x8d, 0x83, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00,
    166	  0x00, 0x00 },
    167	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
    168	  0x82, 0x83, 0x83, 0x84, 0x80, 0x81, 0x80, 0x81, 0x80, 0x82, 0x83,
    169	  0x81, 0x7f, 0x91, 0x8c, 0x82, 0x8d, 0x88, 0x8b, 0x00, 0x00, 0x00,
    170	  0x00, 0x00 },
    171	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
    172	  0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x82,
    173	  0x82, 0x7f, 0x94, 0x89, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    174	  0x00, 0x00 },
    175	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
    176	  0x82, 0x83, 0x83, 0x83, 0x82, 0x82, 0x81, 0x81, 0x80, 0x82, 0x83,
    177	  0x82, 0x7f, 0x91, 0x85, 0x81, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    178	  0x00, 0x00 },
    179	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x81, 0x81,
    180	  0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x83, 0x82, 0x84, 0x83,
    181	  0x82, 0x7f, 0x90, 0x84, 0x81, 0x9a, 0x90, 0x96, 0x00, 0x00, 0x00,
    182	  0x00, 0x00 },
    183	{ 0x00, 0xe4, 0x00, 0xe9, 0x00, 0xe3, 0x84, 0x83, 0x82, 0x80, 0x80,
    184	  0x82, 0x83, 0x83, 0x83, 0x80, 0x80, 0x7f, 0x80, 0x80, 0x81, 0x81,
    185	  0x82, 0x83, 0x7e, 0x80, 0x7c, 0xa4, 0x97, 0x9f, 0x00, 0x00, 0x00,
    186	  0x00, 0x00 },
    187	{ 0x00, 0xe9, 0x00, 0xec, 0x00, 0xe8, 0x84, 0x83, 0x82, 0x81, 0x81,
    188	  0x82, 0x82, 0x82, 0x83, 0x7f, 0x7f, 0x7f, 0x81, 0x80, 0x82, 0x83,
    189	  0x83, 0x84, 0x79, 0x7c, 0x79, 0xb1, 0xa0, 0xaa, 0x00, 0x00, 0x00,
    190	  0x00, 0x00 },
    191	{ 0x00, 0xed, 0x00, 0xf0, 0x00, 0xec, 0x83, 0x83, 0x82, 0x80, 0x80,
    192	  0x81, 0x82, 0x82, 0x82, 0x7f, 0x7f, 0x7e, 0x81, 0x81, 0x82, 0x80,
    193	  0x81, 0x81, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    194	  0x00, 0x00 },
    195	{ 0x00, 0xf1, 0x00, 0xf4, 0x00, 0xf1, 0x83, 0x82, 0x82, 0x80, 0x80,
    196	  0x81, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x7d,
    197	  0x7e, 0x7f, 0x84, 0x84, 0x83, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    198	  0x00, 0x00 },
    199	{ 0x00, 0xf6, 0x00, 0xf7, 0x00, 0xf5, 0x82, 0x82, 0x81, 0x80, 0x80,
    200	  0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x7f, 0x7f, 0x7f, 0x82,
    201	  0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    202	  0x00, 0x00 },
    203	{ 0x00, 0xfa, 0x00, 0xfb, 0x00, 0xfa, 0x81, 0x81, 0x81, 0x80, 0x80,
    204	  0x80, 0x82, 0x82, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    205	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    206	  0x00, 0x00 },
    207	{ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
    208	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    209	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    210	  0x00, 0x00 },
    211	{ 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
    212	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    213	  0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    214	  0x00, 0x00 }
    215};
    216
    217static const unsigned char vint_table[S6E3HA2_VINT_STATUS_MAX] = {
    218	0x18, 0x19, 0x1a, 0x1b, 0x1c,
    219	0x1d, 0x1e, 0x1f, 0x20, 0x21
    220};
    221
    222enum s6e3ha2_type {
    223	HA2_TYPE,
    224	HF2_TYPE,
    225};
    226
    227struct s6e3ha2_panel_desc {
    228	const struct drm_display_mode *mode;
    229	enum s6e3ha2_type type;
    230};
    231
    232struct s6e3ha2 {
    233	struct device *dev;
    234	struct drm_panel panel;
    235	struct backlight_device *bl_dev;
    236
    237	struct regulator_bulk_data supplies[2];
    238	struct gpio_desc *reset_gpio;
    239	struct gpio_desc *enable_gpio;
    240
    241	const struct s6e3ha2_panel_desc *desc;
    242};
    243
    244static int s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len)
    245{
    246	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
    247
    248	return mipi_dsi_dcs_write_buffer(dsi, data, len);
    249}
    250
    251#define s6e3ha2_dcs_write_seq_static(ctx, seq...) do {	\
    252	static const u8 d[] = { seq };			\
    253	int ret;					\
    254	ret = s6e3ha2_dcs_write(ctx, d, ARRAY_SIZE(d));	\
    255	if (ret < 0)					\
    256		return ret;				\
    257} while (0)
    258
    259#define s6e3ha2_call_write_func(ret, func) do {	\
    260	ret = (func);				\
    261	if (ret < 0)				\
    262		return ret;			\
    263} while (0)
    264
    265static int s6e3ha2_test_key_on_f0(struct s6e3ha2 *ctx)
    266{
    267	s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
    268	return 0;
    269}
    270
    271static int s6e3ha2_test_key_off_f0(struct s6e3ha2 *ctx)
    272{
    273	s6e3ha2_dcs_write_seq_static(ctx, 0xf0, 0xa5, 0xa5);
    274	return 0;
    275}
    276
    277static int s6e3ha2_test_key_on_fc(struct s6e3ha2 *ctx)
    278{
    279	s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
    280	return 0;
    281}
    282
    283static int s6e3ha2_test_key_off_fc(struct s6e3ha2 *ctx)
    284{
    285	s6e3ha2_dcs_write_seq_static(ctx, 0xfc, 0xa5, 0xa5);
    286	return 0;
    287}
    288
    289static int s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx)
    290{
    291	s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67);
    292	s6e3ha2_dcs_write_seq_static(ctx, 0xf9, 0x09);
    293	return 0;
    294}
    295
    296static int s6e3ha2_freq_calibration(struct s6e3ha2 *ctx)
    297{
    298	s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c);
    299	if (ctx->desc->type == HF2_TYPE)
    300		s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67, 0x40, 0xc5);
    301	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39);
    302	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0);
    303	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20);
    304
    305	if (ctx->desc->type == HA2_TYPE)
    306		s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62,
    307						  0x40, 0x80, 0xc0, 0x28, 0x28,
    308						  0x28, 0x28, 0x39, 0xc5);
    309	else
    310		s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x14, 0x6d,
    311						  0x40, 0x80, 0xc0, 0x28, 0x28,
    312						  0x28, 0x28, 0x39, 0xc5);
    313
    314	return 0;
    315}
    316
    317static int s6e3ha2_aor_control(struct s6e3ha2 *ctx)
    318{
    319	s6e3ha2_dcs_write_seq_static(ctx, 0xb2, 0x03, 0x10);
    320	return 0;
    321}
    322
    323static int s6e3ha2_caps_elvss_set(struct s6e3ha2 *ctx)
    324{
    325	s6e3ha2_dcs_write_seq_static(ctx, 0xb6, 0x9c, 0x0a);
    326	return 0;
    327}
    328
    329static int s6e3ha2_acl_off(struct s6e3ha2 *ctx)
    330{
    331	s6e3ha2_dcs_write_seq_static(ctx, 0x55, 0x00);
    332	return 0;
    333}
    334
    335static int s6e3ha2_acl_off_opr(struct s6e3ha2 *ctx)
    336{
    337	s6e3ha2_dcs_write_seq_static(ctx, 0xb5, 0x40);
    338	return 0;
    339}
    340
    341static int s6e3ha2_test_global(struct s6e3ha2 *ctx)
    342{
    343	s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x07);
    344	return 0;
    345}
    346
    347static int s6e3ha2_test(struct s6e3ha2 *ctx)
    348{
    349	s6e3ha2_dcs_write_seq_static(ctx, 0xb8, 0x19);
    350	return 0;
    351}
    352
    353static int s6e3ha2_touch_hsync_on1(struct s6e3ha2 *ctx)
    354{
    355	s6e3ha2_dcs_write_seq_static(ctx, 0xbd, 0x33, 0x11, 0x02,
    356					0x16, 0x02, 0x16);
    357	return 0;
    358}
    359
    360static int s6e3ha2_pentile_control(struct s6e3ha2 *ctx)
    361{
    362	s6e3ha2_dcs_write_seq_static(ctx, 0xc0, 0x00, 0x00, 0xd8, 0xd8);
    363	return 0;
    364}
    365
    366static int s6e3ha2_poc_global(struct s6e3ha2 *ctx)
    367{
    368	s6e3ha2_dcs_write_seq_static(ctx, 0xb0, 0x20);
    369	return 0;
    370}
    371
    372static int s6e3ha2_poc_setting(struct s6e3ha2 *ctx)
    373{
    374	s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x08);
    375	return 0;
    376}
    377
    378static int s6e3ha2_pcd_set_off(struct s6e3ha2 *ctx)
    379{
    380	s6e3ha2_dcs_write_seq_static(ctx, 0xcc, 0x40, 0x51);
    381	return 0;
    382}
    383
    384static int s6e3ha2_err_fg_set(struct s6e3ha2 *ctx)
    385{
    386	s6e3ha2_dcs_write_seq_static(ctx, 0xed, 0x44);
    387	return 0;
    388}
    389
    390static int s6e3ha2_hbm_off(struct s6e3ha2 *ctx)
    391{
    392	s6e3ha2_dcs_write_seq_static(ctx, 0x53, 0x00);
    393	return 0;
    394}
    395
    396static int s6e3ha2_te_start_setting(struct s6e3ha2 *ctx)
    397{
    398	s6e3ha2_dcs_write_seq_static(ctx, 0xb9, 0x10, 0x09, 0xff, 0x00, 0x09);
    399	return 0;
    400}
    401
    402static int s6e3ha2_gamma_update(struct s6e3ha2 *ctx)
    403{
    404	s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x03);
    405	ndelay(100); /* need for 100ns delay */
    406	s6e3ha2_dcs_write_seq_static(ctx, 0xf7, 0x00);
    407	return 0;
    408}
    409
    410static int s6e3ha2_get_brightness(struct backlight_device *bl_dev)
    411{
    412	return bl_dev->props.brightness;
    413}
    414
    415static int s6e3ha2_set_vint(struct s6e3ha2 *ctx)
    416{
    417	struct backlight_device *bl_dev = ctx->bl_dev;
    418	unsigned int brightness = bl_dev->props.brightness;
    419	unsigned char data[] = { 0xf4, 0x8b,
    420			vint_table[brightness * (S6E3HA2_VINT_STATUS_MAX - 1) /
    421			S6E3HA2_MAX_BRIGHTNESS] };
    422
    423	return s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data));
    424}
    425
    426static unsigned int s6e3ha2_get_brightness_index(unsigned int brightness)
    427{
    428	return (brightness * (S6E3HA2_NUM_GAMMA_STEPS - 1)) /
    429		S6E3HA2_MAX_BRIGHTNESS;
    430}
    431
    432static int s6e3ha2_update_gamma(struct s6e3ha2 *ctx, unsigned int brightness)
    433{
    434	struct backlight_device *bl_dev = ctx->bl_dev;
    435	unsigned int index = s6e3ha2_get_brightness_index(brightness);
    436	u8 data[S6E3HA2_GAMMA_CMD_CNT + 1] = { 0xca, };
    437	int ret;
    438
    439	memcpy(data + 1, gamma_tbl + index, S6E3HA2_GAMMA_CMD_CNT);
    440	s6e3ha2_call_write_func(ret,
    441				s6e3ha2_dcs_write(ctx, data, ARRAY_SIZE(data)));
    442
    443	s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx));
    444	bl_dev->props.brightness = brightness;
    445
    446	return 0;
    447}
    448
    449static int s6e3ha2_set_brightness(struct backlight_device *bl_dev)
    450{
    451	struct s6e3ha2 *ctx = bl_get_data(bl_dev);
    452	unsigned int brightness = bl_dev->props.brightness;
    453	int ret;
    454
    455	if (brightness < S6E3HA2_MIN_BRIGHTNESS ||
    456		brightness > bl_dev->props.max_brightness) {
    457		dev_err(ctx->dev, "Invalid brightness: %u\n", brightness);
    458		return -EINVAL;
    459	}
    460
    461	if (bl_dev->props.power > FB_BLANK_NORMAL)
    462		return -EPERM;
    463
    464	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx));
    465	s6e3ha2_call_write_func(ret, s6e3ha2_update_gamma(ctx, brightness));
    466	s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx));
    467	s6e3ha2_call_write_func(ret, s6e3ha2_set_vint(ctx));
    468	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx));
    469
    470	return 0;
    471}
    472
    473static const struct backlight_ops s6e3ha2_bl_ops = {
    474	.get_brightness = s6e3ha2_get_brightness,
    475	.update_status = s6e3ha2_set_brightness,
    476};
    477
    478static int s6e3ha2_panel_init(struct s6e3ha2 *ctx)
    479{
    480	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
    481	int ret;
    482
    483	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_exit_sleep_mode(dsi));
    484	usleep_range(5000, 6000);
    485
    486	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx));
    487	s6e3ha2_call_write_func(ret, s6e3ha2_single_dsi_set(ctx));
    488	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx));
    489	s6e3ha2_call_write_func(ret, s6e3ha2_freq_calibration(ctx));
    490	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx));
    491	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx));
    492
    493	return 0;
    494}
    495
    496static int s6e3ha2_power_off(struct s6e3ha2 *ctx)
    497{
    498	return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
    499}
    500
    501static int s6e3ha2_disable(struct drm_panel *panel)
    502{
    503	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
    504	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
    505	int ret;
    506
    507	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_enter_sleep_mode(dsi));
    508	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_off(dsi));
    509
    510	msleep(40);
    511	ctx->bl_dev->props.power = FB_BLANK_NORMAL;
    512
    513	return 0;
    514}
    515
    516static int s6e3ha2_unprepare(struct drm_panel *panel)
    517{
    518	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
    519
    520	return s6e3ha2_power_off(ctx);
    521}
    522
    523static int s6e3ha2_power_on(struct s6e3ha2 *ctx)
    524{
    525	int ret;
    526
    527	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
    528	if (ret < 0)
    529		return ret;
    530
    531	msleep(120);
    532
    533	gpiod_set_value(ctx->enable_gpio, 0);
    534	usleep_range(5000, 6000);
    535	gpiod_set_value(ctx->enable_gpio, 1);
    536
    537	gpiod_set_value(ctx->reset_gpio, 1);
    538	usleep_range(5000, 6000);
    539	gpiod_set_value(ctx->reset_gpio, 0);
    540	usleep_range(5000, 6000);
    541
    542	return 0;
    543}
    544static int s6e3ha2_prepare(struct drm_panel *panel)
    545{
    546	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
    547	int ret;
    548
    549	ret = s6e3ha2_power_on(ctx);
    550	if (ret < 0)
    551		return ret;
    552
    553	ret = s6e3ha2_panel_init(ctx);
    554	if (ret < 0)
    555		goto err;
    556
    557	ctx->bl_dev->props.power = FB_BLANK_NORMAL;
    558
    559	return 0;
    560
    561err:
    562	s6e3ha2_power_off(ctx);
    563	return ret;
    564}
    565
    566static int s6e3ha2_enable(struct drm_panel *panel)
    567{
    568	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
    569	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
    570	int ret;
    571
    572	/* common setting */
    573	s6e3ha2_call_write_func(ret,
    574		mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK));
    575
    576	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_f0(ctx));
    577	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_on_fc(ctx));
    578	s6e3ha2_call_write_func(ret, s6e3ha2_touch_hsync_on1(ctx));
    579	s6e3ha2_call_write_func(ret, s6e3ha2_pentile_control(ctx));
    580	s6e3ha2_call_write_func(ret, s6e3ha2_poc_global(ctx));
    581	s6e3ha2_call_write_func(ret, s6e3ha2_poc_setting(ctx));
    582	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_fc(ctx));
    583
    584	/* pcd setting off for TB */
    585	s6e3ha2_call_write_func(ret, s6e3ha2_pcd_set_off(ctx));
    586	s6e3ha2_call_write_func(ret, s6e3ha2_err_fg_set(ctx));
    587	s6e3ha2_call_write_func(ret, s6e3ha2_te_start_setting(ctx));
    588
    589	/* brightness setting */
    590	s6e3ha2_call_write_func(ret, s6e3ha2_set_brightness(ctx->bl_dev));
    591	s6e3ha2_call_write_func(ret, s6e3ha2_aor_control(ctx));
    592	s6e3ha2_call_write_func(ret, s6e3ha2_caps_elvss_set(ctx));
    593	s6e3ha2_call_write_func(ret, s6e3ha2_gamma_update(ctx));
    594	s6e3ha2_call_write_func(ret, s6e3ha2_acl_off(ctx));
    595	s6e3ha2_call_write_func(ret, s6e3ha2_acl_off_opr(ctx));
    596	s6e3ha2_call_write_func(ret, s6e3ha2_hbm_off(ctx));
    597
    598	/* elvss temp compensation */
    599	s6e3ha2_call_write_func(ret, s6e3ha2_test_global(ctx));
    600	s6e3ha2_call_write_func(ret, s6e3ha2_test(ctx));
    601	s6e3ha2_call_write_func(ret, s6e3ha2_test_key_off_f0(ctx));
    602
    603	s6e3ha2_call_write_func(ret, mipi_dsi_dcs_set_display_on(dsi));
    604	ctx->bl_dev->props.power = FB_BLANK_UNBLANK;
    605
    606	return 0;
    607}
    608
    609static const struct drm_display_mode s6e3ha2_mode = {
    610	.clock = 222372,
    611	.hdisplay = 1440,
    612	.hsync_start = 1440 + 1,
    613	.hsync_end = 1440 + 1 + 1,
    614	.htotal = 1440 + 1 + 1 + 1,
    615	.vdisplay = 2560,
    616	.vsync_start = 2560 + 1,
    617	.vsync_end = 2560 + 1 + 1,
    618	.vtotal = 2560 + 1 + 1 + 15,
    619	.flags = 0,
    620};
    621
    622static const struct s6e3ha2_panel_desc samsung_s6e3ha2 = {
    623	.mode = &s6e3ha2_mode,
    624	.type = HA2_TYPE,
    625};
    626
    627static const struct drm_display_mode s6e3hf2_mode = {
    628	.clock = 247856,
    629	.hdisplay = 1600,
    630	.hsync_start = 1600 + 1,
    631	.hsync_end = 1600 + 1 + 1,
    632	.htotal = 1600 + 1 + 1 + 1,
    633	.vdisplay = 2560,
    634	.vsync_start = 2560 + 1,
    635	.vsync_end = 2560 + 1 + 1,
    636	.vtotal = 2560 + 1 + 1 + 15,
    637	.flags = 0,
    638};
    639
    640static const struct s6e3ha2_panel_desc samsung_s6e3hf2 = {
    641	.mode = &s6e3hf2_mode,
    642	.type = HF2_TYPE,
    643};
    644
    645static int s6e3ha2_get_modes(struct drm_panel *panel,
    646			     struct drm_connector *connector)
    647{
    648	struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
    649	struct drm_display_mode *mode;
    650
    651	mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
    652	if (!mode) {
    653		dev_err(panel->dev, "failed to add mode %ux%u@%u\n",
    654			ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
    655			drm_mode_vrefresh(ctx->desc->mode));
    656		return -ENOMEM;
    657	}
    658
    659	drm_mode_set_name(mode);
    660
    661	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
    662	drm_mode_probed_add(connector, mode);
    663
    664	connector->display_info.width_mm = 71;
    665	connector->display_info.height_mm = 125;
    666
    667	return 1;
    668}
    669
    670static const struct drm_panel_funcs s6e3ha2_drm_funcs = {
    671	.disable = s6e3ha2_disable,
    672	.unprepare = s6e3ha2_unprepare,
    673	.prepare = s6e3ha2_prepare,
    674	.enable = s6e3ha2_enable,
    675	.get_modes = s6e3ha2_get_modes,
    676};
    677
    678static int s6e3ha2_probe(struct mipi_dsi_device *dsi)
    679{
    680	struct device *dev = &dsi->dev;
    681	struct s6e3ha2 *ctx;
    682	int ret;
    683
    684	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
    685	if (!ctx)
    686		return -ENOMEM;
    687
    688	mipi_dsi_set_drvdata(dsi, ctx);
    689
    690	ctx->dev = dev;
    691	ctx->desc = of_device_get_match_data(dev);
    692
    693	dsi->lanes = 4;
    694	dsi->format = MIPI_DSI_FMT_RGB888;
    695	dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS;
    696
    697	ctx->supplies[0].supply = "vdd3";
    698	ctx->supplies[1].supply = "vci";
    699
    700	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
    701				      ctx->supplies);
    702	if (ret < 0) {
    703		dev_err(dev, "failed to get regulators: %d\n", ret);
    704		return ret;
    705	}
    706
    707	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
    708	if (IS_ERR(ctx->reset_gpio)) {
    709		dev_err(dev, "cannot get reset-gpios %ld\n",
    710			PTR_ERR(ctx->reset_gpio));
    711		return PTR_ERR(ctx->reset_gpio);
    712	}
    713
    714	ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
    715	if (IS_ERR(ctx->enable_gpio)) {
    716		dev_err(dev, "cannot get enable-gpios %ld\n",
    717			PTR_ERR(ctx->enable_gpio));
    718		return PTR_ERR(ctx->enable_gpio);
    719	}
    720
    721	ctx->bl_dev = backlight_device_register("s6e3ha2", dev, ctx,
    722						&s6e3ha2_bl_ops, NULL);
    723	if (IS_ERR(ctx->bl_dev)) {
    724		dev_err(dev, "failed to register backlight device\n");
    725		return PTR_ERR(ctx->bl_dev);
    726	}
    727
    728	ctx->bl_dev->props.max_brightness = S6E3HA2_MAX_BRIGHTNESS;
    729	ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS;
    730	ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
    731
    732	drm_panel_init(&ctx->panel, dev, &s6e3ha2_drm_funcs,
    733		       DRM_MODE_CONNECTOR_DSI);
    734
    735	drm_panel_add(&ctx->panel);
    736
    737	ret = mipi_dsi_attach(dsi);
    738	if (ret < 0)
    739		goto remove_panel;
    740
    741	return ret;
    742
    743remove_panel:
    744	drm_panel_remove(&ctx->panel);
    745	backlight_device_unregister(ctx->bl_dev);
    746
    747	return ret;
    748}
    749
    750static int s6e3ha2_remove(struct mipi_dsi_device *dsi)
    751{
    752	struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi);
    753
    754	mipi_dsi_detach(dsi);
    755	drm_panel_remove(&ctx->panel);
    756	backlight_device_unregister(ctx->bl_dev);
    757
    758	return 0;
    759}
    760
    761static const struct of_device_id s6e3ha2_of_match[] = {
    762	{ .compatible = "samsung,s6e3ha2", .data = &samsung_s6e3ha2 },
    763	{ .compatible = "samsung,s6e3hf2", .data = &samsung_s6e3hf2 },
    764	{ }
    765};
    766MODULE_DEVICE_TABLE(of, s6e3ha2_of_match);
    767
    768static struct mipi_dsi_driver s6e3ha2_driver = {
    769	.probe = s6e3ha2_probe,
    770	.remove = s6e3ha2_remove,
    771	.driver = {
    772		.name = "panel-samsung-s6e3ha2",
    773		.of_match_table = s6e3ha2_of_match,
    774	},
    775};
    776module_mipi_dsi_driver(s6e3ha2_driver);
    777
    778MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
    779MODULE_AUTHOR("Hyungwon Hwang <human.hwang@samsung.com>");
    780MODULE_AUTHOR("Hoegeun Kwon <hoegeun.kwon@samsung.com>");
    781MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver");
    782MODULE_LICENSE("GPL v2");