brintos

brintos / linux-shallow public Read only

0
0
Text · 25.2 KiB · ab8b585 Raw
784 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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.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		023#define S6E3HA2_MAX_BRIGHTNESS		10024#define S6E3HA2_DEFAULT_BRIGHTNESS	8025 26#define S6E3HA2_NUM_GAMMA_STEPS		4627#define S6E3HA2_GAMMA_CMD_CNT		3528#define S6E3HA2_VINT_STATUS_MAX		1029 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, 0x21220};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	else310		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 > BACKLIGHT_POWER_REDUCED)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 = BACKLIGHT_POWER_REDUCED;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 = BACKLIGHT_POWER_REDUCED;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 = BACKLIGHT_POWER_ON;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		MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP |697		MIPI_DSI_MODE_VIDEO_NO_HSA | MIPI_DSI_MODE_NO_EOT_PACKET;698 699	ctx->supplies[0].supply = "vdd3";700	ctx->supplies[1].supply = "vci";701 702	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),703				      ctx->supplies);704	if (ret < 0) {705		dev_err(dev, "failed to get regulators: %d\n", ret);706		return ret;707	}708 709	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);710	if (IS_ERR(ctx->reset_gpio)) {711		dev_err(dev, "cannot get reset-gpios %ld\n",712			PTR_ERR(ctx->reset_gpio));713		return PTR_ERR(ctx->reset_gpio);714	}715 716	ctx->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);717	if (IS_ERR(ctx->enable_gpio)) {718		dev_err(dev, "cannot get enable-gpios %ld\n",719			PTR_ERR(ctx->enable_gpio));720		return PTR_ERR(ctx->enable_gpio);721	}722 723	ctx->bl_dev = backlight_device_register("s6e3ha2", dev, ctx,724						&s6e3ha2_bl_ops, NULL);725	if (IS_ERR(ctx->bl_dev)) {726		dev_err(dev, "failed to register backlight device\n");727		return PTR_ERR(ctx->bl_dev);728	}729 730	ctx->bl_dev->props.max_brightness = S6E3HA2_MAX_BRIGHTNESS;731	ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS;732	ctx->bl_dev->props.power = BACKLIGHT_POWER_OFF;733 734	drm_panel_init(&ctx->panel, dev, &s6e3ha2_drm_funcs,735		       DRM_MODE_CONNECTOR_DSI);736	ctx->panel.prepare_prev_first = true;737 738	drm_panel_add(&ctx->panel);739 740	ret = mipi_dsi_attach(dsi);741	if (ret < 0)742		goto remove_panel;743 744	return ret;745 746remove_panel:747	drm_panel_remove(&ctx->panel);748	backlight_device_unregister(ctx->bl_dev);749 750	return ret;751}752 753static void s6e3ha2_remove(struct mipi_dsi_device *dsi)754{755	struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi);756 757	mipi_dsi_detach(dsi);758	drm_panel_remove(&ctx->panel);759	backlight_device_unregister(ctx->bl_dev);760}761 762static const struct of_device_id s6e3ha2_of_match[] = {763	{ .compatible = "samsung,s6e3ha2", .data = &samsung_s6e3ha2 },764	{ .compatible = "samsung,s6e3hf2", .data = &samsung_s6e3hf2 },765	{ }766};767MODULE_DEVICE_TABLE(of, s6e3ha2_of_match);768 769static struct mipi_dsi_driver s6e3ha2_driver = {770	.probe = s6e3ha2_probe,771	.remove = s6e3ha2_remove,772	.driver = {773		.name = "panel-samsung-s6e3ha2",774		.of_match_table = s6e3ha2_of_match,775	},776};777module_mipi_dsi_driver(s6e3ha2_driver);778 779MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");780MODULE_AUTHOR("Hyungwon Hwang <human.hwang@samsung.com>");781MODULE_AUTHOR("Hoegeun Kwon <hoegeun.kwon@samsung.com>");782MODULE_DESCRIPTION("MIPI-DSI based s6e3ha2 AMOLED Panel Driver");783MODULE_LICENSE("GPL v2");784