Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/panel: add S6E8AA0 driver

The patch adds MIPI-DSI based S6E8AA0 AMOLED LCD panel driver.
Driver uses mipi_dsi bus to communicate with panel and exposes drm_panel
interface.

v2
- added bus error handling,
- set maxmimum DSI packet size on init,
- removed unsupported brightness drm_panel callbacks,
- minor improvements

v3
- switched to gpiod framework,
- minor fixes in error handling

Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>

authored by

Andrzej Hajda and committed by
Inki Dae
02051ca0 ffff29d1

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