From f6949f6ad81356a46ad4a078b45d5bb2f36a71d7 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Tue, 1 Jun 2021 08:23:14 +0200 Subject: [PATCH] drm/panel: Add driver for Samsung AMS497EE01 panel This patch adds support for Samsung's AMOLED AMS497EE01 panel with an EA8061V controller. The driver is mostly based on the driver for s6e3fa2 and s6e63m0, with data taken from the downstream android kernel for the device with codename a500f. The panel is used in the msm8916 Samsung Galaxy A5U (EUR) devices, for which there is already partial support in the mainline kernel. Signed-off-by: Henrik Grimler --- .../gpu/drm/panel/msm8916-generated/Kconfig | 6 +- .../panel-samsung-ea8061v-ams497ee01.c | 781 +++++++++++++++++- 2 files changed, 741 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/panel/msm8916-generated/Kconfig b/drivers/gpu/drm/panel/msm8916-generated/Kconfig index 9d07cc04390052..2c5fff91ff874f 100644 --- a/drivers/gpu/drm/panel/msm8916-generated/Kconfig +++ b/drivers/gpu/drm/panel/msm8916-generated/Kconfig @@ -94,7 +94,11 @@ config DRM_PANEL_SAMSUNG_EA8061_AMS549BU19_ID400418 default DRM_PANEL_MSM8916_GENERATED config DRM_PANEL_SAMSUNG_EA8061V_AMS497EE01 - tristate "Samsung EA8061V AMS497EE01" + tristate "Samsung AMS497EE01 panel with EA8061V DSI video mode controller" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + select VIDEOMODE_HELPERS default DRM_PANEL_MSM8916_GENERATED config DRM_PANEL_SAMSUNG_HX8389C_GH9607501A diff --git a/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-ea8061v-ams497ee01.c b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-ea8061v-ams497ee01.c index 995320bcfce00e..877ad5e5fe1a97 100644 --- a/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-ea8061v-ams497ee01.c +++ b/drivers/gpu/drm/panel/msm8916-generated/panel-samsung-ea8061v-ams497ee01.c @@ -2,23 +2,456 @@ // Copyright (c) 2023 FIXME // Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree: // Copyright (c) 2013, The Linux Foundation. All rights reserved. (FIXME) +// +// Mostly based on s6e3fa2 and s6e63m0. Table values dumped from +// Samsung's SM-A500F android kernel +#include +#include +#include + +#include #include #include #include #include #include -#include -#include -#include + +#define EA8061V_AMS497EE01_NUM_GAMMA_LEVELS 62 +#define EA8061V_AMS497EE01_GAMMA_CMD_CNT 34 + +#define EA8061V_AMS497EE01_MIN_BRIGHTNESS 0 +#define EA8061V_AMS497EE01_MAX_BRIGHTNESS (EA8061V_AMS497EE01_NUM_GAMMA_LEVELS - 1) +#define EA8061V_AMS497EE01_DEFAULT_BRIGHTNESS 40 + +/* Commands from manufacturer */ +#define MCS_ACL_OFF 0x5c +#define MCS_ACL_ON 0x4c +#define MCS_ACL_CONTROL 0x55 +#define MCS_AID_CONTROL 0xb2 /* Samsung AMOLED Impulsive Driving */ +#define MCS_ACL_OPR_CONTROL 0xb5 +#define MCS_ELVSS_CONTROL 0xb6 /* Amoled negative power supply */ +#define MCS_TSET 0xb8 /* Set reference conditions */ +#define MCS_GAMMA 0xca +#define MCS_GAMMA_UPDATE 0xf7 + +/* Which ELVSS sequence to use for which candela level. + */ +static const u8 map_candela_to_elvss[EA8061V_AMS497EE01_NUM_GAMMA_LEVELS] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 2, 2, 3, 4, 4, 5, 6, + 7, 7, 7, 8, 9, 10, + 11, 11, 11, 12, 13, 14, 15, 16, 17 +}; + +static const u8 seq_ea8061v_ams497ee01_lux[EA8061V_AMS497EE01_NUM_GAMMA_LEVELS][EA8061V_AMS497EE01_GAMMA_CMD_CNT] = { + { MCS_GAMMA, + 0x00, 0x92, 0x00, 0xac, 0x00, 0x7e, 0x8a, 0x8f, 0x8b, + 0x8d, 0x91, 0x8d, 0x96, 0xa1, 0x99, 0x9b, 0xa5, 0x00, + 0x9c, 0x95, 0xa1, 0x8d, 0x9d, 0xa3, 0xa1, 0xba, 0xbb, + 0xec, 0xbd, 0xd5, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x93, 0x00, 0xac, 0x00, 0x7e, 0x8b, 0x8e, 0x8b, + 0x8d, 0x90, 0x8c, 0x93, 0x9e, 0x96, 0x94, 0xa1, 0x00, + 0x96, 0x96, 0xa2, 0x8d, 0x9e, 0xa2, 0xa1, 0xb9, 0xba, + 0xe1, 0xb4, 0xcd, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x94, 0x00, 0xac, 0x00, 0x7f, 0x8a, 0x8d, 0x8a, + 0x89, 0x8e, 0x8a, 0x92, 0x9d, 0x95, 0x95, 0xa1, 0x00, + 0x97, 0x97, 0xa1, 0x8e, 0x98, 0xa0, 0x9d, 0xb3, 0xb7, + 0xe0, 0xb3, 0xcb, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x94, 0x00, 0xac, 0x00, 0x7f, 0x8b, 0x8d, 0x8b, + 0x89, 0x8e, 0x8a, 0x92, 0x9c, 0x94, 0x93, 0x9e, 0x00, + 0x96, 0x95, 0x9f, 0x8d, 0x98, 0xa0, 0x9c, 0xb2, 0xb4, + 0xe9, 0xba, 0xd2, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x94, 0x00, 0xac, 0x00, 0x7f, 0x8a, 0x8c, 0x8b, + 0x89, 0x8d, 0x89, 0x91, 0x9b, 0x94, 0x93, 0x9e, 0x00, + 0x95, 0x94, 0x9e, 0x8c, 0x97, 0x9e, 0x9c, 0xb3, 0xb4, + 0xde, 0xb1, 0xc5, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x95, 0x00, 0xac, 0x00, 0x80, 0x89, 0x8c, 0x8a, + 0x8a, 0x8d, 0x8b, 0x90, 0x99, 0x92, 0x8f, 0x9a, 0x00, + 0x93, 0x93, 0x9e, 0x8c, 0x99, 0x9e, 0x9c, 0xb1, 0xb3, + 0xd9, 0xae, 0xbf, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x96, 0x00, 0xac, 0x00, 0x81, 0x89, 0x8c, 0x8a, + 0x89, 0x8b, 0x89, 0x90, 0x98, 0x92, 0x92, 0x9c, 0x00, + 0x95, 0x90, 0x9b, 0x88, 0x98, 0x9e, 0x9c, 0xb1, 0xb1, + 0xdd, 0xb0, 0xc3, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x96, 0x00, 0xac, 0x00, 0x81, 0x89, 0x8c, 0x8a, + 0x8a, 0x8b, 0x8a, 0x8e, 0x96, 0x91, 0x92, 0x9b, 0x00, + 0x97, 0x92, 0x9b, 0x8a, 0x92, 0x9d, 0x96, 0xae, 0xae, + 0xdc, 0xb0, 0xc2, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x96, 0x00, 0xac, 0x00, 0x81, 0x89, 0x8b, 0x88, + 0x8b, 0x8c, 0x8b, 0x8f, 0x96, 0x92, 0x8f, 0x99, 0x00, + 0x93, 0x91, 0x9b, 0x88, 0x93, 0x9a, 0x98, 0xaf, 0xad, + 0xe0, 0xb3, 0xc6, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x96, 0x00, 0xac, 0x00, 0x81, 0x8a, 0x8b, 0x89, + 0x89, 0x8b, 0x87, 0x91, 0x97, 0x94, 0x8b, 0x96, 0x00, + 0x91, 0x90, 0x9b, 0x89, 0x93, 0x9b, 0x95, 0xad, 0xac, + 0xdf, 0xb3, 0xc5, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x89, 0x8b, 0x88, + 0x89, 0x8b, 0x88, 0x90, 0x96, 0x92, 0x8f, 0x98, 0x00, + 0x94, 0x8d, 0x98, 0x87, 0x93, 0x9a, 0x95, 0xad, 0xac, + 0xdf, 0xb3, 0xc5, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x89, 0x8b, 0x88, + 0x8a, 0x8b, 0x88, 0x90, 0x96, 0x92, 0x8c, 0x95, 0x00, + 0x92, 0x8d, 0x98, 0x87, 0x92, 0x9a, 0x93, 0xae, 0xac, + 0xd9, 0xae, 0xbf, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x89, 0x8b, 0x88, + 0x8a, 0x8b, 0x88, 0x8e, 0x93, 0x90, 0x8e, 0x97, 0x00, + 0x93, 0x8d, 0x98, 0x88, 0x92, 0x9a, 0x93, 0xa7, 0xa6, + 0xea, 0xbb, 0xd1, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8b, 0x8a, + 0x88, 0x8a, 0x87, 0x8c, 0x93, 0x90, 0x8e, 0x96, 0x00, + 0x93, 0x8a, 0x95, 0x84, 0x90, 0x98, 0x8f, 0xad, 0xab, + 0xdb, 0xb0, 0xc2, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8b, 0x8a, + 0x88, 0x8a, 0x87, 0x8d, 0x93, 0x91, 0x8b, 0x93, 0x00, + 0x91, 0x8e, 0x96, 0x88, 0x90, 0x98, 0x8e, 0xa6, 0xa5, + 0xe3, 0xb7, 0xca, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8b, 0x8a, + 0x88, 0x8a, 0x87, 0x8d, 0x93, 0x91, 0x8c, 0x93, 0x00, + 0x92, 0x89, 0x94, 0x83, 0x8c, 0x94, 0x8b, 0xab, 0xab, + 0xd2, 0xab, 0xba, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8b, 0x8a, + 0x88, 0x8a, 0x87, 0x8c, 0x91, 0x8e, 0x8d, 0x93, 0x00, + 0x92, 0x8c, 0x96, 0x86, 0x91, 0x98, 0x8f, 0xa6, 0xa6, + 0xe7, 0xba, 0xce, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x89, 0x8a, 0x89, + 0x89, 0x8a, 0x88, 0x8d, 0x92, 0x8f, 0x8d, 0x93, 0x00, + 0x92, 0x89, 0x93, 0x83, 0x8f, 0x97, 0x8f, 0xa4, 0xa4, + 0xd7, 0xae, 0xbf, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8b, 0x8a, + 0x88, 0x89, 0x87, 0x8d, 0x92, 0x8f, 0x8d, 0x92, 0x00, + 0x92, 0x89, 0x93, 0x83, 0x8c, 0x94, 0x8b, 0xa2, 0xa2, + 0xe7, 0xba, 0xce, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x89, 0x8a, 0x89, + 0x89, 0x8a, 0x88, 0x8d, 0x91, 0x90, 0x89, 0x8f, 0x00, + 0x8f, 0x8c, 0x95, 0x84, 0x8b, 0x94, 0x8a, 0xa2, 0xa0, + 0xe1, 0xb6, 0xc8, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x89, 0x8a, 0x89, + 0x89, 0x8a, 0x88, 0x8e, 0x91, 0x90, 0x89, 0x8f, 0x00, + 0x90, 0x88, 0x91, 0x81, 0x8c, 0x94, 0x8a, 0xa6, 0xa6, + 0xd6, 0xae, 0xbe, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x89, 0x8a, 0x89, + 0x89, 0x8a, 0x88, 0x8d, 0x90, 0x90, 0x89, 0x8f, 0x00, + 0x8f, 0x88, 0x91, 0x81, 0x8c, 0x93, 0x8a, 0xa7, 0xa6, + 0xd1, 0xaa, 0xb8, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x89, 0x8a, 0x89, + 0x89, 0x8a, 0x88, 0x8e, 0x90, 0x90, 0x86, 0x8c, 0x00, + 0x8e, 0x87, 0x90, 0x7f, 0x8f, 0x96, 0x8e, 0xa2, 0xa0, + 0xd6, 0xad, 0xbd, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x88, 0x89, 0x87, 0x8d, 0x8f, 0x8f, 0x88, 0x8d, 0x00, + 0x90, 0x87, 0x90, 0x7f, 0x8f, 0x96, 0x8e, 0xa2, 0xa0, + 0xd6, 0xad, 0xbd, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x89, 0x89, 0x87, 0x8c, 0x8f, 0x8f, 0x8a, 0x8d, 0x00, + 0x91, 0x88, 0x90, 0x81, 0x8b, 0x93, 0x8a, 0xa1, 0x9e, + 0xcf, 0xa9, 0xb7, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x89, 0x89, 0x87, 0x8a, 0x8e, 0x8e, 0x89, 0x8c, 0x00, + 0x91, 0x87, 0x8f, 0x7f, 0x90, 0x96, 0x90, 0x99, 0x97, + 0xe0, 0xb5, 0xc8, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x89, 0x89, 0x87, 0x8b, 0x8e, 0x8f, 0x89, 0x8c, 0x00, + 0x91, 0x87, 0x8f, 0x7f, 0x89, 0x91, 0x88, 0x9f, 0x9e, + 0xda, 0xb1, 0xc2, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x89, 0x89, 0x87, 0x8b, 0x8e, 0x8f, 0x87, 0x89, 0x00, + 0x8f, 0x87, 0x8d, 0x7e, 0x8f, 0x95, 0x8d, 0x9a, 0x97, + 0xd4, 0xad, 0xbc, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x8a, 0x89, 0x88, 0x8a, 0x8e, 0x8e, 0x88, 0x89, 0x00, + 0x90, 0x81, 0x8a, 0x79, 0x93, 0x98, 0x92, 0x9b, 0x98, + 0xd4, 0xad, 0xbc, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x89, 0x88, 0x87, 0x89, 0x8d, 0x8d, 0x8a, 0x8b, 0x00, + 0x91, 0x81, 0x8a, 0x79, 0x93, 0x97, 0x92, 0x9b, 0x98, + 0xba, 0x9d, 0xa8, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x89, 0x88, 0x87, 0x8a, 0x8d, 0x8e, 0x86, 0x88, 0x00, + 0x8e, 0x87, 0x8d, 0x7d, 0x8e, 0x93, 0x8e, 0x94, 0x91, + 0x9c, 0x8d, 0x92, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x89, 0x88, 0x87, 0x8a, 0x8d, 0x8e, 0x87, 0x88, 0x00, + 0x8f, 0x82, 0x89, 0x79, 0x8d, 0x92, 0x8b, 0x97, 0x95, + 0xdf, 0xb5, 0xc7, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x89, 0x88, 0x87, 0x8b, 0x8d, 0x8e, 0x86, 0x88, 0x00, + 0x8f, 0x82, 0x88, 0x79, 0x8c, 0x92, 0x8b, 0x99, 0x96, + 0xd2, 0xad, 0xbc, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x8a, 0x8a, 0x89, + 0x89, 0x88, 0x87, 0x8b, 0x8d, 0x8e, 0x86, 0x87, 0x00, + 0x8f, 0x82, 0x88, 0x79, 0x8d, 0x92, 0x8c, 0x9b, 0x97, + 0x9c, 0x8d, 0x92, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x97, 0x00, 0xac, 0x00, 0x82, 0x89, 0x89, 0x88, + 0x8a, 0x89, 0x88, 0x8b, 0x8d, 0x8e, 0x86, 0x87, 0x00, + 0x8f, 0x83, 0x88, 0x7a, 0x8e, 0x92, 0x8d, 0x93, 0x8f, + 0xbc, 0xa1, 0xac, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0x9b, 0x00, 0xaf, 0x00, 0x87, 0x88, 0x89, 0x88, + 0x89, 0x88, 0x87, 0x8b, 0x8d, 0x8e, 0x87, 0x86, 0x00, + 0x8f, 0x83, 0x88, 0x7a, 0x8e, 0x92, 0x8d, 0x94, 0x90, + 0xa1, 0x91, 0x97, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xa0, 0x00, 0xb3, 0x00, 0x8d, 0x89, 0x89, 0x88, + 0x89, 0x88, 0x86, 0x8b, 0x8c, 0x8d, 0x85, 0x85, 0x00, + 0x8d, 0x84, 0x89, 0x7c, 0x8a, 0x8e, 0x89, 0x93, 0x8f, + 0xca, 0xa9, 0xb7, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xa4, 0x00, 0xb6, 0x00, 0x92, 0x88, 0x89, 0x89, + 0x88, 0x87, 0x86, 0x8a, 0x8b, 0x8b, 0x87, 0x86, 0x00, + 0x8c, 0x81, 0x86, 0x79, 0x89, 0x8e, 0x88, 0x9b, 0x98, + 0x81, 0x7d, 0x7d, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xa8, 0x00, 0xba, 0x00, 0x97, 0x88, 0x88, 0x88, + 0x88, 0x87, 0x86, 0x87, 0x8b, 0x8a, 0x8a, 0x88, 0x00, + 0x8f, 0x83, 0x88, 0x7d, 0x87, 0x8c, 0x87, 0x95, 0x91, + 0xa9, 0x95, 0x9d, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xad, 0x00, 0xbe, 0x00, 0x9d, 0x87, 0x88, 0x88, + 0x88, 0x87, 0x86, 0x8a, 0x8b, 0x8c, 0x86, 0x85, 0x00, + 0x89, 0x82, 0x88, 0x7d, 0x87, 0x8b, 0x87, 0x96, 0x91, + 0x9c, 0x8d, 0x92, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xb1, 0x00, 0xc1, 0x00, 0xa2, 0x87, 0x88, 0x88, + 0x88, 0x87, 0x86, 0x87, 0x89, 0x89, 0x87, 0x86, 0x00, + 0x8b, 0x80, 0x85, 0x7b, 0x8c, 0x8f, 0x8c, 0x8f, 0x8c, + 0xc4, 0xa5, 0xb2, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xb7, 0x00, 0xc5, 0x00, 0xa8, 0x86, 0x87, 0x87, + 0x88, 0x86, 0x85, 0x88, 0x89, 0x89, 0x87, 0x86, 0x00, + 0x8a, 0x81, 0x86, 0x7d, 0x8a, 0x8d, 0x88, 0x8f, 0x8c, + 0xb7, 0x9d, 0xa7, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xbc, 0x00, 0xc9, 0x00, 0xae, 0x86, 0x87, 0x87, + 0x87, 0x86, 0x85, 0x87, 0x88, 0x87, 0x86, 0x87, 0x00, + 0x8a, 0x80, 0x84, 0x7b, 0x8a, 0x8c, 0x88, 0x90, 0x8d, + 0x9c, 0x8d, 0x92, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xc1, 0x00, 0xcd, 0x00, 0xb4, 0x86, 0x87, 0x87, + 0x87, 0x86, 0x86, 0x86, 0x88, 0x87, 0x87, 0x86, 0x00, + 0x88, 0x82, 0x84, 0x7c, 0x85, 0x89, 0x86, 0x91, 0x8e, + 0x9c, 0x8d, 0x92, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xc6, 0x00, 0xd1, 0x00, 0xba, 0x85, 0x86, 0x86, + 0x86, 0x85, 0x85, 0x85, 0x86, 0x86, 0x88, 0x87, 0x00, + 0x89, 0x82, 0x86, 0x7d, 0x80, 0x86, 0x82, 0x91, 0x8e, + 0xb7, 0x9d, 0xa7, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xca, 0x00, 0xd4, 0x00, 0xbf, 0x86, 0x87, 0x87, + 0x86, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x84, 0x00, + 0x86, 0x82, 0x85, 0x7f, 0x80, 0x86, 0x82, 0x91, 0x8e, + 0x9c, 0x8d, 0x92, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xd0, 0x00, 0xd9, 0x00, 0xc6, 0x84, 0x85, 0x85, + 0x85, 0x84, 0x84, 0x83, 0x85, 0x84, 0x86, 0x85, 0x00, + 0x86, 0x7f, 0x82, 0x7c, 0x87, 0x8a, 0x87, 0x8e, 0x8a, + 0x9c, 0x8d, 0x92, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xd5, 0x00, 0xdd, 0x00, 0xcc, 0x85, 0x86, 0x86, + 0x85, 0x84, 0x84, 0x82, 0x84, 0x83, 0x86, 0x85, 0x00, + 0x85, 0x80, 0x83, 0x7e, 0x83, 0x86, 0x84, 0x8d, 0x89, + 0xa9, 0x95, 0x9d, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xda, 0x00, 0xe1, 0x00, 0xd3, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x82, 0x83, 0x83, 0x86, 0x85, 0x00, + 0x85, 0x83, 0x85, 0x7f, 0x7f, 0x84, 0x81, 0x8f, 0x8b, + 0x8f, 0x85, 0x88, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xda, 0x00, 0xe1, 0x00, 0xd2, 0x84, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x82, 0x83, 0x83, 0x86, 0x85, 0x00, + 0x85, 0x84, 0x85, 0x80, 0x7f, 0x83, 0x81, 0x8f, 0x8b, + 0x74, 0x75, 0x73, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xda, 0x00, 0xe1, 0x00, 0xd2, 0x84, 0x84, 0x84, + 0x83, 0x83, 0x83, 0x84, 0x84, 0x85, 0x83, 0x84, 0x00, + 0x84, 0x82, 0x83, 0x7f, 0x7f, 0x81, 0x80, 0x8e, 0x8a, + 0x85, 0x81, 0x81, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xda, 0x00, 0xe1, 0x00, 0xd2, 0x84, 0x84, 0x84, + 0x83, 0x83, 0x83, 0x84, 0x84, 0x85, 0x83, 0x84, 0x00, + 0x84, 0x7f, 0x80, 0x7b, 0x83, 0x85, 0x85, 0x87, 0x84, + 0xa5, 0x94, 0x9c, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xda, 0x00, 0xe1, 0x00, 0xd2, 0x84, 0x84, 0x84, + 0x83, 0x83, 0x83, 0x82, 0x83, 0x83, 0x82, 0x82, 0x00, + 0x83, 0x82, 0x82, 0x7e, 0x82, 0x85, 0x85, 0x89, 0x85, + 0x7b, 0x7c, 0x7b, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xda, 0x00, 0xe1, 0x00, 0xd2, 0x84, 0x84, 0x84, + 0x83, 0x83, 0x83, 0x82, 0x83, 0x83, 0x83, 0x82, 0x00, + 0x84, 0x81, 0x82, 0x7d, 0x83, 0x85, 0x85, 0x86, 0x86, + 0x97, 0x8c, 0x91, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xda, 0x00, 0xe1, 0x00, 0xd2, 0x84, 0x84, 0x84, + 0x82, 0x82, 0x82, 0x83, 0x84, 0x84, 0x84, 0x82, 0x00, + 0x84, 0x82, 0x82, 0x7e, 0x7e, 0x80, 0x80, 0x8d, 0x8b, + 0x7b, 0x7c, 0x7b, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xda, 0x00, 0xe1, 0x00, 0xd2, 0x83, 0x84, 0x84, + 0x84, 0x84, 0x84, 0x82, 0x83, 0x83, 0x82, 0x82, 0x00, + 0x85, 0x82, 0x82, 0x7e, 0x84, 0x85, 0x85, 0x8b, 0x8a, + 0x7b, 0x7c, 0x7b, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xe0, 0x00, 0xe6, 0x00, 0xda, 0x83, 0x83, 0x83, + 0x83, 0x82, 0x82, 0x83, 0x83, 0x83, 0x82, 0x81, 0x00, + 0x84, 0x83, 0x83, 0x80, 0x81, 0x81, 0x81, 0x8b, 0x8a, + 0x7b, 0x7c, 0x7b, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xe6, 0x00, 0xeb, 0x00, 0xe1, 0x82, 0x83, 0x83, + 0x83, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x00, + 0x83, 0x84, 0x84, 0x82, 0x83, 0x83, 0x83, 0x86, 0x85, + 0x89, 0x84, 0x86, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xec, 0x00, 0xf0, 0x00, 0xe8, 0x82, 0x83, 0x83, + 0x81, 0x81, 0x81, 0x80, 0x81, 0x81, 0x82, 0x82, 0x00, + 0x83, 0x81, 0x81, 0x80, 0x83, 0x83, 0x83, 0x86, 0x85, + 0x89, 0x84, 0x86, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xf1, 0x00, 0xf4, 0x00, 0xee, 0x81, 0x81, 0x81, + 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x81, 0x80, 0x00, + 0x82, 0x81, 0x81, 0x80, 0x83, 0x83, 0x83, 0x86, 0x85, + 0x7b, 0x7c, 0x7b, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x00, 0xf6, 0x00, 0xf8, 0x00, 0xf4, 0x82, 0x82, 0x82, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, + 0x81, 0x82, 0x82, 0x81, 0x7f, 0x7f, 0x7f, 0x86, 0x85, + 0x7b, 0x7c, 0x7b, 0x00, 0x00, 0x00 }, + { MCS_GAMMA, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x00, 0x00, 0x00 } +}; + +/* ELVSS (Amoled negative power supply) tables */ +#define EA8061V_AMS497EE01_NUM_ELVSS_SEQUENCES 18 +#define ELVSS_SEQUENCE_LEN 3 +static const u8 seq_ea8061v_ams497ee01_elvss[EA8061V_AMS497EE01_NUM_ELVSS_SEQUENCES][ELVSS_SEQUENCE_LEN] = { + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x9b }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x9a }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x99 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x98 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x97 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x96 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x95 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x94 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x93 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x92 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x91 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x90 }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x8f }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x8e }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x8d }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x8c }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x8b }, + { MCS_ELVSS_CONTROL, MCS_ACL_OFF, 0x8a } +}; + +#define EA8061V_AMS497EE01_NUM_AID_LEVELS 42 +#define EA8061V_AMS497EE01_AID_CMD_CNT 5 +/* Which AID sequence to use for each candela level. + */ +static const u8 map_candela_to_aid[EA8061V_AMS497EE01_NUM_GAMMA_LEVELS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 41, 41, + 41, 41 +}; + +static const u8 seq_ea8061v_ams497ee01_aid[EA8061V_AMS497EE01_NUM_AID_LEVELS][EA8061V_AMS497EE01_AID_CMD_CNT] = { + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0xdf }, /* 95.63 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0xd3 }, /* 94.71 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0xc7 }, /* 93.79 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0xbb }, /* 92.87 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0xb0 }, /* 92.02 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0xa4 }, /* 91.10 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x99 }, /* 90.26 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x8d }, /* 89.34 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x82 }, /* 88.50 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x76 }, /* 87.58 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x6a }, /* 86.66 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x5f }, /* 85.81 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x52 }, /* 84.82 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x3b }, /* 83.05 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x31 }, /* 82.29 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x25 }, /* 81.37 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x18 }, /* 80.37 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x04, 0x01 }, /* 78.60 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0xf5 }, /* 77.68 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0xdb }, /* 75.69 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0xc5 }, /* 74.00 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0xb7 }, /* 72.93 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0x9e }, /* 71.01 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0x88 }, /* 69.33 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0x64 }, /* 66.56 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0x4b }, /* 64.64 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0x32 }, /* 62.73 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x03, 0x0d }, /* 59.89 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x02, 0xe7 }, /* 56.98 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x02, 0xc2 }, /* 54.14 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x02, 0x9d }, /* 51.30 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x02, 0x79 }, /* 48.54 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x02, 0x45 }, /* 44.56 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x02, 0x13 }, /* 40.72 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x01, 0xe7 }, /* 37.35 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x01, 0xae }, /* 32.98 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x01, 0x76 }, /* 28.68 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x01, 0x39 }, /* 24.00 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x00, 0xf8 }, /* 19.02 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x00, 0xb4 }, /* 13.80 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x00, 0x63 }, /* 7.59 % */ + { MCS_AID_CONTROL, 0x00, 0x00, 0x00, 0x0a } /* 0.77 % */ +}; struct ea8061v_ams497ee01 { struct drm_panel panel; struct mipi_dsi_device *dsi; + + struct backlight_device *bl_dev; + struct regulator_bulk_data supplies[2]; struct gpio_desc *reset_gpio; + bool prepared; + bool enabled; }; static inline @@ -27,42 +460,223 @@ struct ea8061v_ams497ee01 *to_ea8061v_ams497ee01(struct drm_panel *panel) return container_of(panel, struct ea8061v_ams497ee01, panel); } -static void ea8061v_ams497ee01_reset(struct ea8061v_ams497ee01 *ctx) +static int ea8061v_ams497ee01_unlock(struct ea8061v_ams497ee01 *ctx, u8 lock) { - gpiod_set_value_cansleep(ctx->reset_gpio, 0); - msleep(20); - gpiod_set_value_cansleep(ctx->reset_gpio, 1); - usleep_range(1000, 2000); - gpiod_set_value_cansleep(ctx->reset_gpio, 0); - msleep(20); + switch (lock) { + case 0xf0: + mipi_dsi_dcs_write_seq(ctx->dsi, 0xf0, 0x5a, 0x5a); + break; + case 0xf1: + mipi_dsi_dcs_write_seq(ctx->dsi, 0xf1, 0x5a, 0x5a); + break; + case 0xfc: + mipi_dsi_dcs_write_seq(ctx->dsi, 0xfc, 0x5a, 0x5a); + break; + default: + return -EINVAL; + } + return 0; } -static int ea8061v_ams497ee01_on(struct ea8061v_ams497ee01 *ctx) +static int ea8061v_ams497ee01_lock(struct ea8061v_ams497ee01 *ctx, u8 lock) { + switch (lock) { + case 0xf0: + mipi_dsi_dcs_write_seq(ctx->dsi, 0xf0, 0xa5, 0xa5); + break; + case 0xf1: + mipi_dsi_dcs_write_seq(ctx->dsi, 0xf1, 0xa5, 0xa5); + break; + case 0xfc: + mipi_dsi_dcs_write_seq(ctx->dsi, 0xfc, 0xa5, 0xa5); + break; + default: + return -EINVAL; + } + return 0; +} + +static int ea8061v_ams497ee01_apply_gamma(struct ea8061v_ams497ee01 *ctx) +{ + mipi_dsi_dcs_write_seq(ctx->dsi, MCS_GAMMA_UPDATE, 0x01); + return 0; +} + +static int ea8061v_ams497ee01_update_aid(struct ea8061v_ams497ee01 *ctx, + unsigned int brightness) +{ + int ret; + int index = map_candela_to_aid[brightness]; + + ret = mipi_dsi_dcs_write_buffer(ctx->dsi, + seq_ea8061v_ams497ee01_aid[index], + EA8061V_AMS497EE01_AID_CMD_CNT); + if (ret < 0) + return ret; + return 0; +} + +static int ea8061v_ams497ee01_update_elvss(struct ea8061v_ams497ee01 *ctx, + unsigned int brightness) +{ + int ret; + int index = map_candela_to_elvss[brightness]; + + ret = mipi_dsi_dcs_write_buffer(ctx->dsi, + seq_ea8061v_ams497ee01_elvss[index], + ELVSS_SEQUENCE_LEN); + if (ret < 0) + return ret; + return 0; +} + +static int ea8061v_ams497ee01_update_gamma(struct ea8061v_ams497ee01 *ctx, + unsigned int brightness) +{ + int ret; + struct backlight_device *bl_dev = ctx->bl_dev; + + ret = mipi_dsi_dcs_write_buffer(ctx->dsi, + seq_ea8061v_ams497ee01_lux[brightness], + EA8061V_AMS497EE01_GAMMA_CMD_CNT); + if (ret < 0) + return ret; + + bl_dev->props.brightness = brightness; + + return 0; +} + +static int ea8061v_ams497ee01_set_brightness(struct backlight_device *bl_dev) +{ + struct ea8061v_ams497ee01 *ctx = bl_get_data(bl_dev); + unsigned int brightness = bl_dev->props.brightness; struct mipi_dsi_device *dsi = ctx->dsi; struct device *dev = &dsi->dev; int ret; + ret = ea8061v_ams497ee01_unlock(ctx, 0xf0); + if (ret < 0) { + dev_err(dev, "Failed to unlock 0xf0: %d\n", ret); + return ret; + } + ret = ea8061v_ams497ee01_unlock(ctx, 0xf1); + if (ret < 0) { + dev_err(dev, "Failed to unlock 0xf1: %d\n", ret); + return ret; + } + + /* aid/aor */ + ret = ea8061v_ams497ee01_update_aid(ctx, brightness); + if (ret < 0) { + dev_err(dev, "Failed to send aid sequence: %d\n", ret); + return ret; + } + mipi_dsi_dcs_write_seq(dsi, MCS_ACL_OPR_CONTROL, 0x29); + mipi_dsi_dcs_write_seq(dsi, MCS_ACL_CONTROL, 0x00); + + ret = ea8061v_ams497ee01_update_elvss(ctx, brightness); + if (ret < 0) { + dev_err(dev, "Failed to update elvss: %d\n", ret); + return ret; + } + + ret = ea8061v_ams497ee01_update_gamma(ctx, brightness); + if (ret < 0) { + dev_err(dev, "Failed to update gamma: %d\n", ret); + return ret; + } + + ret = ea8061v_ams497ee01_apply_gamma(ctx); + if (ret < 0) { + dev_err(dev, "Failed to apply gamma update: %d\n", ret); + return ret; + } + + ea8061v_ams497ee01_lock(ctx, 0xf1); + if (ret < 0) { + dev_err(dev, "Failed to lock 0xf1: %d\n", ret); + return ret; + } + ea8061v_ams497ee01_lock(ctx, 0xf0); + if (ret < 0) { + dev_err(dev, "Failed to lock 0xf0: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct backlight_ops ea8061v_ams497ee01_bl_ops = { + .update_status = ea8061v_ams497ee01_set_brightness, +}; + +static int ea8061v_ams497ee01_init(struct ea8061v_ams497ee01 *ctx) +{ + struct mipi_dsi_device *dsi = ctx->dsi; + struct device *dev = &dsi->dev; + int ret; + + unsigned int brightness = ctx->bl_dev->props.brightness; + dsi->mode_flags |= MIPI_DSI_MODE_LPM; - mipi_dsi_dcs_write_seq(dsi, 0xf0, 0x5a, 0x5a); - mipi_dsi_dcs_write_seq(dsi, 0xf1, 0x5a, 0x5a); - mipi_dsi_dcs_write_seq(dsi, 0xb8, 0x19, 0x10); + ret = ea8061v_ams497ee01_unlock(ctx, 0xf0); + if (ret < 0) { + dev_err(dev, "Failed to unlock 0xf0: %d\n", ret); + return ret; + } + ret = ea8061v_ams497ee01_unlock(ctx, 0xf1); + if (ret < 0) { + dev_err(dev, "Failed to unlock 0xf1: %d\n", ret); + return ret; + } + + /* Common conditions */ + /* set ref temperature/voltage (0x19 = 25 degC, 0x10 = 7.6 V) */ + mipi_dsi_dcs_write_seq(dsi, MCS_TSET, 0x19, 0x10); + /* ? */ mipi_dsi_dcs_write_seq(dsi, 0xba, 0x57); - mipi_dsi_dcs_write_seq(dsi, 0xfc, 0x5a, 0x5a); + + ret = ea8061v_ams497ee01_unlock(ctx, 0xfc); + if (ret < 0) { + dev_err(dev, "Failed to unlock 0xfc: %d\n", ret); + return ret; + } + + /* skip 11 parameters in HBM sequence? */ mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x0b); + /* ? */ mipi_dsi_dcs_write_seq(dsi, 0xd2, 0x00, 0x85); + /* ? */ mipi_dsi_dcs_write_seq(dsi, 0xcb, 0x70); - mipi_dsi_dcs_write_seq(dsi, 0xfc, 0xa5, 0xa5); - mipi_dsi_dcs_write_seq(dsi, 0xca, - 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, - 0x00); - mipi_dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x00, 0x00, 0x0a); - mipi_dsi_dcs_write_seq(dsi, 0xb6, 0x5c, 0x8a); - mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x01); + + ret = ea8061v_ams497ee01_lock(ctx, 0xfc); + if (ret < 0) { + dev_err(dev, "Failed to lock 0xfc: %d\n", ret); + return ret; + } + /* Brightness control */ + ret = ea8061v_ams497ee01_update_gamma(ctx, brightness); + if (ret < 0) { + dev_err(dev, "Failed to update gamma: %d\n", ret); + return ret; + } + ret = ea8061v_ams497ee01_update_aid(ctx, brightness); + if (ret < 0) { + dev_err(dev, "Failed to send aid sequence: %d\n", ret); + return ret; + } + ret = ea8061v_ams497ee01_update_elvss(ctx, brightness); + if (ret < 0) { + dev_err(dev, "Failed to update elvss: %d\n", ret); + return ret; + } + ret = ea8061v_ams497ee01_apply_gamma(ctx); + if (ret < 0) { + dev_err(dev, "Failed to apply gamma update: %d\n", ret); + return ret; + } ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret < 0) { @@ -71,7 +685,11 @@ static int ea8061v_ams497ee01_on(struct ea8061v_ams497ee01 *ctx) } msleep(120); - mipi_dsi_dcs_write_seq(dsi, 0xf1, 0xa5, 0xa5); + ret = ea8061v_ams497ee01_lock(ctx, 0xf1); + if (ret < 0) { + dev_err(dev, "Failed to lock 0xf1: %d\n", ret); + return ret; + } ret = mipi_dsi_dcs_set_display_on(dsi); if (ret < 0) { @@ -82,28 +700,91 @@ static int ea8061v_ams497ee01_on(struct ea8061v_ams497ee01 *ctx) return 0; } -static int ea8061v_ams497ee01_off(struct ea8061v_ams497ee01 *ctx) +static int ea8061v_ams497ee01_power_on(struct ea8061v_ams497ee01 *ctx) +{ + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + if (ret < 0) { + dev_err(&ctx->dsi->dev, + "Failed to enable regulators: %d\n", ret); + return ret; + } + + /* send reset pulse */ + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + msleep(20); + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(1000, 2000); + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + msleep(20); + + return 0; +} + +static int ea8061v_ams497ee01_power_off(struct ea8061v_ams497ee01 *ctx) { + int ret; + + gpiod_set_value(ctx->reset_gpio, 1); + + ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + if (ret < 0) + return ret; + + return 0; +} + +static int ea8061v_ams497ee01_enable(struct drm_panel *panel) +{ + struct ea8061v_ams497ee01 *ctx = to_ea8061v_ams497ee01(panel); struct mipi_dsi_device *dsi = ctx->dsi; - struct device *dev = &dsi->dev; int ret; + if (ctx->prepared) + return 0; + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + dev_err(&dsi->dev, "Failed to exit sleep mode: %d\n", ret); + return ret; + }; + msleep(120); + + backlight_enable(ctx->bl_dev); + + ctx->enabled = true; + return 0; +} + +static int ea8061v_ams497ee01_disable(struct drm_panel *panel) +{ + struct ea8061v_ams497ee01 *ctx = to_ea8061v_ams497ee01(panel); + struct mipi_dsi_device *dsi = ctx->dsi; + int ret; + + if (!ctx->enabled) + return 0; + + backlight_disable(ctx->bl_dev); + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) { - dev_err(dev, "Failed to set display off: %d\n", ret); + dev_err(&dsi->dev, "Failed to set display off: %d\n", ret); return ret; } msleep(35); ret = mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret < 0) { - dev_err(dev, "Failed to enter sleep mode: %d\n", ret); + dev_err(&dsi->dev, "Failed to enter sleep mode: %d\n", ret); return ret; } msleep(100); + ctx->enabled = false; return 0; } @@ -116,19 +797,16 @@ static int ea8061v_ams497ee01_prepare(struct drm_panel *panel) if (ctx->prepared) return 0; - ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + ret = ea8061v_ams497ee01_power_on(ctx); if (ret < 0) { - dev_err(dev, "Failed to enable regulators: %d\n", ret); + dev_err(dev, "Failed to power on panel: %d\n", ret); return ret; } - ea8061v_ams497ee01_reset(ctx); - - ret = ea8061v_ams497ee01_on(ctx); + ret = ea8061v_ams497ee01_init(ctx); if (ret < 0) { dev_err(dev, "Failed to initialize panel: %d\n", ret); - gpiod_set_value_cansleep(ctx->reset_gpio, 1); - regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); + ea8061v_ams497ee01_power_off(ctx); return ret; } @@ -145,13 +823,10 @@ static int ea8061v_ams497ee01_unprepare(struct drm_panel *panel) if (!ctx->prepared) return 0; - ret = ea8061v_ams497ee01_off(ctx); + ret = ea8061v_ams497ee01_power_off(ctx); if (ret < 0) dev_err(dev, "Failed to un-initialize panel: %d\n", ret); - gpiod_set_value_cansleep(ctx->reset_gpio, 1); - regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); - ctx->prepared = false; return 0; } @@ -191,6 +866,8 @@ static int ea8061v_ams497ee01_get_modes(struct drm_panel *panel, static const struct drm_panel_funcs ea8061v_ams497ee01_panel_funcs = { .prepare = ea8061v_ams497ee01_prepare, + .enable = ea8061v_ams497ee01_enable, + .disable = ea8061v_ams497ee01_disable, .unprepare = ea8061v_ams497ee01_unprepare, .get_modes = ea8061v_ams497ee01_get_modes, }; @@ -205,6 +882,9 @@ static int ea8061v_ams497ee01_probe(struct mipi_dsi_device *dsi) if (!ctx) return -ENOMEM; + ctx->dsi = dsi; + mipi_dsi_set_drvdata(dsi, ctx); + ctx->supplies[0].supply = "vdd3"; ctx->supplies[1].supply = "vci"; ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), @@ -217,14 +897,24 @@ static int ea8061v_ams497ee01_probe(struct mipi_dsi_device *dsi) return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset-gpios\n"); - ctx->dsi = dsi; - mipi_dsi_set_drvdata(dsi, ctx); + ctx->bl_dev = backlight_device_register("panel", dev, ctx, + &ea8061v_ams497ee01_bl_ops, + NULL); dsi->lanes = 4; dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_NO_EOT_PACKET; + if (IS_ERR(ctx->bl_dev)) { + dev_err(dev, "Failed to register backlight device\n"); + return PTR_ERR(ctx->bl_dev); + } + + ctx->bl_dev->props.max_brightness = EA8061V_AMS497EE01_MAX_BRIGHTNESS; + ctx->bl_dev->props.brightness = EA8061V_AMS497EE01_DEFAULT_BRIGHTNESS; + ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; + drm_panel_init(&ctx->panel, dev, &ea8061v_ams497ee01_panel_funcs, DRM_MODE_CONNECTOR_DSI); ctx->panel.prepare_prev_first = true; @@ -248,13 +938,14 @@ static void ea8061v_ams497ee01_remove(struct mipi_dsi_device *dsi) ret = mipi_dsi_detach(dsi); if (ret < 0) - dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); + dev_err(&dsi->dev, + "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); } static const struct of_device_id ea8061v_ams497ee01_of_match[] = { - { .compatible = "samsung,ea8061v-ams497ee01" }, // FIXME + { .compatible = "samsung,ea8061v-ams497ee01" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, ea8061v_ams497ee01_of_match);