mirror of
https://github.com/physwizz/a155-U-u1.git
synced 2025-09-26 19:04:54 +00:00
2339 lines
66 KiB
C
2339 lines
66 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) Samsung Electronics Co., Ltd.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/device.h>
|
|
#include <linux/backlight.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/lcd.h>
|
|
#include <linux/fb.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include "panel_kunit.h"
|
|
#include "panel_drv.h"
|
|
#include "mdnie.h"
|
|
#include "panel_debug.h"
|
|
#include "panel_property.h"
|
|
#ifdef CONFIG_USDM_PANEL_COPR
|
|
#include "copr.h"
|
|
#endif
|
|
#ifdef CONFIG_USDM_PANEL_DPUI
|
|
#include "dpui.h"
|
|
#endif
|
|
#ifdef CONFIG_USDM_PANEL_TESTMODE
|
|
#include "panel_testmode.h"
|
|
#endif
|
|
|
|
#ifdef MDNIE_SELF_TEST
|
|
int g_coord_x = MIN_WCRD_X;
|
|
int g_coord_y = MIN_WCRD_Y;
|
|
#endif
|
|
|
|
static const char * const scr_white_mode_name[] = {
|
|
[SCR_WHITE_MODE_NONE] = "none",
|
|
[SCR_WHITE_MODE_COLOR_COORDINATE] = "coordinate",
|
|
[SCR_WHITE_MODE_ADJUST_LDU] = "adjust-ldu",
|
|
[SCR_WHITE_MODE_SENSOR_RGB] = "sensor-rgb",
|
|
};
|
|
|
|
static const char * const mdnie_mode_name[] = {
|
|
[MDNIE_OFF_MODE] = "off",
|
|
[MDNIE_BYPASS_MODE] = "bypass",
|
|
[MDNIE_LIGHT_NOTIFICATION_MODE] = "light_notification",
|
|
[MDNIE_ACCESSIBILITY_MODE] = "accessibility",
|
|
[MDNIE_COLOR_LENS_MODE] = "color_lens",
|
|
[MDNIE_HDR_MODE] = "hdr",
|
|
[MDNIE_HMD_MODE] = "hmd",
|
|
[MDNIE_NIGHT_MODE] = "night",
|
|
[MDNIE_HBM_CE_MODE] = "hbm_ce",
|
|
[MDNIE_SCENARIO_MODE] = "scenario",
|
|
};
|
|
|
|
static const char * const scenario_mode_name[] = {
|
|
[DYNAMIC] = "dynamic",
|
|
[STANDARD] = "standard",
|
|
[NATURAL] = "natural",
|
|
[MOVIE] = "movie",
|
|
[AUTO] = "auto",
|
|
};
|
|
|
|
static const char * const scenario_name[] = {
|
|
[UI_MODE] = "ui",
|
|
[VIDEO_NORMAL_MODE] = "video_normal",
|
|
[CAMERA_MODE] = "camera",
|
|
[NAVI_MODE] = "navi",
|
|
[GALLERY_MODE] = "gallery",
|
|
[VT_MODE] = "vt",
|
|
[BROWSER_MODE] = "browser",
|
|
[EBOOK_MODE] = "ebook",
|
|
[EMAIL_MODE] = "email",
|
|
[GAME_LOW_MODE] = "game_low",
|
|
[GAME_MID_MODE] = "game_mid",
|
|
[GAME_HIGH_MODE] = "game_high",
|
|
[VIDEO_ENHANCER] = "video_enhancer",
|
|
[VIDEO_ENHANCER_THIRD] = "video_enhancer_third",
|
|
[HMD_8_MODE] = "hmd_8",
|
|
[HMD_16_MODE] = "hmd_16",
|
|
};
|
|
|
|
static const char * const accessibility_name[] = {
|
|
[ACCESSIBILITY_OFF] = "off",
|
|
[NEGATIVE] = "negative",
|
|
[COLOR_BLIND] = "color_blind",
|
|
[SCREEN_CURTAIN] = "screen_curtain",
|
|
[GRAYSCALE] = "grayscale",
|
|
[GRAYSCALE_NEGATIVE] = "grayscale_negative",
|
|
[COLOR_BLIND_HBM] = "color_blind_hbm",
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_mode_enum_items[MAX_MDNIE_MODE] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_OFF_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_BYPASS_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_ACCESSIBILITY_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_LIGHT_NOTIFICATION_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_COLOR_LENS_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_HDR_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_HMD_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_NIGHT_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_HBM_CE_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_SCENARIO_MODE),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_scenario_enum_items[SCENARIO_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(UI_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(VIDEO_NORMAL_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CAMERA_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(NAVI_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(GALLERY_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(VT_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(BROWSER_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(EBOOK_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(EMAIL_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(GAME_LOW_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(GAME_MID_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(GAME_HIGH_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(VIDEO_ENHANCER),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(VIDEO_ENHANCER_THIRD),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HMD_8_MODE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HMD_16_MODE),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_scenario_mode_enum_items[MODE_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(DYNAMIC),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(STANDARD),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(NATURAL),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MOVIE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(AUTO),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_screen_mode_enum_items[MAX_MDNIE_SCREEN_MODE] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_SCREEN_MODE_VIVID),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(MDNIE_SCREEN_MODE_NATURAL),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_bypass_enum_items[BYPASS_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(BYPASS_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(BYPASS_ON),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_accessibility_enum_items[ACCESSIBILITY_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(ACCESSIBILITY_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(NEGATIVE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_BLIND),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(SCREEN_CURTAIN),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(GRAYSCALE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(GRAYSCALE_NEGATIVE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_BLIND_HBM),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_hmd_enum_items[HMD_MDNIE_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HMD_MDNIE_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HMD_3000K),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HMD_4000K),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HMD_5000K),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HMD_6500K),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HMD_7500K),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_hbm_ce_enum_items[HBM_CE_MODE_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HBM_CE_MODE_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HBM_CE_MODE_ON),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_night_mode_enum_items[NIGHT_MODE_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(NIGHT_MODE_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(NIGHT_MODE_ON),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_anti_glare_enum_items[ANTI_GLARE_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(ANTI_GLARE_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(ANTI_GLARE_ON),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_color_lens_enum_items[COLOR_LENS_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_ON),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_color_lens_color_enum_items[COLOR_LENS_COLOR_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_BLUE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_AZURE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_CYAN),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_SPRING_GREEN),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_GREEN),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_CHARTREUSE_GREEN),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_YELLOW),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_ORANGE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_RED),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_ROSE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_MAGENTA),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_COLOR_VIOLET),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_color_lens_level_enum_items[COLOR_LENS_LEVEL_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_LEVEL_20P),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_LEVEL_25P),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_LEVEL_30P),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_LEVEL_35P),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_LEVEL_40P),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_LEVEL_45P),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_LEVEL_50P),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_LEVEL_55P),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(COLOR_LENS_LEVEL_60P),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_hdr_enum_items[HDR_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HDR_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HDR_1),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HDR_2),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(HDR_3),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_light_notification_enum_items[LIGHT_NOTIFICATION_MAX] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(LIGHT_NOTIFICATION_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(LIGHT_NOTIFICATION_ON),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_ccrd_pt_enum_items[MAX_CCRD_PT] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_NONE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_1),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_2),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_3),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_4),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_5),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_6),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_7),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_8),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(CCRD_PT_9),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_ldu_mode_enum_items[MAX_LDU_MODE] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(LDU_MODE_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(LDU_MODE_1),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(LDU_MODE_2),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(LDU_MODE_3),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(LDU_MODE_4),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(LDU_MODE_5),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_scr_white_mode_enum_items[MAX_SCR_WHITE_MODE] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(SCR_WHITE_MODE_NONE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(SCR_WHITE_MODE_COLOR_COORDINATE),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(SCR_WHITE_MODE_ADJUST_LDU),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(SCR_WHITE_MODE_SENSOR_RGB),
|
|
};
|
|
|
|
static struct panel_prop_enum_item mdnie_trans_mode_enum_items[MAX_TRANS_MODE] = {
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(TRANS_OFF),
|
|
__PANEL_PROPERTY_ENUM_ITEM_INITIALIZER(TRANS_ON),
|
|
};
|
|
|
|
static struct panel_prop_list mdnie_property_array[] = {
|
|
/* enum property */
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_MODE_PROPERTY,
|
|
MDNIE_OFF_MODE, mdnie_mode_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_SCENARIO_PROPERTY,
|
|
UI_MODE, mdnie_scenario_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_SCENARIO_MODE_PROPERTY,
|
|
AUTO, mdnie_scenario_mode_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_SCREEN_MODE_PROPERTY,
|
|
MDNIE_SCREEN_MODE_VIVID, mdnie_screen_mode_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_BYPASS_PROPERTY,
|
|
BYPASS_OFF, mdnie_bypass_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_ACCESSIBILITY_PROPERTY,
|
|
ACCESSIBILITY_OFF, mdnie_accessibility_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_HMD_PROPERTY,
|
|
HMD_MDNIE_OFF, mdnie_hmd_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_HBM_CE_PROPERTY,
|
|
HBM_CE_MODE_OFF, mdnie_hbm_ce_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_NIGHT_MODE_PROPERTY,
|
|
NIGHT_MODE_OFF, mdnie_night_mode_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_ANTI_GLARE_PROPERTY,
|
|
ANTI_GLARE_OFF, mdnie_anti_glare_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_COLOR_LENS_PROPERTY,
|
|
COLOR_LENS_OFF, mdnie_color_lens_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_COLOR_LENS_COLOR_PROPERTY,
|
|
COLOR_LENS_COLOR_BLUE, mdnie_color_lens_color_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_COLOR_LENS_LEVEL_PROPERTY,
|
|
COLOR_LENS_LEVEL_20P, mdnie_color_lens_level_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_HDR_PROPERTY,
|
|
HDR_OFF, mdnie_hdr_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_LIGHT_NOTIFICATION_PROPERTY,
|
|
LIGHT_NOTIFICATION_OFF, mdnie_light_notification_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_CCRD_PT_PROPERTY,
|
|
CCRD_PT_NONE, mdnie_ccrd_pt_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_LDU_MODE_PROPERTY,
|
|
LDU_MODE_OFF, mdnie_ldu_mode_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_SCR_WHITE_MODE_PROPERTY,
|
|
SCR_WHITE_MODE_NONE, mdnie_scr_white_mode_enum_items),
|
|
__PANEL_PROPERTY_ENUM_INITIALIZER(MDNIE_TRANS_MODE_PROPERTY,
|
|
TRANS_ON, mdnie_trans_mode_enum_items),
|
|
/* range property */
|
|
__PANEL_PROPERTY_RANGE_INITIALIZER(MDNIE_ENABLE_PROPERTY,
|
|
0, 0, 1),
|
|
__PANEL_PROPERTY_RANGE_INITIALIZER(MDNIE_NIGHT_LEVEL_PROPERTY,
|
|
NIGHT_LEVEL_6500K, 0, 305),
|
|
__PANEL_PROPERTY_RANGE_INITIALIZER(MDNIE_HBM_CE_LEVEL_PROPERTY,
|
|
0, 0, MAX_HBM_CE_LEVEL),
|
|
__PANEL_PROPERTY_RANGE_INITIALIZER(MDNIE_EXTRA_DIM_LEVEL_PROPERTY,
|
|
0, 0, MAX_EXTRA_DIM_LEVEL),
|
|
};
|
|
|
|
__visible_for_testing int mdnie_set_property_value(struct mdnie_info *mdnie,
|
|
char *propname, unsigned int value)
|
|
{
|
|
return panel_set_property_value(to_panel_device(mdnie),
|
|
propname, value);
|
|
}
|
|
|
|
__visible_for_testing int mdnie_set_property(struct mdnie_info *mdnie,
|
|
u32 *property, unsigned int value)
|
|
{
|
|
char *propname = NULL;
|
|
|
|
if (!mdnie) {
|
|
panel_err("mdnie is null\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!property) {
|
|
panel_err("property is null\n");
|
|
return -EINVAL;
|
|
}
|
|
if (property == &mdnie->props.enable)
|
|
propname = MDNIE_ENABLE_PROPERTY;
|
|
else if (property == &mdnie->props.mdnie_mode)
|
|
propname = MDNIE_MODE_PROPERTY;
|
|
else if (property == &mdnie->props.scenario)
|
|
propname = MDNIE_SCENARIO_PROPERTY;
|
|
else if (property == &mdnie->props.scenario_mode)
|
|
propname = MDNIE_SCENARIO_MODE_PROPERTY;
|
|
else if (property == &mdnie->props.screen_mode)
|
|
propname = MDNIE_SCREEN_MODE_PROPERTY;
|
|
else if (property == &mdnie->props.bypass)
|
|
propname = MDNIE_BYPASS_PROPERTY;
|
|
else if (property == &mdnie->props.accessibility)
|
|
propname = MDNIE_ACCESSIBILITY_PROPERTY;
|
|
else if (property == &mdnie->props.hbm_ce_level)
|
|
propname = MDNIE_HBM_CE_LEVEL_PROPERTY;
|
|
else if (property == &mdnie->props.hmd)
|
|
propname = MDNIE_HMD_PROPERTY;
|
|
else if (property == &mdnie->props.night)
|
|
propname = MDNIE_NIGHT_MODE_PROPERTY;
|
|
else if (property == &mdnie->props.night_level)
|
|
propname = MDNIE_NIGHT_LEVEL_PROPERTY;
|
|
else if (property == &mdnie->props.anti_glare)
|
|
propname = MDNIE_ANTI_GLARE_PROPERTY;
|
|
else if (property == &mdnie->props.color_lens)
|
|
propname = MDNIE_COLOR_LENS_PROPERTY;
|
|
else if (property == &mdnie->props.color_lens_color)
|
|
propname = MDNIE_COLOR_LENS_COLOR_PROPERTY;
|
|
else if (property == &mdnie->props.color_lens_level)
|
|
propname = MDNIE_COLOR_LENS_LEVEL_PROPERTY;
|
|
else if (property == &mdnie->props.hdr)
|
|
propname = MDNIE_HDR_PROPERTY;
|
|
else if (property == &mdnie->props.light_notification)
|
|
propname = MDNIE_LIGHT_NOTIFICATION_PROPERTY;
|
|
else if (property == &mdnie->props.ldu)
|
|
propname = MDNIE_LDU_MODE_PROPERTY;
|
|
else if (property == &mdnie->props.scr_white_mode)
|
|
propname = MDNIE_SCR_WHITE_MODE_PROPERTY;
|
|
else if (property == &mdnie->props.trans_mode)
|
|
propname = MDNIE_TRANS_MODE_PROPERTY;
|
|
else if (property == &mdnie->props.extra_dim_level)
|
|
propname = MDNIE_EXTRA_DIM_LEVEL_PROPERTY;
|
|
|
|
if (!propname) {
|
|
panel_err("unknown property\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (mdnie_set_property_value(mdnie,
|
|
propname, value) < 0) {
|
|
panel_warn("failed to set property(%s) %d\n",
|
|
propname, value);
|
|
return -EINVAL;
|
|
}
|
|
*property = value;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mdnie_current_state(struct mdnie_info *mdnie)
|
|
{
|
|
struct panel_device *panel =
|
|
container_of(mdnie, struct panel_device, mdnie);
|
|
int mdnie_mode;
|
|
|
|
if (IS_BYPASS_MODE(mdnie))
|
|
mdnie_mode = MDNIE_BYPASS_MODE;
|
|
else if (IS_LIGHT_NOTIFICATION_MODE(mdnie))
|
|
mdnie_mode = MDNIE_LIGHT_NOTIFICATION_MODE;
|
|
else if (IS_ACCESSIBILITY_MODE(mdnie))
|
|
mdnie_mode = MDNIE_ACCESSIBILITY_MODE;
|
|
else if (IS_COLOR_LENS_MODE(mdnie))
|
|
mdnie_mode = MDNIE_COLOR_LENS_MODE;
|
|
else if (IS_HMD_MODE(mdnie))
|
|
mdnie_mode = MDNIE_HMD_MODE;
|
|
else if (IS_NIGHT_MODE(mdnie))
|
|
mdnie_mode = MDNIE_NIGHT_MODE;
|
|
else if (IS_HBM_CE_MODE(mdnie))
|
|
mdnie_mode = MDNIE_HBM_CE_MODE;
|
|
else if (IS_HDR_MODE(mdnie))
|
|
mdnie_mode = MDNIE_HDR_MODE;
|
|
else if (IS_SCENARIO_MODE(mdnie))
|
|
mdnie_mode = MDNIE_SCENARIO_MODE;
|
|
else
|
|
mdnie_mode = MDNIE_OFF_MODE;
|
|
|
|
if (panel_get_cur_state(panel) == PANEL_STATE_ALPM &&
|
|
((mdnie_mode == MDNIE_ACCESSIBILITY_MODE &&
|
|
(mdnie->props.accessibility == NEGATIVE ||
|
|
mdnie->props.accessibility == GRAYSCALE_NEGATIVE)) ||
|
|
(mdnie_mode == MDNIE_SCENARIO_MODE && !IS_LDU_MODE(mdnie)) ||
|
|
mdnie_mode == MDNIE_COLOR_LENS_MODE ||
|
|
mdnie_mode == MDNIE_HDR_MODE ||
|
|
mdnie_mode == MDNIE_LIGHT_NOTIFICATION_MODE ||
|
|
mdnie_mode == MDNIE_HMD_MODE)) {
|
|
panel_dbg("block mdnie (%s->%s) in doze mode\n",
|
|
mdnie_mode_name[mdnie_mode],
|
|
mdnie_mode_name[MDNIE_BYPASS_MODE]);
|
|
mdnie_mode = MDNIE_BYPASS_MODE;
|
|
}
|
|
|
|
return mdnie_mode;
|
|
}
|
|
|
|
char *mdnie_get_accessibility_sequence_name(struct mdnie_info *mdnie)
|
|
{
|
|
static char *accessibility_seqname_array[] = {
|
|
[ACCESSIBILITY_OFF] = NULL,
|
|
[NEGATIVE] = MDNIE_NEGATIVE_SEQ,
|
|
[COLOR_BLIND] = MDNIE_COLOR_BLIND_SEQ,
|
|
[SCREEN_CURTAIN] = MDNIE_SCREEN_CURTAIN_SEQ,
|
|
[GRAYSCALE] = MDNIE_GRAYSCALE_SEQ,
|
|
[GRAYSCALE_NEGATIVE] = MDNIE_GRAYSCALE_NEGATIVE_SEQ,
|
|
[COLOR_BLIND_HBM] = MDNIE_COLOR_BLIND_HBM_SEQ,
|
|
};
|
|
|
|
if (mdnie->props.accessibility == 0 ||
|
|
(mdnie->props.accessibility >=
|
|
ARRAY_SIZE(accessibility_seqname_array)))
|
|
return NULL;
|
|
|
|
return accessibility_seqname_array[mdnie->props.accessibility];
|
|
}
|
|
|
|
char *mdnie_get_sequence_name(struct mdnie_info *mdnie)
|
|
{
|
|
char *seqname;
|
|
int mdnie_mode = mdnie_current_state(mdnie);
|
|
|
|
switch (mdnie_mode) {
|
|
case MDNIE_BYPASS_MODE:
|
|
seqname = MDNIE_BYPASS_SEQ;
|
|
break;
|
|
case MDNIE_LIGHT_NOTIFICATION_MODE:
|
|
seqname = MDNIE_LIGHT_NOTIFICATION_SEQ;
|
|
break;
|
|
case MDNIE_ACCESSIBILITY_MODE:
|
|
seqname = mdnie_get_accessibility_sequence_name(mdnie);
|
|
break;
|
|
case MDNIE_COLOR_LENS_MODE:
|
|
seqname = MDNIE_COLOR_LENS_SEQ;
|
|
break;
|
|
case MDNIE_HDR_MODE:
|
|
seqname = MDNIE_HDR_SEQ;
|
|
break;
|
|
case MDNIE_HMD_MODE:
|
|
seqname = MDNIE_HMD_SEQ;
|
|
break;
|
|
case MDNIE_NIGHT_MODE:
|
|
seqname = MDNIE_NIGHT_SEQ;
|
|
break;
|
|
case MDNIE_HBM_CE_MODE:
|
|
seqname = MDNIE_HBM_CE_SEQ;
|
|
break;
|
|
case MDNIE_SCENARIO_MODE:
|
|
seqname = MDNIE_SCENARIO_SEQ;
|
|
break;
|
|
default:
|
|
seqname = NULL;
|
|
panel_err("unknown mdnie\n");
|
|
break;
|
|
}
|
|
|
|
if (seqname) {
|
|
panel_dbg("mdnie mode:%s(%d), seq:%s found\n",
|
|
mdnie_mode_name[mdnie_mode], mdnie_mode, seqname);
|
|
} else {
|
|
panel_err("mdnie mode:%s(%d), seq not found\n",
|
|
mdnie_mode_name[mdnie_mode], mdnie_mode);
|
|
}
|
|
|
|
return seqname;
|
|
}
|
|
EXPORT_SYMBOL(mdnie_get_sequence_name);
|
|
|
|
__visible_for_testing int mdnie_get_coordinate(struct mdnie_info *mdnie, int *x, int *y)
|
|
{
|
|
struct panel_device *panel =
|
|
container_of(mdnie, struct panel_device, mdnie);
|
|
u8 coordinate[PANEL_COORD_LEN] = { 0, };
|
|
int ret;
|
|
|
|
if (!mdnie || !x || !y) {
|
|
panel_err("invalid parameter\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = panel_resource_copy(panel, coordinate, "coordinate");
|
|
if (ret < 0) {
|
|
panel_err("failed to copy 'coordinate' resource\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
*x = (coordinate[0] << 8) | coordinate[1];
|
|
*y = (coordinate[2] << 8) | coordinate[3];
|
|
#ifdef MDNIE_SELF_TEST
|
|
*x = g_coord_x;
|
|
*y = g_coord_y;
|
|
#endif
|
|
|
|
if (*x < MIN_WCRD_X || *x > MAX_WCRD_X ||
|
|
*y < MIN_WCRD_Y || *y > MAX_WCRD_Y)
|
|
panel_warn("need to check coord_x:%d coord_y:%d\n", *x, *y);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static bool mdnie_coordinate_changed(struct mdnie_info *mdnie)
|
|
{
|
|
int x, y;
|
|
|
|
mdnie_get_coordinate(mdnie, &x, &y);
|
|
|
|
return (mdnie->props.wcrd_x != x || mdnie->props.wcrd_y != y);
|
|
}
|
|
|
|
static int mdnie_coordinate_area(struct mdnie_info *mdnie, int x, int y)
|
|
{
|
|
s64 result[MAX_CAL_LINE];
|
|
int i, area;
|
|
|
|
for (i = 0; i < MAX_CAL_LINE; i++)
|
|
result[i] = COLOR_OFFSET_FUNC(x, y,
|
|
mdnie->props.line[i].num,
|
|
mdnie->props.line[i].den,
|
|
mdnie->props.line[i].con);
|
|
|
|
area = RECOGNIZE_REGION(result[H_LINE], result[V_LINE]);
|
|
panel_dbg("coord %d %d area Q%d, result %lld %lld\n",
|
|
x, y, area + 1, result[H_LINE], result[V_LINE]);
|
|
|
|
return area;
|
|
}
|
|
|
|
static int mdnie_coordinate_tune_x(struct mdnie_info *mdnie, int x, int y)
|
|
{
|
|
int res, area;
|
|
|
|
area = mdnie_coordinate_area(mdnie, x, y);
|
|
res = ((mdnie->props.coef[area].a * x) + (mdnie->props.coef[area].b * y) +
|
|
(((mdnie->props.coef[area].c * x + (1L << 9)) >> 10) * y) +
|
|
(mdnie->props.coef[area].d * 10000) + (1L << 9)) >> 10;
|
|
|
|
return max(min(res, 1024), 0);
|
|
}
|
|
|
|
static int mdnie_coordinate_tune_y(struct mdnie_info *mdnie, int x, int y)
|
|
{
|
|
int res, area;
|
|
|
|
area = mdnie_coordinate_area(mdnie, x, y);
|
|
res = ((mdnie->props.coef[area].e * x) + (mdnie->props.coef[area].f * y) +
|
|
(((mdnie->props.coef[area].g * x + (1L << 9)) >> 10) * y) +
|
|
(mdnie->props.coef[area].h * 10000) + (1L << 9)) >> 10;
|
|
|
|
return max(min(res, 1024), 0);
|
|
}
|
|
|
|
static void mdnie_coordinate_tune_rgb(struct mdnie_info *mdnie, int x, int y, u8 (*tune_rgb)[MAX_COLOR])
|
|
{
|
|
static int pt[MAX_QUAD][MAX_RGB_PT] = {
|
|
{ CCRD_PT_5, CCRD_PT_2, CCRD_PT_6, CCRD_PT_3 }, /* QUAD_1 */
|
|
{ CCRD_PT_5, CCRD_PT_2, CCRD_PT_4, CCRD_PT_1 }, /* QUAD_2 */
|
|
{ CCRD_PT_5, CCRD_PT_8, CCRD_PT_4, CCRD_PT_7 }, /* QUAD_3 */
|
|
{ CCRD_PT_5, CCRD_PT_8, CCRD_PT_6, CCRD_PT_9 }, /* QUAD_4 */
|
|
};
|
|
int i, c, type, area, tune_x, tune_y, res[MAX_COLOR][MAX_RGB_PT];
|
|
s64 result[MAX_CAL_LINE];
|
|
|
|
area = mdnie_coordinate_area(mdnie, x, y);
|
|
|
|
if (((x - mdnie->props.cal_x_center) * (x - mdnie->props.cal_x_center) + (y - mdnie->props.cal_y_center) * (y - mdnie->props.cal_y_center)) <= mdnie->props.cal_boundary_center) {
|
|
tune_x = 0;
|
|
tune_y = 0;
|
|
} else {
|
|
tune_x = mdnie_coordinate_tune_x(mdnie, x, y);
|
|
tune_y = mdnie_coordinate_tune_y(mdnie, x, y);
|
|
}
|
|
|
|
for (i = 0; i < MAX_CAL_LINE; i++)
|
|
result[i] = COLOR_OFFSET_FUNC(x, y,
|
|
mdnie->props.line[i].num,
|
|
mdnie->props.line[i].den,
|
|
mdnie->props.line[i].con);
|
|
|
|
for (type = 0; type < MAX_WCRD_TYPE; type++) {
|
|
for (c = 0; c < MAX_COLOR; c++) {
|
|
for (i = 0; i < MAX_RGB_PT; i++)
|
|
res[c][i] = mdnie->props.vtx[type][pt[area][i]][c];
|
|
tune_rgb[type][c] =
|
|
((((res[c][RGB_00] * (1024 - tune_x) + (res[c][RGB_10] * tune_x)) * (1024 - tune_y)) +
|
|
((res[c][RGB_01] * (1024 - tune_x) + (res[c][RGB_11] * tune_x)) * tune_y)) + (1L << 19)) >> 20;
|
|
}
|
|
}
|
|
panel_info("coord (x:%4d y:%4d Q%d compV:%8lld compH:%8lld)\t"
|
|
"tune_coord (%4d %4d) tune_rgb[ADT] (%3d %3d %3d) tune_rgb[D65] (%3d %3d %3d)\n",
|
|
x, y, area + 1, result[H_LINE], result[V_LINE], tune_x, tune_y,
|
|
tune_rgb[WCRD_TYPE_ADAPTIVE][0], tune_rgb[WCRD_TYPE_ADAPTIVE][1],
|
|
tune_rgb[WCRD_TYPE_ADAPTIVE][2], tune_rgb[WCRD_TYPE_D65][0],
|
|
tune_rgb[WCRD_TYPE_D65][1], tune_rgb[WCRD_TYPE_D65][2]);
|
|
|
|
}
|
|
|
|
__visible_for_testing int mdnie_init_coordinate_tune(struct mdnie_info *mdnie)
|
|
{
|
|
int x = 0, y = 0;
|
|
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
mdnie_get_coordinate(mdnie, &x, &y);
|
|
mdnie->props.wcrd_x = x;
|
|
mdnie->props.wcrd_y = y;
|
|
mdnie_coordinate_tune_rgb(mdnie, x, y, mdnie->props.coord_wrgb);
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct seqinfo *find_mdnie_sequence(struct mdnie_info *mdnie, char *seqname)
|
|
{
|
|
if (!mdnie) {
|
|
panel_err("mdnie is null\n");
|
|
return NULL;
|
|
}
|
|
|
|
return find_panel_seq_by_name(to_panel_device(mdnie), seqname);
|
|
}
|
|
|
|
bool is_mdnie_sequence_exist(struct mdnie_info *mdnie, char *seqname)
|
|
{
|
|
struct seqinfo *seq;
|
|
|
|
seq = find_mdnie_sequence(mdnie, seqname);
|
|
if (!seq)
|
|
return false;
|
|
|
|
if (!is_valid_sequence(seq))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
int mdnie_do_sequence_nolock(struct mdnie_info *mdnie, char *seqname)
|
|
{
|
|
struct seqinfo *seq;
|
|
|
|
if (!mdnie) {
|
|
panel_err("mdnie is null\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
seq = find_mdnie_sequence(mdnie, seqname);
|
|
if (!seq)
|
|
return -EINVAL;
|
|
|
|
return execute_sequence_nolock(to_panel_device(mdnie), seq);
|
|
}
|
|
|
|
int mdnie_do_sequence(struct mdnie_info *mdnie, char *seqname)
|
|
{
|
|
struct panel_device *panel =
|
|
to_panel_device(mdnie);
|
|
int ret;
|
|
|
|
panel_mutex_lock(&panel->op_lock);
|
|
ret = mdnie_do_sequence_nolock(mdnie, seqname);
|
|
panel_mutex_unlock(&panel->op_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int panel_set_mdnie(struct panel_device *panel)
|
|
{
|
|
int ret;
|
|
struct mdnie_info *mdnie = &panel->mdnie;
|
|
int mdnie_mode = mdnie_current_state(mdnie);
|
|
|
|
if (panel == NULL) {
|
|
panel_err("panel is null\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!IS_PANEL_ACTIVE(panel))
|
|
return -EAGAIN;
|
|
|
|
#ifdef CONFIG_USDM_MDNIE_AFC
|
|
panel_info("do mdnie-seq (mode:%s, afc:%s)\n",
|
|
mdnie_mode_name[mdnie_mode],
|
|
!mdnie->props.afc_on ? "off" : "on");
|
|
#else
|
|
panel_info("do mdnie-seq (mode:%s)\n",
|
|
mdnie_mode_name[mdnie_mode]);
|
|
#endif
|
|
|
|
panel_mutex_lock(&panel->op_lock);
|
|
mdnie_set_property(mdnie,
|
|
&mdnie->props.mdnie_mode, mdnie_mode);
|
|
|
|
if (is_mdnie_sequence_exist(mdnie, MDNIE_PRE_SEQ)) {
|
|
ret = mdnie_do_sequence_nolock(mdnie, MDNIE_PRE_SEQ);
|
|
if (unlikely(ret < 0)) {
|
|
panel_err("failed to run sequence(%s)\n",
|
|
MDNIE_PRE_SEQ);
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
ret = mdnie_do_sequence_nolock(mdnie,
|
|
mdnie_get_sequence_name(mdnie));
|
|
if (unlikely(ret < 0)) {
|
|
panel_err("failed to run sequence(%s)\n",
|
|
mdnie_get_sequence_name(mdnie));
|
|
goto err;
|
|
}
|
|
|
|
if (is_mdnie_sequence_exist(mdnie, MDNIE_POST_SEQ)) {
|
|
ret = mdnie_do_sequence_nolock(mdnie, MDNIE_POST_SEQ);
|
|
if (unlikely(ret < 0)) {
|
|
panel_err("failed to run sequence(%s)\n",
|
|
MDNIE_POST_SEQ);
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_USDM_MDNIE_AFC
|
|
ret = mdnie_do_sequence_nolock(mdnie,
|
|
!mdnie->props.afc_on ?
|
|
MDNIE_AFC_OFF_SEQ : MDNIE_AFC_ON_SEQ);
|
|
if (unlikely(ret < 0)) {
|
|
panel_err("failed to run sequence(%s)\n",
|
|
!mdnie->props.afc_on ?
|
|
MDNIE_AFC_OFF_SEQ : MDNIE_AFC_ON_SEQ);
|
|
goto err;
|
|
}
|
|
#endif
|
|
|
|
err:
|
|
panel_mutex_unlock(&panel->op_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void mdnie_update_scr_white_mode(struct mdnie_info *mdnie)
|
|
{
|
|
int mdnie_mode = mdnie_current_state(mdnie);
|
|
|
|
if (!mdnie->props.wcrd_x || !mdnie->props.wcrd_y) {
|
|
mdnie_set_property(mdnie, &mdnie->props.scr_white_mode, SCR_WHITE_MODE_NONE);
|
|
panel_warn("need to check coord_x:%d coord_y:%d, scr_white_mode %s\n",
|
|
mdnie->props.wcrd_x, mdnie->props.wcrd_y,
|
|
scr_white_mode_name[mdnie->props.scr_white_mode]);
|
|
return;
|
|
}
|
|
|
|
if (mdnie_mode == MDNIE_SCENARIO_MODE) {
|
|
if ((IS_LDU_MODE(mdnie)) && (mdnie->props.scenario != EBOOK_MODE)) {
|
|
mdnie_set_property(mdnie,
|
|
&mdnie->props.scr_white_mode,
|
|
SCR_WHITE_MODE_ADJUST_LDU);
|
|
} else if (mdnie->props.update_sensorRGB &&
|
|
mdnie->props.scenario_mode == AUTO &&
|
|
(mdnie->props.scenario == BROWSER_MODE ||
|
|
mdnie->props.scenario == EBOOK_MODE)) {
|
|
mdnie_set_property(mdnie,
|
|
&mdnie->props.scr_white_mode,
|
|
SCR_WHITE_MODE_SENSOR_RGB);
|
|
mdnie->props.update_sensorRGB = false;
|
|
} else if (mdnie->props.scenario <= SCENARIO_MAX &&
|
|
mdnie->props.scenario != EBOOK_MODE) {
|
|
mdnie_set_property(mdnie,
|
|
&mdnie->props.scr_white_mode,
|
|
SCR_WHITE_MODE_COLOR_COORDINATE);
|
|
} else {
|
|
mdnie_set_property(mdnie,
|
|
&mdnie->props.scr_white_mode,
|
|
SCR_WHITE_MODE_NONE);
|
|
}
|
|
} else if (mdnie_mode == MDNIE_HBM_CE_MODE &&
|
|
!mdnie->props.force_scr_white_mode_none_on_hbm) {
|
|
mdnie_set_property(mdnie,
|
|
&mdnie->props.scr_white_mode,
|
|
SCR_WHITE_MODE_COLOR_COORDINATE);
|
|
} else {
|
|
mdnie_set_property(mdnie,
|
|
&mdnie->props.scr_white_mode,
|
|
SCR_WHITE_MODE_NONE);
|
|
}
|
|
|
|
panel_dbg("scr_white_mode %s\n",
|
|
scr_white_mode_name[mdnie->props.scr_white_mode]);
|
|
}
|
|
|
|
int mdnie_set_def_wrgb(struct mdnie_info *mdnie,
|
|
unsigned char r, unsigned char g, unsigned char b)
|
|
{
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
mdnie->props.def_wrgb[RED] = r;
|
|
mdnie->props.def_wrgb[GREEN] = g;
|
|
mdnie->props.def_wrgb[BLUE] = b;
|
|
|
|
panel_dbg("def_wrgb: %d(%02X) %d(%02X) %d(%02X)\n",
|
|
mdnie->props.def_wrgb[RED], mdnie->props.def_wrgb[RED],
|
|
mdnie->props.def_wrgb[GREEN], mdnie->props.def_wrgb[GREEN],
|
|
mdnie->props.def_wrgb[BLUE], mdnie->props.def_wrgb[BLUE]);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(mdnie_set_def_wrgb);
|
|
|
|
int mdnie_set_cur_wrgb(struct mdnie_info *mdnie,
|
|
unsigned char r, unsigned char g, unsigned char b)
|
|
{
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
mdnie->props.cur_wrgb[RED] = r;
|
|
mdnie->props.cur_wrgb[GREEN] = g;
|
|
mdnie->props.cur_wrgb[BLUE] = b;
|
|
|
|
panel_dbg("cur_wrgb: %d(%02X) %d(%02X) %d(%02X)\n",
|
|
mdnie->props.cur_wrgb[RED], mdnie->props.cur_wrgb[RED],
|
|
mdnie->props.cur_wrgb[GREEN], mdnie->props.cur_wrgb[GREEN],
|
|
mdnie->props.cur_wrgb[BLUE], mdnie->props.cur_wrgb[BLUE]);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(mdnie_set_cur_wrgb);
|
|
|
|
int mdnie_cur_wrgb_to_byte_array(struct mdnie_info *mdnie,
|
|
unsigned char *dst, unsigned int stride)
|
|
{
|
|
if (!mdnie || !dst || !stride)
|
|
return -EINVAL;
|
|
|
|
copy_to_sliced_byte_array(dst,
|
|
mdnie->props.cur_wrgb, 0, MAX_COLOR * stride, stride);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(mdnie_cur_wrgb_to_byte_array);
|
|
|
|
#define MDNIE_DEFAULT_ANTI_GLARE_RATIO (100)
|
|
|
|
int mdnie_get_anti_glare_ratio(struct mdnie_info *mdnie)
|
|
{
|
|
if (!mdnie->props.anti_glare)
|
|
return MDNIE_DEFAULT_ANTI_GLARE_RATIO;
|
|
|
|
if (mdnie->props.anti_glare_level >=
|
|
ARRAY_SIZE(mdnie->props.anti_glare_ratio))
|
|
return MDNIE_DEFAULT_ANTI_GLARE_RATIO;
|
|
|
|
return mdnie->props.anti_glare_ratio[mdnie->props.anti_glare_level];
|
|
}
|
|
EXPORT_SYMBOL(mdnie_get_anti_glare_ratio);
|
|
|
|
int mdnie_update_wrgb(struct mdnie_info *mdnie,
|
|
unsigned char r, unsigned char g, unsigned char b)
|
|
{
|
|
unsigned char src[MAX_COLOR] = { r, g, b };
|
|
unsigned char dst[MAX_COLOR] = { 0, };
|
|
int i, value;
|
|
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
if (mdnie->props.scr_white_mode < 0 ||
|
|
mdnie->props.scr_white_mode >= MAX_SCR_WHITE_MODE) {
|
|
panel_warn("out of range %d\n",
|
|
mdnie->props.scr_white_mode);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (mdnie->props.scr_white_mode == SCR_WHITE_MODE_COLOR_COORDINATE) {
|
|
mdnie_set_def_wrgb(mdnie, r, g, b);
|
|
for_each_color(i) {
|
|
value = (int)mdnie->props.def_wrgb[i] +
|
|
(int)(((mdnie->props.scenario_mode == AUTO) || (mdnie->props.scenario_mode == DYNAMIC)) ?
|
|
mdnie->props.def_wrgb_ofs[i] : 0);
|
|
dst[i] = min(max(value, 0), 255);
|
|
}
|
|
mdnie_set_cur_wrgb(mdnie, dst[RED], dst[GREEN], dst[BLUE]);
|
|
} else if (mdnie->props.scr_white_mode == SCR_WHITE_MODE_ADJUST_LDU) {
|
|
for_each_color(i) {
|
|
value = (int)src[i] + (int)(((mdnie->props.scenario_mode == AUTO) &&
|
|
(mdnie->props.scenario != EBOOK_MODE)) ?
|
|
mdnie->props.def_wrgb_ofs[i] : 0);
|
|
dst[i] = min(max(value, 0), 255);
|
|
}
|
|
mdnie_set_cur_wrgb(mdnie, dst[RED], dst[GREEN], dst[BLUE]);
|
|
} else if (mdnie->props.scr_white_mode == SCR_WHITE_MODE_SENSOR_RGB) {
|
|
mdnie_set_cur_wrgb(mdnie, r, g, b);
|
|
} else {
|
|
panel_warn("wrgb is not updated in scr_white_mode(%d)\n",
|
|
mdnie->props.scr_white_mode);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(mdnie_update_wrgb);
|
|
|
|
int panel_mdnie_update(struct panel_device *panel)
|
|
{
|
|
int ret;
|
|
struct mdnie_info *mdnie = &panel->mdnie;
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
if (!IS_MDNIE_ENABLED(mdnie)) {
|
|
panel_info("mdnie is off state\n");
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (mdnie_coordinate_changed(mdnie)) {
|
|
mdnie_init_coordinate_tune(mdnie);
|
|
}
|
|
mdnie_update_scr_white_mode(mdnie);
|
|
|
|
ret = panel_set_mdnie(panel);
|
|
if (ret < 0 && ret != -EAGAIN) {
|
|
panel_err("failed to set mdnie %d\n", ret);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
return ret;
|
|
}
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
#ifdef CONFIG_USDM_PANEL_COPR
|
|
copr_update_start(&panel->copr, 3);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mdnie_update(struct mdnie_info *mdnie)
|
|
{
|
|
int ret;
|
|
struct panel_device *panel =
|
|
container_of(mdnie, struct panel_device, mdnie);
|
|
|
|
panel_wake_lock(panel, WAKE_TIMEOUT_MSEC);
|
|
ret = panel_mdnie_update(panel);
|
|
panel_wake_unlock(panel);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifdef MDNIE_SELF_TEST
|
|
static void mdnie_coordinate_tune_test(struct mdnie_info *mdnie)
|
|
{
|
|
int i, x, y;
|
|
u8 tune_rgb[MAX_WCRD_TYPE][MAX_COLOR];
|
|
int input[27][2] = {
|
|
{ 2936, 3144 }, { 2987, 3203 }, { 3032, 3265 }, { 2954, 3108 }, { 2991, 3158 }, { 3041, 3210 }, { 2967, 3058 }, { 3004, 3091 },
|
|
{ 3063, 3156 }, { 2985, 3206 }, { 3032, 3238 }, { 2955, 3094 }, { 2997, 3151 }, { 3045, 3191 }, { 2971, 3047 }, { 3020, 3100 },
|
|
{ 3066, 3144 }, { 2983, 3131 }, { 2987, 3170 }, { 2975, 3159 }, { 3021, 3112 }, { 2982, 3122 }, { 2987, 3130 }, { 2930, 3260 },
|
|
{ 2930, 3050 }, { 3060, 3050 }, { 3060, 3260 },
|
|
};
|
|
u8 output[27][MAX_COLOR] = {
|
|
{ 0xFF, 0xFA, 0xF9 }, { 0xFE, 0xFA, 0xFE }, { 0xF8, 0xF6, 0xFF }, { 0xFF, 0xFD, 0xFB },
|
|
{ 0xFF, 0xFE, 0xFF }, { 0xF9, 0xFA, 0xFF }, { 0xFC, 0xFF, 0xF9 }, { 0xFB, 0xFF, 0xFB },
|
|
{ 0xF9, 0xFF, 0xFF }, { 0xFE, 0xFA, 0xFE }, { 0xF9, 0xF8, 0xFF }, { 0xFE, 0xFE, 0xFA },
|
|
{ 0xFE, 0xFF, 0xFF }, { 0xF8, 0xFC, 0xFF }, { 0xFA, 0xFF, 0xF8 }, { 0xF9, 0xFF, 0xFC },
|
|
{ 0xF8, 0xFF, 0xFF }, { 0xFE, 0xFF, 0xFD }, { 0xFF, 0xFD, 0xFF }, { 0xFF, 0xFD, 0xFD },
|
|
{ 0xF9, 0xFF, 0xFC }, { 0xFE, 0xFF, 0xFD }, { 0xFE, 0xFF, 0xFD }, { 0xFF, 0xFF, 0xFF },
|
|
{ 0xFF, 0xFF, 0xFF }, { 0xFF, 0xFF, 0xFF }, { 0xFF, 0xFF, 0xFF },
|
|
};
|
|
|
|
for (x = MIN_WCRD_X; x <= MAX_WCRD_X; x += 10)
|
|
for (y = MIN_WCRD_Y; y <= MAX_WCRD_Y; y += 10)
|
|
mdnie_coordinate_tune_rgb(mdnie, x, y, tune_rgb);
|
|
|
|
for (i = 0; i < 27; i++) {
|
|
g_coord_x = input[i][0];
|
|
g_coord_y = input[i][1];
|
|
mdnie_update(mdnie);
|
|
panel_info("compare %02X %02X %02X : %02X %02X %02X (%s)\n",
|
|
output[i][0], output[i][1], output[i][2],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][0],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][1],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][2],
|
|
output[i][0] == mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][0] &&
|
|
output[i][1] == mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][1] &&
|
|
output[i][2] == mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][2] ? "SUCCESS" : "FAILED");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static ssize_t mode_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", mdnie->props.scenario_mode);
|
|
}
|
|
|
|
static ssize_t mode_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
unsigned int value = 0;
|
|
int ret;
|
|
|
|
ret = kstrtouint(buf, 0, &value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (value >= MODE_MAX) {
|
|
panel_err("invalid value=%d\n", value);
|
|
return -EINVAL;
|
|
}
|
|
|
|
panel_info("value=%d\n", value);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.scenario_mode, value);
|
|
mdnie_set_property(mdnie, &mdnie->props.screen_mode,
|
|
(value == AUTO) ? MDNIE_SCREEN_MODE_VIVID :
|
|
MDNIE_SCREEN_MODE_NATURAL);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t scenario_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", mdnie->props.scenario);
|
|
}
|
|
|
|
static ssize_t scenario_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
unsigned int value;
|
|
int ret;
|
|
|
|
ret = kstrtouint(buf, 0, &value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (!SCENARIO_IS_VALID(value)) {
|
|
panel_err("invalid scenario %d\n", value);
|
|
return -EINVAL;
|
|
}
|
|
|
|
panel_info("value=%d\n", value);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.scenario, value);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t accessibility_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", mdnie->props.accessibility);
|
|
}
|
|
|
|
static ssize_t accessibility_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
unsigned int s[12] = {0, };
|
|
int i, value = 0, ret;
|
|
|
|
ret = sscanf(buf, "%d %x %x %x %x %x %x %x %x %x %x %x %x",
|
|
&value, &s[0], &s[1], &s[2], &s[3],
|
|
&s[4], &s[5], &s[6], &s[7], &s[8], &s[9], &s[10], &s[11]);
|
|
|
|
if (ret <= 0 || ret > ARRAY_SIZE(s) + 1 ||
|
|
((ret - 1) > (MAX_MDNIE_SCR_LEN / 2))) {
|
|
panel_err("invalid size %d\n", ret);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (value < 0 || value >= ACCESSIBILITY_MAX) {
|
|
panel_err("unknown accessibility %d\n", value);
|
|
return -EINVAL;
|
|
}
|
|
|
|
panel_info("value: %d, cnt: %d\n", value, ret);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.accessibility, value);
|
|
if (ret > 1 && (value == COLOR_BLIND || value == COLOR_BLIND_HBM)) {
|
|
for (i = 0; i < ret - 1; i++) {
|
|
mdnie->props.scr[i * 2 + 0] = GET_LSB_8BIT(s[i]);
|
|
mdnie->props.scr[i * 2 + 1] = GET_MSB_8BIT(s[i]);
|
|
}
|
|
mdnie->props.sz_scr = (ret - 1) * 2;
|
|
}
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
panel_info("%s\n", buf);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t bypass_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", mdnie->props.bypass);
|
|
}
|
|
|
|
static ssize_t bypass_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
unsigned int value;
|
|
int ret;
|
|
|
|
ret = kstrtouint(buf, 0, &value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (value >= BYPASS_MAX) {
|
|
panel_err("invalid value=%d\n", value);
|
|
return -EINVAL;
|
|
}
|
|
|
|
panel_info("value=%d\n", value);
|
|
|
|
value = (value) ? BYPASS_ON : BYPASS_OFF;
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.bypass, value);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t lux_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", mdnie->props.hbm_ce_level);
|
|
}
|
|
|
|
static ssize_t lux_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
int i, ret, value;
|
|
unsigned int hbm_ce_level;
|
|
unsigned int anti_glare_level;
|
|
bool update = false;
|
|
|
|
ret = kstrtoint(buf, 0, &value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
for (i = 0; i < MAX_HBM_CE_LEVEL; i++) {
|
|
if (!mdnie->props.hbm_ce_lux[i])
|
|
break;
|
|
|
|
if (value < mdnie->props.hbm_ce_lux[i])
|
|
break;
|
|
}
|
|
hbm_ce_level = i;
|
|
|
|
if (mdnie->props.hbm_ce_level != hbm_ce_level)
|
|
update = true;
|
|
|
|
mdnie_set_property_value(mdnie, MDNIE_HBM_CE_PROPERTY,
|
|
(hbm_ce_level > 0) ? HBM_CE_MODE_ON : HBM_CE_MODE_OFF);
|
|
mdnie_set_property(mdnie, &mdnie->props.hbm_ce_level, hbm_ce_level);
|
|
|
|
if (value < 0) {
|
|
anti_glare_level = 0;
|
|
} else {
|
|
for (i = 0; i < MAX_ANTI_GLARE_LEVEL; i++) {
|
|
if (!mdnie->props.anti_glare_lux[i])
|
|
break;
|
|
|
|
if (value >= mdnie->props.anti_glare_lux[i])
|
|
break;
|
|
}
|
|
anti_glare_level = i;
|
|
}
|
|
|
|
if (mdnie->props.anti_glare_level != anti_glare_level) {
|
|
mdnie->props.anti_glare_level = anti_glare_level;
|
|
update = true;
|
|
}
|
|
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
if (update) {
|
|
panel_info("hbm_ce:%d anti_glare:%d (lux:%d)\n",
|
|
mdnie->props.hbm_ce_level,
|
|
mdnie->props.anti_glare_level,
|
|
value);
|
|
mdnie_update(mdnie);
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
/* Temporary solution: Do not use this sysfs as official purpose */
|
|
static ssize_t mdnie_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
char *seqname = mdnie_get_sequence_name(mdnie);
|
|
int mdnie_mode = mdnie_current_state(mdnie);
|
|
unsigned int i, len = 0;
|
|
|
|
if (!IS_MDNIE_ENABLED(mdnie)) {
|
|
panel_err("mdnie state is off\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"mdnie %s-mode, seq:%s\n",
|
|
mdnie_mode_name[mdnie_mode], seqname);
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"accessibility %s(%d), hdr %d, hmd %d, hbm_ce %d\n",
|
|
accessibility_name[mdnie->props.accessibility],
|
|
mdnie->props.accessibility, mdnie->props.hdr,
|
|
mdnie->props.hmd, mdnie->props.hbm_ce_level);
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"scenario %s(%d), mode %s(%d)\n",
|
|
scenario_name[mdnie->props.scenario], mdnie->props.scenario,
|
|
scenario_mode_name[mdnie->props.scenario_mode], mdnie->props.scenario_mode);
|
|
len += snprintf(buf + len, PAGE_SIZE - len, "scr_white_mode %s\n",
|
|
scr_white_mode_name[mdnie->props.scr_white_mode]);
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"mdnie_ldu %d, coord x %d, y %d area Q%d\n",
|
|
mdnie->props.ldu, mdnie->props.wcrd_x, mdnie->props.wcrd_y,
|
|
mdnie_coordinate_area(mdnie, mdnie->props.wcrd_x, mdnie->props.wcrd_y) + 1);
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"coord_wrgb[adpt] r:%d(%02X) g:%d(%02X) b:%d(%02X)\n",
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][0],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][0],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][1],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][1],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][2],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_ADAPTIVE][2]);
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"coord_wrgb[d65] r:%d(%02X) g:%d(%02X) b:%d(%02X)\n",
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_D65][0],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_D65][0],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_D65][1],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_D65][1],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_D65][2],
|
|
mdnie->props.coord_wrgb[WCRD_TYPE_D65][2]);
|
|
len += snprintf(buf + len, PAGE_SIZE - len, "cur_wrgb r:%d(%02X) g:%d(%02X) b:%d(%02X)\n",
|
|
mdnie->props.cur_wrgb[0], mdnie->props.cur_wrgb[0],
|
|
mdnie->props.cur_wrgb[1], mdnie->props.cur_wrgb[1],
|
|
mdnie->props.cur_wrgb[2], mdnie->props.cur_wrgb[2]);
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"ssr_wrgb r:%d(%02X) g:%d(%02X) b:%d(%02X)\n",
|
|
mdnie->props.ssr_wrgb[0], mdnie->props.ssr_wrgb[0],
|
|
mdnie->props.ssr_wrgb[1], mdnie->props.ssr_wrgb[1],
|
|
mdnie->props.ssr_wrgb[2], mdnie->props.ssr_wrgb[2]);
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"def_wrgb r:%d(%02X) g:%d(%02X) b:%d(%02X) offset r:%d g:%d b:%d\n",
|
|
mdnie->props.def_wrgb[0], mdnie->props.def_wrgb[0],
|
|
mdnie->props.def_wrgb[1], mdnie->props.def_wrgb[1],
|
|
mdnie->props.def_wrgb[2], mdnie->props.def_wrgb[2],
|
|
mdnie->props.def_wrgb_ofs[0], mdnie->props.def_wrgb_ofs[1],
|
|
mdnie->props.def_wrgb_ofs[2]);
|
|
|
|
len += snprintf(buf + len, PAGE_SIZE - len, "scr : ");
|
|
if (mdnie->props.sz_scr) {
|
|
for (i = 0; i < mdnie->props.sz_scr; i++)
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"%02x ", mdnie->props.scr[i]);
|
|
} else {
|
|
len += snprintf(buf + len, PAGE_SIZE - len, "none");
|
|
}
|
|
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
|
|
|
|
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"night_mode %s, level %d\n",
|
|
mdnie->props.night ? "on" : "off",
|
|
mdnie->props.night_level);
|
|
|
|
#ifdef MDNIE_SELF_TEST
|
|
mdnie_coordinate_tune_test(mdnie);
|
|
#endif
|
|
|
|
return len;
|
|
}
|
|
|
|
static ssize_t sensorRGB_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d %d %d\n", mdnie->props.cur_wrgb[0],
|
|
mdnie->props.cur_wrgb[1], mdnie->props.cur_wrgb[2]);
|
|
}
|
|
|
|
static ssize_t sensorRGB_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
unsigned int white_red, white_green, white_blue;
|
|
int mdnie_mode = mdnie_current_state(mdnie), ret;
|
|
|
|
ret = sscanf(buf, "%u %u %u",
|
|
&white_red, &white_green, &white_blue);
|
|
if (ret != 3)
|
|
return -EINVAL;
|
|
|
|
panel_info("white_r %u, white_g %u, white_b %u\n",
|
|
white_red, white_green, white_blue);
|
|
|
|
if (mdnie_mode == MDNIE_SCENARIO_MODE &&
|
|
mdnie->props.scenario_mode == AUTO &&
|
|
(mdnie->props.scenario == BROWSER_MODE ||
|
|
mdnie->props.scenario == EBOOK_MODE)) {
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie->props.ssr_wrgb[0] = white_red;
|
|
mdnie->props.ssr_wrgb[1] = white_green;
|
|
mdnie->props.ssr_wrgb[2] = white_blue;
|
|
mdnie->props.update_sensorRGB = true;
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t whiteRGB_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d %d %d\n", mdnie->props.def_wrgb_ofs[0],
|
|
mdnie->props.def_wrgb_ofs[1], mdnie->props.def_wrgb_ofs[2]);
|
|
}
|
|
|
|
static ssize_t whiteRGB_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
int wr_offset, wg_offset, wb_offset;
|
|
int ret;
|
|
|
|
ret = sscanf(buf, "%d %d %d",
|
|
&wr_offset, &wg_offset, &wb_offset);
|
|
if (ret != 3)
|
|
return -EINVAL;
|
|
|
|
if (!IS_VALID_WRGB_OFS(wr_offset) ||
|
|
!IS_VALID_WRGB_OFS(wg_offset) ||
|
|
!IS_VALID_WRGB_OFS(wb_offset)) {
|
|
panel_err("invalid offset %d %d %d\n",
|
|
wr_offset, wg_offset, wb_offset);
|
|
return -EINVAL;
|
|
}
|
|
|
|
panel_info("wr_offset %d, wg_offset %d, wb_offset %d\n",
|
|
wr_offset, wg_offset, wb_offset);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie->props.def_wrgb_ofs[0] = wr_offset;
|
|
mdnie->props.def_wrgb_ofs[1] = wg_offset;
|
|
mdnie->props.def_wrgb_ofs[2] = wb_offset;
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t night_mode_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d %d\n",
|
|
mdnie->props.night, mdnie->props.night_level);
|
|
}
|
|
|
|
static ssize_t night_mode_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
int enable, level, ret;
|
|
|
|
ret = sscanf(buf, "%d %d", &enable, &level);
|
|
if (ret != 2)
|
|
return -EINVAL;
|
|
|
|
if (level < 0 || level >= mdnie->props.num_night_level)
|
|
return -EINVAL;
|
|
|
|
panel_info("night_mode %s level %d\n",
|
|
enable ? "on" : "off", level);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.night, !!enable);
|
|
mdnie_set_property(mdnie, &mdnie->props.night_level, level);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t anti_glare_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", mdnie->props.anti_glare);
|
|
}
|
|
|
|
static ssize_t anti_glare_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
int enable, ret;
|
|
|
|
ret = sscanf(buf, "%d", &enable);
|
|
if (ret != 1)
|
|
return -EINVAL;
|
|
|
|
if (enable < ANTI_GLARE_OFF || enable >= ANTI_GLARE_MAX)
|
|
return -EINVAL;
|
|
|
|
panel_info("anti_glare %s\n", enable ? "on" : "off");
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.anti_glare, enable);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t extra_dim_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", mdnie->props.extra_dim_level);
|
|
}
|
|
|
|
static ssize_t extra_dim_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
int level, ret;
|
|
|
|
ret = sscanf(buf, "%d", &level);
|
|
if (ret != 1)
|
|
return -EINVAL;
|
|
|
|
if (level < 0 || level > MAX_EXTRA_DIM_LEVEL)
|
|
return -EINVAL;
|
|
|
|
panel_info("extra_dim level %d\n", level);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.extra_dim_level, level);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t color_lens_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d %d %d\n",
|
|
mdnie->props.color_lens,
|
|
mdnie->props.color_lens_color,
|
|
mdnie->props.color_lens_level);
|
|
}
|
|
|
|
static ssize_t color_lens_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
int enable, level, color, ret;
|
|
|
|
ret = sscanf(buf, "%d %d %d", &enable, &color, &level);
|
|
if (ret != 3)
|
|
return -EINVAL;
|
|
|
|
if (color < 0 || color >= COLOR_LENS_COLOR_MAX)
|
|
return -EINVAL;
|
|
|
|
if (level < 0 || level >= COLOR_LENS_LEVEL_MAX)
|
|
return -EINVAL;
|
|
|
|
panel_info("color_lens_mode %s color %d level %d\n",
|
|
enable ? "on" : "off", color, level);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.color_lens, !!enable);
|
|
mdnie_set_property(mdnie, &mdnie->props.color_lens_color, color);
|
|
mdnie_set_property(mdnie, &mdnie->props.color_lens_level, level);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t hdr_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", mdnie->props.hdr);
|
|
}
|
|
|
|
static ssize_t hdr_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
unsigned int value;
|
|
int ret;
|
|
|
|
ret = kstrtouint(buf, 0, &value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (value >= HDR_MAX) {
|
|
panel_err("invalid value=%d\n", value);
|
|
return -EINVAL;
|
|
}
|
|
|
|
panel_info("value=%d\n", value);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.hdr, value);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t light_notification_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", mdnie->props.light_notification);
|
|
}
|
|
|
|
static ssize_t light_notification_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
unsigned int value;
|
|
int ret;
|
|
|
|
ret = kstrtouint(buf, 0, &value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (value >= LIGHT_NOTIFICATION_MAX)
|
|
return -EINVAL;
|
|
|
|
panel_info("value=%d\n", value);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.light_notification, value);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t mdnie_ldu_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d %d %d\n", mdnie->props.cur_wrgb[0],
|
|
mdnie->props.cur_wrgb[1], mdnie->props.cur_wrgb[2]);
|
|
}
|
|
|
|
static ssize_t mdnie_ldu_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
int value, ret;
|
|
|
|
ret = kstrtoint(buf, 10, &value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (value < 0 || value >= MAX_LDU_MODE) {
|
|
panel_err("out of range %d\n",
|
|
value);
|
|
return -EINVAL;
|
|
}
|
|
|
|
panel_info("value=%d\n", value);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.ldu, value);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
|
|
#ifdef CONFIG_USDM_PANEL_HMD
|
|
static ssize_t hmt_color_temperature_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "hmd_mode: %d\n", mdnie->props.hmd);
|
|
}
|
|
|
|
static ssize_t hmt_color_temperature_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
unsigned int value;
|
|
int ret;
|
|
|
|
ret = kstrtouint(buf, 0, &value);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (value >= HMD_MDNIE_MAX)
|
|
return -EINVAL;
|
|
|
|
if (value == mdnie->props.hmd)
|
|
return count;
|
|
|
|
panel_info("value=%d\n", value);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.hmd, value);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_USDM_MDNIE_AFC
|
|
static ssize_t afc_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
int len = 0;
|
|
size_t i;
|
|
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
"%d", mdnie->props.afc_on);
|
|
for (i = 0; i < ARRAY_SIZE(mdnie->props.afc_roi); i++)
|
|
len += snprintf(buf + len, PAGE_SIZE - len,
|
|
" %d", mdnie->props.afc_roi[i]);
|
|
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
|
|
|
|
return len;
|
|
}
|
|
|
|
static ssize_t afc_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
int s[12] = {0, };
|
|
int value = 0, ret;
|
|
size_t i;
|
|
|
|
ret = sscanf(buf, "%i %i %i %i %i %i %i %i %i %i %i %i %i",
|
|
&value, &s[0], &s[1], &s[2], &s[3],
|
|
&s[4], &s[5], &s[6], &s[7], &s[8], &s[9], &s[10], &s[11]);
|
|
|
|
if ((ret != 1 && ret != ARRAY_SIZE(s) + 1) ||
|
|
ARRAY_SIZE(s) != MAX_AFC_ROI_LEN) {
|
|
panel_err("invalid size %d\n", ret);
|
|
return -EINVAL;
|
|
}
|
|
|
|
panel_info("value=%d, cnt=%d\n", value, ret);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie->props.afc_on = !!value;
|
|
for (i = 0; i < ARRAY_SIZE(mdnie->props.afc_roi); i++)
|
|
mdnie->props.afc_roi[i] = s[i] & 0xFF;
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
panel_info("%s\n", buf);
|
|
mdnie_update(mdnie);
|
|
|
|
return count;
|
|
}
|
|
#endif
|
|
|
|
ssize_t mdnie_store_check_test_mode(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
{
|
|
struct panel_device_attr *pattr = container_of(attr, struct panel_device_attr, dev_attr);
|
|
#ifdef CONFIG_USDM_PANEL_TESTMODE
|
|
struct mdnie_info *mdnie = dev_get_drvdata(dev);
|
|
struct panel_device *panel = to_panel_device(mdnie);
|
|
ssize_t ret;
|
|
|
|
if (panel_testmode_is_on(panel)) {
|
|
if (buf[0] != '!') {
|
|
panel_info("%s_store: testmode is running. ignore inputs.\n", attr->attr.name);
|
|
return size;
|
|
}
|
|
ret = pattr->store(dev, attr, buf + 1, size - 1);
|
|
if (ret >= 0)
|
|
ret += 1;
|
|
return ret;
|
|
}
|
|
#endif
|
|
return pattr->store(dev, attr, buf, size);
|
|
}
|
|
|
|
struct panel_device_attr mdnie_dev_attrs[] = {
|
|
__MDNIE_ATTR_RW(mode, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(scenario, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(accessibility, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(bypass, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(lux, 0000, PA_DEFAULT),
|
|
__MDNIE_ATTR_RO(mdnie, 0444, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(sensorRGB, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(whiteRGB, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(night_mode, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(anti_glare, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(extra_dim, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(color_lens, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(hdr, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(light_notification, 0664, PA_DEFAULT),
|
|
__MDNIE_ATTR_RW(mdnie_ldu, 0664, PA_DEFAULT),
|
|
#ifdef CONFIG_USDM_PANEL_HMD
|
|
__MDNIE_ATTR_RW(hmt_color_temperature, 0664, PA_DEFAULT),
|
|
#endif
|
|
#ifdef CONFIG_USDM_MDNIE_AFC
|
|
__MDNIE_ATTR_RW(afc, 0664, PA_DEFAULT),
|
|
#endif
|
|
};
|
|
|
|
int mdnie_enable(struct mdnie_info *mdnie)
|
|
{
|
|
struct panel_device *panel =
|
|
container_of(mdnie, struct panel_device, mdnie);
|
|
int ret;
|
|
|
|
if (IS_MDNIE_ENABLED(mdnie)) {
|
|
panel_info("mdnie already enabled\n");
|
|
panel_mdnie_update(panel);
|
|
return 0;
|
|
}
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.enable, 1);
|
|
mdnie_set_property(mdnie, &mdnie->props.light_notification, LIGHT_NOTIFICATION_OFF);
|
|
if (IS_HBM_CE_MODE(mdnie))
|
|
mdnie_set_property(mdnie, &mdnie->props.trans_mode, TRANS_ON);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
ret = panel_mdnie_update(panel);
|
|
if (ret < 0)
|
|
mdnie_set_property(mdnie, &mdnie->props.enable, 0);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.trans_mode, TRANS_ON);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
panel_info("done %u\n", mdnie->props.enable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mdnie_disable(struct mdnie_info *mdnie)
|
|
{
|
|
if (!IS_MDNIE_ENABLED(mdnie)) {
|
|
panel_info("mdnie already disabled\n");
|
|
return 0;
|
|
}
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.enable, 0);
|
|
mdnie_set_property(mdnie, &mdnie->props.trans_mode, TRANS_OFF);
|
|
mdnie->props.update_sensorRGB = false;
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
panel_info("done\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int fb_notifier_callback(struct notifier_block *self,
|
|
unsigned long event, void *data)
|
|
{
|
|
struct mdnie_info *mdnie;
|
|
struct fb_event *evdata = data;
|
|
int fb_blank;
|
|
|
|
switch (event) {
|
|
case FB_EVENT_BLANK:
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
mdnie = container_of(self, struct mdnie_info, fb_notif);
|
|
|
|
fb_blank = *(int *)evdata->data;
|
|
|
|
panel_dbg("%d\n", fb_blank);
|
|
|
|
if (evdata->info->node != 0)
|
|
return 0;
|
|
|
|
if (fb_blank == FB_BLANK_UNBLANK) {
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_set_property(mdnie, &mdnie->props.light_notification, LIGHT_NOTIFICATION_OFF);
|
|
if (IS_HBM_CE_MODE(mdnie))
|
|
mdnie_set_property(mdnie, &mdnie->props.trans_mode, TRANS_ON);
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
mdnie_update(mdnie);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mdnie_register_fb(struct mdnie_info *mdnie)
|
|
{
|
|
memset(&mdnie->fb_notif, 0, sizeof(mdnie->fb_notif));
|
|
mdnie->fb_notif.notifier_call = fb_notifier_callback;
|
|
fb_register_client(&mdnie->fb_notif);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mdnie_unregister_fb(struct mdnie_info *mdnie)
|
|
{
|
|
fb_unregister_client(&mdnie->fb_notif);
|
|
mdnie->fb_notif.notifier_call = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_USDM_PANEL_DPUI
|
|
static int dpui_notifier_callback(struct notifier_block *self,
|
|
unsigned long event, void *data)
|
|
{
|
|
struct mdnie_info *mdnie;
|
|
struct panel_device *panel;
|
|
struct panel_info *panel_data;
|
|
char tbuf[MAX_DPUI_VAL_LEN];
|
|
u8 coordinate[PANEL_COORD_LEN] = { 0, };
|
|
int size;
|
|
|
|
mdnie = container_of(self, struct mdnie_info, dpui_notif);
|
|
panel = container_of(mdnie, struct panel_device, mdnie);
|
|
panel_data = &panel->panel_data;
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
|
|
panel_resource_copy(panel, coordinate, "coordinate");
|
|
size = snprintf(tbuf, MAX_DPUI_VAL_LEN, "%d",
|
|
(coordinate[0] << 8) | coordinate[1]);
|
|
set_dpui_field(DPUI_KEY_WCRD_X, tbuf, size);
|
|
size = snprintf(tbuf, MAX_DPUI_VAL_LEN, "%d",
|
|
(coordinate[2] << 8) | coordinate[3]);
|
|
set_dpui_field(DPUI_KEY_WCRD_Y, tbuf, size);
|
|
|
|
size = snprintf(tbuf, MAX_DPUI_VAL_LEN, "%d",
|
|
mdnie->props.def_wrgb_ofs[0]);
|
|
set_dpui_field(DPUI_KEY_WOFS_R, tbuf, size);
|
|
size = snprintf(tbuf, MAX_DPUI_VAL_LEN, "%d",
|
|
mdnie->props.def_wrgb_ofs[1]);
|
|
set_dpui_field(DPUI_KEY_WOFS_G, tbuf, size);
|
|
size = snprintf(tbuf, MAX_DPUI_VAL_LEN, "%d",
|
|
mdnie->props.def_wrgb_ofs[2]);
|
|
set_dpui_field(DPUI_KEY_WOFS_B, tbuf, size);
|
|
|
|
#if 0 /* disable for GKI build */
|
|
mdnie_get_efs(MDNIE_WOFS_ORG_PATH, def_wrgb_ofs_org);
|
|
|
|
size = snprintf(tbuf, MAX_DPUI_VAL_LEN, "%d", def_wrgb_ofs_org[0]);
|
|
set_dpui_field(DPUI_KEY_WOFS_R_ORG, tbuf, size);
|
|
size = snprintf(tbuf, MAX_DPUI_VAL_LEN, "%d", def_wrgb_ofs_org[1]);
|
|
set_dpui_field(DPUI_KEY_WOFS_G_ORG, tbuf, size);
|
|
size = snprintf(tbuf, MAX_DPUI_VAL_LEN, "%d", def_wrgb_ofs_org[2]);
|
|
set_dpui_field(DPUI_KEY_WOFS_B_ORG, tbuf, size);
|
|
#endif
|
|
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int mdnie_register_dpui(struct mdnie_info *mdnie)
|
|
{
|
|
memset(&mdnie->dpui_notif, 0, sizeof(mdnie->dpui_notif));
|
|
mdnie->dpui_notif.notifier_call = dpui_notifier_callback;
|
|
return dpui_logging_register(&mdnie->dpui_notif, DPUI_TYPE_PANEL);
|
|
}
|
|
|
|
static int mdnie_unregister_dpui(struct mdnie_info *mdnie)
|
|
{
|
|
dpui_logging_unregister(&mdnie->dpui_notif);
|
|
mdnie->dpui_notif.notifier_call = NULL;
|
|
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_USDM_PANEL_DPUI */
|
|
|
|
__visible_for_testing int mdnie_init_property(struct mdnie_info *mdnie, struct mdnie_tune *mdnie_tune)
|
|
{
|
|
int ret;
|
|
|
|
if (!mdnie || !mdnie_tune)
|
|
return -EINVAL;
|
|
|
|
mdnie->props.tuning = 0;
|
|
mdnie->props.update_sensorRGB = false;
|
|
mdnie->props.sz_scr = 0;
|
|
|
|
/* initialization by mdnie_tune */
|
|
mdnie->props.num_ldu_mode = mdnie_tune->num_ldu_mode;
|
|
mdnie->props.num_night_level = mdnie_tune->num_night_level;
|
|
mdnie->props.num_color_lens_color = mdnie_tune->num_color_lens_color;
|
|
mdnie->props.num_color_lens_level = mdnie_tune->num_color_lens_level;
|
|
memcpy(mdnie->props.line, mdnie_tune->line, sizeof(mdnie->props.line));
|
|
memcpy(mdnie->props.coef, mdnie_tune->coef, sizeof(mdnie->props.coef));
|
|
memcpy(mdnie->props.vtx, mdnie_tune->vtx, sizeof(mdnie->props.vtx));
|
|
memcpy(mdnie->props.adjust_ldu_wrgb, mdnie_tune->adjust_ldu_wrgb, sizeof(mdnie->props.adjust_ldu_wrgb));
|
|
mdnie->props.cal_x_center = mdnie_tune->cal_x_center;
|
|
mdnie->props.cal_y_center = mdnie_tune->cal_y_center;
|
|
mdnie->props.cal_boundary_center = mdnie_tune->cal_boundary_center;
|
|
mdnie->props.hbm_ce_lux = kmemdup(mdnie_tune->hbm_ce_lux,
|
|
sizeof(mdnie_tune->hbm_ce_lux), GFP_KERNEL);
|
|
memcpy(mdnie->props.anti_glare_lux, mdnie_tune->anti_glare_lux,
|
|
sizeof(mdnie_tune->anti_glare_lux));
|
|
memcpy(mdnie->props.anti_glare_ratio, mdnie_tune->anti_glare_ratio,
|
|
sizeof(mdnie_tune->anti_glare_ratio));
|
|
mdnie->props.scr_white_len = mdnie_tune->scr_white_len;
|
|
mdnie->props.scr_cr_ofs = mdnie_tune->scr_cr_ofs;
|
|
mdnie->props.night_mode_ofs = mdnie_tune->night_mode_ofs;
|
|
mdnie->props.color_lens_ofs = mdnie_tune->color_lens_ofs;
|
|
mdnie->props.force_scr_white_mode_none_on_hbm =
|
|
mdnie_tune->force_scr_white_mode_none_on_hbm;
|
|
|
|
ret = panel_add_property_from_array(to_panel_device(mdnie),
|
|
mdnie_property_array,
|
|
ARRAY_SIZE(mdnie_property_array));
|
|
if (ret < 0) {
|
|
panel_err("failed to add mdnie property array\n");
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_deinit_property(struct mdnie_info *mdnie)
|
|
{
|
|
int ret;
|
|
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
ret = panel_delete_property_from_array(to_panel_device(mdnie),
|
|
mdnie_property_array,
|
|
ARRAY_SIZE(mdnie_property_array));
|
|
if (ret < 0) {
|
|
panel_err("failed to delete mdnie property array\n");
|
|
return ret;
|
|
}
|
|
|
|
kfree(mdnie->props.hbm_ce_lux);
|
|
mdnie->props.hbm_ce_lux = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_set_name(struct mdnie_info *mdnie, unsigned int id)
|
|
{
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
if (id == 0)
|
|
snprintf(mdnie->name, MAX_MDNIE_DEV_NAME_SIZE,
|
|
"%s", MDNIE_DEV_NAME);
|
|
else
|
|
snprintf(mdnie->name, MAX_MDNIE_DEV_NAME_SIZE,
|
|
"%s-%d", MDNIE_DEV_NAME, id);
|
|
|
|
return 0;
|
|
}
|
|
|
|
__visible_for_testing const char *mdnie_get_name(struct mdnie_info *mdnie)
|
|
{
|
|
return mdnie ? mdnie->name : NULL;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_create_class(struct mdnie_info *mdnie)
|
|
{
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
mdnie->class = class_create(THIS_MODULE, mdnie_get_name(mdnie));
|
|
if (IS_ERR_OR_NULL(mdnie->class)) {
|
|
panel_err("failed to create mdnie class\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_destroy_class(struct mdnie_info *mdnie)
|
|
{
|
|
if (!mdnie || !mdnie->class)
|
|
return -EINVAL;
|
|
|
|
class_destroy(mdnie->class);
|
|
mdnie->class = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_create_device(struct mdnie_info *mdnie)
|
|
{
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
if (!to_panel_device(mdnie)->lcd_dev) {
|
|
panel_err("lcd_device is null\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
mdnie->dev = device_create(mdnie->class,
|
|
to_panel_device(mdnie)->lcd_dev,
|
|
0, &mdnie, "%s", mdnie_get_name(mdnie));
|
|
if (IS_ERR_OR_NULL(mdnie->dev)) {
|
|
panel_err("failed to create mdnie device\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev_set_drvdata(mdnie->dev, mdnie);
|
|
|
|
return 0;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_destroy_device(struct mdnie_info *mdnie)
|
|
{
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
if (!mdnie->dev) {
|
|
panel_err("mdnie device is null\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
device_unregister(mdnie->dev);
|
|
mdnie->dev = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_create_device_files(struct mdnie_info *mdnie)
|
|
{
|
|
int i, ret;
|
|
|
|
if (!mdnie || !mdnie->dev)
|
|
return -EINVAL;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(mdnie_dev_attrs); i++) {
|
|
ret = device_create_file(mdnie->dev, &mdnie_dev_attrs[i].dev_attr);
|
|
if (ret < 0) {
|
|
panel_err("failed to add %s sysfs entries, %d\n",
|
|
mdnie_dev_attrs[i].dev_attr.attr.name, ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_remove_device_files(struct mdnie_info *mdnie)
|
|
{
|
|
int i;
|
|
|
|
if (!mdnie || !mdnie->dev)
|
|
return -EINVAL;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(mdnie_dev_attrs); i++)
|
|
device_remove_file(mdnie->dev, &mdnie_dev_attrs[i].dev_attr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_create_class_and_device(struct mdnie_info *mdnie)
|
|
{
|
|
int ret;
|
|
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
ret = mdnie_create_class(mdnie);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
ret = mdnie_create_device(mdnie);
|
|
if (ret < 0)
|
|
goto error1;
|
|
|
|
ret = mdnie_create_device_files(mdnie);
|
|
if (ret < 0)
|
|
goto error2;
|
|
|
|
return 0;
|
|
|
|
error2:
|
|
mdnie_destroy_device(mdnie);
|
|
error1:
|
|
mdnie_destroy_class(mdnie);
|
|
|
|
return ret;
|
|
}
|
|
|
|
__visible_for_testing int mdnie_remove_class_and_device(struct mdnie_info *mdnie)
|
|
{
|
|
int ret;
|
|
|
|
ret = mdnie_remove_device_files(mdnie);
|
|
if (ret < 0)
|
|
return -EINVAL;
|
|
|
|
ret = mdnie_destroy_device(mdnie);
|
|
if (ret < 0)
|
|
return -EINVAL;
|
|
|
|
ret = mdnie_destroy_class(mdnie);
|
|
if (ret < 0)
|
|
return -EINVAL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mdnie_init(struct mdnie_info *mdnie)
|
|
{
|
|
int ret;
|
|
struct panel_device *panel;
|
|
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
panel = to_panel_device(mdnie);
|
|
panel_mutex_init(panel, &mdnie->lock);
|
|
|
|
ret = mdnie_set_name(mdnie, panel->id);
|
|
if (ret < 0)
|
|
return -EINVAL;
|
|
|
|
ret = mdnie_create_class_and_device(mdnie);
|
|
if (ret < 0)
|
|
return -EINVAL;
|
|
|
|
panel_info("mdnie init success\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mdnie_exit(struct mdnie_info *mdnie)
|
|
{
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
mdnie_remove_class_and_device(mdnie);
|
|
memset(mdnie->name, 0, sizeof(mdnie->name));
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mdnie_prepare(struct mdnie_info *mdnie, struct mdnie_tune *mdnie_tune)
|
|
{
|
|
int ret = 0;
|
|
struct panel_device *panel;
|
|
|
|
if (!mdnie || !mdnie_tune)
|
|
return -EINVAL;
|
|
|
|
panel = to_panel_device(mdnie);
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
ret = mdnie_init_property(mdnie, mdnie_tune);
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
ret = panel_add_command_from_initdata_seqtbl(mdnie_tune->seqtbl,
|
|
mdnie_tune->nr_seqtbl, &panel->command_initdata_list);
|
|
if (ret < 0) {
|
|
panel_err("failed to panel_add_command_from_initdata_seqtbl\n");
|
|
goto err;
|
|
}
|
|
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
return 0;
|
|
|
|
err:
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
panel_err("failed to prepare mdnie\n");
|
|
|
|
return ret;
|
|
}
|
|
|
|
int mdnie_unprepare(struct mdnie_info *mdnie)
|
|
{
|
|
int ret;
|
|
struct panel_device *panel;
|
|
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
panel = to_panel_device(mdnie);
|
|
panel_mutex_lock(&mdnie->lock);
|
|
ret = mdnie_deinit_property(mdnie);
|
|
if (ret < 0)
|
|
goto err;
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
return 0;
|
|
|
|
err:
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
panel_err("failed to unprepare mdnie\n");
|
|
|
|
return ret;
|
|
}
|
|
|
|
int mdnie_probe(struct mdnie_info *mdnie, struct mdnie_tune *mdnie_tune)
|
|
{
|
|
int ret;
|
|
|
|
if (unlikely(!mdnie || !mdnie_tune)) {
|
|
panel_err("invalid argument\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
panel_mutex_lock(&mdnie->lock);
|
|
|
|
ret = mdnie_register_fb(mdnie);
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
#ifdef CONFIG_USDM_PANEL_DPUI
|
|
ret = mdnie_register_dpui(mdnie);
|
|
if (ret < 0)
|
|
goto err;
|
|
#endif
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
ret = mdnie_enable(mdnie);
|
|
if (ret < 0) {
|
|
panel_err("failed to enable mdnie\n");
|
|
return ret;
|
|
}
|
|
|
|
panel_info("mdnie probe success\n");
|
|
|
|
return 0;
|
|
|
|
err:
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
panel_err("failed to probe mdnie\n");
|
|
|
|
return ret;
|
|
}
|
|
|
|
int mdnie_remove(struct mdnie_info *mdnie)
|
|
{
|
|
if (!mdnie)
|
|
return -EINVAL;
|
|
|
|
mdnie_disable(mdnie);
|
|
panel_mutex_lock(&mdnie->lock);
|
|
#ifdef CONFIG_USDM_PANEL_DPUI
|
|
mdnie_unregister_dpui(mdnie);
|
|
#endif
|
|
mdnie_unregister_fb(mdnie);
|
|
|
|
panel_mutex_unlock(&mdnie->lock);
|
|
|
|
return 0;
|
|
}
|
|
|