Linux Audio

Check our new training course

Loading...
v5.4
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * MIPI-DSI based s6e8aa0 AMOLED LCD 5.3 inch panel driver.
   4 *
   5 * Copyright (c) 2013 Samsung Electronics Co., Ltd
   6 *
   7 * Inki Dae, <inki.dae@samsung.com>
   8 * Donghwa Lee, <dh09.lee@samsung.com>
   9 * Joongmock Shin <jmock.shin@samsung.com>
  10 * Eunchul Kim <chulspro.kim@samsung.com>
  11 * Tomasz Figa <t.figa@samsung.com>
  12 * Andrzej Hajda <a.hajda@samsung.com>
 
 
 
 
  13*/
  14
  15#include <linux/delay.h>
 
 
 
  16#include <linux/gpio/consumer.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19#include <linux/regulator/consumer.h>
  20
  21#include <video/mipi_display.h>
  22#include <video/of_videomode.h>
  23#include <video/videomode.h>
  24
  25#include <drm/drm_mipi_dsi.h>
  26#include <drm/drm_modes.h>
  27#include <drm/drm_panel.h>
  28#include <drm/drm_print.h>
  29
  30#define LDI_MTP_LENGTH			24
  31#define GAMMA_LEVEL_NUM			25
  32#define GAMMA_TABLE_LEN			26
  33
  34#define PANELCTL_SS_MASK		(1 << 5)
  35#define PANELCTL_SS_1_800		(0 << 5)
  36#define PANELCTL_SS_800_1		(1 << 5)
  37#define PANELCTL_GTCON_MASK		(7 << 2)
  38#define PANELCTL_GTCON_110		(6 << 2)
  39#define PANELCTL_GTCON_111		(7 << 2)
  40
  41#define PANELCTL_CLK1_CON_MASK		(7 << 3)
  42#define PANELCTL_CLK1_000		(0 << 3)
  43#define PANELCTL_CLK1_001		(1 << 3)
  44#define PANELCTL_CLK2_CON_MASK		(7 << 0)
  45#define PANELCTL_CLK2_000		(0 << 0)
  46#define PANELCTL_CLK2_001		(1 << 0)
  47
  48#define PANELCTL_INT1_CON_MASK		(7 << 3)
  49#define PANELCTL_INT1_000		(0 << 3)
  50#define PANELCTL_INT1_001		(1 << 3)
  51#define PANELCTL_INT2_CON_MASK		(7 << 0)
  52#define PANELCTL_INT2_000		(0 << 0)
  53#define PANELCTL_INT2_001		(1 << 0)
  54
  55#define PANELCTL_BICTL_CON_MASK		(7 << 3)
  56#define PANELCTL_BICTL_000		(0 << 3)
  57#define PANELCTL_BICTL_001		(1 << 3)
  58#define PANELCTL_BICTLB_CON_MASK	(7 << 0)
  59#define PANELCTL_BICTLB_000		(0 << 0)
  60#define PANELCTL_BICTLB_001		(1 << 0)
  61
  62#define PANELCTL_EM_CLK1_CON_MASK	(7 << 3)
  63#define PANELCTL_EM_CLK1_110		(6 << 3)
  64#define PANELCTL_EM_CLK1_111		(7 << 3)
  65#define PANELCTL_EM_CLK1B_CON_MASK	(7 << 0)
  66#define PANELCTL_EM_CLK1B_110		(6 << 0)
  67#define PANELCTL_EM_CLK1B_111		(7 << 0)
  68
  69#define PANELCTL_EM_CLK2_CON_MASK	(7 << 3)
  70#define PANELCTL_EM_CLK2_110		(6 << 3)
  71#define PANELCTL_EM_CLK2_111		(7 << 3)
  72#define PANELCTL_EM_CLK2B_CON_MASK	(7 << 0)
  73#define PANELCTL_EM_CLK2B_110		(6 << 0)
  74#define PANELCTL_EM_CLK2B_111		(7 << 0)
  75
  76#define PANELCTL_EM_INT1_CON_MASK	(7 << 3)
  77#define PANELCTL_EM_INT1_000		(0 << 3)
  78#define PANELCTL_EM_INT1_001		(1 << 3)
  79#define PANELCTL_EM_INT2_CON_MASK	(7 << 0)
  80#define PANELCTL_EM_INT2_000		(0 << 0)
  81#define PANELCTL_EM_INT2_001		(1 << 0)
  82
  83#define AID_DISABLE			(0x4)
  84#define AID_1				(0x5)
  85#define AID_2				(0x6)
  86#define AID_3				(0x7)
  87
  88typedef u8 s6e8aa0_gamma_table[GAMMA_TABLE_LEN];
  89
  90struct s6e8aa0_variant {
  91	u8 version;
  92	const s6e8aa0_gamma_table *gamma_tables;
  93};
  94
  95struct s6e8aa0 {
  96	struct device *dev;
  97	struct drm_panel panel;
  98
  99	struct regulator_bulk_data supplies[2];
 100	struct gpio_desc *reset_gpio;
 101	u32 power_on_delay;
 102	u32 reset_delay;
 103	u32 init_delay;
 104	bool flip_horizontal;
 105	bool flip_vertical;
 106	struct videomode vm;
 107	u32 width_mm;
 108	u32 height_mm;
 109
 110	u8 version;
 111	u8 id;
 112	const struct s6e8aa0_variant *variant;
 113	int brightness;
 114
 115	/* This field is tested by functions directly accessing DSI bus before
 116	 * transfer, transfer is skipped if it is set. In case of transfer
 117	 * failure or unexpected response the field is set to error value.
 118	 * Such construct allows to eliminate many checks in higher level
 119	 * functions.
 120	 */
 121	int error;
 122};
 123
 124static inline struct s6e8aa0 *panel_to_s6e8aa0(struct drm_panel *panel)
 125{
 126	return container_of(panel, struct s6e8aa0, panel);
 127}
 128
 129static int s6e8aa0_clear_error(struct s6e8aa0 *ctx)
 130{
 131	int ret = ctx->error;
 132
 133	ctx->error = 0;
 134	return ret;
 135}
 136
 137static void s6e8aa0_dcs_write(struct s6e8aa0 *ctx, const void *data, size_t len)
 138{
 139	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 140	ssize_t ret;
 141
 142	if (ctx->error < 0)
 143		return;
 144
 145	ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
 146	if (ret < 0) {
 147		dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret,
 148			(int)len, data);
 149		ctx->error = ret;
 150	}
 151}
 152
 153static int s6e8aa0_dcs_read(struct s6e8aa0 *ctx, u8 cmd, void *data, size_t len)
 154{
 155	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 156	int ret;
 157
 158	if (ctx->error < 0)
 159		return ctx->error;
 160
 161	ret = mipi_dsi_dcs_read(dsi, cmd, data, len);
 162	if (ret < 0) {
 163		dev_err(ctx->dev, "error %d reading dcs seq(%#x)\n", ret, cmd);
 164		ctx->error = ret;
 165	}
 166
 167	return ret;
 168}
 169
 170#define s6e8aa0_dcs_write_seq(ctx, seq...) \
 171({\
 172	const u8 d[] = { seq };\
 173	BUILD_BUG_ON_MSG(ARRAY_SIZE(d) > 64, "DCS sequence too big for stack");\
 174	s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\
 175})
 176
 177#define s6e8aa0_dcs_write_seq_static(ctx, seq...) \
 178({\
 179	static const u8 d[] = { seq };\
 180	s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\
 181})
 182
 183static void s6e8aa0_apply_level_1_key(struct s6e8aa0 *ctx)
 184{
 185	s6e8aa0_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
 186}
 187
 188static void s6e8aa0_panel_cond_set_v142(struct s6e8aa0 *ctx)
 189{
 190	static const u8 aids[] = {
 191		0x04, 0x04, 0x04, 0x04, 0x04, 0x60, 0x80, 0xA0
 192	};
 193	u8 aid = aids[ctx->id >> 5];
 194	u8 cfg = 0x3d;
 195	u8 clk_con = 0xc8;
 196	u8 int_con = 0x08;
 197	u8 bictl_con = 0x48;
 198	u8 em_clk1_con = 0xff;
 199	u8 em_clk2_con = 0xff;
 200	u8 em_int_con = 0xc8;
 201
 202	if (ctx->flip_vertical) {
 203		/* GTCON */
 204		cfg &= ~(PANELCTL_GTCON_MASK);
 205		cfg |= (PANELCTL_GTCON_110);
 206	}
 207
 208	if (ctx->flip_horizontal) {
 209		/* SS */
 210		cfg &= ~(PANELCTL_SS_MASK);
 211		cfg |= (PANELCTL_SS_1_800);
 212	}
 213
 214	if (ctx->flip_horizontal || ctx->flip_vertical) {
 215		/* CLK1,2_CON */
 216		clk_con &= ~(PANELCTL_CLK1_CON_MASK |
 217			PANELCTL_CLK2_CON_MASK);
 218		clk_con |= (PANELCTL_CLK1_000 | PANELCTL_CLK2_001);
 219
 220		/* INT1,2_CON */
 221		int_con &= ~(PANELCTL_INT1_CON_MASK |
 222			PANELCTL_INT2_CON_MASK);
 223		int_con |= (PANELCTL_INT1_000 | PANELCTL_INT2_001);
 224
 225		/* BICTL,B_CON */
 226		bictl_con &= ~(PANELCTL_BICTL_CON_MASK |
 227			PANELCTL_BICTLB_CON_MASK);
 228		bictl_con |= (PANELCTL_BICTL_000 |
 229			PANELCTL_BICTLB_001);
 230
 231		/* EM_CLK1,1B_CON */
 232		em_clk1_con &= ~(PANELCTL_EM_CLK1_CON_MASK |
 233			PANELCTL_EM_CLK1B_CON_MASK);
 234		em_clk1_con |= (PANELCTL_EM_CLK1_110 |
 235			PANELCTL_EM_CLK1B_110);
 236
 237		/* EM_CLK2,2B_CON */
 238		em_clk2_con &= ~(PANELCTL_EM_CLK2_CON_MASK |
 239			PANELCTL_EM_CLK2B_CON_MASK);
 240		em_clk2_con |= (PANELCTL_EM_CLK2_110 |
 241			PANELCTL_EM_CLK2B_110);
 242
 243		/* EM_INT1,2_CON */
 244		em_int_con &= ~(PANELCTL_EM_INT1_CON_MASK |
 245			PANELCTL_EM_INT2_CON_MASK);
 246		em_int_con |= (PANELCTL_EM_INT1_000 |
 247			PANELCTL_EM_INT2_001);
 248	}
 249
 250	s6e8aa0_dcs_write_seq(ctx,
 251		0xf8, cfg, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00,
 252		0x3c, 0x78, 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00,
 253		0x00, 0x20, aid, 0x08, 0x6e, 0x00, 0x00, 0x00,
 254		0x02, 0x07, 0x07, 0x23, 0x23, 0xc0, clk_con, int_con,
 255		bictl_con, 0xc1, 0x00, 0xc1, em_clk1_con, em_clk2_con,
 256		em_int_con);
 257}
 258
 259static void s6e8aa0_panel_cond_set(struct s6e8aa0 *ctx)
 260{
 261	if (ctx->version < 142)
 262		s6e8aa0_dcs_write_seq_static(ctx,
 263			0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x94, 0x00,
 264			0x3c, 0x78, 0x10, 0x27, 0x08, 0x6e, 0x00, 0x00,
 265			0x00, 0x00, 0x04, 0x08, 0x6e, 0x00, 0x00, 0x00,
 266			0x00, 0x07, 0x07, 0x23, 0x6e, 0xc0, 0xc1, 0x01,
 267			0x81, 0xc1, 0x00, 0xc3, 0xf6, 0xf6, 0xc1
 268		);
 269	else
 270		s6e8aa0_panel_cond_set_v142(ctx);
 271}
 272
 273static void s6e8aa0_display_condition_set(struct s6e8aa0 *ctx)
 274{
 275	s6e8aa0_dcs_write_seq_static(ctx, 0xf2, 0x80, 0x03, 0x0d);
 276}
 277
 278static void s6e8aa0_etc_source_control(struct s6e8aa0 *ctx)
 279{
 280	s6e8aa0_dcs_write_seq_static(ctx, 0xf6, 0x00, 0x02, 0x00);
 281}
 282
 283static void s6e8aa0_etc_pentile_control(struct s6e8aa0 *ctx)
 284{
 285	static const u8 pent32[] = {
 286		0xb6, 0x0c, 0x02, 0x03, 0x32, 0xc0, 0x44, 0x44, 0xc0, 0x00
 287	};
 288
 289	static const u8 pent142[] = {
 290		0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0, 0x00
 291	};
 292
 293	if (ctx->version < 142)
 294		s6e8aa0_dcs_write(ctx, pent32, ARRAY_SIZE(pent32));
 295	else
 296		s6e8aa0_dcs_write(ctx, pent142, ARRAY_SIZE(pent142));
 297}
 298
 299static void s6e8aa0_etc_power_control(struct s6e8aa0 *ctx)
 300{
 301	static const u8 pwr142[] = {
 302		0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x1e, 0x33, 0x02
 303	};
 304
 305	static const u8 pwr32[] = {
 306		0xf4, 0xcf, 0x0a, 0x15, 0x10, 0x19, 0x33, 0x02
 307	};
 308
 309	if (ctx->version < 142)
 310		s6e8aa0_dcs_write(ctx, pwr32, ARRAY_SIZE(pwr32));
 311	else
 312		s6e8aa0_dcs_write(ctx, pwr142, ARRAY_SIZE(pwr142));
 313}
 314
 315static void s6e8aa0_etc_elvss_control(struct s6e8aa0 *ctx)
 316{
 317	u8 id = ctx->id ? 0 : 0x95;
 318
 319	s6e8aa0_dcs_write_seq(ctx, 0xb1, 0x04, id);
 320}
 321
 322static void s6e8aa0_elvss_nvm_set_v142(struct s6e8aa0 *ctx)
 323{
 324	u8 br;
 325
 326	switch (ctx->brightness) {
 327	case 0 ... 6: /* 30cd ~ 100cd */
 328		br = 0xdf;
 329		break;
 330	case 7 ... 11: /* 120cd ~ 150cd */
 331		br = 0xdd;
 332		break;
 333	case 12 ... 15: /* 180cd ~ 210cd */
 334	default:
 335		br = 0xd9;
 336		break;
 337	case 16 ... 24: /* 240cd ~ 300cd */
 338		br = 0xd0;
 339		break;
 340	}
 341
 342	s6e8aa0_dcs_write_seq(ctx, 0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e,
 343		0xc4, 0x0f, 0x40, 0x41, br, 0x00, 0x60, 0x19);
 344}
 345
 346static void s6e8aa0_elvss_nvm_set(struct s6e8aa0 *ctx)
 347{
 348	if (ctx->version < 142)
 349		s6e8aa0_dcs_write_seq_static(ctx,
 350			0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e, 0xc4, 0x07,
 351			0x40, 0x41, 0xc1, 0x00, 0x60, 0x19);
 352	else
 353		s6e8aa0_elvss_nvm_set_v142(ctx);
 354};
 355
 356static void s6e8aa0_apply_level_2_key(struct s6e8aa0 *ctx)
 357{
 358	s6e8aa0_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
 359}
 360
 361static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v142[GAMMA_LEVEL_NUM] = {
 362	{
 363		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x62, 0x55, 0x55,
 364		0xaf, 0xb1, 0xb1, 0xbd, 0xce, 0xb7, 0x9a, 0xb1,
 365		0x90, 0xb2, 0xc4, 0xae, 0x00, 0x60, 0x00, 0x40,
 366		0x00, 0x70,
 367	}, {
 368		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x74, 0x68, 0x69,
 369		0xb8, 0xc1, 0xb7, 0xbd, 0xcd, 0xb8, 0x93, 0xab,
 370		0x88, 0xb4, 0xc4, 0xb1, 0x00, 0x6b, 0x00, 0x4d,
 371		0x00, 0x7d,
 372	}, {
 373		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x95, 0x8a, 0x89,
 374		0xb4, 0xc6, 0xb2, 0xc5, 0xd2, 0xbf, 0x90, 0xa8,
 375		0x85, 0xb5, 0xc4, 0xb3, 0x00, 0x7b, 0x00, 0x5d,
 376		0x00, 0x8f,
 377	}, {
 378		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9f, 0x98, 0x92,
 379		0xb3, 0xc4, 0xb0, 0xbc, 0xcc, 0xb4, 0x91, 0xa6,
 380		0x87, 0xb5, 0xc5, 0xb4, 0x00, 0x87, 0x00, 0x6a,
 381		0x00, 0x9e,
 382	}, {
 383		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x99, 0x93, 0x8b,
 384		0xb2, 0xc2, 0xb0, 0xbd, 0xce, 0xb4, 0x90, 0xa6,
 385		0x87, 0xb3, 0xc3, 0xb2, 0x00, 0x8d, 0x00, 0x70,
 386		0x00, 0xa4,
 387	}, {
 388		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xa5, 0x99,
 389		0xb2, 0xc2, 0xb0, 0xbb, 0xcd, 0xb1, 0x93, 0xa7,
 390		0x8a, 0xb2, 0xc1, 0xb0, 0x00, 0x92, 0x00, 0x75,
 391		0x00, 0xaa,
 392	}, {
 393		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xa0, 0x93,
 394		0xb6, 0xc4, 0xb4, 0xb5, 0xc8, 0xaa, 0x94, 0xa9,
 395		0x8c, 0xb2, 0xc0, 0xb0, 0x00, 0x97, 0x00, 0x7a,
 396		0x00, 0xaf,
 397	}, {
 398		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xa7, 0x96,
 399		0xb3, 0xc2, 0xb0, 0xba, 0xcb, 0xb0, 0x94, 0xa8,
 400		0x8c, 0xb0, 0xbf, 0xaf, 0x00, 0x9f, 0x00, 0x83,
 401		0x00, 0xb9,
 402	}, {
 403		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9d, 0xa2, 0x90,
 404		0xb6, 0xc5, 0xb3, 0xb8, 0xc9, 0xae, 0x94, 0xa8,
 405		0x8d, 0xaf, 0xbd, 0xad, 0x00, 0xa4, 0x00, 0x88,
 406		0x00, 0xbf,
 407	}, {
 408		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xac, 0x97,
 409		0xb4, 0xc4, 0xb1, 0xbb, 0xcb, 0xb2, 0x93, 0xa7,
 410		0x8d, 0xae, 0xbc, 0xad, 0x00, 0xa7, 0x00, 0x8c,
 411		0x00, 0xc3,
 412	}, {
 413		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa2, 0xa9, 0x93,
 414		0xb6, 0xc5, 0xb2, 0xba, 0xc9, 0xb0, 0x93, 0xa7,
 415		0x8d, 0xae, 0xbb, 0xac, 0x00, 0xab, 0x00, 0x90,
 416		0x00, 0xc8,
 417	}, {
 418		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9e, 0xa6, 0x8f,
 419		0xb7, 0xc6, 0xb3, 0xb8, 0xc8, 0xb0, 0x93, 0xa6,
 420		0x8c, 0xae, 0xbb, 0xad, 0x00, 0xae, 0x00, 0x93,
 421		0x00, 0xcc,
 422	}, {
 423		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb4, 0x9c,
 424		0xb3, 0xc3, 0xaf, 0xb7, 0xc7, 0xaf, 0x93, 0xa6,
 425		0x8c, 0xaf, 0xbc, 0xad, 0x00, 0xb1, 0x00, 0x97,
 426		0x00, 0xcf,
 427	}, {
 428		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xb1, 0x98,
 429		0xb1, 0xc2, 0xab, 0xba, 0xc9, 0xb2, 0x93, 0xa6,
 430		0x8d, 0xae, 0xba, 0xab, 0x00, 0xb5, 0x00, 0x9b,
 431		0x00, 0xd4,
 432	}, {
 433		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xae, 0x94,
 434		0xb2, 0xc3, 0xac, 0xbb, 0xca, 0xb4, 0x91, 0xa4,
 435		0x8a, 0xae, 0xba, 0xac, 0x00, 0xb8, 0x00, 0x9e,
 436		0x00, 0xd8,
 437	}, {
 438		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb7, 0x9c,
 439		0xae, 0xc0, 0xa9, 0xba, 0xc9, 0xb3, 0x92, 0xa5,
 440		0x8b, 0xad, 0xb9, 0xab, 0x00, 0xbb, 0x00, 0xa1,
 441		0x00, 0xdc,
 442	}, {
 443		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb4, 0x97,
 444		0xb0, 0xc1, 0xaa, 0xb9, 0xc8, 0xb2, 0x92, 0xa5,
 445		0x8c, 0xae, 0xb9, 0xab, 0x00, 0xbe, 0x00, 0xa4,
 446		0x00, 0xdf,
 447	}, {
 448		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94,
 449		0xb0, 0xc2, 0xab, 0xbb, 0xc9, 0xb3, 0x91, 0xa4,
 450		0x8b, 0xad, 0xb8, 0xaa, 0x00, 0xc1, 0x00, 0xa8,
 451		0x00, 0xe2,
 452	}, {
 453		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94,
 454		0xae, 0xbf, 0xa8, 0xb9, 0xc8, 0xb3, 0x92, 0xa4,
 455		0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xc4, 0x00, 0xab,
 456		0x00, 0xe6,
 457	}, {
 458		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb6, 0x98,
 459		0xaf, 0xc0, 0xa8, 0xb8, 0xc7, 0xb2, 0x93, 0xa5,
 460		0x8d, 0xad, 0xb7, 0xa9, 0x00, 0xc7, 0x00, 0xae,
 461		0x00, 0xe9,
 462	}, {
 463		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95,
 464		0xaf, 0xc1, 0xa9, 0xb9, 0xc8, 0xb3, 0x92, 0xa4,
 465		0x8b, 0xad, 0xb7, 0xaa, 0x00, 0xc9, 0x00, 0xb0,
 466		0x00, 0xec,
 467	}, {
 468		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95,
 469		0xac, 0xbe, 0xa6, 0xbb, 0xc9, 0xb4, 0x90, 0xa3,
 470		0x8a, 0xad, 0xb7, 0xa9, 0x00, 0xcc, 0x00, 0xb4,
 471		0x00, 0xf0,
 472	}, {
 473		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xb0, 0x91,
 474		0xae, 0xc0, 0xa6, 0xba, 0xc8, 0xb4, 0x91, 0xa4,
 475		0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xcf, 0x00, 0xb7,
 476		0x00, 0xf3,
 477	}, {
 478		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb8, 0x98,
 479		0xab, 0xbd, 0xa4, 0xbb, 0xc9, 0xb5, 0x91, 0xa3,
 480		0x8b, 0xac, 0xb6, 0xa8, 0x00, 0xd1, 0x00, 0xb9,
 481		0x00, 0xf6,
 482	}, {
 483		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb5, 0x95,
 484		0xa9, 0xbc, 0xa1, 0xbb, 0xc9, 0xb5, 0x91, 0xa3,
 485		0x8a, 0xad, 0xb6, 0xa8, 0x00, 0xd6, 0x00, 0xbf,
 486		0x00, 0xfc,
 487	},
 488};
 489
 490static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v96[GAMMA_LEVEL_NUM] = {
 491	{
 492		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 493		0xdf, 0x1f, 0xd7, 0xdc, 0xb7, 0xe1, 0xc0, 0xaf,
 494		0xc4, 0xd2, 0xd0, 0xcf, 0x00, 0x4d, 0x00, 0x40,
 495		0x00, 0x5f,
 496	}, {
 497		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 498		0xd5, 0x35, 0xcf, 0xdc, 0xc1, 0xe1, 0xbf, 0xb3,
 499		0xc1, 0xd2, 0xd1, 0xce,	0x00, 0x53, 0x00, 0x46,
 500		0x00, 0x67,
 501	}, {
 502		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 503		0xd2, 0x64, 0xcf, 0xdb, 0xc6, 0xe1, 0xbd, 0xb3,
 504		0xbd, 0xd2, 0xd2, 0xce,	0x00, 0x59, 0x00, 0x4b,
 505		0x00, 0x6e,
 506	}, {
 507		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 508		0xd0, 0x7c, 0xcf, 0xdb, 0xc9, 0xe0, 0xbc, 0xb4,
 509		0xbb, 0xcf, 0xd1, 0xcc, 0x00, 0x5f, 0x00, 0x50,
 510		0x00, 0x75,
 511	}, {
 512		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 513		0xd0, 0x8e, 0xd1, 0xdb, 0xcc, 0xdf, 0xbb, 0xb6,
 514		0xb9, 0xd0, 0xd1, 0xcd,	0x00, 0x63, 0x00, 0x54,
 515		0x00, 0x7a,
 516	}, {
 517		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 518		0xd1, 0x9e, 0xd5, 0xda, 0xcd, 0xdd, 0xbb, 0xb7,
 519		0xb9, 0xce, 0xce, 0xc9,	0x00, 0x68, 0x00, 0x59,
 520		0x00, 0x81,
 521	}, {
 522		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 523		0xd0, 0xa5, 0xd6, 0xda, 0xcf, 0xdd, 0xbb, 0xb7,
 524		0xb8, 0xcc, 0xcd, 0xc7,	0x00, 0x6c, 0x00, 0x5c,
 525		0x00, 0x86,
 526	}, {
 527		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xfe,
 528		0xd0, 0xae, 0xd7, 0xd9, 0xd0, 0xdb, 0xb9, 0xb6,
 529		0xb5, 0xca, 0xcc, 0xc5,	0x00, 0x74, 0x00, 0x63,
 530		0x00, 0x90,
 531	}, {
 532		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf9,
 533		0xcf, 0xb0, 0xd6, 0xd9, 0xd1, 0xdb, 0xb9, 0xb6,
 534		0xb4, 0xca, 0xcb, 0xc5,	0x00, 0x77, 0x00, 0x66,
 535		0x00, 0x94,
 536	}, {
 537		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf7,
 538		0xcf, 0xb3, 0xd7, 0xd8, 0xd1, 0xd9, 0xb7, 0xb6,
 539		0xb3, 0xc9, 0xca, 0xc3,	0x00, 0x7b, 0x00, 0x69,
 540		0x00, 0x99,
 541
 542	}, {
 543		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfd, 0x2f, 0xf7,
 544		0xdf, 0xb5, 0xd6, 0xd8, 0xd1, 0xd8, 0xb6, 0xb5,
 545		0xb2, 0xca, 0xcb, 0xc4,	0x00, 0x7e, 0x00, 0x6c,
 546		0x00, 0x9d,
 547	}, {
 548		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfa, 0x2f, 0xf5,
 549		0xce, 0xb6, 0xd5, 0xd7, 0xd2, 0xd8, 0xb6, 0xb4,
 550		0xb0, 0xc7, 0xc9, 0xc1,	0x00, 0x84, 0x00, 0x71,
 551		0x00, 0xa5,
 552	}, {
 553		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf7, 0x2f, 0xf2,
 554		0xce, 0xb9, 0xd5, 0xd8, 0xd2, 0xd8, 0xb4, 0xb4,
 555		0xaf, 0xc7, 0xc9, 0xc1,	0x00, 0x87, 0x00, 0x73,
 556		0x00, 0xa8,
 557	}, {
 558		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf5, 0x2f, 0xf0,
 559		0xdf, 0xba, 0xd5, 0xd7, 0xd2, 0xd7, 0xb4, 0xb4,
 560		0xaf, 0xc5, 0xc7, 0xbf,	0x00, 0x8a, 0x00, 0x76,
 561		0x00, 0xac,
 562	}, {
 563		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf2, 0x2f, 0xed,
 564		0xcE, 0xbb, 0xd4, 0xd6, 0xd2, 0xd6, 0xb5, 0xb4,
 565		0xaF, 0xc5, 0xc7, 0xbf,	0x00, 0x8c, 0x00, 0x78,
 566		0x00, 0xaf,
 567	}, {
 568		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x2f, 0xeb,
 569		0xcd, 0xbb, 0xd2, 0xd7, 0xd3, 0xd6, 0xb3, 0xb4,
 570		0xae, 0xc5, 0xc6, 0xbe,	0x00, 0x91, 0x00, 0x7d,
 571		0x00, 0xb6,
 572	}, {
 573		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xee, 0x2f, 0xea,
 574		0xce, 0xbd, 0xd4, 0xd6, 0xd2, 0xd5, 0xb2, 0xb3,
 575		0xad, 0xc3, 0xc4, 0xbb,	0x00, 0x94, 0x00, 0x7f,
 576		0x00, 0xba,
 577	}, {
 578		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xec, 0x2f, 0xe8,
 579		0xce, 0xbe, 0xd3, 0xd6, 0xd3, 0xd5, 0xb2, 0xb2,
 580		0xac, 0xc3, 0xc5, 0xbc,	0x00, 0x96, 0x00, 0x81,
 581		0x00, 0xbd,
 582	}, {
 583		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xeb, 0x2f, 0xe7,
 584		0xce, 0xbf, 0xd3, 0xd6, 0xd2, 0xd5, 0xb1, 0xb2,
 585		0xab, 0xc2, 0xc4, 0xbb,	0x00, 0x99, 0x00, 0x83,
 586		0x00, 0xc0,
 587	}, {
 588		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x5f, 0xe9,
 589		0xca, 0xbf, 0xd3, 0xd5, 0xd2, 0xd4, 0xb2, 0xb2,
 590		0xab, 0xc1, 0xc4, 0xba,	0x00, 0x9b, 0x00, 0x85,
 591		0x00, 0xc3,
 592	}, {
 593		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xea, 0x5f, 0xe8,
 594		0xee, 0xbf, 0xd2, 0xd5, 0xd2, 0xd4, 0xb1, 0xb2,
 595		0xab, 0xc1, 0xc2, 0xb9,	0x00, 0x9D, 0x00, 0x87,
 596		0x00, 0xc6,
 597	}, {
 598		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe9, 0x5f, 0xe7,
 599		0xcd, 0xbf, 0xd2, 0xd6, 0xd2, 0xd4, 0xb1, 0xb2,
 600		0xab, 0xbe, 0xc0, 0xb7,	0x00, 0xa1, 0x00, 0x8a,
 601		0x00, 0xca,
 602	}, {
 603		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x61, 0xe6,
 604		0xcd, 0xbf, 0xd1, 0xd6, 0xd3, 0xd4, 0xaf, 0xb0,
 605		0xa9, 0xbe, 0xc1, 0xb7,	0x00, 0xa3, 0x00, 0x8b,
 606		0x00, 0xce,
 607	}, {
 608		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x62, 0xe5,
 609		0xcc, 0xc0, 0xd0, 0xd6, 0xd2, 0xd4, 0xaf, 0xb1,
 610		0xa9, 0xbd, 0xc0, 0xb6,	0x00, 0xa5, 0x00, 0x8d,
 611		0x00, 0xd0,
 612	}, {
 613		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe7, 0x7f, 0xe3,
 614		0xcc, 0xc1, 0xd0, 0xd5, 0xd3, 0xd3, 0xae, 0xaf,
 615		0xa8, 0xbe, 0xc0, 0xb7,	0x00, 0xa8, 0x00, 0x90,
 616		0x00, 0xd3,
 617	}
 618};
 619
 620static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v32[GAMMA_LEVEL_NUM] = {
 621	{
 622		0xfa, 0x01, 0x43, 0x14, 0x45, 0x72, 0x5e, 0x6b,
 623		0xa1, 0xa7, 0x9a, 0xb4, 0xcb, 0xb8, 0x92, 0xac,
 624		0x97, 0xb4, 0xc3, 0xb5, 0x00, 0x4e, 0x00, 0x37,
 625		0x00, 0x58,
 626	}, {
 627		0xfa, 0x01, 0x43, 0x14, 0x45, 0x85, 0x71, 0x7d,
 628		0xa6, 0xb6, 0xa1, 0xb5, 0xca, 0xba, 0x93, 0xac,
 629		0x98, 0xb2, 0xc0, 0xaf, 0x00, 0x59, 0x00, 0x43,
 630		0x00, 0x64,
 631	}, {
 632		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa4, 0x94, 0x9e,
 633		0xa0, 0xbb, 0x9c, 0xc3, 0xd2, 0xc6, 0x93, 0xaa,
 634		0x95, 0xb7, 0xc2, 0xb4, 0x00, 0x65, 0x00, 0x50,
 635		0x00, 0x74,
 636	}, {
 637		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa1, 0xa6,
 638		0xa0, 0xb9, 0x9b, 0xc3, 0xd1, 0xc8, 0x90, 0xa6,
 639		0x90, 0xbb, 0xc3, 0xb7, 0x00, 0x6f, 0x00, 0x5b,
 640		0x00, 0x80,
 641	}, {
 642		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa6, 0x9d, 0x9f,
 643		0x9f, 0xb8, 0x9a, 0xc7, 0xd5, 0xcc, 0x90, 0xa5,
 644		0x8f, 0xb8, 0xc1, 0xb6, 0x00, 0x74, 0x00, 0x60,
 645		0x00, 0x85,
 646	}, {
 647		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb3, 0xae, 0xae,
 648		0x9e, 0xb7, 0x9a, 0xc8, 0xd6, 0xce, 0x91, 0xa6,
 649		0x90, 0xb6, 0xc0, 0xb3, 0x00, 0x78, 0x00, 0x65,
 650		0x00, 0x8a,
 651	}, {
 652		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa9, 0xa8,
 653		0xa3, 0xb9, 0x9e, 0xc4, 0xd3, 0xcb, 0x94, 0xa6,
 654		0x90, 0xb6, 0xbf, 0xb3, 0x00, 0x7c, 0x00, 0x69,
 655		0x00, 0x8e,
 656	}, {
 657		0xfa, 0x01, 0x43, 0x14, 0x45, 0xaf, 0xaf, 0xa9,
 658		0xa5, 0xbc, 0xa2, 0xc7, 0xd5, 0xcd, 0x93, 0xa5,
 659		0x8f, 0xb4, 0xbd, 0xb1, 0x00, 0x83, 0x00, 0x70,
 660		0x00, 0x96,
 661	}, {
 662		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xab, 0xa3,
 663		0xaa, 0xbf, 0xa7, 0xc5, 0xd3, 0xcb, 0x93, 0xa5,
 664		0x8f, 0xb2, 0xbb, 0xb0, 0x00, 0x86, 0x00, 0x74,
 665		0x00, 0x9b,
 666	}, {
 667		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xb5, 0xab,
 668		0xab, 0xc0, 0xa9, 0xc7, 0xd4, 0xcc, 0x94, 0xa4,
 669		0x8f, 0xb1, 0xbb, 0xaf, 0x00, 0x8a, 0x00, 0x77,
 670		0x00, 0x9e,
 671	}, {
 672		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb2, 0xa7,
 673		0xae, 0xc2, 0xab, 0xc5, 0xd3, 0xca, 0x93, 0xa4,
 674		0x8f, 0xb1, 0xba, 0xae, 0x00, 0x8d, 0x00, 0x7b,
 675		0x00, 0xa2,
 676	}, {
 677		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xaf, 0xa3,
 678		0xb0, 0xc3, 0xae, 0xc4, 0xd1, 0xc8, 0x93, 0xa4,
 679		0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x8f, 0x00, 0x7d,
 680		0x00, 0xa5,
 681	}, {
 682		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbd, 0xaf,
 683		0xae, 0xc1, 0xab, 0xc2, 0xd0, 0xc6, 0x94, 0xa4,
 684		0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x92, 0x00, 0x80,
 685		0x00, 0xa8,
 686	}, {
 687		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xb9, 0xac,
 688		0xad, 0xc1, 0xab, 0xc4, 0xd1, 0xc7, 0x95, 0xa4,
 689		0x90, 0xb0, 0xb9, 0xad, 0x00, 0x95, 0x00, 0x84,
 690		0x00, 0xac,
 691	}, {
 692		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb6, 0xa7,
 693		0xaf, 0xc2, 0xae, 0xc5, 0xd1, 0xc7, 0x93, 0xa3,
 694		0x8e, 0xb0, 0xb9, 0xad, 0x00, 0x98, 0x00, 0x86,
 695		0x00, 0xaf,
 696	}, {
 697		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbf, 0xaf,
 698		0xad, 0xc1, 0xab, 0xc3, 0xd0, 0xc6, 0x94, 0xa3,
 699		0x8f, 0xaf, 0xb8, 0xac, 0x00, 0x9a, 0x00, 0x89,
 700		0x00, 0xb2,
 701	}, {
 702		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xbc, 0xac,
 703		0xaf, 0xc2, 0xad, 0xc2, 0xcf, 0xc4, 0x94, 0xa3,
 704		0x90, 0xaf, 0xb8, 0xad, 0x00, 0x9c, 0x00, 0x8b,
 705		0x00, 0xb5,
 706	}, {
 707		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7,
 708		0xb1, 0xc4, 0xaf, 0xc3, 0xcf, 0xc5, 0x94, 0xa3,
 709		0x8f, 0xae, 0xb7, 0xac, 0x00, 0x9f, 0x00, 0x8e,
 710		0x00, 0xb8,
 711	}, {
 712		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7,
 713		0xaf, 0xc2, 0xad, 0xc1, 0xce, 0xc3, 0x95, 0xa3,
 714		0x90, 0xad, 0xb6, 0xab, 0x00, 0xa2, 0x00, 0x91,
 715		0x00, 0xbb,
 716	}, {
 717		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xbe, 0xac,
 718		0xb1, 0xc4, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa4,
 719		0x91, 0xad, 0xb6, 0xab, 0x00, 0xa4, 0x00, 0x93,
 720		0x00, 0xbd,
 721	}, {
 722		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8,
 723		0xb3, 0xc5, 0xb2, 0xc1, 0xcd, 0xc2, 0x95, 0xa3,
 724		0x90, 0xad, 0xb6, 0xab, 0x00, 0xa6, 0x00, 0x95,
 725		0x00, 0xc0,
 726	}, {
 727		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8,
 728		0xb0, 0xc3, 0xaf, 0xc2, 0xce, 0xc2, 0x94, 0xa2,
 729		0x90, 0xac, 0xb6, 0xab, 0x00, 0xa8, 0x00, 0x98,
 730		0x00, 0xc3,
 731	}, {
 732		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xb8, 0xa5,
 733		0xb3, 0xc5, 0xb2, 0xc1, 0xcc, 0xc0, 0x95, 0xa2,
 734		0x90, 0xad, 0xb6, 0xab, 0x00, 0xaa, 0x00, 0x9a,
 735		0x00, 0xc5,
 736	}, {
 737		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xc0, 0xac,
 738		0xb0, 0xc3, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa2,
 739		0x90, 0xac, 0xb5, 0xa9, 0x00, 0xac, 0x00, 0x9c,
 740		0x00, 0xc8,
 741	}, {
 742		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbd, 0xa8,
 743		0xaf, 0xc2, 0xaf, 0xc1, 0xcc, 0xc0, 0x95, 0xa2,
 744		0x90, 0xac, 0xb5, 0xaa, 0x00, 0xb1, 0x00, 0xa1,
 745		0x00, 0xcc,
 746	},
 747};
 748
 749static const struct s6e8aa0_variant s6e8aa0_variants[] = {
 750	{
 751		.version = 32,
 752		.gamma_tables = s6e8aa0_gamma_tables_v32,
 753	}, {
 754		.version = 96,
 755		.gamma_tables = s6e8aa0_gamma_tables_v96,
 756	}, {
 757		.version = 142,
 758		.gamma_tables = s6e8aa0_gamma_tables_v142,
 759	}, {
 760		.version = 210,
 761		.gamma_tables = s6e8aa0_gamma_tables_v142,
 762	}
 763};
 764
 765static void s6e8aa0_brightness_set(struct s6e8aa0 *ctx)
 766{
 767	const u8 *gamma;
 768
 769	if (ctx->error)
 770		return;
 771
 772	gamma = ctx->variant->gamma_tables[ctx->brightness];
 773
 774	if (ctx->version >= 142)
 775		s6e8aa0_elvss_nvm_set(ctx);
 776
 777	s6e8aa0_dcs_write(ctx, gamma, GAMMA_TABLE_LEN);
 778
 779	/* update gamma table. */
 780	s6e8aa0_dcs_write_seq_static(ctx, 0xf7, 0x03);
 781}
 782
 783static void s6e8aa0_panel_init(struct s6e8aa0 *ctx)
 784{
 785	s6e8aa0_apply_level_1_key(ctx);
 786	s6e8aa0_apply_level_2_key(ctx);
 787	msleep(20);
 788
 789	s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE);
 790	msleep(40);
 791
 792	s6e8aa0_panel_cond_set(ctx);
 793	s6e8aa0_display_condition_set(ctx);
 794	s6e8aa0_brightness_set(ctx);
 795	s6e8aa0_etc_source_control(ctx);
 796	s6e8aa0_etc_pentile_control(ctx);
 797	s6e8aa0_elvss_nvm_set(ctx);
 798	s6e8aa0_etc_power_control(ctx);
 799	s6e8aa0_etc_elvss_control(ctx);
 800	msleep(ctx->init_delay);
 801}
 802
 803static void s6e8aa0_set_maximum_return_packet_size(struct s6e8aa0 *ctx,
 804						   u16 size)
 805{
 806	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 807	int ret;
 808
 809	if (ctx->error < 0)
 810		return;
 811
 812	ret = mipi_dsi_set_maximum_return_packet_size(dsi, size);
 813	if (ret < 0) {
 814		dev_err(ctx->dev,
 815			"error %d setting maximum return packet size to %d\n",
 816			ret, size);
 817		ctx->error = ret;
 818	}
 819}
 820
 821static void s6e8aa0_read_mtp_id(struct s6e8aa0 *ctx)
 822{
 823	u8 id[3];
 824	int ret, i;
 825
 826	ret = s6e8aa0_dcs_read(ctx, 0xd1, id, ARRAY_SIZE(id));
 827	if (ret < 0 || ret < ARRAY_SIZE(id) || id[0] == 0x00) {
 828		dev_err(ctx->dev, "read id failed\n");
 829		ctx->error = -EIO;
 830		return;
 831	}
 832
 833	dev_info(ctx->dev, "ID: 0x%2x, 0x%2x, 0x%2x\n", id[0], id[1], id[2]);
 834
 835	for (i = 0; i < ARRAY_SIZE(s6e8aa0_variants); ++i) {
 836		if (id[1] == s6e8aa0_variants[i].version)
 837			break;
 838	}
 839	if (i >= ARRAY_SIZE(s6e8aa0_variants)) {
 840		dev_err(ctx->dev, "unsupported display version %d\n", id[1]);
 841		ctx->error = -EINVAL;
 842		return;
 843	}
 844
 845	ctx->variant = &s6e8aa0_variants[i];
 846	ctx->version = id[1];
 847	ctx->id = id[2];
 848}
 849
 850static void s6e8aa0_set_sequence(struct s6e8aa0 *ctx)
 851{
 852	s6e8aa0_set_maximum_return_packet_size(ctx, 3);
 853	s6e8aa0_read_mtp_id(ctx);
 854	s6e8aa0_panel_init(ctx);
 855	s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
 856}
 857
 858static int s6e8aa0_power_on(struct s6e8aa0 *ctx)
 859{
 860	int ret;
 861
 862	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
 863	if (ret < 0)
 864		return ret;
 865
 866	msleep(ctx->power_on_delay);
 867
 868	gpiod_set_value(ctx->reset_gpio, 0);
 869	usleep_range(10000, 11000);
 870	gpiod_set_value(ctx->reset_gpio, 1);
 871
 872	msleep(ctx->reset_delay);
 873
 874	return 0;
 875}
 876
 877static int s6e8aa0_power_off(struct s6e8aa0 *ctx)
 878{
 879	return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
 880}
 881
 882static int s6e8aa0_disable(struct drm_panel *panel)
 883{
 884	return 0;
 885}
 886
 887static int s6e8aa0_unprepare(struct drm_panel *panel)
 888{
 889	struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 890
 891	s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
 892	s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF);
 893	msleep(40);
 894
 895	s6e8aa0_clear_error(ctx);
 896
 897	return s6e8aa0_power_off(ctx);
 898}
 899
 900static int s6e8aa0_prepare(struct drm_panel *panel)
 901{
 902	struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 903	int ret;
 904
 905	ret = s6e8aa0_power_on(ctx);
 906	if (ret < 0)
 907		return ret;
 908
 909	s6e8aa0_set_sequence(ctx);
 910	ret = ctx->error;
 911
 912	if (ret < 0)
 913		s6e8aa0_unprepare(panel);
 914
 915	return ret;
 916}
 917
 918static int s6e8aa0_enable(struct drm_panel *panel)
 919{
 920	return 0;
 921}
 922
 923static int s6e8aa0_get_modes(struct drm_panel *panel)
 924{
 925	struct drm_connector *connector = panel->connector;
 926	struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 927	struct drm_display_mode *mode;
 928
 929	mode = drm_mode_create(connector->dev);
 930	if (!mode) {
 931		DRM_ERROR("failed to create a new display mode\n");
 932		return 0;
 933	}
 934
 935	drm_display_mode_from_videomode(&ctx->vm, mode);
 936	mode->width_mm = ctx->width_mm;
 937	mode->height_mm = ctx->height_mm;
 938	connector->display_info.width_mm = mode->width_mm;
 939	connector->display_info.height_mm = mode->height_mm;
 940
 941	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 942	drm_mode_probed_add(connector, mode);
 943
 944	return 1;
 945}
 946
 947static const struct drm_panel_funcs s6e8aa0_drm_funcs = {
 948	.disable = s6e8aa0_disable,
 949	.unprepare = s6e8aa0_unprepare,
 950	.prepare = s6e8aa0_prepare,
 951	.enable = s6e8aa0_enable,
 952	.get_modes = s6e8aa0_get_modes,
 953};
 954
 955static int s6e8aa0_parse_dt(struct s6e8aa0 *ctx)
 956{
 957	struct device *dev = ctx->dev;
 958	struct device_node *np = dev->of_node;
 959	int ret;
 960
 961	ret = of_get_videomode(np, &ctx->vm, 0);
 962	if (ret < 0)
 963		return ret;
 964
 965	of_property_read_u32(np, "power-on-delay", &ctx->power_on_delay);
 966	of_property_read_u32(np, "reset-delay", &ctx->reset_delay);
 967	of_property_read_u32(np, "init-delay", &ctx->init_delay);
 968	of_property_read_u32(np, "panel-width-mm", &ctx->width_mm);
 969	of_property_read_u32(np, "panel-height-mm", &ctx->height_mm);
 970
 971	ctx->flip_horizontal = of_property_read_bool(np, "flip-horizontal");
 972	ctx->flip_vertical = of_property_read_bool(np, "flip-vertical");
 973
 974	return 0;
 975}
 976
 977static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
 978{
 979	struct device *dev = &dsi->dev;
 980	struct s6e8aa0 *ctx;
 981	int ret;
 982
 983	ctx = devm_kzalloc(dev, sizeof(struct s6e8aa0), GFP_KERNEL);
 984	if (!ctx)
 985		return -ENOMEM;
 986
 987	mipi_dsi_set_drvdata(dsi, ctx);
 988
 989	ctx->dev = dev;
 990
 991	dsi->lanes = 4;
 992	dsi->format = MIPI_DSI_FMT_RGB888;
 993	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
 994		| MIPI_DSI_MODE_VIDEO_HFP | MIPI_DSI_MODE_VIDEO_HBP
 995		| MIPI_DSI_MODE_VIDEO_HSA | MIPI_DSI_MODE_EOT_PACKET
 996		| MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_AUTO_VERT;
 997
 998	ret = s6e8aa0_parse_dt(ctx);
 999	if (ret < 0)
1000		return ret;
1001
1002	ctx->supplies[0].supply = "vdd3";
1003	ctx->supplies[1].supply = "vci";
1004	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
1005				      ctx->supplies);
1006	if (ret < 0) {
1007		dev_err(dev, "failed to get regulators: %d\n", ret);
1008		return ret;
1009	}
1010
1011	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
1012	if (IS_ERR(ctx->reset_gpio)) {
1013		dev_err(dev, "cannot get reset-gpios %ld\n",
1014			PTR_ERR(ctx->reset_gpio));
1015		return PTR_ERR(ctx->reset_gpio);
1016	}
1017
1018	ctx->brightness = GAMMA_LEVEL_NUM - 1;
1019
1020	drm_panel_init(&ctx->panel);
1021	ctx->panel.dev = dev;
1022	ctx->panel.funcs = &s6e8aa0_drm_funcs;
1023
1024	ret = drm_panel_add(&ctx->panel);
1025	if (ret < 0)
1026		return ret;
1027
1028	ret = mipi_dsi_attach(dsi);
1029	if (ret < 0)
1030		drm_panel_remove(&ctx->panel);
1031
1032	return ret;
1033}
1034
1035static int s6e8aa0_remove(struct mipi_dsi_device *dsi)
1036{
1037	struct s6e8aa0 *ctx = mipi_dsi_get_drvdata(dsi);
1038
1039	mipi_dsi_detach(dsi);
1040	drm_panel_remove(&ctx->panel);
1041
1042	return 0;
1043}
1044
1045static const struct of_device_id s6e8aa0_of_match[] = {
1046	{ .compatible = "samsung,s6e8aa0" },
1047	{ }
1048};
1049MODULE_DEVICE_TABLE(of, s6e8aa0_of_match);
1050
1051static struct mipi_dsi_driver s6e8aa0_driver = {
1052	.probe = s6e8aa0_probe,
1053	.remove = s6e8aa0_remove,
1054	.driver = {
1055		.name = "panel-samsung-s6e8aa0",
1056		.of_match_table = s6e8aa0_of_match,
1057	},
1058};
1059module_mipi_dsi_driver(s6e8aa0_driver);
1060
1061MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
1062MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
1063MODULE_AUTHOR("Joongmock Shin <jmock.shin@samsung.com>");
1064MODULE_AUTHOR("Eunchul Kim <chulspro.kim@samsung.com>");
1065MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
1066MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1067MODULE_DESCRIPTION("MIPI-DSI based s6e8aa0 AMOLED LCD Panel Driver");
1068MODULE_LICENSE("GPL v2");
v4.10.11
 
   1/*
   2 * MIPI-DSI based s6e8aa0 AMOLED LCD 5.3 inch panel driver.
   3 *
   4 * Copyright (c) 2013 Samsung Electronics Co., Ltd
   5 *
   6 * Inki Dae, <inki.dae@samsung.com>
   7 * Donghwa Lee, <dh09.lee@samsung.com>
   8 * Joongmock Shin <jmock.shin@samsung.com>
   9 * Eunchul Kim <chulspro.kim@samsung.com>
  10 * Tomasz Figa <t.figa@samsung.com>
  11 * Andrzej Hajda <a.hajda@samsung.com>
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License version 2 as
  15 * published by the Free Software Foundation.
  16*/
  17
  18#include <drm/drmP.h>
  19#include <drm/drm_mipi_dsi.h>
  20#include <drm/drm_panel.h>
  21
  22#include <linux/gpio/consumer.h>
 
 
  23#include <linux/regulator/consumer.h>
  24
  25#include <video/mipi_display.h>
  26#include <video/of_videomode.h>
  27#include <video/videomode.h>
  28
 
 
 
 
 
  29#define LDI_MTP_LENGTH			24
  30#define GAMMA_LEVEL_NUM			25
  31#define GAMMA_TABLE_LEN			26
  32
  33#define PANELCTL_SS_MASK		(1 << 5)
  34#define PANELCTL_SS_1_800		(0 << 5)
  35#define PANELCTL_SS_800_1		(1 << 5)
  36#define PANELCTL_GTCON_MASK		(7 << 2)
  37#define PANELCTL_GTCON_110		(6 << 2)
  38#define PANELCTL_GTCON_111		(7 << 2)
  39
  40#define PANELCTL_CLK1_CON_MASK		(7 << 3)
  41#define PANELCTL_CLK1_000		(0 << 3)
  42#define PANELCTL_CLK1_001		(1 << 3)
  43#define PANELCTL_CLK2_CON_MASK		(7 << 0)
  44#define PANELCTL_CLK2_000		(0 << 0)
  45#define PANELCTL_CLK2_001		(1 << 0)
  46
  47#define PANELCTL_INT1_CON_MASK		(7 << 3)
  48#define PANELCTL_INT1_000		(0 << 3)
  49#define PANELCTL_INT1_001		(1 << 3)
  50#define PANELCTL_INT2_CON_MASK		(7 << 0)
  51#define PANELCTL_INT2_000		(0 << 0)
  52#define PANELCTL_INT2_001		(1 << 0)
  53
  54#define PANELCTL_BICTL_CON_MASK		(7 << 3)
  55#define PANELCTL_BICTL_000		(0 << 3)
  56#define PANELCTL_BICTL_001		(1 << 3)
  57#define PANELCTL_BICTLB_CON_MASK	(7 << 0)
  58#define PANELCTL_BICTLB_000		(0 << 0)
  59#define PANELCTL_BICTLB_001		(1 << 0)
  60
  61#define PANELCTL_EM_CLK1_CON_MASK	(7 << 3)
  62#define PANELCTL_EM_CLK1_110		(6 << 3)
  63#define PANELCTL_EM_CLK1_111		(7 << 3)
  64#define PANELCTL_EM_CLK1B_CON_MASK	(7 << 0)
  65#define PANELCTL_EM_CLK1B_110		(6 << 0)
  66#define PANELCTL_EM_CLK1B_111		(7 << 0)
  67
  68#define PANELCTL_EM_CLK2_CON_MASK	(7 << 3)
  69#define PANELCTL_EM_CLK2_110		(6 << 3)
  70#define PANELCTL_EM_CLK2_111		(7 << 3)
  71#define PANELCTL_EM_CLK2B_CON_MASK	(7 << 0)
  72#define PANELCTL_EM_CLK2B_110		(6 << 0)
  73#define PANELCTL_EM_CLK2B_111		(7 << 0)
  74
  75#define PANELCTL_EM_INT1_CON_MASK	(7 << 3)
  76#define PANELCTL_EM_INT1_000		(0 << 3)
  77#define PANELCTL_EM_INT1_001		(1 << 3)
  78#define PANELCTL_EM_INT2_CON_MASK	(7 << 0)
  79#define PANELCTL_EM_INT2_000		(0 << 0)
  80#define PANELCTL_EM_INT2_001		(1 << 0)
  81
  82#define AID_DISABLE			(0x4)
  83#define AID_1				(0x5)
  84#define AID_2				(0x6)
  85#define AID_3				(0x7)
  86
  87typedef u8 s6e8aa0_gamma_table[GAMMA_TABLE_LEN];
  88
  89struct s6e8aa0_variant {
  90	u8 version;
  91	const s6e8aa0_gamma_table *gamma_tables;
  92};
  93
  94struct s6e8aa0 {
  95	struct device *dev;
  96	struct drm_panel panel;
  97
  98	struct regulator_bulk_data supplies[2];
  99	struct gpio_desc *reset_gpio;
 100	u32 power_on_delay;
 101	u32 reset_delay;
 102	u32 init_delay;
 103	bool flip_horizontal;
 104	bool flip_vertical;
 105	struct videomode vm;
 106	u32 width_mm;
 107	u32 height_mm;
 108
 109	u8 version;
 110	u8 id;
 111	const struct s6e8aa0_variant *variant;
 112	int brightness;
 113
 114	/* This field is tested by functions directly accessing DSI bus before
 115	 * transfer, transfer is skipped if it is set. In case of transfer
 116	 * failure or unexpected response the field is set to error value.
 117	 * Such construct allows to eliminate many checks in higher level
 118	 * functions.
 119	 */
 120	int error;
 121};
 122
 123static inline struct s6e8aa0 *panel_to_s6e8aa0(struct drm_panel *panel)
 124{
 125	return container_of(panel, struct s6e8aa0, panel);
 126}
 127
 128static int s6e8aa0_clear_error(struct s6e8aa0 *ctx)
 129{
 130	int ret = ctx->error;
 131
 132	ctx->error = 0;
 133	return ret;
 134}
 135
 136static void s6e8aa0_dcs_write(struct s6e8aa0 *ctx, const void *data, size_t len)
 137{
 138	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 139	ssize_t ret;
 140
 141	if (ctx->error < 0)
 142		return;
 143
 144	ret = mipi_dsi_dcs_write_buffer(dsi, data, len);
 145	if (ret < 0) {
 146		dev_err(ctx->dev, "error %zd writing dcs seq: %*ph\n", ret,
 147			(int)len, data);
 148		ctx->error = ret;
 149	}
 150}
 151
 152static int s6e8aa0_dcs_read(struct s6e8aa0 *ctx, u8 cmd, void *data, size_t len)
 153{
 154	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 155	int ret;
 156
 157	if (ctx->error < 0)
 158		return ctx->error;
 159
 160	ret = mipi_dsi_dcs_read(dsi, cmd, data, len);
 161	if (ret < 0) {
 162		dev_err(ctx->dev, "error %d reading dcs seq(%#x)\n", ret, cmd);
 163		ctx->error = ret;
 164	}
 165
 166	return ret;
 167}
 168
 169#define s6e8aa0_dcs_write_seq(ctx, seq...) \
 170({\
 171	const u8 d[] = { seq };\
 172	BUILD_BUG_ON_MSG(ARRAY_SIZE(d) > 64, "DCS sequence too big for stack");\
 173	s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\
 174})
 175
 176#define s6e8aa0_dcs_write_seq_static(ctx, seq...) \
 177({\
 178	static const u8 d[] = { seq };\
 179	s6e8aa0_dcs_write(ctx, d, ARRAY_SIZE(d));\
 180})
 181
 182static void s6e8aa0_apply_level_1_key(struct s6e8aa0 *ctx)
 183{
 184	s6e8aa0_dcs_write_seq_static(ctx, 0xf0, 0x5a, 0x5a);
 185}
 186
 187static void s6e8aa0_panel_cond_set_v142(struct s6e8aa0 *ctx)
 188{
 189	static const u8 aids[] = {
 190		0x04, 0x04, 0x04, 0x04, 0x04, 0x60, 0x80, 0xA0
 191	};
 192	u8 aid = aids[ctx->id >> 5];
 193	u8 cfg = 0x3d;
 194	u8 clk_con = 0xc8;
 195	u8 int_con = 0x08;
 196	u8 bictl_con = 0x48;
 197	u8 em_clk1_con = 0xff;
 198	u8 em_clk2_con = 0xff;
 199	u8 em_int_con = 0xc8;
 200
 201	if (ctx->flip_vertical) {
 202		/* GTCON */
 203		cfg &= ~(PANELCTL_GTCON_MASK);
 204		cfg |= (PANELCTL_GTCON_110);
 205	}
 206
 207	if (ctx->flip_horizontal) {
 208		/* SS */
 209		cfg &= ~(PANELCTL_SS_MASK);
 210		cfg |= (PANELCTL_SS_1_800);
 211	}
 212
 213	if (ctx->flip_horizontal || ctx->flip_vertical) {
 214		/* CLK1,2_CON */
 215		clk_con &= ~(PANELCTL_CLK1_CON_MASK |
 216			PANELCTL_CLK2_CON_MASK);
 217		clk_con |= (PANELCTL_CLK1_000 | PANELCTL_CLK2_001);
 218
 219		/* INT1,2_CON */
 220		int_con &= ~(PANELCTL_INT1_CON_MASK |
 221			PANELCTL_INT2_CON_MASK);
 222		int_con |= (PANELCTL_INT1_000 | PANELCTL_INT2_001);
 223
 224		/* BICTL,B_CON */
 225		bictl_con &= ~(PANELCTL_BICTL_CON_MASK |
 226			PANELCTL_BICTLB_CON_MASK);
 227		bictl_con |= (PANELCTL_BICTL_000 |
 228			PANELCTL_BICTLB_001);
 229
 230		/* EM_CLK1,1B_CON */
 231		em_clk1_con &= ~(PANELCTL_EM_CLK1_CON_MASK |
 232			PANELCTL_EM_CLK1B_CON_MASK);
 233		em_clk1_con |= (PANELCTL_EM_CLK1_110 |
 234			PANELCTL_EM_CLK1B_110);
 235
 236		/* EM_CLK2,2B_CON */
 237		em_clk2_con &= ~(PANELCTL_EM_CLK2_CON_MASK |
 238			PANELCTL_EM_CLK2B_CON_MASK);
 239		em_clk2_con |= (PANELCTL_EM_CLK2_110 |
 240			PANELCTL_EM_CLK2B_110);
 241
 242		/* EM_INT1,2_CON */
 243		em_int_con &= ~(PANELCTL_EM_INT1_CON_MASK |
 244			PANELCTL_EM_INT2_CON_MASK);
 245		em_int_con |= (PANELCTL_EM_INT1_000 |
 246			PANELCTL_EM_INT2_001);
 247	}
 248
 249	s6e8aa0_dcs_write_seq(ctx,
 250		0xf8, cfg, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00,
 251		0x3c, 0x78, 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00,
 252		0x00, 0x20, aid, 0x08, 0x6e, 0x00, 0x00, 0x00,
 253		0x02, 0x07, 0x07, 0x23, 0x23, 0xc0, clk_con, int_con,
 254		bictl_con, 0xc1, 0x00, 0xc1, em_clk1_con, em_clk2_con,
 255		em_int_con);
 256}
 257
 258static void s6e8aa0_panel_cond_set(struct s6e8aa0 *ctx)
 259{
 260	if (ctx->version < 142)
 261		s6e8aa0_dcs_write_seq_static(ctx,
 262			0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x94, 0x00,
 263			0x3c, 0x78, 0x10, 0x27, 0x08, 0x6e, 0x00, 0x00,
 264			0x00, 0x00, 0x04, 0x08, 0x6e, 0x00, 0x00, 0x00,
 265			0x00, 0x07, 0x07, 0x23, 0x6e, 0xc0, 0xc1, 0x01,
 266			0x81, 0xc1, 0x00, 0xc3, 0xf6, 0xf6, 0xc1
 267		);
 268	else
 269		s6e8aa0_panel_cond_set_v142(ctx);
 270}
 271
 272static void s6e8aa0_display_condition_set(struct s6e8aa0 *ctx)
 273{
 274	s6e8aa0_dcs_write_seq_static(ctx, 0xf2, 0x80, 0x03, 0x0d);
 275}
 276
 277static void s6e8aa0_etc_source_control(struct s6e8aa0 *ctx)
 278{
 279	s6e8aa0_dcs_write_seq_static(ctx, 0xf6, 0x00, 0x02, 0x00);
 280}
 281
 282static void s6e8aa0_etc_pentile_control(struct s6e8aa0 *ctx)
 283{
 284	static const u8 pent32[] = {
 285		0xb6, 0x0c, 0x02, 0x03, 0x32, 0xc0, 0x44, 0x44, 0xc0, 0x00
 286	};
 287
 288	static const u8 pent142[] = {
 289		0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0, 0x00
 290	};
 291
 292	if (ctx->version < 142)
 293		s6e8aa0_dcs_write(ctx, pent32, ARRAY_SIZE(pent32));
 294	else
 295		s6e8aa0_dcs_write(ctx, pent142, ARRAY_SIZE(pent142));
 296}
 297
 298static void s6e8aa0_etc_power_control(struct s6e8aa0 *ctx)
 299{
 300	static const u8 pwr142[] = {
 301		0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x1e, 0x33, 0x02
 302	};
 303
 304	static const u8 pwr32[] = {
 305		0xf4, 0xcf, 0x0a, 0x15, 0x10, 0x19, 0x33, 0x02
 306	};
 307
 308	if (ctx->version < 142)
 309		s6e8aa0_dcs_write(ctx, pwr32, ARRAY_SIZE(pwr32));
 310	else
 311		s6e8aa0_dcs_write(ctx, pwr142, ARRAY_SIZE(pwr142));
 312}
 313
 314static void s6e8aa0_etc_elvss_control(struct s6e8aa0 *ctx)
 315{
 316	u8 id = ctx->id ? 0 : 0x95;
 317
 318	s6e8aa0_dcs_write_seq(ctx, 0xb1, 0x04, id);
 319}
 320
 321static void s6e8aa0_elvss_nvm_set_v142(struct s6e8aa0 *ctx)
 322{
 323	u8 br;
 324
 325	switch (ctx->brightness) {
 326	case 0 ... 6: /* 30cd ~ 100cd */
 327		br = 0xdf;
 328		break;
 329	case 7 ... 11: /* 120cd ~ 150cd */
 330		br = 0xdd;
 331		break;
 332	case 12 ... 15: /* 180cd ~ 210cd */
 333	default:
 334		br = 0xd9;
 335		break;
 336	case 16 ... 24: /* 240cd ~ 300cd */
 337		br = 0xd0;
 338		break;
 339	}
 340
 341	s6e8aa0_dcs_write_seq(ctx, 0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e,
 342		0xc4, 0x0f, 0x40, 0x41, br, 0x00, 0x60, 0x19);
 343}
 344
 345static void s6e8aa0_elvss_nvm_set(struct s6e8aa0 *ctx)
 346{
 347	if (ctx->version < 142)
 348		s6e8aa0_dcs_write_seq_static(ctx,
 349			0xd9, 0x14, 0x40, 0x0c, 0xcb, 0xce, 0x6e, 0xc4, 0x07,
 350			0x40, 0x41, 0xc1, 0x00, 0x60, 0x19);
 351	else
 352		s6e8aa0_elvss_nvm_set_v142(ctx);
 353};
 354
 355static void s6e8aa0_apply_level_2_key(struct s6e8aa0 *ctx)
 356{
 357	s6e8aa0_dcs_write_seq_static(ctx, 0xfc, 0x5a, 0x5a);
 358}
 359
 360static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v142[GAMMA_LEVEL_NUM] = {
 361	{
 362		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x62, 0x55, 0x55,
 363		0xaf, 0xb1, 0xb1, 0xbd, 0xce, 0xb7, 0x9a, 0xb1,
 364		0x90, 0xb2, 0xc4, 0xae, 0x00, 0x60, 0x00, 0x40,
 365		0x00, 0x70,
 366	}, {
 367		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x74, 0x68, 0x69,
 368		0xb8, 0xc1, 0xb7, 0xbd, 0xcd, 0xb8, 0x93, 0xab,
 369		0x88, 0xb4, 0xc4, 0xb1, 0x00, 0x6b, 0x00, 0x4d,
 370		0x00, 0x7d,
 371	}, {
 372		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x95, 0x8a, 0x89,
 373		0xb4, 0xc6, 0xb2, 0xc5, 0xd2, 0xbf, 0x90, 0xa8,
 374		0x85, 0xb5, 0xc4, 0xb3, 0x00, 0x7b, 0x00, 0x5d,
 375		0x00, 0x8f,
 376	}, {
 377		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9f, 0x98, 0x92,
 378		0xb3, 0xc4, 0xb0, 0xbc, 0xcc, 0xb4, 0x91, 0xa6,
 379		0x87, 0xb5, 0xc5, 0xb4, 0x00, 0x87, 0x00, 0x6a,
 380		0x00, 0x9e,
 381	}, {
 382		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x99, 0x93, 0x8b,
 383		0xb2, 0xc2, 0xb0, 0xbd, 0xce, 0xb4, 0x90, 0xa6,
 384		0x87, 0xb3, 0xc3, 0xb2, 0x00, 0x8d, 0x00, 0x70,
 385		0x00, 0xa4,
 386	}, {
 387		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xa5, 0x99,
 388		0xb2, 0xc2, 0xb0, 0xbb, 0xcd, 0xb1, 0x93, 0xa7,
 389		0x8a, 0xb2, 0xc1, 0xb0, 0x00, 0x92, 0x00, 0x75,
 390		0x00, 0xaa,
 391	}, {
 392		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xa0, 0x93,
 393		0xb6, 0xc4, 0xb4, 0xb5, 0xc8, 0xaa, 0x94, 0xa9,
 394		0x8c, 0xb2, 0xc0, 0xb0, 0x00, 0x97, 0x00, 0x7a,
 395		0x00, 0xaf,
 396	}, {
 397		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xa7, 0x96,
 398		0xb3, 0xc2, 0xb0, 0xba, 0xcb, 0xb0, 0x94, 0xa8,
 399		0x8c, 0xb0, 0xbf, 0xaf, 0x00, 0x9f, 0x00, 0x83,
 400		0x00, 0xb9,
 401	}, {
 402		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9d, 0xa2, 0x90,
 403		0xb6, 0xc5, 0xb3, 0xb8, 0xc9, 0xae, 0x94, 0xa8,
 404		0x8d, 0xaf, 0xbd, 0xad, 0x00, 0xa4, 0x00, 0x88,
 405		0x00, 0xbf,
 406	}, {
 407		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xac, 0x97,
 408		0xb4, 0xc4, 0xb1, 0xbb, 0xcb, 0xb2, 0x93, 0xa7,
 409		0x8d, 0xae, 0xbc, 0xad, 0x00, 0xa7, 0x00, 0x8c,
 410		0x00, 0xc3,
 411	}, {
 412		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa2, 0xa9, 0x93,
 413		0xb6, 0xc5, 0xb2, 0xba, 0xc9, 0xb0, 0x93, 0xa7,
 414		0x8d, 0xae, 0xbb, 0xac, 0x00, 0xab, 0x00, 0x90,
 415		0x00, 0xc8,
 416	}, {
 417		0xfa, 0x01, 0x71, 0x31, 0x7b, 0x9e, 0xa6, 0x8f,
 418		0xb7, 0xc6, 0xb3, 0xb8, 0xc8, 0xb0, 0x93, 0xa6,
 419		0x8c, 0xae, 0xbb, 0xad, 0x00, 0xae, 0x00, 0x93,
 420		0x00, 0xcc,
 421	}, {
 422		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb4, 0x9c,
 423		0xb3, 0xc3, 0xaf, 0xb7, 0xc7, 0xaf, 0x93, 0xa6,
 424		0x8c, 0xaf, 0xbc, 0xad, 0x00, 0xb1, 0x00, 0x97,
 425		0x00, 0xcf,
 426	}, {
 427		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa6, 0xb1, 0x98,
 428		0xb1, 0xc2, 0xab, 0xba, 0xc9, 0xb2, 0x93, 0xa6,
 429		0x8d, 0xae, 0xba, 0xab, 0x00, 0xb5, 0x00, 0x9b,
 430		0x00, 0xd4,
 431	}, {
 432		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xae, 0x94,
 433		0xb2, 0xc3, 0xac, 0xbb, 0xca, 0xb4, 0x91, 0xa4,
 434		0x8a, 0xae, 0xba, 0xac, 0x00, 0xb8, 0x00, 0x9e,
 435		0x00, 0xd8,
 436	}, {
 437		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xab, 0xb7, 0x9c,
 438		0xae, 0xc0, 0xa9, 0xba, 0xc9, 0xb3, 0x92, 0xa5,
 439		0x8b, 0xad, 0xb9, 0xab, 0x00, 0xbb, 0x00, 0xa1,
 440		0x00, 0xdc,
 441	}, {
 442		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb4, 0x97,
 443		0xb0, 0xc1, 0xaa, 0xb9, 0xc8, 0xb2, 0x92, 0xa5,
 444		0x8c, 0xae, 0xb9, 0xab, 0x00, 0xbe, 0x00, 0xa4,
 445		0x00, 0xdf,
 446	}, {
 447		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94,
 448		0xb0, 0xc2, 0xab, 0xbb, 0xc9, 0xb3, 0x91, 0xa4,
 449		0x8b, 0xad, 0xb8, 0xaa, 0x00, 0xc1, 0x00, 0xa8,
 450		0x00, 0xe2,
 451	}, {
 452		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa3, 0xb0, 0x94,
 453		0xae, 0xbf, 0xa8, 0xb9, 0xc8, 0xb3, 0x92, 0xa4,
 454		0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xc4, 0x00, 0xab,
 455		0x00, 0xe6,
 456	}, {
 457		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb6, 0x98,
 458		0xaf, 0xc0, 0xa8, 0xb8, 0xc7, 0xb2, 0x93, 0xa5,
 459		0x8d, 0xad, 0xb7, 0xa9, 0x00, 0xc7, 0x00, 0xae,
 460		0x00, 0xe9,
 461	}, {
 462		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95,
 463		0xaf, 0xc1, 0xa9, 0xb9, 0xc8, 0xb3, 0x92, 0xa4,
 464		0x8b, 0xad, 0xb7, 0xaa, 0x00, 0xc9, 0x00, 0xb0,
 465		0x00, 0xec,
 466	}, {
 467		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb3, 0x95,
 468		0xac, 0xbe, 0xa6, 0xbb, 0xc9, 0xb4, 0x90, 0xa3,
 469		0x8a, 0xad, 0xb7, 0xa9, 0x00, 0xcc, 0x00, 0xb4,
 470		0x00, 0xf0,
 471	}, {
 472		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa0, 0xb0, 0x91,
 473		0xae, 0xc0, 0xa6, 0xba, 0xc8, 0xb4, 0x91, 0xa4,
 474		0x8b, 0xad, 0xb7, 0xa9, 0x00, 0xcf, 0x00, 0xb7,
 475		0x00, 0xf3,
 476	}, {
 477		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa7, 0xb8, 0x98,
 478		0xab, 0xbd, 0xa4, 0xbb, 0xc9, 0xb5, 0x91, 0xa3,
 479		0x8b, 0xac, 0xb6, 0xa8, 0x00, 0xd1, 0x00, 0xb9,
 480		0x00, 0xf6,
 481	}, {
 482		0xfa, 0x01, 0x71, 0x31, 0x7b, 0xa4, 0xb5, 0x95,
 483		0xa9, 0xbc, 0xa1, 0xbb, 0xc9, 0xb5, 0x91, 0xa3,
 484		0x8a, 0xad, 0xb6, 0xa8, 0x00, 0xd6, 0x00, 0xbf,
 485		0x00, 0xfc,
 486	},
 487};
 488
 489static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v96[GAMMA_LEVEL_NUM] = {
 490	{
 491		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 492		0xdf, 0x1f, 0xd7, 0xdc, 0xb7, 0xe1, 0xc0, 0xaf,
 493		0xc4, 0xd2, 0xd0, 0xcf, 0x00, 0x4d, 0x00, 0x40,
 494		0x00, 0x5f,
 495	}, {
 496		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 497		0xd5, 0x35, 0xcf, 0xdc, 0xc1, 0xe1, 0xbf, 0xb3,
 498		0xc1, 0xd2, 0xd1, 0xce,	0x00, 0x53, 0x00, 0x46,
 499		0x00, 0x67,
 500	}, {
 501		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 502		0xd2, 0x64, 0xcf, 0xdb, 0xc6, 0xe1, 0xbd, 0xb3,
 503		0xbd, 0xd2, 0xd2, 0xce,	0x00, 0x59, 0x00, 0x4b,
 504		0x00, 0x6e,
 505	}, {
 506		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 507		0xd0, 0x7c, 0xcf, 0xdb, 0xc9, 0xe0, 0xbc, 0xb4,
 508		0xbb, 0xcf, 0xd1, 0xcc, 0x00, 0x5f, 0x00, 0x50,
 509		0x00, 0x75,
 510	}, {
 511		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 512		0xd0, 0x8e, 0xd1, 0xdb, 0xcc, 0xdf, 0xbb, 0xb6,
 513		0xb9, 0xd0, 0xd1, 0xcd,	0x00, 0x63, 0x00, 0x54,
 514		0x00, 0x7a,
 515	}, {
 516		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 517		0xd1, 0x9e, 0xd5, 0xda, 0xcd, 0xdd, 0xbb, 0xb7,
 518		0xb9, 0xce, 0xce, 0xc9,	0x00, 0x68, 0x00, 0x59,
 519		0x00, 0x81,
 520	}, {
 521		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0xff,
 522		0xd0, 0xa5, 0xd6, 0xda, 0xcf, 0xdd, 0xbb, 0xb7,
 523		0xb8, 0xcc, 0xcd, 0xc7,	0x00, 0x6c, 0x00, 0x5c,
 524		0x00, 0x86,
 525	}, {
 526		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xfe,
 527		0xd0, 0xae, 0xd7, 0xd9, 0xd0, 0xdb, 0xb9, 0xb6,
 528		0xb5, 0xca, 0xcc, 0xc5,	0x00, 0x74, 0x00, 0x63,
 529		0x00, 0x90,
 530	}, {
 531		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf9,
 532		0xcf, 0xb0, 0xd6, 0xd9, 0xd1, 0xdb, 0xb9, 0xb6,
 533		0xb4, 0xca, 0xcb, 0xc5,	0x00, 0x77, 0x00, 0x66,
 534		0x00, 0x94,
 535	}, {
 536		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xff, 0x1f, 0xf7,
 537		0xcf, 0xb3, 0xd7, 0xd8, 0xd1, 0xd9, 0xb7, 0xb6,
 538		0xb3, 0xc9, 0xca, 0xc3,	0x00, 0x7b, 0x00, 0x69,
 539		0x00, 0x99,
 540
 541	}, {
 542		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfd, 0x2f, 0xf7,
 543		0xdf, 0xb5, 0xd6, 0xd8, 0xd1, 0xd8, 0xb6, 0xb5,
 544		0xb2, 0xca, 0xcb, 0xc4,	0x00, 0x7e, 0x00, 0x6c,
 545		0x00, 0x9d,
 546	}, {
 547		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xfa, 0x2f, 0xf5,
 548		0xce, 0xb6, 0xd5, 0xd7, 0xd2, 0xd8, 0xb6, 0xb4,
 549		0xb0, 0xc7, 0xc9, 0xc1,	0x00, 0x84, 0x00, 0x71,
 550		0x00, 0xa5,
 551	}, {
 552		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf7, 0x2f, 0xf2,
 553		0xce, 0xb9, 0xd5, 0xd8, 0xd2, 0xd8, 0xb4, 0xb4,
 554		0xaf, 0xc7, 0xc9, 0xc1,	0x00, 0x87, 0x00, 0x73,
 555		0x00, 0xa8,
 556	}, {
 557		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf5, 0x2f, 0xf0,
 558		0xdf, 0xba, 0xd5, 0xd7, 0xd2, 0xd7, 0xb4, 0xb4,
 559		0xaf, 0xc5, 0xc7, 0xbf,	0x00, 0x8a, 0x00, 0x76,
 560		0x00, 0xac,
 561	}, {
 562		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xf2, 0x2f, 0xed,
 563		0xcE, 0xbb, 0xd4, 0xd6, 0xd2, 0xd6, 0xb5, 0xb4,
 564		0xaF, 0xc5, 0xc7, 0xbf,	0x00, 0x8c, 0x00, 0x78,
 565		0x00, 0xaf,
 566	}, {
 567		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x2f, 0xeb,
 568		0xcd, 0xbb, 0xd2, 0xd7, 0xd3, 0xd6, 0xb3, 0xb4,
 569		0xae, 0xc5, 0xc6, 0xbe,	0x00, 0x91, 0x00, 0x7d,
 570		0x00, 0xb6,
 571	}, {
 572		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xee, 0x2f, 0xea,
 573		0xce, 0xbd, 0xd4, 0xd6, 0xd2, 0xd5, 0xb2, 0xb3,
 574		0xad, 0xc3, 0xc4, 0xbb,	0x00, 0x94, 0x00, 0x7f,
 575		0x00, 0xba,
 576	}, {
 577		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xec, 0x2f, 0xe8,
 578		0xce, 0xbe, 0xd3, 0xd6, 0xd3, 0xd5, 0xb2, 0xb2,
 579		0xac, 0xc3, 0xc5, 0xbc,	0x00, 0x96, 0x00, 0x81,
 580		0x00, 0xbd,
 581	}, {
 582		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xeb, 0x2f, 0xe7,
 583		0xce, 0xbf, 0xd3, 0xd6, 0xd2, 0xd5, 0xb1, 0xb2,
 584		0xab, 0xc2, 0xc4, 0xbb,	0x00, 0x99, 0x00, 0x83,
 585		0x00, 0xc0,
 586	}, {
 587		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xef, 0x5f, 0xe9,
 588		0xca, 0xbf, 0xd3, 0xd5, 0xd2, 0xd4, 0xb2, 0xb2,
 589		0xab, 0xc1, 0xc4, 0xba,	0x00, 0x9b, 0x00, 0x85,
 590		0x00, 0xc3,
 591	}, {
 592		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xea, 0x5f, 0xe8,
 593		0xee, 0xbf, 0xd2, 0xd5, 0xd2, 0xd4, 0xb1, 0xb2,
 594		0xab, 0xc1, 0xc2, 0xb9,	0x00, 0x9D, 0x00, 0x87,
 595		0x00, 0xc6,
 596	}, {
 597		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe9, 0x5f, 0xe7,
 598		0xcd, 0xbf, 0xd2, 0xd6, 0xd2, 0xd4, 0xb1, 0xb2,
 599		0xab, 0xbe, 0xc0, 0xb7,	0x00, 0xa1, 0x00, 0x8a,
 600		0x00, 0xca,
 601	}, {
 602		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x61, 0xe6,
 603		0xcd, 0xbf, 0xd1, 0xd6, 0xd3, 0xd4, 0xaf, 0xb0,
 604		0xa9, 0xbe, 0xc1, 0xb7,	0x00, 0xa3, 0x00, 0x8b,
 605		0x00, 0xce,
 606	}, {
 607		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe8, 0x62, 0xe5,
 608		0xcc, 0xc0, 0xd0, 0xd6, 0xd2, 0xd4, 0xaf, 0xb1,
 609		0xa9, 0xbd, 0xc0, 0xb6,	0x00, 0xa5, 0x00, 0x8d,
 610		0x00, 0xd0,
 611	}, {
 612		0xfa, 0x01, 0x1f, 0x1f, 0x1f, 0xe7, 0x7f, 0xe3,
 613		0xcc, 0xc1, 0xd0, 0xd5, 0xd3, 0xd3, 0xae, 0xaf,
 614		0xa8, 0xbe, 0xc0, 0xb7,	0x00, 0xa8, 0x00, 0x90,
 615		0x00, 0xd3,
 616	}
 617};
 618
 619static const s6e8aa0_gamma_table s6e8aa0_gamma_tables_v32[GAMMA_LEVEL_NUM] = {
 620	{
 621		0xfa, 0x01, 0x43, 0x14, 0x45, 0x72, 0x5e, 0x6b,
 622		0xa1, 0xa7, 0x9a, 0xb4, 0xcb, 0xb8, 0x92, 0xac,
 623		0x97, 0xb4, 0xc3, 0xb5, 0x00, 0x4e, 0x00, 0x37,
 624		0x00, 0x58,
 625	}, {
 626		0xfa, 0x01, 0x43, 0x14, 0x45, 0x85, 0x71, 0x7d,
 627		0xa6, 0xb6, 0xa1, 0xb5, 0xca, 0xba, 0x93, 0xac,
 628		0x98, 0xb2, 0xc0, 0xaf, 0x00, 0x59, 0x00, 0x43,
 629		0x00, 0x64,
 630	}, {
 631		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa4, 0x94, 0x9e,
 632		0xa0, 0xbb, 0x9c, 0xc3, 0xd2, 0xc6, 0x93, 0xaa,
 633		0x95, 0xb7, 0xc2, 0xb4, 0x00, 0x65, 0x00, 0x50,
 634		0x00, 0x74,
 635	}, {
 636		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa1, 0xa6,
 637		0xa0, 0xb9, 0x9b, 0xc3, 0xd1, 0xc8, 0x90, 0xa6,
 638		0x90, 0xbb, 0xc3, 0xb7, 0x00, 0x6f, 0x00, 0x5b,
 639		0x00, 0x80,
 640	}, {
 641		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa6, 0x9d, 0x9f,
 642		0x9f, 0xb8, 0x9a, 0xc7, 0xd5, 0xcc, 0x90, 0xa5,
 643		0x8f, 0xb8, 0xc1, 0xb6, 0x00, 0x74, 0x00, 0x60,
 644		0x00, 0x85,
 645	}, {
 646		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb3, 0xae, 0xae,
 647		0x9e, 0xb7, 0x9a, 0xc8, 0xd6, 0xce, 0x91, 0xa6,
 648		0x90, 0xb6, 0xc0, 0xb3, 0x00, 0x78, 0x00, 0x65,
 649		0x00, 0x8a,
 650	}, {
 651		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xa9, 0xa8,
 652		0xa3, 0xb9, 0x9e, 0xc4, 0xd3, 0xcb, 0x94, 0xa6,
 653		0x90, 0xb6, 0xbf, 0xb3, 0x00, 0x7c, 0x00, 0x69,
 654		0x00, 0x8e,
 655	}, {
 656		0xfa, 0x01, 0x43, 0x14, 0x45, 0xaf, 0xaf, 0xa9,
 657		0xa5, 0xbc, 0xa2, 0xc7, 0xd5, 0xcd, 0x93, 0xa5,
 658		0x8f, 0xb4, 0xbd, 0xb1, 0x00, 0x83, 0x00, 0x70,
 659		0x00, 0x96,
 660	}, {
 661		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xab, 0xa3,
 662		0xaa, 0xbf, 0xa7, 0xc5, 0xd3, 0xcb, 0x93, 0xa5,
 663		0x8f, 0xb2, 0xbb, 0xb0, 0x00, 0x86, 0x00, 0x74,
 664		0x00, 0x9b,
 665	}, {
 666		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xb5, 0xab,
 667		0xab, 0xc0, 0xa9, 0xc7, 0xd4, 0xcc, 0x94, 0xa4,
 668		0x8f, 0xb1, 0xbb, 0xaf, 0x00, 0x8a, 0x00, 0x77,
 669		0x00, 0x9e,
 670	}, {
 671		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb2, 0xa7,
 672		0xae, 0xc2, 0xab, 0xc5, 0xd3, 0xca, 0x93, 0xa4,
 673		0x8f, 0xb1, 0xba, 0xae, 0x00, 0x8d, 0x00, 0x7b,
 674		0x00, 0xa2,
 675	}, {
 676		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xaf, 0xa3,
 677		0xb0, 0xc3, 0xae, 0xc4, 0xd1, 0xc8, 0x93, 0xa4,
 678		0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x8f, 0x00, 0x7d,
 679		0x00, 0xa5,
 680	}, {
 681		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbd, 0xaf,
 682		0xae, 0xc1, 0xab, 0xc2, 0xd0, 0xc6, 0x94, 0xa4,
 683		0x8f, 0xb1, 0xba, 0xaf, 0x00, 0x92, 0x00, 0x80,
 684		0x00, 0xa8,
 685	}, {
 686		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xb9, 0xac,
 687		0xad, 0xc1, 0xab, 0xc4, 0xd1, 0xc7, 0x95, 0xa4,
 688		0x90, 0xb0, 0xb9, 0xad, 0x00, 0x95, 0x00, 0x84,
 689		0x00, 0xac,
 690	}, {
 691		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb6, 0xa7,
 692		0xaf, 0xc2, 0xae, 0xc5, 0xd1, 0xc7, 0x93, 0xa3,
 693		0x8e, 0xb0, 0xb9, 0xad, 0x00, 0x98, 0x00, 0x86,
 694		0x00, 0xaf,
 695	}, {
 696		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb4, 0xbf, 0xaf,
 697		0xad, 0xc1, 0xab, 0xc3, 0xd0, 0xc6, 0x94, 0xa3,
 698		0x8f, 0xaf, 0xb8, 0xac, 0x00, 0x9a, 0x00, 0x89,
 699		0x00, 0xb2,
 700	}, {
 701		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xbc, 0xac,
 702		0xaf, 0xc2, 0xad, 0xc2, 0xcf, 0xc4, 0x94, 0xa3,
 703		0x90, 0xaf, 0xb8, 0xad, 0x00, 0x9c, 0x00, 0x8b,
 704		0x00, 0xb5,
 705	}, {
 706		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7,
 707		0xb1, 0xc4, 0xaf, 0xc3, 0xcf, 0xc5, 0x94, 0xa3,
 708		0x8f, 0xae, 0xb7, 0xac, 0x00, 0x9f, 0x00, 0x8e,
 709		0x00, 0xb8,
 710	}, {
 711		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xb9, 0xa7,
 712		0xaf, 0xc2, 0xad, 0xc1, 0xce, 0xc3, 0x95, 0xa3,
 713		0x90, 0xad, 0xb6, 0xab, 0x00, 0xa2, 0x00, 0x91,
 714		0x00, 0xbb,
 715	}, {
 716		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb1, 0xbe, 0xac,
 717		0xb1, 0xc4, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa4,
 718		0x91, 0xad, 0xb6, 0xab, 0x00, 0xa4, 0x00, 0x93,
 719		0x00, 0xbd,
 720	}, {
 721		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8,
 722		0xb3, 0xc5, 0xb2, 0xc1, 0xcd, 0xc2, 0x95, 0xa3,
 723		0x90, 0xad, 0xb6, 0xab, 0x00, 0xa6, 0x00, 0x95,
 724		0x00, 0xc0,
 725	}, {
 726		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbb, 0xa8,
 727		0xb0, 0xc3, 0xaf, 0xc2, 0xce, 0xc2, 0x94, 0xa2,
 728		0x90, 0xac, 0xb6, 0xab, 0x00, 0xa8, 0x00, 0x98,
 729		0x00, 0xc3,
 730	}, {
 731		0xfa, 0x01, 0x43, 0x14, 0x45, 0xa9, 0xb8, 0xa5,
 732		0xb3, 0xc5, 0xb2, 0xc1, 0xcc, 0xc0, 0x95, 0xa2,
 733		0x90, 0xad, 0xb6, 0xab, 0x00, 0xaa, 0x00, 0x9a,
 734		0x00, 0xc5,
 735	}, {
 736		0xfa, 0x01, 0x43, 0x14, 0x45, 0xb0, 0xc0, 0xac,
 737		0xb0, 0xc3, 0xaf, 0xc1, 0xcd, 0xc1, 0x95, 0xa2,
 738		0x90, 0xac, 0xb5, 0xa9, 0x00, 0xac, 0x00, 0x9c,
 739		0x00, 0xc8,
 740	}, {
 741		0xfa, 0x01, 0x43, 0x14, 0x45, 0xad, 0xbd, 0xa8,
 742		0xaf, 0xc2, 0xaf, 0xc1, 0xcc, 0xc0, 0x95, 0xa2,
 743		0x90, 0xac, 0xb5, 0xaa, 0x00, 0xb1, 0x00, 0xa1,
 744		0x00, 0xcc,
 745	},
 746};
 747
 748static const struct s6e8aa0_variant s6e8aa0_variants[] = {
 749	{
 750		.version = 32,
 751		.gamma_tables = s6e8aa0_gamma_tables_v32,
 752	}, {
 753		.version = 96,
 754		.gamma_tables = s6e8aa0_gamma_tables_v96,
 755	}, {
 756		.version = 142,
 757		.gamma_tables = s6e8aa0_gamma_tables_v142,
 758	}, {
 759		.version = 210,
 760		.gamma_tables = s6e8aa0_gamma_tables_v142,
 761	}
 762};
 763
 764static void s6e8aa0_brightness_set(struct s6e8aa0 *ctx)
 765{
 766	const u8 *gamma;
 767
 768	if (ctx->error)
 769		return;
 770
 771	gamma = ctx->variant->gamma_tables[ctx->brightness];
 772
 773	if (ctx->version >= 142)
 774		s6e8aa0_elvss_nvm_set(ctx);
 775
 776	s6e8aa0_dcs_write(ctx, gamma, GAMMA_TABLE_LEN);
 777
 778	/* update gamma table. */
 779	s6e8aa0_dcs_write_seq_static(ctx, 0xf7, 0x03);
 780}
 781
 782static void s6e8aa0_panel_init(struct s6e8aa0 *ctx)
 783{
 784	s6e8aa0_apply_level_1_key(ctx);
 785	s6e8aa0_apply_level_2_key(ctx);
 786	msleep(20);
 787
 788	s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE);
 789	msleep(40);
 790
 791	s6e8aa0_panel_cond_set(ctx);
 792	s6e8aa0_display_condition_set(ctx);
 793	s6e8aa0_brightness_set(ctx);
 794	s6e8aa0_etc_source_control(ctx);
 795	s6e8aa0_etc_pentile_control(ctx);
 796	s6e8aa0_elvss_nvm_set(ctx);
 797	s6e8aa0_etc_power_control(ctx);
 798	s6e8aa0_etc_elvss_control(ctx);
 799	msleep(ctx->init_delay);
 800}
 801
 802static void s6e8aa0_set_maximum_return_packet_size(struct s6e8aa0 *ctx,
 803						   u16 size)
 804{
 805	struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
 806	int ret;
 807
 808	if (ctx->error < 0)
 809		return;
 810
 811	ret = mipi_dsi_set_maximum_return_packet_size(dsi, size);
 812	if (ret < 0) {
 813		dev_err(ctx->dev,
 814			"error %d setting maximum return packet size to %d\n",
 815			ret, size);
 816		ctx->error = ret;
 817	}
 818}
 819
 820static void s6e8aa0_read_mtp_id(struct s6e8aa0 *ctx)
 821{
 822	u8 id[3];
 823	int ret, i;
 824
 825	ret = s6e8aa0_dcs_read(ctx, 0xd1, id, ARRAY_SIZE(id));
 826	if (ret < ARRAY_SIZE(id) || id[0] == 0x00) {
 827		dev_err(ctx->dev, "read id failed\n");
 828		ctx->error = -EIO;
 829		return;
 830	}
 831
 832	dev_info(ctx->dev, "ID: 0x%2x, 0x%2x, 0x%2x\n", id[0], id[1], id[2]);
 833
 834	for (i = 0; i < ARRAY_SIZE(s6e8aa0_variants); ++i) {
 835		if (id[1] == s6e8aa0_variants[i].version)
 836			break;
 837	}
 838	if (i >= ARRAY_SIZE(s6e8aa0_variants)) {
 839		dev_err(ctx->dev, "unsupported display version %d\n", id[1]);
 840		ctx->error = -EINVAL;
 841		return;
 842	}
 843
 844	ctx->variant = &s6e8aa0_variants[i];
 845	ctx->version = id[1];
 846	ctx->id = id[2];
 847}
 848
 849static void s6e8aa0_set_sequence(struct s6e8aa0 *ctx)
 850{
 851	s6e8aa0_set_maximum_return_packet_size(ctx, 3);
 852	s6e8aa0_read_mtp_id(ctx);
 853	s6e8aa0_panel_init(ctx);
 854	s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON);
 855}
 856
 857static int s6e8aa0_power_on(struct s6e8aa0 *ctx)
 858{
 859	int ret;
 860
 861	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
 862	if (ret < 0)
 863		return ret;
 864
 865	msleep(ctx->power_on_delay);
 866
 867	gpiod_set_value(ctx->reset_gpio, 0);
 868	usleep_range(10000, 11000);
 869	gpiod_set_value(ctx->reset_gpio, 1);
 870
 871	msleep(ctx->reset_delay);
 872
 873	return 0;
 874}
 875
 876static int s6e8aa0_power_off(struct s6e8aa0 *ctx)
 877{
 878	return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
 879}
 880
 881static int s6e8aa0_disable(struct drm_panel *panel)
 882{
 883	return 0;
 884}
 885
 886static int s6e8aa0_unprepare(struct drm_panel *panel)
 887{
 888	struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 889
 890	s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE);
 891	s6e8aa0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF);
 892	msleep(40);
 893
 894	s6e8aa0_clear_error(ctx);
 895
 896	return s6e8aa0_power_off(ctx);
 897}
 898
 899static int s6e8aa0_prepare(struct drm_panel *panel)
 900{
 901	struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 902	int ret;
 903
 904	ret = s6e8aa0_power_on(ctx);
 905	if (ret < 0)
 906		return ret;
 907
 908	s6e8aa0_set_sequence(ctx);
 909	ret = ctx->error;
 910
 911	if (ret < 0)
 912		s6e8aa0_unprepare(panel);
 913
 914	return ret;
 915}
 916
 917static int s6e8aa0_enable(struct drm_panel *panel)
 918{
 919	return 0;
 920}
 921
 922static int s6e8aa0_get_modes(struct drm_panel *panel)
 923{
 924	struct drm_connector *connector = panel->connector;
 925	struct s6e8aa0 *ctx = panel_to_s6e8aa0(panel);
 926	struct drm_display_mode *mode;
 927
 928	mode = drm_mode_create(connector->dev);
 929	if (!mode) {
 930		DRM_ERROR("failed to create a new display mode\n");
 931		return 0;
 932	}
 933
 934	drm_display_mode_from_videomode(&ctx->vm, mode);
 935	mode->width_mm = ctx->width_mm;
 936	mode->height_mm = ctx->height_mm;
 937	connector->display_info.width_mm = mode->width_mm;
 938	connector->display_info.height_mm = mode->height_mm;
 939
 940	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 941	drm_mode_probed_add(connector, mode);
 942
 943	return 1;
 944}
 945
 946static const struct drm_panel_funcs s6e8aa0_drm_funcs = {
 947	.disable = s6e8aa0_disable,
 948	.unprepare = s6e8aa0_unprepare,
 949	.prepare = s6e8aa0_prepare,
 950	.enable = s6e8aa0_enable,
 951	.get_modes = s6e8aa0_get_modes,
 952};
 953
 954static int s6e8aa0_parse_dt(struct s6e8aa0 *ctx)
 955{
 956	struct device *dev = ctx->dev;
 957	struct device_node *np = dev->of_node;
 958	int ret;
 959
 960	ret = of_get_videomode(np, &ctx->vm, 0);
 961	if (ret < 0)
 962		return ret;
 963
 964	of_property_read_u32(np, "power-on-delay", &ctx->power_on_delay);
 965	of_property_read_u32(np, "reset-delay", &ctx->reset_delay);
 966	of_property_read_u32(np, "init-delay", &ctx->init_delay);
 967	of_property_read_u32(np, "panel-width-mm", &ctx->width_mm);
 968	of_property_read_u32(np, "panel-height-mm", &ctx->height_mm);
 969
 970	ctx->flip_horizontal = of_property_read_bool(np, "flip-horizontal");
 971	ctx->flip_vertical = of_property_read_bool(np, "flip-vertical");
 972
 973	return 0;
 974}
 975
 976static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
 977{
 978	struct device *dev = &dsi->dev;
 979	struct s6e8aa0 *ctx;
 980	int ret;
 981
 982	ctx = devm_kzalloc(dev, sizeof(struct s6e8aa0), GFP_KERNEL);
 983	if (!ctx)
 984		return -ENOMEM;
 985
 986	mipi_dsi_set_drvdata(dsi, ctx);
 987
 988	ctx->dev = dev;
 989
 990	dsi->lanes = 4;
 991	dsi->format = MIPI_DSI_FMT_RGB888;
 992	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
 993		| MIPI_DSI_MODE_VIDEO_HFP | MIPI_DSI_MODE_VIDEO_HBP
 994		| MIPI_DSI_MODE_VIDEO_HSA | MIPI_DSI_MODE_EOT_PACKET
 995		| MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_AUTO_VERT;
 996
 997	ret = s6e8aa0_parse_dt(ctx);
 998	if (ret < 0)
 999		return ret;
1000
1001	ctx->supplies[0].supply = "vdd3";
1002	ctx->supplies[1].supply = "vci";
1003	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies),
1004				      ctx->supplies);
1005	if (ret < 0) {
1006		dev_err(dev, "failed to get regulators: %d\n", ret);
1007		return ret;
1008	}
1009
1010	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
1011	if (IS_ERR(ctx->reset_gpio)) {
1012		dev_err(dev, "cannot get reset-gpios %ld\n",
1013			PTR_ERR(ctx->reset_gpio));
1014		return PTR_ERR(ctx->reset_gpio);
1015	}
1016
1017	ctx->brightness = GAMMA_LEVEL_NUM - 1;
1018
1019	drm_panel_init(&ctx->panel);
1020	ctx->panel.dev = dev;
1021	ctx->panel.funcs = &s6e8aa0_drm_funcs;
1022
1023	ret = drm_panel_add(&ctx->panel);
1024	if (ret < 0)
1025		return ret;
1026
1027	ret = mipi_dsi_attach(dsi);
1028	if (ret < 0)
1029		drm_panel_remove(&ctx->panel);
1030
1031	return ret;
1032}
1033
1034static int s6e8aa0_remove(struct mipi_dsi_device *dsi)
1035{
1036	struct s6e8aa0 *ctx = mipi_dsi_get_drvdata(dsi);
1037
1038	mipi_dsi_detach(dsi);
1039	drm_panel_remove(&ctx->panel);
1040
1041	return 0;
1042}
1043
1044static const struct of_device_id s6e8aa0_of_match[] = {
1045	{ .compatible = "samsung,s6e8aa0" },
1046	{ }
1047};
1048MODULE_DEVICE_TABLE(of, s6e8aa0_of_match);
1049
1050static struct mipi_dsi_driver s6e8aa0_driver = {
1051	.probe = s6e8aa0_probe,
1052	.remove = s6e8aa0_remove,
1053	.driver = {
1054		.name = "panel-samsung-s6e8aa0",
1055		.of_match_table = s6e8aa0_of_match,
1056	},
1057};
1058module_mipi_dsi_driver(s6e8aa0_driver);
1059
1060MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
1061MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
1062MODULE_AUTHOR("Joongmock Shin <jmock.shin@samsung.com>");
1063MODULE_AUTHOR("Eunchul Kim <chulspro.kim@samsung.com>");
1064MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
1065MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1066MODULE_DESCRIPTION("MIPI-DSI based s6e8aa0 AMOLED LCD Panel Driver");
1067MODULE_LICENSE("GPL v2");