1254a47ceSLohita Mudimela // SPDX-License-Identifier: MIT 2254a47ceSLohita Mudimela // 3254a47ceSLohita Mudimela // Copyright 2026 Advanced Micro Devices, Inc. 4254a47ceSLohita Mudimela 5254a47ceSLohita Mudimela #include "dm_services.h" 6254a47ceSLohita Mudimela #include "dc.h" 7254a47ceSLohita Mudimela #include "mod_power.h" 8254a47ceSLohita Mudimela #include "core_types.h" 9254a47ceSLohita Mudimela #include "dmcu.h" 10254a47ceSLohita Mudimela #include "abm.h" 11254a47ceSLohita Mudimela #include "power_helpers.h" 12254a47ceSLohita Mudimela #include "dce/dmub_psr.h" 13254a47ceSLohita Mudimela #include "dal_asic_id.h" 14254a47ceSLohita Mudimela #include "link_service.h" 15254a47ceSLohita Mudimela #include <linux/math.h> 16254a47ceSLohita Mudimela 17254a47ceSLohita Mudimela #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ 18254a47ceSLohita Mudimela #define DC_TRACE_LEVEL_MESSAGEP(...) /* do nothing */ 19254a47ceSLohita Mudimela 20254a47ceSLohita Mudimela #define DIV_ROUNDUP(a, b) (((a)+((b)/2))/(b)) 21254a47ceSLohita Mudimela #define bswap16_based_on_endian(big_endian, value) \ 22254a47ceSLohita Mudimela ((big_endian) ? cpu_to_be16(value) : cpu_to_le16(value)) 23254a47ceSLohita Mudimela 24254a47ceSLohita Mudimela /* Possible Min Reduction config from least aggressive to most aggressive 25254a47ceSLohita Mudimela * 0 1 2 3 4 5 6 7 8 9 10 11 12 26254a47ceSLohita Mudimela * 100 98.0 94.1 94.1 85.1 80.3 75.3 69.4 60.0 57.6 50.2 49.8 40.0 % 27254a47ceSLohita Mudimela */ 28254a47ceSLohita Mudimela static const unsigned char min_reduction_table[13] = { 29254a47ceSLohita Mudimela 0xff, 0xfa, 0xf0, 0xf0, 0xd9, 0xcd, 0xc0, 0xb1, 0x99, 0x93, 0x80, 0x82, 0x66}; 30254a47ceSLohita Mudimela 31254a47ceSLohita Mudimela /* Possible Max Reduction configs from least aggressive to most aggressive 32254a47ceSLohita Mudimela * 0 1 2 3 4 5 6 7 8 9 10 11 12 33254a47ceSLohita Mudimela * 96.1 89.8 85.1 80.3 69.4 64.7 64.7 50.2 39.6 30.2 30.2 30.2 19.6 % 34254a47ceSLohita Mudimela */ 35254a47ceSLohita Mudimela static const unsigned char max_reduction_table[13] = { 36254a47ceSLohita Mudimela 0xf5, 0xe5, 0xd9, 0xcd, 0xb1, 0xa5, 0xa5, 0x80, 0x65, 0x4d, 0x4d, 0x4d, 0x32}; 37254a47ceSLohita Mudimela 38254a47ceSLohita Mudimela /* Possible ABM 2.2 Min Reduction configs from least aggressive to most aggressive 39254a47ceSLohita Mudimela * 0 1 2 3 4 5 6 7 8 9 10 11 12 40254a47ceSLohita Mudimela * 100 100 100 100 100 100 100 100 100 92.2 83.1 75.3 75.3 % 41254a47ceSLohita Mudimela */ 42254a47ceSLohita Mudimela static const unsigned char min_reduction_table_v_2_2[13] = { 43254a47ceSLohita Mudimela 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xd4, 0xc0, 0xc0}; 44254a47ceSLohita Mudimela 45254a47ceSLohita Mudimela /* Possible ABM 2.2 Max Reduction configs from least aggressive to most aggressive 46254a47ceSLohita Mudimela * 0 1 2 3 4 5 6 7 8 9 10 11 12 47254a47ceSLohita Mudimela * 96.1 89.8 74.9 69.4 64.7 52.2 48.6 39.6 30.2 25.1 19.6 12.5 12.5 % 48254a47ceSLohita Mudimela */ 49254a47ceSLohita Mudimela static const unsigned char max_reduction_table_v_2_2[13] = { 50254a47ceSLohita Mudimela 0xf5, 0xe5, 0xbf, 0xb1, 0xa5, 0x85, 0x7c, 0x65, 0x4d, 0x40, 0x32, 0x20, 0x20}; 51254a47ceSLohita Mudimela 52254a47ceSLohita Mudimela /* Predefined ABM configuration sets. We may have different configuration sets 53254a47ceSLohita Mudimela * in order to satisfy different power/quality requirements. 54254a47ceSLohita Mudimela */ 55254a47ceSLohita Mudimela static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_level] = { 56254a47ceSLohita Mudimela /* ABM Level 1, ABM Level 2, ABM Level 3, ABM Level 4 */ 57254a47ceSLohita Mudimela { 2, 5, 7, 8 }, /* Default - Medium aggressiveness */ 58254a47ceSLohita Mudimela { 2, 5, 8, 11 }, /* Alt #1 - Increased aggressiveness */ 59254a47ceSLohita Mudimela { 0, 2, 4, 8 }, /* Alt #2 - Minimal aggressiveness */ 60254a47ceSLohita Mudimela { 3, 6, 10, 12 }, /* Alt #3 - Super aggressiveness */ 61254a47ceSLohita Mudimela }; 62254a47ceSLohita Mudimela 63254a47ceSLohita Mudimela struct abm_parameters { 64254a47ceSLohita Mudimela unsigned char min_reduction; 65254a47ceSLohita Mudimela unsigned char max_reduction; 66254a47ceSLohita Mudimela unsigned char bright_pos_gain; 67254a47ceSLohita Mudimela unsigned char dark_pos_gain; 68254a47ceSLohita Mudimela unsigned char brightness_gain; 69254a47ceSLohita Mudimela unsigned char contrast_factor; 70254a47ceSLohita Mudimela unsigned char deviation_gain; 71254a47ceSLohita Mudimela unsigned char min_knee; 72254a47ceSLohita Mudimela unsigned char max_knee; 73254a47ceSLohita Mudimela unsigned short blRampReduction; 74254a47ceSLohita Mudimela unsigned short blRampStart; 75254a47ceSLohita Mudimela }; 76254a47ceSLohita Mudimela 77254a47ceSLohita Mudimela static const struct abm_parameters abm_settings_config0[abm_defines_max_level] = { 78254a47ceSLohita Mudimela // min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blRed blStart 79254a47ceSLohita Mudimela {0xff, 0xbf, 0x20, 0x00, 0xff, 0x99, 0xb3, 0x40, 0xe0, 0xf777, 0xcccc}, 80254a47ceSLohita Mudimela {0xde, 0x85, 0x20, 0x00, 0xe0, 0x90, 0xa8, 0x40, 0xc8, 0xf777, 0xcccc}, 81254a47ceSLohita Mudimela {0xb0, 0x50, 0x20, 0x00, 0xc0, 0x88, 0x78, 0x70, 0xa0, 0xeeee, 0x9999}, 82254a47ceSLohita Mudimela {0x82, 0x40, 0x20, 0x00, 0x00, 0xb8, 0xb3, 0x70, 0x70, 0xe333, 0xb333}, 83254a47ceSLohita Mudimela }; 84254a47ceSLohita Mudimela 85254a47ceSLohita Mudimela static const struct abm_parameters abm_settings_config1[abm_defines_max_level] = { 86254a47ceSLohita Mudimela // min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blRed blStart 87254a47ceSLohita Mudimela {0xf0, 0xd9, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xcccc, 0xcccc}, 88254a47ceSLohita Mudimela {0xcd, 0xa5, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xcccc, 0xcccc}, 89254a47ceSLohita Mudimela {0x99, 0x65, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xcccc, 0xcccc}, 90254a47ceSLohita Mudimela {0x82, 0x4d, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xcccc, 0xcccc}, 91254a47ceSLohita Mudimela }; 92254a47ceSLohita Mudimela 93254a47ceSLohita Mudimela static const struct abm_parameters abm_settings_config2[abm_defines_max_level] = { 94254a47ceSLohita Mudimela // min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blRed blStart 95254a47ceSLohita Mudimela {0xf0, 0xbf, 0x20, 0x00, 0x88, 0x99, 0xb3, 0x40, 0xe0, 0x0000, 0xcccc}, 96254a47ceSLohita Mudimela {0xd8, 0x85, 0x20, 0x00, 0x70, 0x90, 0xa8, 0x40, 0xc8, 0x0700, 0xb333}, 97254a47ceSLohita Mudimela {0xb8, 0x58, 0x20, 0x00, 0x64, 0x88, 0x78, 0x70, 0xa0, 0x7000, 0x9999}, 98254a47ceSLohita Mudimela {0x82, 0x40, 0x20, 0x00, 0x00, 0xb8, 0xb3, 0x70, 0x70, 0xc333, 0xb333}, 99254a47ceSLohita Mudimela }; 100254a47ceSLohita Mudimela 101254a47ceSLohita Mudimela static const struct abm_parameters * const abm_settings[] = { 102254a47ceSLohita Mudimela abm_settings_config0, 103254a47ceSLohita Mudimela abm_settings_config1, 104254a47ceSLohita Mudimela abm_settings_config2, 105254a47ceSLohita Mudimela }; 106254a47ceSLohita Mudimela 107254a47ceSLohita Mudimela static const struct dm_bl_data_point custom_backlight_curve0[] = { 108254a47ceSLohita Mudimela {2, 14}, {4, 16}, {6, 18}, {8, 21}, {10, 23}, {12, 26}, {14, 29}, {16, 32}, {18, 35}, 109254a47ceSLohita Mudimela {20, 38}, {22, 41}, {24, 44}, {26, 48}, {28, 52}, {30, 55}, {32, 59}, {34, 62}, 110254a47ceSLohita Mudimela {36, 67}, {38, 71}, {40, 75}, {42, 80}, {44, 84}, {46, 88}, {48, 93}, {50, 98}, 111254a47ceSLohita Mudimela {52, 103}, {54, 108}, {56, 113}, {58, 118}, {60, 123}, {62, 129}, {64, 135}, {66, 140}, 112254a47ceSLohita Mudimela {68, 146}, {70, 152}, {72, 158}, {74, 164}, {76, 171}, {78, 177}, {80, 183}, {82, 190}, 113254a47ceSLohita Mudimela {84, 197}, {86, 204}, {88, 211}, {90, 218}, {92, 225}, {94, 232}, {96, 240}, {98, 247}}; 114254a47ceSLohita Mudimela 115254a47ceSLohita Mudimela struct custom_backlight_profile { 116254a47ceSLohita Mudimela uint8_t ac_level_percentage; 117254a47ceSLohita Mudimela uint8_t dc_level_percentage; 118254a47ceSLohita Mudimela uint8_t min_input_signal; 119254a47ceSLohita Mudimela uint8_t max_input_signal; 120254a47ceSLohita Mudimela uint8_t num_data_points; 121254a47ceSLohita Mudimela const struct dm_bl_data_point *data_points; 122254a47ceSLohita Mudimela }; 123254a47ceSLohita Mudimela 124254a47ceSLohita Mudimela static const struct custom_backlight_profile custom_backlight_profiles[] = { 125254a47ceSLohita Mudimela {100, 32, 12, 255, ARRAY_SIZE(custom_backlight_curve0), custom_backlight_curve0}, 126254a47ceSLohita Mudimela }; 127254a47ceSLohita Mudimela 128254a47ceSLohita Mudimela #define NUM_AMBI_LEVEL 5 129254a47ceSLohita Mudimela #define NUM_AGGR_LEVEL 4 130254a47ceSLohita Mudimela #define NUM_POWER_FN_SEGS 8 131254a47ceSLohita Mudimela #define NUM_BL_CURVE_SEGS 16 132254a47ceSLohita Mudimela #define IRAM_SIZE 256 133254a47ceSLohita Mudimela 134254a47ceSLohita Mudimela #define IRAM_RESERVE_AREA_START_V2 0xF0 // reserve 0xF0~0xF6 are write by DMCU only 135254a47ceSLohita Mudimela #define IRAM_RESERVE_AREA_END_V2 0xF6 // reserve 0xF0~0xF6 are write by DMCU only 136254a47ceSLohita Mudimela 137254a47ceSLohita Mudimela #define IRAM_RESERVE_AREA_START_V2_2 0xF0 // reserve 0xF0~0xFF are write by DMCU only 138254a47ceSLohita Mudimela #define IRAM_RESERVE_AREA_END_V2_2 0xFF // reserve 0xF0~0xFF are write by DMCU only 139254a47ceSLohita Mudimela 140254a47ceSLohita Mudimela #pragma pack(push, 1) 141254a47ceSLohita Mudimela /* NOTE: iRAM is 256B in size */ 142254a47ceSLohita Mudimela struct iram_table_v_2 { 143254a47ceSLohita Mudimela /* flags */ 144254a47ceSLohita Mudimela uint16_t min_abm_backlight; /* 0x00 U16 */ 145254a47ceSLohita Mudimela 146254a47ceSLohita Mudimela /* parameters for ABM2.0 algorithm */ 147254a47ceSLohita Mudimela uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x02 U0.8 */ 148254a47ceSLohita Mudimela uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x16 U0.8 */ 149254a47ceSLohita Mudimela uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x2a U2.6 */ 150254a47ceSLohita Mudimela uint8_t bright_neg_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x3e U2.6 */ 151254a47ceSLohita Mudimela uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x52 U2.6 */ 152254a47ceSLohita Mudimela uint8_t dark_neg_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x66 U2.6 */ 153254a47ceSLohita Mudimela uint8_t iir_curve[NUM_AMBI_LEVEL]; /* 0x7a U0.8 */ 154254a47ceSLohita Mudimela uint8_t deviation_gain; /* 0x7f U0.8 */ 155254a47ceSLohita Mudimela 156254a47ceSLohita Mudimela /* parameters for crgb conversion */ 157254a47ceSLohita Mudimela uint16_t crgb_thresh[NUM_POWER_FN_SEGS]; /* 0x80 U3.13 */ 158254a47ceSLohita Mudimela uint16_t crgb_offset[NUM_POWER_FN_SEGS]; /* 0x90 U1.15 */ 159254a47ceSLohita Mudimela uint16_t crgb_slope[NUM_POWER_FN_SEGS]; /* 0xa0 U4.12 */ 160254a47ceSLohita Mudimela 161254a47ceSLohita Mudimela /* parameters for custom curve */ 162254a47ceSLohita Mudimela /* thresholds for brightness --> backlight */ 163254a47ceSLohita Mudimela uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS]; /* 0xb0 U16.0 */ 164254a47ceSLohita Mudimela /* offsets for brightness --> backlight */ 165254a47ceSLohita Mudimela uint16_t backlight_offsets[NUM_BL_CURVE_SEGS]; /* 0xd0 U16.0 */ 166254a47ceSLohita Mudimela 167254a47ceSLohita Mudimela /* For reading PSR State directly from IRAM */ 168254a47ceSLohita Mudimela uint8_t psr_state; /* 0xf0 */ 169254a47ceSLohita Mudimela uint8_t dmcu_mcp_interface_version; /* 0xf1 */ 170254a47ceSLohita Mudimela uint8_t dmcu_abm_feature_version; /* 0xf2 */ 171254a47ceSLohita Mudimela uint8_t dmcu_psr_feature_version; /* 0xf3 */ 172254a47ceSLohita Mudimela uint16_t dmcu_version; /* 0xf4 */ 173254a47ceSLohita Mudimela uint8_t dmcu_state; /* 0xf6 */ 174254a47ceSLohita Mudimela 175254a47ceSLohita Mudimela uint16_t blRampReduction; /* 0xf7 */ 176254a47ceSLohita Mudimela uint16_t blRampStart; /* 0xf9 */ 177254a47ceSLohita Mudimela uint8_t dummy5; /* 0xfb */ 178254a47ceSLohita Mudimela uint8_t dummy6; /* 0xfc */ 179254a47ceSLohita Mudimela uint8_t dummy7; /* 0xfd */ 180254a47ceSLohita Mudimela uint8_t dummy8; /* 0xfe */ 181254a47ceSLohita Mudimela uint8_t dummy9; /* 0xff */ 182254a47ceSLohita Mudimela }; 183254a47ceSLohita Mudimela 184254a47ceSLohita Mudimela struct iram_table_v_2_2 { 185254a47ceSLohita Mudimela /* flags */ 186254a47ceSLohita Mudimela uint16_t flags; /* 0x00 U16 */ 187254a47ceSLohita Mudimela 188254a47ceSLohita Mudimela /* parameters for ABM2.2 algorithm */ 189254a47ceSLohita Mudimela uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x02 U0.8 */ 190254a47ceSLohita Mudimela uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x16 U0.8 */ 191254a47ceSLohita Mudimela uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x2a U2.6 */ 192254a47ceSLohita Mudimela uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL]; /* 0x3e U2.6 */ 193254a47ceSLohita Mudimela uint8_t hybrid_factor[NUM_AGGR_LEVEL]; /* 0x52 U0.8 */ 194254a47ceSLohita Mudimela uint8_t contrast_factor[NUM_AGGR_LEVEL]; /* 0x56 U0.8 */ 195254a47ceSLohita Mudimela uint8_t deviation_gain[NUM_AGGR_LEVEL]; /* 0x5a U0.8 */ 196254a47ceSLohita Mudimela uint8_t iir_curve[NUM_AMBI_LEVEL]; /* 0x5e U0.8 */ 197254a47ceSLohita Mudimela uint8_t min_knee[NUM_AGGR_LEVEL]; /* 0x63 U0.8 */ 198254a47ceSLohita Mudimela uint8_t max_knee[NUM_AGGR_LEVEL]; /* 0x67 U0.8 */ 199254a47ceSLohita Mudimela uint16_t min_abm_backlight; /* 0x6b U16 */ 200254a47ceSLohita Mudimela uint8_t pad[19]; /* 0x6d U0.8 */ 201254a47ceSLohita Mudimela 202254a47ceSLohita Mudimela /* parameters for crgb conversion */ 203254a47ceSLohita Mudimela uint16_t crgb_thresh[NUM_POWER_FN_SEGS]; /* 0x80 U3.13 */ 204254a47ceSLohita Mudimela uint16_t crgb_offset[NUM_POWER_FN_SEGS]; /* 0x90 U1.15 */ 205254a47ceSLohita Mudimela uint16_t crgb_slope[NUM_POWER_FN_SEGS]; /* 0xa0 U4.12 */ 206254a47ceSLohita Mudimela 207254a47ceSLohita Mudimela /* parameters for custom curve */ 208254a47ceSLohita Mudimela /* thresholds for brightness --> backlight */ 209254a47ceSLohita Mudimela uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS]; /* 0xb0 U16.0 */ 210254a47ceSLohita Mudimela /* offsets for brightness --> backlight */ 211254a47ceSLohita Mudimela uint16_t backlight_offsets[NUM_BL_CURVE_SEGS]; /* 0xd0 U16.0 */ 212254a47ceSLohita Mudimela 213254a47ceSLohita Mudimela /* For reading PSR State directly from IRAM */ 214254a47ceSLohita Mudimela uint8_t psr_state; /* 0xf0 */ 215254a47ceSLohita Mudimela uint8_t dmcu_mcp_interface_version; /* 0xf1 */ 216254a47ceSLohita Mudimela uint8_t dmcu_abm_feature_version; /* 0xf2 */ 217254a47ceSLohita Mudimela uint8_t dmcu_psr_feature_version; /* 0xf3 */ 218254a47ceSLohita Mudimela uint16_t dmcu_version; /* 0xf4 */ 219254a47ceSLohita Mudimela uint8_t dmcu_state; /* 0xf6 */ 220254a47ceSLohita Mudimela 221254a47ceSLohita Mudimela uint8_t dummy1; /* 0xf7 */ 222254a47ceSLohita Mudimela uint8_t dummy2; /* 0xf8 */ 223254a47ceSLohita Mudimela uint8_t dummy3; /* 0xf9 */ 224254a47ceSLohita Mudimela uint8_t dummy4; /* 0xfa */ 225254a47ceSLohita Mudimela uint8_t dummy5; /* 0xfb */ 226254a47ceSLohita Mudimela uint8_t dummy6; /* 0xfc */ 227254a47ceSLohita Mudimela uint8_t dummy7; /* 0xfd */ 228254a47ceSLohita Mudimela uint8_t dummy8; /* 0xfe */ 229254a47ceSLohita Mudimela uint8_t dummy9; /* 0xff */ 230254a47ceSLohita Mudimela }; 231254a47ceSLohita Mudimela #pragma pack(pop) 232254a47ceSLohita Mudimela 233254a47ceSLohita Mudimela #define MOD_POWER_MAX_CONCURRENT_STREAMS 32 234254a47ceSLohita Mudimela #define SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS 500 235254a47ceSLohita Mudimela 236254a47ceSLohita Mudimela /* If system or panel does not report some sort of brightness percent to nits 237254a47ceSLohita Mudimela * mapping, we will use following default values so backlight control using 238254a47ceSLohita Mudimela * nits based interfaces will still work, but might not describe panel 239254a47ceSLohita Mudimela * correctly. In this case percentage based backlight control should ideally 240254a47ceSLohita Mudimela * be used. 241254a47ceSLohita Mudimela * Min = 5 nits 242254a47ceSLohita Mudimela * Max = 300 nits 243254a47ceSLohita Mudimela */ 244254a47ceSLohita Mudimela 245254a47ceSLohita Mudimela #define MOD_POWER_TO_CORE(mod_power)\ 246254a47ceSLohita Mudimela container_of(mod_power, struct core_power, mod_public) 247254a47ceSLohita Mudimela 248254a47ceSLohita Mudimela static uint16_t backlight_8_to_16(unsigned int backlight_8bit) 249254a47ceSLohita Mudimela { 250254a47ceSLohita Mudimela return (uint16_t)(backlight_8bit * 0x101); 251254a47ceSLohita Mudimela } 252254a47ceSLohita Mudimela 253254a47ceSLohita Mudimela unsigned int backlight_millipercent_to_millinit( 254254a47ceSLohita Mudimela struct core_power *core_power, unsigned int millipercent, unsigned int inst) 255254a47ceSLohita Mudimela { 256254a47ceSLohita Mudimela unsigned int millinit = 0; 257254a47ceSLohita Mudimela unsigned long long numerator = 0; 258254a47ceSLohita Mudimela 259254a47ceSLohita Mudimela if (core_power == NULL) 260254a47ceSLohita Mudimela return 0; 261254a47ceSLohita Mudimela 262254a47ceSLohita Mudimela numerator = ((unsigned long long)millipercent) * 263254a47ceSLohita Mudimela core_power->bl_prop[inst].nits_range; 264254a47ceSLohita Mudimela millinit = ((unsigned int)div_u64(numerator, 100000)) + 265254a47ceSLohita Mudimela core_power->bl_prop[inst].min_brightness_millinits; 266254a47ceSLohita Mudimela 267254a47ceSLohita Mudimela return millinit; 268254a47ceSLohita Mudimela } 269254a47ceSLohita Mudimela 270254a47ceSLohita Mudimela static unsigned int backlight_millinit_to_millipercent( 271254a47ceSLohita Mudimela struct core_power *core_power, unsigned int millinit, unsigned int inst) 272254a47ceSLohita Mudimela { 273254a47ceSLohita Mudimela unsigned int millipercent = 0; 274254a47ceSLohita Mudimela unsigned long long numerator = 0; 275254a47ceSLohita Mudimela 276254a47ceSLohita Mudimela if (core_power == NULL) 277254a47ceSLohita Mudimela return 0; 278254a47ceSLohita Mudimela 279254a47ceSLohita Mudimela if (millinit <= core_power->bl_prop[inst].min_brightness_millinits) 280254a47ceSLohita Mudimela return 0; 281254a47ceSLohita Mudimela 282254a47ceSLohita Mudimela if (millinit >= core_power->bl_prop[inst].max_brightness_millinits) 283254a47ceSLohita Mudimela return (100 * 1000); 284254a47ceSLohita Mudimela 285254a47ceSLohita Mudimela numerator = (((unsigned long long)millinit) - 286254a47ceSLohita Mudimela core_power->bl_prop[inst].min_brightness_millinits) * 100000; 287254a47ceSLohita Mudimela millipercent = ((unsigned int)div_u64(numerator, 288254a47ceSLohita Mudimela core_power->bl_prop[inst].nits_range)); 289254a47ceSLohita Mudimela 290254a47ceSLohita Mudimela return millipercent; 291254a47ceSLohita Mudimela } 292254a47ceSLohita Mudimela 293254a47ceSLohita Mudimela static unsigned int backlight_pwm_to_millipercent( 294254a47ceSLohita Mudimela struct core_power *core_power, unsigned int pwm, unsigned int inst) 295254a47ceSLohita Mudimela { 296254a47ceSLohita Mudimela unsigned int millipercent = 0; 297254a47ceSLohita Mudimela unsigned int max_index = 0; 298254a47ceSLohita Mudimela 299254a47ceSLohita Mudimela if (core_power == NULL) 300254a47ceSLohita Mudimela return 0; 301254a47ceSLohita Mudimela 302254a47ceSLohita Mudimela if (!core_power->bl_prop[inst].backlight_caps_valid) 303254a47ceSLohita Mudimela return 0; 304254a47ceSLohita Mudimela 305254a47ceSLohita Mudimela /* Doesn't really make sense to have one single backlight level 306254a47ceSLohita Mudimela * possible... 307254a47ceSLohita Mudimela */ 308254a47ceSLohita Mudimela if (core_power->bl_prop[inst].num_backlight_levels < 2) 309254a47ceSLohita Mudimela return 0; 310254a47ceSLohita Mudimela 311254a47ceSLohita Mudimela max_index = core_power->bl_prop[inst].num_backlight_levels - 1; 312254a47ceSLohita Mudimela 313254a47ceSLohita Mudimela if (pwm <= core_power->bl_prop[inst].backlight_lut[0]) 314254a47ceSLohita Mudimela return 0; 315254a47ceSLohita Mudimela 316254a47ceSLohita Mudimela if (pwm > core_power->bl_prop[inst].backlight_lut[max_index]) 317254a47ceSLohita Mudimela return (100 * 1000); 318254a47ceSLohita Mudimela 319254a47ceSLohita Mudimela /* We need to do a binary search over the array for where the pwm level 320254a47ceSLohita Mudimela * is in the lut. Based on the index we can determine percentage. 321254a47ceSLohita Mudimela */ 322254a47ceSLohita Mudimela unsigned int min = 0; 323254a47ceSLohita Mudimela unsigned int max = max_index; 324254a47ceSLohita Mudimela unsigned int mid = 0; 325254a47ceSLohita Mudimela 326254a47ceSLohita Mudimela while (max >= min) { 327254a47ceSLohita Mudimela mid = (min + max) / 2; /* floor of half range */ 328254a47ceSLohita Mudimela 329254a47ceSLohita Mudimela if (core_power->bl_prop[inst].backlight_lut[mid] < pwm) 330254a47ceSLohita Mudimela min = mid + 1; 331254a47ceSLohita Mudimela else if (core_power->bl_prop[inst].backlight_lut[mid] > pwm) 332254a47ceSLohita Mudimela max = mid - 1; 333254a47ceSLohita Mudimela else 334254a47ceSLohita Mudimela break; 335254a47ceSLohita Mudimela } 336254a47ceSLohita Mudimela 337254a47ceSLohita Mudimela /* In this case, exact match is not found. Check if mid/min/max 338254a47ceSLohita Mudimela * value is actually closer. 339254a47ceSLohita Mudimela */ 340254a47ceSLohita Mudimela if (max < min) { 341254a47ceSLohita Mudimela unsigned int min_delta; 342254a47ceSLohita Mudimela unsigned int mid_delta; 343254a47ceSLohita Mudimela unsigned int max_delta; 344254a47ceSLohita Mudimela 345254a47ceSLohita Mudimela min_delta = (core_power->bl_prop[inst].backlight_lut[min] > pwm) ? 346254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[min] - pwm : 347254a47ceSLohita Mudimela pwm - core_power->bl_prop[inst].backlight_lut[min]; 348254a47ceSLohita Mudimela 349254a47ceSLohita Mudimela mid_delta = (core_power->bl_prop[inst].backlight_lut[mid] > pwm) ? 350254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[mid] - pwm : 351254a47ceSLohita Mudimela pwm - core_power->bl_prop[inst].backlight_lut[mid]; 352254a47ceSLohita Mudimela 353254a47ceSLohita Mudimela max_delta = (core_power->bl_prop[inst].backlight_lut[max] > pwm) ? 354254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[max] - pwm : 355254a47ceSLohita Mudimela pwm - core_power->bl_prop[inst].backlight_lut[max]; 356254a47ceSLohita Mudimela 357254a47ceSLohita Mudimela if ((min_delta < mid_delta) && (min_delta < max_delta)) 358254a47ceSLohita Mudimela mid = min; 359254a47ceSLohita Mudimela 360254a47ceSLohita Mudimela if ((max_delta < mid_delta) && (max_delta < min_delta)) 361254a47ceSLohita Mudimela mid = max; 362254a47ceSLohita Mudimela } 363254a47ceSLohita Mudimela 364254a47ceSLohita Mudimela /* No interpolation, just take closest index */ 365254a47ceSLohita Mudimela millipercent = 1000 * 100 * mid / max_index; 366254a47ceSLohita Mudimela 367254a47ceSLohita Mudimela return millipercent; 368254a47ceSLohita Mudimela } 369254a47ceSLohita Mudimela 370254a47ceSLohita Mudimela static unsigned int backlight_pwm_to_millinit( 371254a47ceSLohita Mudimela struct core_power *core_power, unsigned int pwm, unsigned int inst) 372254a47ceSLohita Mudimela { 373254a47ceSLohita Mudimela unsigned int millinit = 0; 374254a47ceSLohita Mudimela 375254a47ceSLohita Mudimela if (core_power == NULL) 376254a47ceSLohita Mudimela return 0; 377254a47ceSLohita Mudimela 378254a47ceSLohita Mudimela if (pwm <= core_power->bl_prop[inst].min_backlight_pwm) 379254a47ceSLohita Mudimela return core_power->bl_prop[inst].min_brightness_millinits; 380254a47ceSLohita Mudimela 381254a47ceSLohita Mudimela if (pwm >= core_power->bl_prop[inst].max_backlight_pwm) 382254a47ceSLohita Mudimela return core_power->bl_prop[inst].max_brightness_millinits; 383254a47ceSLohita Mudimela 384254a47ceSLohita Mudimela millinit = ((unsigned int)div_u64(((unsigned long long)pwm - 385254a47ceSLohita Mudimela core_power->bl_prop[inst].min_backlight_pwm) * 386254a47ceSLohita Mudimela core_power->bl_prop[inst].nits_range, 387254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_range)); 388254a47ceSLohita Mudimela 389254a47ceSLohita Mudimela millinit += core_power->bl_prop[inst].min_brightness_millinits; 390254a47ceSLohita Mudimela 391254a47ceSLohita Mudimela if (millinit > core_power->bl_prop[inst].max_brightness_millinits) 392254a47ceSLohita Mudimela millinit = core_power->bl_prop[inst].max_brightness_millinits; 393254a47ceSLohita Mudimela 394254a47ceSLohita Mudimela return millinit; 395254a47ceSLohita Mudimela } 396254a47ceSLohita Mudimela 397254a47ceSLohita Mudimela unsigned int backlight_millipercent_to_pwm( 398254a47ceSLohita Mudimela struct core_power *core_power, unsigned int millipercent, unsigned int inst) 399254a47ceSLohita Mudimela { 400254a47ceSLohita Mudimela unsigned int pwm = (unsigned int)-1; 401254a47ceSLohita Mudimela unsigned int index = 0; 402254a47ceSLohita Mudimela 403254a47ceSLohita Mudimela if (core_power == NULL) 404254a47ceSLohita Mudimela return 0; 405254a47ceSLohita Mudimela 406254a47ceSLohita Mudimela // Bypass the brightness mapping LUT 407254a47ceSLohita Mudimela if (core_power->bl_prop->use_linear_backlight_curve) { 408254a47ceSLohita Mudimela pwm = core_power->bl_prop[inst].min_backlight_pwm + 409254a47ceSLohita Mudimela (unsigned int) div_u64((unsigned long long) millipercent * 410254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_range, 411254a47ceSLohita Mudimela 100000); 412254a47ceSLohita Mudimela 413254a47ceSLohita Mudimela if (pwm > core_power->bl_prop[inst].max_backlight_pwm) 414254a47ceSLohita Mudimela pwm = core_power->bl_prop[inst].max_backlight_pwm; 415254a47ceSLohita Mudimela 416254a47ceSLohita Mudimela return pwm; 417254a47ceSLohita Mudimela } 418254a47ceSLohita Mudimela 419254a47ceSLohita Mudimela if (millipercent >= (100 * 1000)) 420254a47ceSLohita Mudimela return core_power->bl_prop[inst].backlight_lut[core_power->bl_prop[inst].num_backlight_levels - 1]; 421254a47ceSLohita Mudimela 422254a47ceSLohita Mudimela /* This will give the floor index. */ 423254a47ceSLohita Mudimela index = ((core_power->bl_prop[inst].num_backlight_levels - 1) * 424254a47ceSLohita Mudimela millipercent) / 100000; 425254a47ceSLohita Mudimela /* Null check otherwise eDP doesn't lightup when connected to DP1 */ 426254a47ceSLohita Mudimela if (core_power->bl_prop[inst].backlight_lut == NULL) 427254a47ceSLohita Mudimela return pwm; 428254a47ceSLohita Mudimela 429254a47ceSLohita Mudimela pwm = core_power->bl_prop[inst].backlight_lut[index]; 430254a47ceSLohita Mudimela 431254a47ceSLohita Mudimela return pwm; 432254a47ceSLohita Mudimela } 433254a47ceSLohita Mudimela 434254a47ceSLohita Mudimela static unsigned int backlight_millinit_to_pwm( 435254a47ceSLohita Mudimela struct core_power *core_power, unsigned int millinit, unsigned int inst) 436254a47ceSLohita Mudimela { 437254a47ceSLohita Mudimela unsigned int pwm = 0; 438254a47ceSLohita Mudimela 439254a47ceSLohita Mudimela if (core_power == NULL) 440254a47ceSLohita Mudimela return 0; 441254a47ceSLohita Mudimela 442254a47ceSLohita Mudimela /* For nits based brightness, the signal will be a value 443254a47ceSLohita Mudimela * between the minimum and maximum value. 444254a47ceSLohita Mudimela */ 445254a47ceSLohita Mudimela if (millinit >= core_power->bl_prop[inst].max_brightness_millinits) 446254a47ceSLohita Mudimela return core_power->bl_prop[inst].max_backlight_pwm; 447254a47ceSLohita Mudimela else if (millinit <= core_power->bl_prop[inst].min_brightness_millinits) 448254a47ceSLohita Mudimela return core_power->bl_prop[inst].min_backlight_pwm; 449254a47ceSLohita Mudimela 450254a47ceSLohita Mudimela pwm = ((unsigned int)div_u64(((unsigned long long)millinit - 451254a47ceSLohita Mudimela core_power->bl_prop[inst].min_brightness_millinits) * 452254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_range, 453254a47ceSLohita Mudimela core_power->bl_prop[inst].nits_range)); 454254a47ceSLohita Mudimela 455254a47ceSLohita Mudimela pwm += core_power->bl_prop[inst].min_backlight_pwm; 456254a47ceSLohita Mudimela 457254a47ceSLohita Mudimela if (pwm > core_power->bl_prop[inst].max_backlight_pwm) 458254a47ceSLohita Mudimela pwm = core_power->bl_prop[inst].max_backlight_pwm; 459254a47ceSLohita Mudimela 460254a47ceSLohita Mudimela return pwm; 461254a47ceSLohita Mudimela } 462254a47ceSLohita Mudimela 463254a47ceSLohita Mudimela static bool validate_ext_backlight_caps( 464254a47ceSLohita Mudimela struct dm_acpi_atif_backlight_caps *ext_backlight_caps) 465254a47ceSLohita Mudimela { 466254a47ceSLohita Mudimela unsigned int i; 467254a47ceSLohita Mudimela unsigned int num_of_data_points = 0; 468254a47ceSLohita Mudimela unsigned int last_signal_level = 0; 469254a47ceSLohita Mudimela unsigned int last_luminance = 0; 470254a47ceSLohita Mudimela 471254a47ceSLohita Mudimela num_of_data_points = ext_backlight_caps->num_data_points; 472254a47ceSLohita Mudimela 473254a47ceSLohita Mudimela /* Validation rules: 474254a47ceSLohita Mudimela * 1. BIOS should carry customized data points and 475254a47ceSLohita Mudimela * the number of data points should not be larger than 99. 476254a47ceSLohita Mudimela * 2. The max_input_signal should be larger than min_input_signal. 477254a47ceSLohita Mudimela * 3. For each data point: 478254a47ceSLohita Mudimela * a. luminance should be in ascending order and 479254a47ceSLohita Mudimela * should not be 0 or 100 since the corresponding signal_level 480254a47ceSLohita Mudimela * are assigned by min_input_signal and max_input_signal. 481254a47ceSLohita Mudimela * b. signal_level should be in ascending order and 482254a47ceSLohita Mudimela * be within the range of min/max_input_signal. 483254a47ceSLohita Mudimela */ 484254a47ceSLohita Mudimela if (num_of_data_points > BL_DATA_POINTS) 485254a47ceSLohita Mudimela return false; 486254a47ceSLohita Mudimela 487254a47ceSLohita Mudimela if (ext_backlight_caps->min_input_signal >= ext_backlight_caps->max_input_signal) 488254a47ceSLohita Mudimela return false; 489254a47ceSLohita Mudimela 490254a47ceSLohita Mudimela last_signal_level = ext_backlight_caps->min_input_signal; 491254a47ceSLohita Mudimela for (i = 0; i < num_of_data_points; i++) { 492254a47ceSLohita Mudimela unsigned int luminance = ext_backlight_caps->data_points[i].luminance; 493254a47ceSLohita Mudimela unsigned int signal_level = ext_backlight_caps->data_points[i].signal_level; 494254a47ceSLohita Mudimela 495254a47ceSLohita Mudimela if ((luminance <= last_luminance) || (luminance > BL_DATA_POINTS)) 496254a47ceSLohita Mudimela return false; 497254a47ceSLohita Mudimela 498254a47ceSLohita Mudimela if ((signal_level <= last_signal_level) || (signal_level >= ext_backlight_caps->max_input_signal)) 499254a47ceSLohita Mudimela return false; 500254a47ceSLohita Mudimela 501254a47ceSLohita Mudimela last_signal_level = signal_level; 502254a47ceSLohita Mudimela last_luminance = luminance; 503254a47ceSLohita Mudimela } 504254a47ceSLohita Mudimela 505254a47ceSLohita Mudimela return true; 506254a47ceSLohita Mudimela } 507254a47ceSLohita Mudimela 508254a47ceSLohita Mudimela /* hard coded to default backlight curve. */ 509254a47ceSLohita Mudimela void initialize_backlight_caps(struct core_power *core_power, unsigned int inst) 510254a47ceSLohita Mudimela { 511254a47ceSLohita Mudimela unsigned int i; 512254a47ceSLohita Mudimela struct dm_acpi_atif_backlight_caps *ext_backlight_caps = NULL; 513254a47ceSLohita Mudimela bool custom_curve_present = false; 514254a47ceSLohita Mudimela unsigned int num_levels = 0; 515254a47ceSLohita Mudimela struct dc *dc = NULL; 516254a47ceSLohita Mudimela enum dm_acpi_display_type acpi_display_type = 517254a47ceSLohita Mudimela (inst == 0) ? AcpiDisplayType_LCD1 : AcpiDisplayType_LCD2; 518254a47ceSLohita Mudimela 519254a47ceSLohita Mudimela if (core_power == NULL) 520254a47ceSLohita Mudimela return; 521254a47ceSLohita Mudimela dc = core_power->dc; 522254a47ceSLohita Mudimela 523254a47ceSLohita Mudimela num_levels = core_power->bl_prop[inst].num_backlight_levels; 524254a47ceSLohita Mudimela 525254a47ceSLohita Mudimela /* Allocate memory for ATIF output 526254a47ceSLohita Mudimela * (do not want to use 256 bytes on the stack) 527254a47ceSLohita Mudimela */ 528254a47ceSLohita Mudimela ext_backlight_caps = (struct dm_acpi_atif_backlight_caps *) 529254a47ceSLohita Mudimela (kzalloc(sizeof(struct dm_acpi_atif_backlight_caps), 530254a47ceSLohita Mudimela GFP_KERNEL)); 531254a47ceSLohita Mudimela 532254a47ceSLohita Mudimela if (ext_backlight_caps == NULL) 533254a47ceSLohita Mudimela return; 534254a47ceSLohita Mudimela 535254a47ceSLohita Mudimela /* Retrieve ACPI extended brightness caps */ 536254a47ceSLohita Mudimela if (dm_query_extended_brightness_caps 537254a47ceSLohita Mudimela (dc->ctx, acpi_display_type, ext_backlight_caps)) { 538254a47ceSLohita Mudimela custom_curve_present = validate_ext_backlight_caps(ext_backlight_caps); 539254a47ceSLohita Mudimela } 540254a47ceSLohita Mudimela 541254a47ceSLohita Mudimela if (core_power->bl_prop[inst].use_custom_backlight_caps && 542254a47ceSLohita Mudimela fill_custom_backlight_caps( 543254a47ceSLohita Mudimela core_power->bl_prop[inst].custom_backlight_caps_config_no, 544254a47ceSLohita Mudimela ext_backlight_caps)) { 545254a47ceSLohita Mudimela custom_curve_present = validate_ext_backlight_caps(ext_backlight_caps); 546254a47ceSLohita Mudimela } 547254a47ceSLohita Mudimela 548254a47ceSLohita Mudimela if (custom_curve_present) { 549254a47ceSLohita Mudimela unsigned int index = 1; 550254a47ceSLohita Mudimela unsigned int num_of_data_points = ext_backlight_caps->num_data_points; 551254a47ceSLohita Mudimela 552254a47ceSLohita Mudimela core_power->bl_prop[inst].ac_backlight_percent = 553254a47ceSLohita Mudimela ext_backlight_caps->ac_level_percentage; 554254a47ceSLohita Mudimela core_power->bl_prop[inst].dc_backlight_percent = 555254a47ceSLohita Mudimela ext_backlight_caps->dc_level_percentage; 556254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[0] = 557254a47ceSLohita Mudimela backlight_8_to_16( 558254a47ceSLohita Mudimela ext_backlight_caps->min_input_signal); 559254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[num_levels - 1] = 560254a47ceSLohita Mudimela backlight_8_to_16( 561254a47ceSLohita Mudimela ext_backlight_caps->max_input_signal); 562254a47ceSLohita Mudimela 563254a47ceSLohita Mudimela /* Filling translation table from data points - 564254a47ceSLohita Mudimela * between every two provided data points we 565254a47ceSLohita Mudimela * lineary interpolate missing values 566254a47ceSLohita Mudimela */ 567254a47ceSLohita Mudimela for (i = 0; i < num_of_data_points; i++) { 568254a47ceSLohita Mudimela unsigned int luminance = 569254a47ceSLohita Mudimela ext_backlight_caps->data_points[i].luminance; 570254a47ceSLohita Mudimela unsigned int signal_level = 571254a47ceSLohita Mudimela backlight_8_to_16( 572254a47ceSLohita Mudimela ext_backlight_caps->data_points[i].signal_level); 573254a47ceSLohita Mudimela 574254a47ceSLohita Mudimela /* Since luminance is a percentage, scale it by num_levels*/ 575254a47ceSLohita Mudimela luminance = (luminance * num_levels) / 101; 576254a47ceSLohita Mudimela 577254a47ceSLohita Mudimela /* Lineary interpolate missing values */ 578254a47ceSLohita Mudimela if (index < luminance) { 579254a47ceSLohita Mudimela unsigned int base_value = 580254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[index-1]; 581254a47ceSLohita Mudimela unsigned int delta_signal = 582254a47ceSLohita Mudimela signal_level - base_value; 583254a47ceSLohita Mudimela unsigned int delta_luma = 584254a47ceSLohita Mudimela luminance - index + 1; 585254a47ceSLohita Mudimela unsigned int step = delta_signal; 586254a47ceSLohita Mudimela 587254a47ceSLohita Mudimela for (; index < luminance; index++) { 588254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[index] = 589254a47ceSLohita Mudimela base_value + (step / delta_luma); 590254a47ceSLohita Mudimela step += delta_signal; 591254a47ceSLohita Mudimela } 592254a47ceSLohita Mudimela } 593254a47ceSLohita Mudimela 594254a47ceSLohita Mudimela /* Now [index == luminance], 595254a47ceSLohita Mudimela * so we can add data point to the translation table 596254a47ceSLohita Mudimela */ 597254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[index++] = signal_level; 598254a47ceSLohita Mudimela } 599254a47ceSLohita Mudimela 600254a47ceSLohita Mudimela /* Complete the final segment of interpolation - 601254a47ceSLohita Mudimela * between last datapoint and maximum value 602254a47ceSLohita Mudimela */ 603254a47ceSLohita Mudimela if (index < num_levels - 1) { 604254a47ceSLohita Mudimela unsigned int base_value = 605254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[index-1]; 606254a47ceSLohita Mudimela unsigned int delta_signal = 607254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[num_levels - 1] - 608254a47ceSLohita Mudimela base_value; 609254a47ceSLohita Mudimela unsigned int delta_luma = num_levels - index; 610254a47ceSLohita Mudimela unsigned int step = delta_signal; 611254a47ceSLohita Mudimela 612254a47ceSLohita Mudimela for (; index < num_levels - 1; index++) { 613254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[index] = 614254a47ceSLohita Mudimela base_value + (step / delta_luma); 615254a47ceSLohita Mudimela step += delta_signal; 616254a47ceSLohita Mudimela } 617254a47ceSLohita Mudimela } 618254a47ceSLohita Mudimela /* Build backlight translation table based on default curve */ 619254a47ceSLohita Mudimela } else { 620254a47ceSLohita Mudimela /* Defines default backlight curve F(x) = A(x*x) + Bx + C. 621254a47ceSLohita Mudimela * 622254a47ceSLohita Mudimela * Backlight curve should always satisfy: 623254a47ceSLohita Mudimela * F(0) = min, F(100) = max, 624254a47ceSLohita Mudimela * So polynom coefficients are: 625254a47ceSLohita Mudimela * A is 0.0255 - B/100 - min/10000 - (255-max)/10000 = 626254a47ceSLohita Mudimela * (max - min)/10000 - B/100 627254a47ceSLohita Mudimela * B is adjustable factor to modify the curve. 628254a47ceSLohita Mudimela * Bigger B results in less concave curve. 629254a47ceSLohita Mudimela * B range is [0..(max-min)/100] 630254a47ceSLohita Mudimela * C is backlight minimum 631254a47ceSLohita Mudimela */ 632254a47ceSLohita Mudimela unsigned int backlight_curve_coeff_a_factor = 633254a47ceSLohita Mudimela num_levels * num_levels; 634254a47ceSLohita Mudimela unsigned int backlight_curve_coeff_b = num_levels; 635254a47ceSLohita Mudimela unsigned int delta = 636254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[num_levels - 1] - 637254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[0]; 638254a47ceSLohita Mudimela unsigned int coeffC = core_power->bl_prop[inst].backlight_lut[0]; 639254a47ceSLohita Mudimela unsigned int coeffB = 640254a47ceSLohita Mudimela (backlight_curve_coeff_b < delta ? 641254a47ceSLohita Mudimela backlight_curve_coeff_b : delta); 642254a47ceSLohita Mudimela unsigned long long coeffA = delta - coeffB; /* coeffB is B*100 */ 643254a47ceSLohita Mudimela 644254a47ceSLohita Mudimela for (i = 1; i < num_levels - 1; i++) { 645254a47ceSLohita Mudimela uint64_t lut_val = div_u64(coeffA * i * i, backlight_curve_coeff_a_factor) + 646254a47ceSLohita Mudimela div_u64((uint64_t)coeffB * i, backlight_curve_coeff_b) + coeffC; 647254a47ceSLohita Mudimela 648254a47ceSLohita Mudimela ASSERT(lut_val <= 0xFFFFFFFF); 649254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[i] = (unsigned int)lut_val; 650254a47ceSLohita Mudimela } 651254a47ceSLohita Mudimela } 652254a47ceSLohita Mudimela 653254a47ceSLohita Mudimela if (ext_backlight_caps != NULL) 654254a47ceSLohita Mudimela kfree(ext_backlight_caps); 655254a47ceSLohita Mudimela 656254a47ceSLohita Mudimela /* Successfully initialized */ 657254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_caps_valid = true; 658254a47ceSLohita Mudimela } 659254a47ceSLohita Mudimela 660254a47ceSLohita Mudimela static void varibright_set_level(struct core_power *core_power) 661254a47ceSLohita Mudimela { 662254a47ceSLohita Mudimela if (!core_power->varibright_prop.varibright_active || 663254a47ceSLohita Mudimela !core_power->varibright_prop.varibright_user_enable) 664254a47ceSLohita Mudimela core_power->varibright_prop.varibright_hw_level = 0; 665254a47ceSLohita Mudimela else 666254a47ceSLohita Mudimela core_power->varibright_prop.varibright_hw_level = 667254a47ceSLohita Mudimela core_power->varibright_prop.varibright_level; 668254a47ceSLohita Mudimela } 669254a47ceSLohita Mudimela 670254a47ceSLohita Mudimela bool mod_power_hw_init_backlight(struct mod_power *mod_power) 671254a47ceSLohita Mudimela { 672254a47ceSLohita Mudimela struct core_power *core_power = NULL; 673254a47ceSLohita Mudimela struct dc *dc = NULL; 674254a47ceSLohita Mudimela struct dmcu *dmcu = NULL; 675254a47ceSLohita Mudimela struct dmcu_iram_parameters params; 676254a47ceSLohita Mudimela unsigned int i; 677254a47ceSLohita Mudimela 678254a47ceSLohita Mudimela if (mod_power == NULL) 679254a47ceSLohita Mudimela return false; 680254a47ceSLohita Mudimela 681254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 682254a47ceSLohita Mudimela dc = core_power->dc; 683254a47ceSLohita Mudimela 684254a47ceSLohita Mudimela for (i = 0; i < core_power->edp_num; i++) { 685254a47ceSLohita Mudimela params.set = core_power->varibright_prop.varibright_config_setting; 686254a47ceSLohita Mudimela params.backlight_ramping_override = core_power->bl_prop[i].backlight_ramping_override; 687254a47ceSLohita Mudimela params.backlight_ramping_reduction = core_power->bl_prop[i].backlight_ramping_reduction; 688254a47ceSLohita Mudimela params.backlight_ramping_start = core_power->bl_prop[i].backlight_ramping_start; 689254a47ceSLohita Mudimela params.backlight_lut_array = core_power->bl_prop[i].backlight_lut; 690254a47ceSLohita Mudimela params.backlight_lut_array_size = core_power->bl_prop[i].num_backlight_levels; 691254a47ceSLohita Mudimela params.min_abm_backlight = core_power->bl_prop[i].min_abm_backlight; 692254a47ceSLohita Mudimela 693254a47ceSLohita Mudimela dmcu = dc->res_pool->dmcu; 694254a47ceSLohita Mudimela 695254a47ceSLohita Mudimela // In the case where abm is implemented on dmcub, 696254a47ceSLohita Mudimela // dmcu object will be null. 697254a47ceSLohita Mudimela // ABM 2.4 and up are implemented on dmcub. 698254a47ceSLohita Mudimela if (dmcu) { 699254a47ceSLohita Mudimela //DMCU does not support multiple eDP 700254a47ceSLohita Mudimela return dmcu_load_iram(dmcu, params); 701254a47ceSLohita Mudimela } else if (dc->ctx->dmub_srv) { 702254a47ceSLohita Mudimela if (!dmub_init_abm_config(dc->res_pool, params, i)) 703254a47ceSLohita Mudimela return false; 704254a47ceSLohita Mudimela } else 705254a47ceSLohita Mudimela return false; 706254a47ceSLohita Mudimela } 707254a47ceSLohita Mudimela return true; 708254a47ceSLohita Mudimela } 709254a47ceSLohita Mudimela 710254a47ceSLohita Mudimela void mod_power_update_backlight_on_mode_change( 711254a47ceSLohita Mudimela struct core_power *core_power, 712254a47ceSLohita Mudimela struct dc_link *link, 713254a47ceSLohita Mudimela unsigned int panel_inst, 714254a47ceSLohita Mudimela uint8_t aux_inst, 715254a47ceSLohita Mudimela bool is_hdr) 716254a47ceSLohita Mudimela { 717254a47ceSLohita Mudimela struct set_backlight_level_params backlight_level_params = { 0 }; 718254a47ceSLohita Mudimela 719254a47ceSLohita Mudimela if (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 || 720254a47ceSLohita Mudimela link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1) 721254a47ceSLohita Mudimela dc_link_set_backlight_level_nits(link, core_power->bl_state[panel_inst].isHDR, 722254a47ceSLohita Mudimela core_power->bl_state[panel_inst].backlight_millinit, 0); 723254a47ceSLohita Mudimela 724254a47ceSLohita Mudimela backlight_level_params.frame_ramp = 0; 725254a47ceSLohita Mudimela 726254a47ceSLohita Mudimela fill_backlight_level_params(core_power, &backlight_level_params, panel_inst, aux_inst, 727254a47ceSLohita Mudimela core_power->bl_state[panel_inst].backlight_pwm, link->backlight_control_type, 728254a47ceSLohita Mudimela core_power->bl_state[panel_inst].backlight_millinit, 0, is_hdr); 729254a47ceSLohita Mudimela 730254a47ceSLohita Mudimela dc_link_set_backlight_level(link, &backlight_level_params); 731254a47ceSLohita Mudimela } 732254a47ceSLohita Mudimela 733254a47ceSLohita Mudimela static bool set_backlight_millinits_aux(struct core_power *core_power, 734254a47ceSLohita Mudimela struct dc_stream_state *stream, 735254a47ceSLohita Mudimela unsigned int backlight_millinits, 736254a47ceSLohita Mudimela unsigned int transition_time_millisec, 737254a47ceSLohita Mudimela unsigned int inst) 738254a47ceSLohita Mudimela { 739254a47ceSLohita Mudimela struct dc_link *link = NULL; 740254a47ceSLohita Mudimela 741254a47ceSLohita Mudimela if (core_power == NULL) 742254a47ceSLohita Mudimela return false; 743254a47ceSLohita Mudimela 744254a47ceSLohita Mudimela if (stream == NULL) 745254a47ceSLohita Mudimela return true; 746254a47ceSLohita Mudimela 747254a47ceSLohita Mudimela link = dc_stream_get_link(stream); 748254a47ceSLohita Mudimela 749254a47ceSLohita Mudimela return dc_link_set_backlight_level_nits(link, core_power->bl_state[inst].isHDR, 750254a47ceSLohita Mudimela backlight_millinits, transition_time_millisec); 751254a47ceSLohita Mudimela } 752254a47ceSLohita Mudimela 753254a47ceSLohita Mudimela static bool set_backlight(struct core_power *core_power, 754254a47ceSLohita Mudimela struct dc_stream_state *stream, 755254a47ceSLohita Mudimela struct set_backlight_level_params *backlight_level_params, 756254a47ceSLohita Mudimela unsigned int inst) 757254a47ceSLohita Mudimela { 758254a47ceSLohita Mudimela bool retv = false; 759254a47ceSLohita Mudimela unsigned int frame_ramp = 0; 760254a47ceSLohita Mudimela unsigned int vsync_rate_hz; 761254a47ceSLohita Mudimela union dmcu_abm_set_bl_params params; 762254a47ceSLohita Mudimela const struct dc_link *link = NULL; 763254a47ceSLohita Mudimela unsigned int backlight_pwm_u16_16 = backlight_level_params->backlight_pwm_u16_16; 764254a47ceSLohita Mudimela unsigned int transition_time_millisec = backlight_level_params->transition_time_in_ms; 765254a47ceSLohita Mudimela 766254a47ceSLohita Mudimela if (core_power == NULL) 767254a47ceSLohita Mudimela return false; 768254a47ceSLohita Mudimela 769254a47ceSLohita Mudimela core_power->bl_state[inst].backlight_pwm = backlight_pwm_u16_16; 770254a47ceSLohita Mudimela 771254a47ceSLohita Mudimela if (stream == NULL) 772254a47ceSLohita Mudimela return true; 773254a47ceSLohita Mudimela 774254a47ceSLohita Mudimela if (stream->link->connector_signal != SIGNAL_TYPE_EDP) 775254a47ceSLohita Mudimela return false; 776254a47ceSLohita Mudimela 777254a47ceSLohita Mudimela if (transition_time_millisec != 0) { 778254a47ceSLohita Mudimela unsigned int v_total = 779254a47ceSLohita Mudimela (stream->adjust.v_total_max == 0) ? stream->timing.v_total : stream->adjust.v_total_max; 780254a47ceSLohita Mudimela 781254a47ceSLohita Mudimela vsync_rate_hz = (unsigned int)div_u64(div_u64((stream-> 782254a47ceSLohita Mudimela timing.pix_clk_100hz * 100), 783254a47ceSLohita Mudimela v_total), 784254a47ceSLohita Mudimela stream->timing.h_total); 785254a47ceSLohita Mudimela 786254a47ceSLohita Mudimela if (core_power->bl_state[inst].smooth_brightness_enabled) 787254a47ceSLohita Mudimela frame_ramp = ((vsync_rate_hz * 788254a47ceSLohita Mudimela transition_time_millisec) + 500) / 1000; 789254a47ceSLohita Mudimela } 790254a47ceSLohita Mudimela 791254a47ceSLohita Mudimela core_power->bl_state[inst].frame_ramp = frame_ramp; 792254a47ceSLohita Mudimela params.u32All = 0; 793254a47ceSLohita Mudimela params.bits.gradual_change = (frame_ramp > 0); 794254a47ceSLohita Mudimela params.bits.frame_ramp = frame_ramp; 795254a47ceSLohita Mudimela link = dc_stream_get_link(stream); 796254a47ceSLohita Mudimela 797254a47ceSLohita Mudimela mod_power_set_psr_event(&core_power->mod_public, stream, true, psr_event_hw_programming, true); 798254a47ceSLohita Mudimela mod_power_set_replay_event(&core_power->mod_public, stream, true, replay_event_hw_programming, true); 799254a47ceSLohita Mudimela 800254a47ceSLohita Mudimela backlight_level_params->frame_ramp = params.u32All; 801254a47ceSLohita Mudimela retv = dc_link_set_backlight_level(link, backlight_level_params); 802254a47ceSLohita Mudimela 803254a47ceSLohita Mudimela mod_power_set_psr_event(&core_power->mod_public, stream, false, psr_event_hw_programming, false); 804254a47ceSLohita Mudimela mod_power_set_replay_event(&core_power->mod_public, stream, false, replay_event_hw_programming, false); 805254a47ceSLohita Mudimela 806254a47ceSLohita Mudimela return retv; 807254a47ceSLohita Mudimela } 808254a47ceSLohita Mudimela 809254a47ceSLohita Mudimela void fill_backlight_level_params(struct core_power *core_power, 810254a47ceSLohita Mudimela struct set_backlight_level_params *backlight_level_params, 811254a47ceSLohita Mudimela int panel_inst, uint8_t aux_inst, unsigned int backlight_pwm, 812254a47ceSLohita Mudimela enum backlight_control_type backlight_control_type, 813254a47ceSLohita Mudimela unsigned int backlight_millinit, unsigned int transition_time_millisec, 814254a47ceSLohita Mudimela bool is_hdr) 815254a47ceSLohita Mudimela { 816254a47ceSLohita Mudimela struct pwr_backlight_properties *bl_prop = &core_power->bl_prop[panel_inst]; 817254a47ceSLohita Mudimela 818254a47ceSLohita Mudimela backlight_level_params->aux_inst = aux_inst; 819254a47ceSLohita Mudimela backlight_level_params->backlight_pwm_u16_16 = backlight_pwm; 820254a47ceSLohita Mudimela backlight_level_params->control_type = backlight_control_type; 821254a47ceSLohita Mudimela backlight_level_params->backlight_millinits = backlight_millinit; 822254a47ceSLohita Mudimela backlight_level_params->transition_time_in_ms = transition_time_millisec; 823254a47ceSLohita Mudimela backlight_level_params->min_luminance = bl_prop->min_brightness_millinits; 824254a47ceSLohita Mudimela backlight_level_params->max_luminance = bl_prop->max_brightness_millinits; 825254a47ceSLohita Mudimela backlight_level_params->min_backlight_pwm = bl_prop->min_backlight_pwm; 826254a47ceSLohita Mudimela backlight_level_params->max_backlight_pwm = bl_prop->max_backlight_pwm; 827254a47ceSLohita Mudimela 828254a47ceSLohita Mudimela if (backlight_control_type == BACKLIGHT_CONTROL_AMD_AUX && !is_hdr) 829254a47ceSLohita Mudimela backlight_level_params->control_type = BACKLIGHT_CONTROL_PWM; 830254a47ceSLohita Mudimela } 831254a47ceSLohita Mudimela 832254a47ceSLohita Mudimela bool mod_power_set_backlight_nits(struct mod_power *mod_power, 833254a47ceSLohita Mudimela struct dc_stream_state *stream, 834254a47ceSLohita Mudimela unsigned int backlight_millinit, 835254a47ceSLohita Mudimela unsigned int transition_time_millisec, 836254a47ceSLohita Mudimela bool skip_aux, 837254a47ceSLohita Mudimela bool is_hdr) 838254a47ceSLohita Mudimela { 839254a47ceSLohita Mudimela struct core_power *core_power = NULL; 840254a47ceSLohita Mudimela unsigned int backlight_pwm; 841254a47ceSLohita Mudimela unsigned int panel_inst = 0; 842254a47ceSLohita Mudimela struct set_backlight_level_params backlight_level_params = { 0 }; 843254a47ceSLohita Mudimela const struct dc_link *link = NULL; 844254a47ceSLohita Mudimela uint8_t aux_inst = 0; 845254a47ceSLohita Mudimela 846254a47ceSLohita Mudimela if (mod_power == NULL) 847254a47ceSLohita Mudimela return false; 848254a47ceSLohita Mudimela 849254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 850254a47ceSLohita Mudimela link = dc_stream_get_link(stream); 851254a47ceSLohita Mudimela 852*7d447370SGabe Teeger if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) { 853*7d447370SGabe Teeger aux_inst = (uint8_t)link->aux_hw_inst; 854*7d447370SGabe Teeger } else { 855254a47ceSLohita Mudimela ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF); 856254a47ceSLohita Mudimela aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel; 857*7d447370SGabe Teeger } 858254a47ceSLohita Mudimela 859254a47ceSLohita Mudimela if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &panel_inst)) 860254a47ceSLohita Mudimela return false; 861254a47ceSLohita Mudimela 862254a47ceSLohita Mudimela if (!skip_aux) { 863254a47ceSLohita Mudimela if (!set_backlight_millinits_aux(core_power, stream, 864254a47ceSLohita Mudimela backlight_millinit, transition_time_millisec, panel_inst)) 865254a47ceSLohita Mudimela return false; 866254a47ceSLohita Mudimela } 867254a47ceSLohita Mudimela // always send both AUX (above) and PWM (below) 868254a47ceSLohita Mudimela core_power->bl_state[panel_inst].backlight_millinit = backlight_millinit; 869254a47ceSLohita Mudimela 870254a47ceSLohita Mudimela core_power->bl_state[panel_inst].backlight_millipercent = 871254a47ceSLohita Mudimela backlight_millinit_to_millipercent( 872254a47ceSLohita Mudimela core_power, backlight_millinit, panel_inst); 873254a47ceSLohita Mudimela 874254a47ceSLohita Mudimela backlight_pwm = backlight_millinit_to_pwm( 875254a47ceSLohita Mudimela core_power, backlight_millinit, panel_inst); 876254a47ceSLohita Mudimela 877254a47ceSLohita Mudimela fill_backlight_level_params(core_power, &backlight_level_params, panel_inst, aux_inst, backlight_pwm, 878254a47ceSLohita Mudimela link->backlight_control_type, backlight_millinit, transition_time_millisec, is_hdr); 879254a47ceSLohita Mudimela 880254a47ceSLohita Mudimela return set_backlight(core_power, stream, 881254a47ceSLohita Mudimela &backlight_level_params, panel_inst); 882254a47ceSLohita Mudimela } 883254a47ceSLohita Mudimela 884254a47ceSLohita Mudimela bool mod_power_backlight_percent_to_nits(struct mod_power *mod_power, 885254a47ceSLohita Mudimela struct dc_stream_state *stream, 886254a47ceSLohita Mudimela unsigned int backlight_millipercent, 887254a47ceSLohita Mudimela unsigned int *backlight_millinit) 888254a47ceSLohita Mudimela { 889254a47ceSLohita Mudimela struct core_power *core_power = NULL; 890254a47ceSLohita Mudimela unsigned int inst = 0; 891254a47ceSLohita Mudimela 892254a47ceSLohita Mudimela if (mod_power == NULL) 893254a47ceSLohita Mudimela return false; 894254a47ceSLohita Mudimela 895254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 896254a47ceSLohita Mudimela 897254a47ceSLohita Mudimela if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst)) 898254a47ceSLohita Mudimela return false; 899254a47ceSLohita Mudimela 900254a47ceSLohita Mudimela *backlight_millinit = backlight_millipercent_to_millinit( 901254a47ceSLohita Mudimela core_power, backlight_millipercent, inst); 902254a47ceSLohita Mudimela return true; 903254a47ceSLohita Mudimela } 904254a47ceSLohita Mudimela 905254a47ceSLohita Mudimela bool mod_power_backlight_nits_to_percent(struct mod_power *mod_power, 906254a47ceSLohita Mudimela struct dc_stream_state *stream, 907254a47ceSLohita Mudimela unsigned int backlight_millinit, 908254a47ceSLohita Mudimela unsigned int *backlight_millipercent) 909254a47ceSLohita Mudimela { 910254a47ceSLohita Mudimela struct core_power *core_power = NULL; 911254a47ceSLohita Mudimela unsigned int inst = 0; 912254a47ceSLohita Mudimela 913254a47ceSLohita Mudimela if (mod_power == NULL) 914254a47ceSLohita Mudimela return false; 915254a47ceSLohita Mudimela 916254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 917254a47ceSLohita Mudimela 918254a47ceSLohita Mudimela if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst)) 919254a47ceSLohita Mudimela return false; 920254a47ceSLohita Mudimela 921254a47ceSLohita Mudimela *backlight_millipercent = backlight_millinit_to_millipercent( 922254a47ceSLohita Mudimela core_power, backlight_millinit, inst); 923254a47ceSLohita Mudimela return true; 924254a47ceSLohita Mudimela } 925254a47ceSLohita Mudimela 926254a47ceSLohita Mudimela bool mod_power_set_backlight_percent(struct mod_power *mod_power, 927254a47ceSLohita Mudimela struct dc_stream_state *stream, 928254a47ceSLohita Mudimela unsigned int backlight_millipercent, 929254a47ceSLohita Mudimela unsigned int transition_time_millisec, 930254a47ceSLohita Mudimela bool is_hdr) 931254a47ceSLohita Mudimela { 932254a47ceSLohita Mudimela struct core_power *core_power = NULL; 933254a47ceSLohita Mudimela struct set_backlight_level_params backlight_level_params = { 0 }; 934254a47ceSLohita Mudimela const struct dc_link *link = NULL; 935254a47ceSLohita Mudimela unsigned int backlight_pwm; 936254a47ceSLohita Mudimela unsigned int panel_inst = 0; 937254a47ceSLohita Mudimela uint8_t aux_inst = 0; 938254a47ceSLohita Mudimela 939254a47ceSLohita Mudimela if (mod_power == NULL) 940254a47ceSLohita Mudimela return false; 941254a47ceSLohita Mudimela 942254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 943254a47ceSLohita Mudimela link = dc_stream_get_link(stream); 944*7d447370SGabe Teeger if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) { 945*7d447370SGabe Teeger aux_inst = (uint8_t)link->aux_hw_inst; 946*7d447370SGabe Teeger } else { 947254a47ceSLohita Mudimela ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF); 948254a47ceSLohita Mudimela aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel; 949*7d447370SGabe Teeger } 950254a47ceSLohita Mudimela 951254a47ceSLohita Mudimela if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &panel_inst)) 952254a47ceSLohita Mudimela return false; 953254a47ceSLohita Mudimela core_power->bl_state[panel_inst].backlight_millipercent = backlight_millipercent; 954254a47ceSLohita Mudimela 955254a47ceSLohita Mudimela core_power->bl_state[panel_inst].backlight_millinit = 956254a47ceSLohita Mudimela backlight_millipercent_to_millinit( 957254a47ceSLohita Mudimela core_power, backlight_millipercent, panel_inst); 958254a47ceSLohita Mudimela 959254a47ceSLohita Mudimela backlight_pwm = backlight_millipercent_to_pwm( 960254a47ceSLohita Mudimela core_power, backlight_millipercent, panel_inst); 961254a47ceSLohita Mudimela 962254a47ceSLohita Mudimela fill_backlight_level_params(core_power, &backlight_level_params, panel_inst, 963254a47ceSLohita Mudimela aux_inst, backlight_pwm, link->backlight_control_type, 964254a47ceSLohita Mudimela core_power->bl_state[panel_inst].backlight_millinit, transition_time_millisec, is_hdr); 965254a47ceSLohita Mudimela 966254a47ceSLohita Mudimela return set_backlight(core_power, stream, 967254a47ceSLohita Mudimela &backlight_level_params, panel_inst); 968254a47ceSLohita Mudimela } 969254a47ceSLohita Mudimela 970254a47ceSLohita Mudimela void mod_power_update_backlight(struct mod_power *mod_power, 971254a47ceSLohita Mudimela struct dc_stream_state *stream, 972254a47ceSLohita Mudimela unsigned int backlight_millipercent) 973254a47ceSLohita Mudimela { 974254a47ceSLohita Mudimela struct core_power *core_power = NULL; 975254a47ceSLohita Mudimela unsigned int inst = 0; 976254a47ceSLohita Mudimela 977254a47ceSLohita Mudimela if (mod_power == NULL) 978254a47ceSLohita Mudimela return; 979254a47ceSLohita Mudimela 980254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 981254a47ceSLohita Mudimela 982254a47ceSLohita Mudimela if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst)) 983254a47ceSLohita Mudimela return; 984254a47ceSLohita Mudimela core_power->bl_state[inst].backlight_millipercent = backlight_millipercent; 985254a47ceSLohita Mudimela 986254a47ceSLohita Mudimela core_power->bl_state[inst].backlight_millinit = 987254a47ceSLohita Mudimela backlight_millipercent_to_millinit( 988254a47ceSLohita Mudimela core_power, backlight_millipercent, inst); 989254a47ceSLohita Mudimela 990254a47ceSLohita Mudimela core_power->bl_state[inst].backlight_pwm = backlight_millipercent_to_pwm( 991254a47ceSLohita Mudimela core_power, backlight_millipercent, inst); 992254a47ceSLohita Mudimela } 993254a47ceSLohita Mudimela 994254a47ceSLohita Mudimela void mod_power_update_backlight_nits(struct mod_power *mod_power, 995254a47ceSLohita Mudimela struct dc_stream_state *stream, 996254a47ceSLohita Mudimela unsigned int backlight_millinit) 997254a47ceSLohita Mudimela { 998254a47ceSLohita Mudimela struct core_power *core_power = NULL; 999254a47ceSLohita Mudimela unsigned int inst = 0; 1000254a47ceSLohita Mudimela 1001254a47ceSLohita Mudimela if (mod_power == NULL) 1002254a47ceSLohita Mudimela return; 1003254a47ceSLohita Mudimela 1004254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1005254a47ceSLohita Mudimela 1006254a47ceSLohita Mudimela if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst)) 1007254a47ceSLohita Mudimela return; 1008254a47ceSLohita Mudimela 1009254a47ceSLohita Mudimela core_power->bl_state[inst].backlight_millinit = backlight_millinit; 1010254a47ceSLohita Mudimela 1011254a47ceSLohita Mudimela core_power->bl_state[inst].backlight_millipercent = backlight_millinit_to_millipercent( 1012254a47ceSLohita Mudimela core_power, backlight_millinit, inst); 1013254a47ceSLohita Mudimela core_power->bl_state[inst].backlight_pwm = backlight_millinit_to_pwm( 1014254a47ceSLohita Mudimela core_power, backlight_millinit, inst); 1015254a47ceSLohita Mudimela } 1016254a47ceSLohita Mudimela 1017254a47ceSLohita Mudimela bool mod_power_get_backlight_pwm(struct mod_power *mod_power, 1018254a47ceSLohita Mudimela unsigned int *backlight_pwm, 1019254a47ceSLohita Mudimela unsigned int inst) 1020254a47ceSLohita Mudimela { 1021254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1022254a47ceSLohita Mudimela 1023254a47ceSLohita Mudimela if (mod_power == NULL) 1024254a47ceSLohita Mudimela return false; 1025254a47ceSLohita Mudimela 1026254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1027254a47ceSLohita Mudimela 1028254a47ceSLohita Mudimela *backlight_pwm = core_power->bl_state[inst].backlight_pwm; 1029254a47ceSLohita Mudimela 1030254a47ceSLohita Mudimela return true; 1031254a47ceSLohita Mudimela } 1032254a47ceSLohita Mudimela 1033254a47ceSLohita Mudimela bool mod_power_get_backlight_nits(struct mod_power *mod_power, 1034254a47ceSLohita Mudimela unsigned int *backlight_millinit, 1035254a47ceSLohita Mudimela unsigned int inst) 1036254a47ceSLohita Mudimela { 1037254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1038254a47ceSLohita Mudimela 1039254a47ceSLohita Mudimela if (mod_power == NULL) 1040254a47ceSLohita Mudimela return false; 1041254a47ceSLohita Mudimela 1042254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1043254a47ceSLohita Mudimela 1044254a47ceSLohita Mudimela *backlight_millinit = core_power->bl_state[inst].backlight_millinit; 1045254a47ceSLohita Mudimela 1046254a47ceSLohita Mudimela return true; 1047254a47ceSLohita Mudimela } 1048254a47ceSLohita Mudimela 1049254a47ceSLohita Mudimela bool mod_power_get_backlight_percent(struct mod_power *mod_power, 1050254a47ceSLohita Mudimela unsigned int *backlight_millipercent, 1051254a47ceSLohita Mudimela unsigned int inst) 1052254a47ceSLohita Mudimela { 1053254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1054254a47ceSLohita Mudimela 1055254a47ceSLohita Mudimela if (mod_power == NULL) 1056254a47ceSLohita Mudimela return false; 1057254a47ceSLohita Mudimela 1058254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1059254a47ceSLohita Mudimela 1060254a47ceSLohita Mudimela *backlight_millipercent = core_power->bl_state[inst].backlight_millipercent; 1061254a47ceSLohita Mudimela 1062254a47ceSLohita Mudimela return true; 1063254a47ceSLohita Mudimela } 1064254a47ceSLohita Mudimela 1065254a47ceSLohita Mudimela bool mod_power_get_hw_target_backlight_pwm_nits(struct mod_power *mod_power, 1066254a47ceSLohita Mudimela const struct dc_link *link, 1067254a47ceSLohita Mudimela unsigned int *backlight_millinit, 1068254a47ceSLohita Mudimela unsigned int inst) 1069254a47ceSLohita Mudimela { 1070254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1071254a47ceSLohita Mudimela unsigned int backlight_u16_16 = 0; 1072254a47ceSLohita Mudimela 1073254a47ceSLohita Mudimela if (mod_power == NULL) 1074254a47ceSLohita Mudimela return false; 1075254a47ceSLohita Mudimela 1076254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1077254a47ceSLohita Mudimela 1078254a47ceSLohita Mudimela if (mod_power_get_hw_target_backlight_pwm(mod_power, link, 1079254a47ceSLohita Mudimela &backlight_u16_16)) { 1080254a47ceSLohita Mudimela *backlight_millinit = 1081254a47ceSLohita Mudimela backlight_pwm_to_millinit(core_power, 1082254a47ceSLohita Mudimela backlight_u16_16, inst); 1083254a47ceSLohita Mudimela return true; 1084254a47ceSLohita Mudimela } 1085254a47ceSLohita Mudimela return false; 1086254a47ceSLohita Mudimela } 1087254a47ceSLohita Mudimela 1088254a47ceSLohita Mudimela bool mod_power_get_hw_target_backlight_pwm_percent(struct mod_power *mod_power, 1089254a47ceSLohita Mudimela const struct dc_link *link, 1090254a47ceSLohita Mudimela unsigned int *backlight_millipercent, 1091254a47ceSLohita Mudimela unsigned int inst) 1092254a47ceSLohita Mudimela { 1093254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1094254a47ceSLohita Mudimela unsigned int backlight_u16_16 = 0; 1095254a47ceSLohita Mudimela 1096254a47ceSLohita Mudimela if (mod_power == NULL) 1097254a47ceSLohita Mudimela return false; 1098254a47ceSLohita Mudimela 1099254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1100254a47ceSLohita Mudimela 1101254a47ceSLohita Mudimela if (mod_power_get_hw_target_backlight_pwm(mod_power, link, 1102254a47ceSLohita Mudimela &backlight_u16_16)) { 1103254a47ceSLohita Mudimela *backlight_millipercent = 1104254a47ceSLohita Mudimela backlight_pwm_to_millipercent(core_power, 1105254a47ceSLohita Mudimela backlight_u16_16, inst); 1106254a47ceSLohita Mudimela return true; 1107254a47ceSLohita Mudimela } 1108254a47ceSLohita Mudimela return false; 1109254a47ceSLohita Mudimela } 1110254a47ceSLohita Mudimela 1111254a47ceSLohita Mudimela bool mod_power_get_hw_target_backlight_pwm(struct mod_power *mod_power, 1112254a47ceSLohita Mudimela const struct dc_link *link, 1113254a47ceSLohita Mudimela unsigned int *backlight_u16_16) 1114254a47ceSLohita Mudimela { 1115254a47ceSLohita Mudimela if (mod_power == NULL) 1116254a47ceSLohita Mudimela return false; 1117254a47ceSLohita Mudimela 1118254a47ceSLohita Mudimela *backlight_u16_16 = dc_link_get_target_backlight_pwm(link); 1119254a47ceSLohita Mudimela 1120254a47ceSLohita Mudimela return true; 1121254a47ceSLohita Mudimela } 1122254a47ceSLohita Mudimela 1123254a47ceSLohita Mudimela bool mod_power_get_hw_backlight_pwm_nits(struct mod_power *mod_power, 1124254a47ceSLohita Mudimela const struct dc_link *link, 1125254a47ceSLohita Mudimela unsigned int *backlight_millinit, 1126254a47ceSLohita Mudimela unsigned int inst) 1127254a47ceSLohita Mudimela { 1128254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1129254a47ceSLohita Mudimela unsigned int backlight_u16_16 = 0; 1130254a47ceSLohita Mudimela 1131254a47ceSLohita Mudimela if (mod_power == NULL) 1132254a47ceSLohita Mudimela return false; 1133254a47ceSLohita Mudimela 1134254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1135254a47ceSLohita Mudimela 1136254a47ceSLohita Mudimela if (mod_power_get_hw_backlight_pwm(mod_power, link, &backlight_u16_16)) { 1137254a47ceSLohita Mudimela *backlight_millinit = 1138254a47ceSLohita Mudimela backlight_pwm_to_millinit(core_power, 1139254a47ceSLohita Mudimela backlight_u16_16, inst); 1140254a47ceSLohita Mudimela return true; 1141254a47ceSLohita Mudimela } 1142254a47ceSLohita Mudimela return false; 1143254a47ceSLohita Mudimela } 1144254a47ceSLohita Mudimela 1145254a47ceSLohita Mudimela bool mod_power_get_hw_backlight_aux_nits(struct mod_power *mod_power, 1146254a47ceSLohita Mudimela struct dc_stream_state **streams, int num_streams, 1147254a47ceSLohita Mudimela unsigned int *backlight_millinit_avg, 1148254a47ceSLohita Mudimela unsigned int *backlight_millinit_peak) 1149254a47ceSLohita Mudimela { 1150254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1151254a47ceSLohita Mudimela struct dc_link *link = NULL; 1152254a47ceSLohita Mudimela int stream_index; 1153254a47ceSLohita Mudimela 1154254a47ceSLohita Mudimela if (mod_power == NULL) 1155254a47ceSLohita Mudimela return false; 1156254a47ceSLohita Mudimela 1157254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1158254a47ceSLohita Mudimela 1159254a47ceSLohita Mudimela if (core_power == NULL) 1160254a47ceSLohita Mudimela return false; 1161254a47ceSLohita Mudimela 1162254a47ceSLohita Mudimela if (num_streams < 1) 1163254a47ceSLohita Mudimela return true; 1164254a47ceSLohita Mudimela 1165254a47ceSLohita Mudimela for (stream_index = 0; stream_index < num_streams; stream_index++) 1166254a47ceSLohita Mudimela if (streams[stream_index]->link->connector_signal == SIGNAL_TYPE_EDP || 1167254a47ceSLohita Mudimela streams[stream_index]->link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT) 1168254a47ceSLohita Mudimela break; 1169254a47ceSLohita Mudimela 1170254a47ceSLohita Mudimela if (stream_index == num_streams) 1171254a47ceSLohita Mudimela return false; 1172254a47ceSLohita Mudimela 1173254a47ceSLohita Mudimela link = dc_stream_get_link(streams[stream_index]); 1174254a47ceSLohita Mudimela if (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 0) 1175254a47ceSLohita Mudimela return false; 1176254a47ceSLohita Mudimela 1177254a47ceSLohita Mudimela return dc_link_get_backlight_level_nits(link, backlight_millinit_avg, 1178254a47ceSLohita Mudimela backlight_millinit_peak); 1179254a47ceSLohita Mudimela } 1180254a47ceSLohita Mudimela 1181254a47ceSLohita Mudimela bool mod_power_get_hw_backlight_pwm_percent(struct mod_power *mod_power, 1182254a47ceSLohita Mudimela const struct dc_link *link, 1183254a47ceSLohita Mudimela unsigned int *backlight_millipercent, 1184254a47ceSLohita Mudimela unsigned int inst) 1185254a47ceSLohita Mudimela { 1186254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1187254a47ceSLohita Mudimela unsigned int backlight_u16_16 = 0; 1188254a47ceSLohita Mudimela 1189254a47ceSLohita Mudimela if (mod_power == NULL) 1190254a47ceSLohita Mudimela return false; 1191254a47ceSLohita Mudimela 1192254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1193254a47ceSLohita Mudimela 1194254a47ceSLohita Mudimela if (mod_power_get_hw_backlight_pwm(mod_power, link, &backlight_u16_16)) { 1195254a47ceSLohita Mudimela *backlight_millipercent = 1196254a47ceSLohita Mudimela backlight_pwm_to_millipercent(core_power, 1197254a47ceSLohita Mudimela backlight_u16_16, inst); 1198254a47ceSLohita Mudimela return true; 1199254a47ceSLohita Mudimela } 1200254a47ceSLohita Mudimela return false; 1201254a47ceSLohita Mudimela } 1202254a47ceSLohita Mudimela 1203254a47ceSLohita Mudimela bool mod_power_get_hw_backlight_pwm(struct mod_power *mod_power, 1204254a47ceSLohita Mudimela const struct dc_link *link, 1205254a47ceSLohita Mudimela unsigned int *backlight_u16_16) 1206254a47ceSLohita Mudimela { 1207254a47ceSLohita Mudimela if (mod_power == NULL) 1208254a47ceSLohita Mudimela return false; 1209254a47ceSLohita Mudimela 1210254a47ceSLohita Mudimela *backlight_u16_16 = dc_link_get_backlight_level(link); 1211254a47ceSLohita Mudimela 1212254a47ceSLohita Mudimela return true; 1213254a47ceSLohita Mudimela } 1214254a47ceSLohita Mudimela 1215254a47ceSLohita Mudimela bool mod_power_get_panel_backlight_boundaries( 1216254a47ceSLohita Mudimela struct mod_power *mod_power, 1217254a47ceSLohita Mudimela unsigned int *out_min_backlight, 1218254a47ceSLohita Mudimela unsigned int *out_max_backlight, 1219254a47ceSLohita Mudimela unsigned int *out_ac_backlight_percent, 1220254a47ceSLohita Mudimela unsigned int *out_dc_backlight_percent, 1221254a47ceSLohita Mudimela unsigned int inst) 1222254a47ceSLohita Mudimela { 1223254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1224254a47ceSLohita Mudimela 1225254a47ceSLohita Mudimela if (mod_power == NULL) 1226254a47ceSLohita Mudimela return false; 1227254a47ceSLohita Mudimela 1228254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1229254a47ceSLohita Mudimela 1230254a47ceSLohita Mudimela /* If cache was successfully updated, 1231254a47ceSLohita Mudimela * copy the values to output structure and return success 1232254a47ceSLohita Mudimela */ 1233254a47ceSLohita Mudimela if (core_power->bl_prop[inst].backlight_caps_valid) { 1234254a47ceSLohita Mudimela *out_min_backlight = core_power->bl_prop[inst].backlight_lut[0]; 1235254a47ceSLohita Mudimela *out_max_backlight = 1236254a47ceSLohita Mudimela core_power->bl_prop[inst].backlight_lut[ 1237254a47ceSLohita Mudimela core_power->bl_prop[inst].num_backlight_levels - 1]; 1238254a47ceSLohita Mudimela *out_ac_backlight_percent = 1239254a47ceSLohita Mudimela core_power->bl_prop[inst].ac_backlight_percent; 1240254a47ceSLohita Mudimela *out_dc_backlight_percent = 1241254a47ceSLohita Mudimela core_power->bl_prop[inst].dc_backlight_percent; 1242254a47ceSLohita Mudimela 1243254a47ceSLohita Mudimela return true; 1244254a47ceSLohita Mudimela } 1245254a47ceSLohita Mudimela 1246254a47ceSLohita Mudimela return false; 1247254a47ceSLohita Mudimela } 1248254a47ceSLohita Mudimela 1249254a47ceSLohita Mudimela bool mod_power_set_smooth_brightness(struct mod_power *mod_power, 1250254a47ceSLohita Mudimela bool enable_brightness, 1251254a47ceSLohita Mudimela unsigned int inst) 1252254a47ceSLohita Mudimela { 1253254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1254254a47ceSLohita Mudimela 1255254a47ceSLohita Mudimela if (mod_power == NULL) 1256254a47ceSLohita Mudimela return false; 1257254a47ceSLohita Mudimela 1258254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1259254a47ceSLohita Mudimela 1260254a47ceSLohita Mudimela core_power->bl_state[inst].smooth_brightness_enabled = enable_brightness; 1261254a47ceSLohita Mudimela 1262254a47ceSLohita Mudimela return true; 1263254a47ceSLohita Mudimela } 1264254a47ceSLohita Mudimela 1265254a47ceSLohita Mudimela bool mod_power_varibright_feature_enable(struct mod_power *mod_power, bool enable, 1266254a47ceSLohita Mudimela struct dc_stream_update *stream_update) 1267254a47ceSLohita Mudimela { 1268254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1269254a47ceSLohita Mudimela 1270254a47ceSLohita Mudimela if (mod_power == NULL) 1271254a47ceSLohita Mudimela return false; 1272254a47ceSLohita Mudimela 1273254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1274254a47ceSLohita Mudimela core_power->varibright_prop.varibright_user_enable = enable; 1275254a47ceSLohita Mudimela 1276254a47ceSLohita Mudimela /* find abm hw level to program, and save in stream update */ 1277254a47ceSLohita Mudimela varibright_set_level(core_power); 1278254a47ceSLohita Mudimela *stream_update->abm_level = core_power->varibright_prop.varibright_hw_level; 1279254a47ceSLohita Mudimela 1280254a47ceSLohita Mudimela DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION, 1281254a47ceSLohita Mudimela WPP_BIT_FLAG_Backlight_ABM, 1282254a47ceSLohita Mudimela ">ABM feature enable: enable=%u su->varibright_level=%u varibright_hw_level=%u", 1283254a47ceSLohita Mudimela (unsigned int) enable, 1284254a47ceSLohita Mudimela *stream_update->abm_level, 1285254a47ceSLohita Mudimela core_power->varibright_prop.varibright_hw_level); 1286254a47ceSLohita Mudimela return true; 1287254a47ceSLohita Mudimela } 1288254a47ceSLohita Mudimela 1289254a47ceSLohita Mudimela bool mod_power_varibright_activate(struct mod_power *mod_power, 1290254a47ceSLohita Mudimela bool activate, 1291254a47ceSLohita Mudimela struct dc_stream_update *stream_update) 1292254a47ceSLohita Mudimela { 1293254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1294254a47ceSLohita Mudimela 1295254a47ceSLohita Mudimela if (mod_power == NULL) 1296254a47ceSLohita Mudimela return false; 1297254a47ceSLohita Mudimela 1298254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1299254a47ceSLohita Mudimela core_power->varibright_prop.varibright_active = activate; 1300254a47ceSLohita Mudimela 1301254a47ceSLohita Mudimela /* find abm hw level to program, and save in stream update */ 1302254a47ceSLohita Mudimela varibright_set_level(core_power); 1303254a47ceSLohita Mudimela *stream_update->abm_level = core_power->varibright_prop.varibright_hw_level; 1304254a47ceSLohita Mudimela 1305254a47ceSLohita Mudimela DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION, 1306254a47ceSLohita Mudimela WPP_BIT_FLAG_Backlight_ABM, 1307254a47ceSLohita Mudimela ">ABM activate: activate=%u su->varibright_level=%u", 1308254a47ceSLohita Mudimela (unsigned int) activate, 1309254a47ceSLohita Mudimela *stream_update->abm_level); 1310254a47ceSLohita Mudimela return true; 1311254a47ceSLohita Mudimela } 1312254a47ceSLohita Mudimela bool mod_power_varibright_set_level(struct mod_power *mod_power, unsigned int level, 1313254a47ceSLohita Mudimela struct dc_stream_update *stream_update) 1314254a47ceSLohita Mudimela { 1315254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1316254a47ceSLohita Mudimela 1317254a47ceSLohita Mudimela if (mod_power == NULL) 1318254a47ceSLohita Mudimela return false; 1319254a47ceSLohita Mudimela 1320254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1321254a47ceSLohita Mudimela core_power->varibright_prop.varibright_level = level; 1322254a47ceSLohita Mudimela core_power->varibright_prop.varibright_hw_level = level; 1323254a47ceSLohita Mudimela 1324254a47ceSLohita Mudimela /* find abm hw level to program, and save in stream update */ 1325254a47ceSLohita Mudimela varibright_set_level(core_power); 1326254a47ceSLohita Mudimela *stream_update->abm_level = core_power->varibright_prop.varibright_hw_level; 1327254a47ceSLohita Mudimela 1328254a47ceSLohita Mudimela DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION, 1329254a47ceSLohita Mudimela WPP_BIT_FLAG_Backlight_ABM, 1330254a47ceSLohita Mudimela ">ABM set level: level=%u -> (varibright_level=%u varibright_hw_level=%u) -> su->varibright_level=%u", 1331254a47ceSLohita Mudimela level, 1332254a47ceSLohita Mudimela core_power->varibright_prop.varibright_level, 1333254a47ceSLohita Mudimela core_power->varibright_prop.varibright_hw_level, 1334254a47ceSLohita Mudimela *stream_update->abm_level); 1335254a47ceSLohita Mudimela return true; 1336254a47ceSLohita Mudimela } 1337254a47ceSLohita Mudimela 1338254a47ceSLohita Mudimela bool mod_power_varibright_set_hw_level(struct mod_power *mod_power, unsigned int level, 1339254a47ceSLohita Mudimela struct dc_stream_update *stream_update) 1340254a47ceSLohita Mudimela { 1341254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1342254a47ceSLohita Mudimela 1343254a47ceSLohita Mudimela if (mod_power == NULL) 1344254a47ceSLohita Mudimela return false; 1345254a47ceSLohita Mudimela 1346254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1347254a47ceSLohita Mudimela 1348254a47ceSLohita Mudimela if (level == 0 || level == ABM_LEVEL_IMMEDIATE_DISABLE) 1349254a47ceSLohita Mudimela core_power->varibright_prop.varibright_active = 0; 1350254a47ceSLohita Mudimela else 1351254a47ceSLohita Mudimela core_power->varibright_prop.varibright_active = 1; 1352254a47ceSLohita Mudimela core_power->varibright_prop.varibright_hw_level = level; 1353254a47ceSLohita Mudimela *stream_update->abm_level = core_power->varibright_prop.varibright_hw_level; 1354254a47ceSLohita Mudimela 1355254a47ceSLohita Mudimela DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION, 1356254a47ceSLohita Mudimela WPP_BIT_FLAG_Backlight_ABM, 1357254a47ceSLohita Mudimela ">ABM set level: level=%u -> (varibright_level=%u varibright_hw_level=%u) -> su->varibright_level=%u", 1358254a47ceSLohita Mudimela level, 1359254a47ceSLohita Mudimela core_power->varibright_prop.varibright_level, 1360254a47ceSLohita Mudimela core_power->varibright_prop.varibright_hw_level, 1361254a47ceSLohita Mudimela *stream_update->abm_level); 1362254a47ceSLohita Mudimela return true; 1363254a47ceSLohita Mudimela } 1364254a47ceSLohita Mudimela 1365254a47ceSLohita Mudimela bool mod_power_get_varibright_level(struct mod_power *mod_power, 1366254a47ceSLohita Mudimela unsigned int *varibright_level) 1367254a47ceSLohita Mudimela { 1368254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1369254a47ceSLohita Mudimela 1370254a47ceSLohita Mudimela if (mod_power == NULL) 1371254a47ceSLohita Mudimela return false; 1372254a47ceSLohita Mudimela 1373254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1374254a47ceSLohita Mudimela 1375254a47ceSLohita Mudimela *varibright_level = core_power->varibright_prop.varibright_level; 1376254a47ceSLohita Mudimela 1377254a47ceSLohita Mudimela DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION, 1378254a47ceSLohita Mudimela WPP_BIT_FLAG_Backlight_ABM, 1379254a47ceSLohita Mudimela ">get varibright level: cp->varibright_level=%u", 1380254a47ceSLohita Mudimela *varibright_level); 1381254a47ceSLohita Mudimela return true; 1382254a47ceSLohita Mudimela 1383254a47ceSLohita Mudimela } 1384254a47ceSLohita Mudimela 1385254a47ceSLohita Mudimela bool mod_power_get_varibright_hw_level(struct mod_power *mod_power, 1386254a47ceSLohita Mudimela unsigned int *varibright_level) 1387254a47ceSLohita Mudimela { 1388254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1389254a47ceSLohita Mudimela 1390254a47ceSLohita Mudimela if (mod_power == NULL) 1391254a47ceSLohita Mudimela return false; 1392254a47ceSLohita Mudimela 1393254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1394254a47ceSLohita Mudimela 1395254a47ceSLohita Mudimela *varibright_level = core_power->varibright_prop.varibright_hw_level; 1396254a47ceSLohita Mudimela DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION, 1397254a47ceSLohita Mudimela WPP_BIT_FLAG_Backlight_ABM, 1398254a47ceSLohita Mudimela ">get varibright HW level: hw_level=%u", 1399254a47ceSLohita Mudimela *varibright_level); 1400254a47ceSLohita Mudimela return true; 1401254a47ceSLohita Mudimela } 1402254a47ceSLohita Mudimela 1403254a47ceSLohita Mudimela bool mod_power_get_varibright_default_level(struct mod_power *mod_power, 1404254a47ceSLohita Mudimela unsigned int *varibright_level) 1405254a47ceSLohita Mudimela { 1406254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1407254a47ceSLohita Mudimela 1408254a47ceSLohita Mudimela if (mod_power == NULL) 1409254a47ceSLohita Mudimela return false; 1410254a47ceSLohita Mudimela 1411254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1412254a47ceSLohita Mudimela 1413254a47ceSLohita Mudimela *varibright_level = core_power->varibright_prop.def_varibright_level; 1414254a47ceSLohita Mudimela DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION, 1415254a47ceSLohita Mudimela WPP_BIT_FLAG_Backlight_ABM, 1416254a47ceSLohita Mudimela ">get varibright default level: def_varibright_level=%u", 1417254a47ceSLohita Mudimela *varibright_level); 1418254a47ceSLohita Mudimela return true; 1419254a47ceSLohita Mudimela } 1420254a47ceSLohita Mudimela 1421254a47ceSLohita Mudimela bool mod_power_get_varibright_enable(struct mod_power *mod_power, 1422254a47ceSLohita Mudimela bool *varibright_enable) 1423254a47ceSLohita Mudimela { 1424254a47ceSLohita Mudimela struct core_power *core_power = NULL; 1425254a47ceSLohita Mudimela 1426254a47ceSLohita Mudimela if (mod_power == NULL) 1427254a47ceSLohita Mudimela return false; 1428254a47ceSLohita Mudimela 1429254a47ceSLohita Mudimela core_power = MOD_POWER_TO_CORE(mod_power); 1430254a47ceSLohita Mudimela 1431254a47ceSLohita Mudimela *varibright_enable = core_power->varibright_prop.varibright_user_enable; 1432254a47ceSLohita Mudimela DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION, 1433254a47ceSLohita Mudimela WPP_BIT_FLAG_Backlight_ABM, 1434254a47ceSLohita Mudimela ">get varibright enable state: varibright_user_enable=%u", 1435254a47ceSLohita Mudimela (unsigned int) (*varibright_enable)); 1436254a47ceSLohita Mudimela return true; 1437254a47ceSLohita Mudimela } 1438254a47ceSLohita Mudimela 1439254a47ceSLohita Mudimela bool mod_power_is_abm_active(struct mod_power *mod_power, 1440254a47ceSLohita Mudimela const struct dc_link *link, 1441254a47ceSLohita Mudimela unsigned int inst) 1442254a47ceSLohita Mudimela { 1443254a47ceSLohita Mudimela unsigned int user_backlight = 0; 1444254a47ceSLohita Mudimela unsigned int current_backlight = 0; 1445254a47ceSLohita Mudimela bool is_active = false; 1446254a47ceSLohita Mudimela 1447254a47ceSLohita Mudimela if (mod_power == NULL) 1448254a47ceSLohita Mudimela return false; 1449254a47ceSLohita Mudimela 1450254a47ceSLohita Mudimela mod_power_get_backlight_pwm(mod_power, &user_backlight, inst); 1451254a47ceSLohita Mudimela mod_power_get_hw_backlight_pwm(mod_power, link, ¤t_backlight); 1452254a47ceSLohita Mudimela 1453254a47ceSLohita Mudimela if (user_backlight != current_backlight) 1454254a47ceSLohita Mudimela is_active = true; 1455254a47ceSLohita Mudimela else 1456254a47ceSLohita Mudimela is_active = false; 1457254a47ceSLohita Mudimela DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION, 1458254a47ceSLohita Mudimela WPP_BIT_FLAG_Backlight_ABM, 1459254a47ceSLohita Mudimela ">get ABM active state: is_active=%u (user_backlight_pwm=%u, current_backlight_pwm=%u)", 1460254a47ceSLohita Mudimela (unsigned int)is_active, 1461254a47ceSLohita Mudimela user_backlight, 1462254a47ceSLohita Mudimela current_backlight); 1463254a47ceSLohita Mudimela return is_active; 1464254a47ceSLohita Mudimela } 1465254a47ceSLohita Mudimela 1466254a47ceSLohita Mudimela static void fill_backlight_transform_table(struct dmcu_iram_parameters params, 1467254a47ceSLohita Mudimela struct iram_table_v_2 *table) 1468254a47ceSLohita Mudimela { 1469254a47ceSLohita Mudimela unsigned int i; 1470254a47ceSLohita Mudimela unsigned int num_entries = NUM_BL_CURVE_SEGS; 1471254a47ceSLohita Mudimela unsigned int lut_index; 1472254a47ceSLohita Mudimela 1473254a47ceSLohita Mudimela table->backlight_thresholds[0] = 0; 1474254a47ceSLohita Mudimela ASSERT(params.backlight_lut_array[0] <= 0xFFFF); 1475254a47ceSLohita Mudimela table->backlight_offsets[0] = (uint16_t)params.backlight_lut_array[0]; 1476254a47ceSLohita Mudimela table->backlight_thresholds[num_entries-1] = 0xFFFF; 1477254a47ceSLohita Mudimela ASSERT(params.backlight_lut_array[params.backlight_lut_array_size - 1] <= 0xFFFF); 1478254a47ceSLohita Mudimela table->backlight_offsets[num_entries-1] = 1479254a47ceSLohita Mudimela (uint16_t)params.backlight_lut_array[params.backlight_lut_array_size - 1]; 1480254a47ceSLohita Mudimela 1481254a47ceSLohita Mudimela /* Setup all brightness levels between 0% and 100% exclusive 1482254a47ceSLohita Mudimela * Fills brightness-to-backlight transform table. Backlight custom curve 1483254a47ceSLohita Mudimela * describes transform from brightness to backlight. It will be defined 1484254a47ceSLohita Mudimela * as set of thresholds and set of offsets, together, implying 1485254a47ceSLohita Mudimela * extrapolation of custom curve into 16 uniformly spanned linear 1486254a47ceSLohita Mudimela * segments. Each threshold/offset represented by 16 bit entry in 1487254a47ceSLohita Mudimela * format U4.10. 1488254a47ceSLohita Mudimela */ 1489254a47ceSLohita Mudimela for (i = 1; i+1 < num_entries; i++) { 1490254a47ceSLohita Mudimela lut_index = (params.backlight_lut_array_size - 1) * i / (num_entries - 1); 1491254a47ceSLohita Mudimela 1492254a47ceSLohita Mudimela ASSERT(lut_index < params.backlight_lut_array_size); 1493254a47ceSLohita Mudimela 1494254a47ceSLohita Mudimela unsigned int threshold_val = DIV_ROUNDUP((i * 65536), num_entries); 1495254a47ceSLohita Mudimela unsigned int offset_val = params.backlight_lut_array[lut_index]; 1496254a47ceSLohita Mudimela 1497254a47ceSLohita Mudimela ASSERT(threshold_val <= 0xFFFF); 1498254a47ceSLohita Mudimela ASSERT(offset_val <= 0xFFFF); 1499254a47ceSLohita Mudimela 1500254a47ceSLohita Mudimela table->backlight_thresholds[i] = cpu_to_be16((uint16_t)threshold_val); 1501254a47ceSLohita Mudimela table->backlight_offsets[i] = cpu_to_be16((uint16_t)offset_val); 1502254a47ceSLohita Mudimela } 1503254a47ceSLohita Mudimela } 1504254a47ceSLohita Mudimela 1505254a47ceSLohita Mudimela static void fill_backlight_transform_table_v_2_2(struct dmcu_iram_parameters params, 1506254a47ceSLohita Mudimela struct iram_table_v_2_2 *table, bool big_endian) 1507254a47ceSLohita Mudimela { 1508254a47ceSLohita Mudimela unsigned int i; 1509254a47ceSLohita Mudimela unsigned int num_entries = NUM_BL_CURVE_SEGS; 1510254a47ceSLohita Mudimela unsigned int lut_index; 1511254a47ceSLohita Mudimela 1512254a47ceSLohita Mudimela table->backlight_thresholds[0] = 0; 1513254a47ceSLohita Mudimela ASSERT(params.backlight_lut_array[0] <= 0xFFFF); 1514254a47ceSLohita Mudimela table->backlight_offsets[0] = (uint16_t)params.backlight_lut_array[0]; 1515254a47ceSLohita Mudimela table->backlight_thresholds[num_entries-1] = 0xFFFF; 1516254a47ceSLohita Mudimela ASSERT(params.backlight_lut_array[params.backlight_lut_array_size - 1] <= 0xFFFF); 1517254a47ceSLohita Mudimela table->backlight_offsets[num_entries-1] = 1518254a47ceSLohita Mudimela (uint16_t)params.backlight_lut_array[params.backlight_lut_array_size - 1]; 1519254a47ceSLohita Mudimela 1520254a47ceSLohita Mudimela /* Setup all brightness levels between 0% and 100% exclusive 1521254a47ceSLohita Mudimela * Fills brightness-to-backlight transform table. Backlight custom curve 1522254a47ceSLohita Mudimela * describes transform from brightness to backlight. It will be defined 1523254a47ceSLohita Mudimela * as set of thresholds and set of offsets, together, implying 1524254a47ceSLohita Mudimela * extrapolation of custom curve into 16 uniformly spanned linear 1525254a47ceSLohita Mudimela * segments. Each threshold/offset represented by 16 bit entry in 1526254a47ceSLohita Mudimela * format U4.10. 1527254a47ceSLohita Mudimela */ 1528254a47ceSLohita Mudimela for (i = 1; i+1 < num_entries; i++) { 1529254a47ceSLohita Mudimela lut_index = DIV_ROUNDUP((i * params.backlight_lut_array_size), num_entries); 1530254a47ceSLohita Mudimela ASSERT(lut_index < params.backlight_lut_array_size); 1531254a47ceSLohita Mudimela 1532254a47ceSLohita Mudimela unsigned int threshold_val = DIV_ROUNDUP((i * 65536), num_entries); 1533254a47ceSLohita Mudimela unsigned int offset_val = params.backlight_lut_array[lut_index]; 1534254a47ceSLohita Mudimela 1535254a47ceSLohita Mudimela ASSERT(threshold_val <= 0xFFFF); 1536254a47ceSLohita Mudimela ASSERT(offset_val <= 0xFFFF); 1537254a47ceSLohita Mudimela 1538254a47ceSLohita Mudimela table->backlight_thresholds[i] = (big_endian) ? 1539254a47ceSLohita Mudimela cpu_to_be16((uint16_t)threshold_val) : cpu_to_le16((uint16_t)threshold_val); 1540254a47ceSLohita Mudimela table->backlight_offsets[i] = (big_endian) ? 1541254a47ceSLohita Mudimela cpu_to_be16((uint16_t)offset_val) : cpu_to_le16((uint16_t)offset_val); 1542254a47ceSLohita Mudimela } 1543254a47ceSLohita Mudimela } 1544254a47ceSLohita Mudimela 1545254a47ceSLohita Mudimela static void fill_iram_v_2(struct iram_table_v_2 *ram_table, struct dmcu_iram_parameters params) 1546254a47ceSLohita Mudimela { 1547254a47ceSLohita Mudimela unsigned int set = params.set; 1548254a47ceSLohita Mudimela 1549254a47ceSLohita Mudimela ram_table->min_abm_backlight = 1550254a47ceSLohita Mudimela cpu_to_be16(params.min_abm_backlight); 1551254a47ceSLohita Mudimela ram_table->deviation_gain = 0xb3; 1552254a47ceSLohita Mudimela 1553254a47ceSLohita Mudimela ram_table->blRampReduction = 1554254a47ceSLohita Mudimela cpu_to_be16(params.backlight_ramping_reduction); 1555254a47ceSLohita Mudimela ram_table->blRampStart = 1556254a47ceSLohita Mudimela cpu_to_be16(params.backlight_ramping_start); 1557254a47ceSLohita Mudimela 1558254a47ceSLohita Mudimela ram_table->min_reduction[0][0] = min_reduction_table[abm_config[set][0]]; 1559254a47ceSLohita Mudimela ram_table->min_reduction[1][0] = min_reduction_table[abm_config[set][0]]; 1560254a47ceSLohita Mudimela ram_table->min_reduction[2][0] = min_reduction_table[abm_config[set][0]]; 1561254a47ceSLohita Mudimela ram_table->min_reduction[3][0] = min_reduction_table[abm_config[set][0]]; 1562254a47ceSLohita Mudimela ram_table->min_reduction[4][0] = min_reduction_table[abm_config[set][0]]; 1563254a47ceSLohita Mudimela ram_table->max_reduction[0][0] = max_reduction_table[abm_config[set][0]]; 1564254a47ceSLohita Mudimela ram_table->max_reduction[1][0] = max_reduction_table[abm_config[set][0]]; 1565254a47ceSLohita Mudimela ram_table->max_reduction[2][0] = max_reduction_table[abm_config[set][0]]; 1566254a47ceSLohita Mudimela ram_table->max_reduction[3][0] = max_reduction_table[abm_config[set][0]]; 1567254a47ceSLohita Mudimela ram_table->max_reduction[4][0] = max_reduction_table[abm_config[set][0]]; 1568254a47ceSLohita Mudimela 1569254a47ceSLohita Mudimela ram_table->min_reduction[0][1] = min_reduction_table[abm_config[set][1]]; 1570254a47ceSLohita Mudimela ram_table->min_reduction[1][1] = min_reduction_table[abm_config[set][1]]; 1571254a47ceSLohita Mudimela ram_table->min_reduction[2][1] = min_reduction_table[abm_config[set][1]]; 1572254a47ceSLohita Mudimela ram_table->min_reduction[3][1] = min_reduction_table[abm_config[set][1]]; 1573254a47ceSLohita Mudimela ram_table->min_reduction[4][1] = min_reduction_table[abm_config[set][1]]; 1574254a47ceSLohita Mudimela ram_table->max_reduction[0][1] = max_reduction_table[abm_config[set][1]]; 1575254a47ceSLohita Mudimela ram_table->max_reduction[1][1] = max_reduction_table[abm_config[set][1]]; 1576254a47ceSLohita Mudimela ram_table->max_reduction[2][1] = max_reduction_table[abm_config[set][1]]; 1577254a47ceSLohita Mudimela ram_table->max_reduction[3][1] = max_reduction_table[abm_config[set][1]]; 1578254a47ceSLohita Mudimela ram_table->max_reduction[4][1] = max_reduction_table[abm_config[set][1]]; 1579254a47ceSLohita Mudimela 1580254a47ceSLohita Mudimela ram_table->min_reduction[0][2] = min_reduction_table[abm_config[set][2]]; 1581254a47ceSLohita Mudimela ram_table->min_reduction[1][2] = min_reduction_table[abm_config[set][2]]; 1582254a47ceSLohita Mudimela ram_table->min_reduction[2][2] = min_reduction_table[abm_config[set][2]]; 1583254a47ceSLohita Mudimela ram_table->min_reduction[3][2] = min_reduction_table[abm_config[set][2]]; 1584254a47ceSLohita Mudimela ram_table->min_reduction[4][2] = min_reduction_table[abm_config[set][2]]; 1585254a47ceSLohita Mudimela ram_table->max_reduction[0][2] = max_reduction_table[abm_config[set][2]]; 1586254a47ceSLohita Mudimela ram_table->max_reduction[1][2] = max_reduction_table[abm_config[set][2]]; 1587254a47ceSLohita Mudimela ram_table->max_reduction[2][2] = max_reduction_table[abm_config[set][2]]; 1588254a47ceSLohita Mudimela ram_table->max_reduction[3][2] = max_reduction_table[abm_config[set][2]]; 1589254a47ceSLohita Mudimela ram_table->max_reduction[4][2] = max_reduction_table[abm_config[set][2]]; 1590254a47ceSLohita Mudimela 1591254a47ceSLohita Mudimela ram_table->min_reduction[0][3] = min_reduction_table[abm_config[set][3]]; 1592254a47ceSLohita Mudimela ram_table->min_reduction[1][3] = min_reduction_table[abm_config[set][3]]; 1593254a47ceSLohita Mudimela ram_table->min_reduction[2][3] = min_reduction_table[abm_config[set][3]]; 1594254a47ceSLohita Mudimela ram_table->min_reduction[3][3] = min_reduction_table[abm_config[set][3]]; 1595254a47ceSLohita Mudimela ram_table->min_reduction[4][3] = min_reduction_table[abm_config[set][3]]; 1596254a47ceSLohita Mudimela ram_table->max_reduction[0][3] = max_reduction_table[abm_config[set][3]]; 1597254a47ceSLohita Mudimela ram_table->max_reduction[1][3] = max_reduction_table[abm_config[set][3]]; 1598254a47ceSLohita Mudimela ram_table->max_reduction[2][3] = max_reduction_table[abm_config[set][3]]; 1599254a47ceSLohita Mudimela ram_table->max_reduction[3][3] = max_reduction_table[abm_config[set][3]]; 1600254a47ceSLohita Mudimela ram_table->max_reduction[4][3] = max_reduction_table[abm_config[set][3]]; 1601254a47ceSLohita Mudimela 1602254a47ceSLohita Mudimela ram_table->bright_pos_gain[0][0] = 0x20; 1603254a47ceSLohita Mudimela ram_table->bright_pos_gain[0][1] = 0x20; 1604254a47ceSLohita Mudimela ram_table->bright_pos_gain[0][2] = 0x20; 1605254a47ceSLohita Mudimela ram_table->bright_pos_gain[0][3] = 0x20; 1606254a47ceSLohita Mudimela ram_table->bright_pos_gain[1][0] = 0x20; 1607254a47ceSLohita Mudimela ram_table->bright_pos_gain[1][1] = 0x20; 1608254a47ceSLohita Mudimela ram_table->bright_pos_gain[1][2] = 0x20; 1609254a47ceSLohita Mudimela ram_table->bright_pos_gain[1][3] = 0x20; 1610254a47ceSLohita Mudimela ram_table->bright_pos_gain[2][0] = 0x20; 1611254a47ceSLohita Mudimela ram_table->bright_pos_gain[2][1] = 0x20; 1612254a47ceSLohita Mudimela ram_table->bright_pos_gain[2][2] = 0x20; 1613254a47ceSLohita Mudimela ram_table->bright_pos_gain[2][3] = 0x20; 1614254a47ceSLohita Mudimela ram_table->bright_pos_gain[3][0] = 0x20; 1615254a47ceSLohita Mudimela ram_table->bright_pos_gain[3][1] = 0x20; 1616254a47ceSLohita Mudimela ram_table->bright_pos_gain[3][2] = 0x20; 1617254a47ceSLohita Mudimela ram_table->bright_pos_gain[3][3] = 0x20; 1618254a47ceSLohita Mudimela ram_table->bright_pos_gain[4][0] = 0x20; 1619254a47ceSLohita Mudimela ram_table->bright_pos_gain[4][1] = 0x20; 1620254a47ceSLohita Mudimela ram_table->bright_pos_gain[4][2] = 0x20; 1621254a47ceSLohita Mudimela ram_table->bright_pos_gain[4][3] = 0x20; 1622254a47ceSLohita Mudimela ram_table->bright_neg_gain[0][0] = 0x00; 1623254a47ceSLohita Mudimela ram_table->bright_neg_gain[0][1] = 0x00; 1624254a47ceSLohita Mudimela ram_table->bright_neg_gain[0][2] = 0x00; 1625254a47ceSLohita Mudimela ram_table->bright_neg_gain[0][3] = 0x00; 1626254a47ceSLohita Mudimela ram_table->bright_neg_gain[1][0] = 0x00; 1627254a47ceSLohita Mudimela ram_table->bright_neg_gain[1][1] = 0x00; 1628254a47ceSLohita Mudimela ram_table->bright_neg_gain[1][2] = 0x00; 1629254a47ceSLohita Mudimela ram_table->bright_neg_gain[1][3] = 0x00; 1630254a47ceSLohita Mudimela ram_table->bright_neg_gain[2][0] = 0x00; 1631254a47ceSLohita Mudimela ram_table->bright_neg_gain[2][1] = 0x00; 1632254a47ceSLohita Mudimela ram_table->bright_neg_gain[2][2] = 0x00; 1633254a47ceSLohita Mudimela ram_table->bright_neg_gain[2][3] = 0x00; 1634254a47ceSLohita Mudimela ram_table->bright_neg_gain[3][0] = 0x00; 1635254a47ceSLohita Mudimela ram_table->bright_neg_gain[3][1] = 0x00; 1636254a47ceSLohita Mudimela ram_table->bright_neg_gain[3][2] = 0x00; 1637254a47ceSLohita Mudimela ram_table->bright_neg_gain[3][3] = 0x00; 1638254a47ceSLohita Mudimela ram_table->bright_neg_gain[4][0] = 0x00; 1639254a47ceSLohita Mudimela ram_table->bright_neg_gain[4][1] = 0x00; 1640254a47ceSLohita Mudimela ram_table->bright_neg_gain[4][2] = 0x00; 1641254a47ceSLohita Mudimela ram_table->bright_neg_gain[4][3] = 0x00; 1642254a47ceSLohita Mudimela ram_table->dark_pos_gain[0][0] = 0x00; 1643254a47ceSLohita Mudimela ram_table->dark_pos_gain[0][1] = 0x00; 1644254a47ceSLohita Mudimela ram_table->dark_pos_gain[0][2] = 0x00; 1645254a47ceSLohita Mudimela ram_table->dark_pos_gain[0][3] = 0x00; 1646254a47ceSLohita Mudimela ram_table->dark_pos_gain[1][0] = 0x00; 1647254a47ceSLohita Mudimela ram_table->dark_pos_gain[1][1] = 0x00; 1648254a47ceSLohita Mudimela ram_table->dark_pos_gain[1][2] = 0x00; 1649254a47ceSLohita Mudimela ram_table->dark_pos_gain[1][3] = 0x00; 1650254a47ceSLohita Mudimela ram_table->dark_pos_gain[2][0] = 0x00; 1651254a47ceSLohita Mudimela ram_table->dark_pos_gain[2][1] = 0x00; 1652254a47ceSLohita Mudimela ram_table->dark_pos_gain[2][2] = 0x00; 1653254a47ceSLohita Mudimela ram_table->dark_pos_gain[2][3] = 0x00; 1654254a47ceSLohita Mudimela ram_table->dark_pos_gain[3][0] = 0x00; 1655254a47ceSLohita Mudimela ram_table->dark_pos_gain[3][1] = 0x00; 1656254a47ceSLohita Mudimela ram_table->dark_pos_gain[3][2] = 0x00; 1657254a47ceSLohita Mudimela ram_table->dark_pos_gain[3][3] = 0x00; 1658254a47ceSLohita Mudimela ram_table->dark_pos_gain[4][0] = 0x00; 1659254a47ceSLohita Mudimela ram_table->dark_pos_gain[4][1] = 0x00; 1660254a47ceSLohita Mudimela ram_table->dark_pos_gain[4][2] = 0x00; 1661254a47ceSLohita Mudimela ram_table->dark_pos_gain[4][3] = 0x00; 1662254a47ceSLohita Mudimela ram_table->dark_neg_gain[0][0] = 0x00; 1663254a47ceSLohita Mudimela ram_table->dark_neg_gain[0][1] = 0x00; 1664254a47ceSLohita Mudimela ram_table->dark_neg_gain[0][2] = 0x00; 1665254a47ceSLohita Mudimela ram_table->dark_neg_gain[0][3] = 0x00; 1666254a47ceSLohita Mudimela ram_table->dark_neg_gain[1][0] = 0x00; 1667254a47ceSLohita Mudimela ram_table->dark_neg_gain[1][1] = 0x00; 1668254a47ceSLohita Mudimela ram_table->dark_neg_gain[1][2] = 0x00; 1669254a47ceSLohita Mudimela ram_table->dark_neg_gain[1][3] = 0x00; 1670254a47ceSLohita Mudimela ram_table->dark_neg_gain[2][0] = 0x00; 1671254a47ceSLohita Mudimela ram_table->dark_neg_gain[2][1] = 0x00; 1672254a47ceSLohita Mudimela ram_table->dark_neg_gain[2][2] = 0x00; 1673254a47ceSLohita Mudimela ram_table->dark_neg_gain[2][3] = 0x00; 1674254a47ceSLohita Mudimela ram_table->dark_neg_gain[3][0] = 0x00; 1675254a47ceSLohita Mudimela ram_table->dark_neg_gain[3][1] = 0x00; 1676254a47ceSLohita Mudimela ram_table->dark_neg_gain[3][2] = 0x00; 1677254a47ceSLohita Mudimela ram_table->dark_neg_gain[3][3] = 0x00; 1678254a47ceSLohita Mudimela ram_table->dark_neg_gain[4][0] = 0x00; 1679254a47ceSLohita Mudimela ram_table->dark_neg_gain[4][1] = 0x00; 1680254a47ceSLohita Mudimela ram_table->dark_neg_gain[4][2] = 0x00; 1681254a47ceSLohita Mudimela ram_table->dark_neg_gain[4][3] = 0x00; 1682254a47ceSLohita Mudimela 1683254a47ceSLohita Mudimela ram_table->iir_curve[0] = 0x65; 1684254a47ceSLohita Mudimela ram_table->iir_curve[1] = 0x65; 1685254a47ceSLohita Mudimela ram_table->iir_curve[2] = 0x65; 1686254a47ceSLohita Mudimela ram_table->iir_curve[3] = 0x65; 1687254a47ceSLohita Mudimela ram_table->iir_curve[4] = 0x65; 1688254a47ceSLohita Mudimela 1689254a47ceSLohita Mudimela //Gamma 2.4 1690254a47ceSLohita Mudimela ram_table->crgb_thresh[0] = cpu_to_be16(0x13b6); 1691254a47ceSLohita Mudimela ram_table->crgb_thresh[1] = cpu_to_be16(0x1648); 1692254a47ceSLohita Mudimela ram_table->crgb_thresh[2] = cpu_to_be16(0x18e3); 1693254a47ceSLohita Mudimela ram_table->crgb_thresh[3] = cpu_to_be16(0x1b41); 1694254a47ceSLohita Mudimela ram_table->crgb_thresh[4] = cpu_to_be16(0x1d46); 1695254a47ceSLohita Mudimela ram_table->crgb_thresh[5] = cpu_to_be16(0x1f21); 1696254a47ceSLohita Mudimela ram_table->crgb_thresh[6] = cpu_to_be16(0x2167); 1697254a47ceSLohita Mudimela ram_table->crgb_thresh[7] = cpu_to_be16(0x2384); 1698254a47ceSLohita Mudimela ram_table->crgb_offset[0] = cpu_to_be16(0x2999); 1699254a47ceSLohita Mudimela ram_table->crgb_offset[1] = cpu_to_be16(0x3999); 1700254a47ceSLohita Mudimela ram_table->crgb_offset[2] = cpu_to_be16(0x4666); 1701254a47ceSLohita Mudimela ram_table->crgb_offset[3] = cpu_to_be16(0x5999); 1702254a47ceSLohita Mudimela ram_table->crgb_offset[4] = cpu_to_be16(0x6333); 1703254a47ceSLohita Mudimela ram_table->crgb_offset[5] = cpu_to_be16(0x7800); 1704254a47ceSLohita Mudimela ram_table->crgb_offset[6] = cpu_to_be16(0x8c00); 1705254a47ceSLohita Mudimela ram_table->crgb_offset[7] = cpu_to_be16(0xa000); 1706254a47ceSLohita Mudimela ram_table->crgb_slope[0] = cpu_to_be16(0x3147); 1707254a47ceSLohita Mudimela ram_table->crgb_slope[1] = cpu_to_be16(0x2978); 1708254a47ceSLohita Mudimela ram_table->crgb_slope[2] = cpu_to_be16(0x23a2); 1709254a47ceSLohita Mudimela ram_table->crgb_slope[3] = cpu_to_be16(0x1f55); 1710254a47ceSLohita Mudimela ram_table->crgb_slope[4] = cpu_to_be16(0x1c63); 1711254a47ceSLohita Mudimela ram_table->crgb_slope[5] = cpu_to_be16(0x1a0f); 1712254a47ceSLohita Mudimela ram_table->crgb_slope[6] = cpu_to_be16(0x178d); 1713254a47ceSLohita Mudimela ram_table->crgb_slope[7] = cpu_to_be16(0x15ab); 1714254a47ceSLohita Mudimela 1715254a47ceSLohita Mudimela fill_backlight_transform_table( 1716254a47ceSLohita Mudimela params, ram_table); 1717254a47ceSLohita Mudimela } 1718254a47ceSLohita Mudimela 1719254a47ceSLohita Mudimela static void fill_iram_v_2_2(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parameters params) 1720254a47ceSLohita Mudimela { 1721254a47ceSLohita Mudimela unsigned int set = params.set; 1722254a47ceSLohita Mudimela 1723254a47ceSLohita Mudimela ram_table->flags = 0x0; 1724254a47ceSLohita Mudimela 1725254a47ceSLohita Mudimela ram_table->min_abm_backlight = 1726254a47ceSLohita Mudimela cpu_to_be16(params.min_abm_backlight); 1727254a47ceSLohita Mudimela 1728254a47ceSLohita Mudimela ram_table->deviation_gain[0] = 0xb3; 1729254a47ceSLohita Mudimela ram_table->deviation_gain[1] = 0xa8; 1730254a47ceSLohita Mudimela ram_table->deviation_gain[2] = 0x98; 1731254a47ceSLohita Mudimela ram_table->deviation_gain[3] = 0x68; 1732254a47ceSLohita Mudimela 1733254a47ceSLohita Mudimela ram_table->min_reduction[0][0] = min_reduction_table_v_2_2[abm_config[set][0]]; 1734254a47ceSLohita Mudimela ram_table->min_reduction[1][0] = min_reduction_table_v_2_2[abm_config[set][0]]; 1735254a47ceSLohita Mudimela ram_table->min_reduction[2][0] = min_reduction_table_v_2_2[abm_config[set][0]]; 1736254a47ceSLohita Mudimela ram_table->min_reduction[3][0] = min_reduction_table_v_2_2[abm_config[set][0]]; 1737254a47ceSLohita Mudimela ram_table->min_reduction[4][0] = min_reduction_table_v_2_2[abm_config[set][0]]; 1738254a47ceSLohita Mudimela ram_table->max_reduction[0][0] = max_reduction_table_v_2_2[abm_config[set][0]]; 1739254a47ceSLohita Mudimela ram_table->max_reduction[1][0] = max_reduction_table_v_2_2[abm_config[set][0]]; 1740254a47ceSLohita Mudimela ram_table->max_reduction[2][0] = max_reduction_table_v_2_2[abm_config[set][0]]; 1741254a47ceSLohita Mudimela ram_table->max_reduction[3][0] = max_reduction_table_v_2_2[abm_config[set][0]]; 1742254a47ceSLohita Mudimela ram_table->max_reduction[4][0] = max_reduction_table_v_2_2[abm_config[set][0]]; 1743254a47ceSLohita Mudimela 1744254a47ceSLohita Mudimela ram_table->min_reduction[0][1] = min_reduction_table_v_2_2[abm_config[set][1]]; 1745254a47ceSLohita Mudimela ram_table->min_reduction[1][1] = min_reduction_table_v_2_2[abm_config[set][1]]; 1746254a47ceSLohita Mudimela ram_table->min_reduction[2][1] = min_reduction_table_v_2_2[abm_config[set][1]]; 1747254a47ceSLohita Mudimela ram_table->min_reduction[3][1] = min_reduction_table_v_2_2[abm_config[set][1]]; 1748254a47ceSLohita Mudimela ram_table->min_reduction[4][1] = min_reduction_table_v_2_2[abm_config[set][1]]; 1749254a47ceSLohita Mudimela ram_table->max_reduction[0][1] = max_reduction_table_v_2_2[abm_config[set][1]]; 1750254a47ceSLohita Mudimela ram_table->max_reduction[1][1] = max_reduction_table_v_2_2[abm_config[set][1]]; 1751254a47ceSLohita Mudimela ram_table->max_reduction[2][1] = max_reduction_table_v_2_2[abm_config[set][1]]; 1752254a47ceSLohita Mudimela ram_table->max_reduction[3][1] = max_reduction_table_v_2_2[abm_config[set][1]]; 1753254a47ceSLohita Mudimela ram_table->max_reduction[4][1] = max_reduction_table_v_2_2[abm_config[set][1]]; 1754254a47ceSLohita Mudimela 1755254a47ceSLohita Mudimela ram_table->min_reduction[0][2] = min_reduction_table_v_2_2[abm_config[set][2]]; 1756254a47ceSLohita Mudimela ram_table->min_reduction[1][2] = min_reduction_table_v_2_2[abm_config[set][2]]; 1757254a47ceSLohita Mudimela ram_table->min_reduction[2][2] = min_reduction_table_v_2_2[abm_config[set][2]]; 1758254a47ceSLohita Mudimela ram_table->min_reduction[3][2] = min_reduction_table_v_2_2[abm_config[set][2]]; 1759254a47ceSLohita Mudimela ram_table->min_reduction[4][2] = min_reduction_table_v_2_2[abm_config[set][2]]; 1760254a47ceSLohita Mudimela ram_table->max_reduction[0][2] = max_reduction_table_v_2_2[abm_config[set][2]]; 1761254a47ceSLohita Mudimela ram_table->max_reduction[1][2] = max_reduction_table_v_2_2[abm_config[set][2]]; 1762254a47ceSLohita Mudimela ram_table->max_reduction[2][2] = max_reduction_table_v_2_2[abm_config[set][2]]; 1763254a47ceSLohita Mudimela ram_table->max_reduction[3][2] = max_reduction_table_v_2_2[abm_config[set][2]]; 1764254a47ceSLohita Mudimela ram_table->max_reduction[4][2] = max_reduction_table_v_2_2[abm_config[set][2]]; 1765254a47ceSLohita Mudimela 1766254a47ceSLohita Mudimela ram_table->min_reduction[0][3] = min_reduction_table_v_2_2[abm_config[set][3]]; 1767254a47ceSLohita Mudimela ram_table->min_reduction[1][3] = min_reduction_table_v_2_2[abm_config[set][3]]; 1768254a47ceSLohita Mudimela ram_table->min_reduction[2][3] = min_reduction_table_v_2_2[abm_config[set][3]]; 1769254a47ceSLohita Mudimela ram_table->min_reduction[3][3] = min_reduction_table_v_2_2[abm_config[set][3]]; 1770254a47ceSLohita Mudimela ram_table->min_reduction[4][3] = min_reduction_table_v_2_2[abm_config[set][3]]; 1771254a47ceSLohita Mudimela ram_table->max_reduction[0][3] = max_reduction_table_v_2_2[abm_config[set][3]]; 1772254a47ceSLohita Mudimela ram_table->max_reduction[1][3] = max_reduction_table_v_2_2[abm_config[set][3]]; 1773254a47ceSLohita Mudimela ram_table->max_reduction[2][3] = max_reduction_table_v_2_2[abm_config[set][3]]; 1774254a47ceSLohita Mudimela ram_table->max_reduction[3][3] = max_reduction_table_v_2_2[abm_config[set][3]]; 1775254a47ceSLohita Mudimela ram_table->max_reduction[4][3] = max_reduction_table_v_2_2[abm_config[set][3]]; 1776254a47ceSLohita Mudimela 1777254a47ceSLohita Mudimela ram_table->bright_pos_gain[0][0] = 0x20; 1778254a47ceSLohita Mudimela ram_table->bright_pos_gain[0][1] = 0x20; 1779254a47ceSLohita Mudimela ram_table->bright_pos_gain[0][2] = 0x20; 1780254a47ceSLohita Mudimela ram_table->bright_pos_gain[0][3] = 0x20; 1781254a47ceSLohita Mudimela ram_table->bright_pos_gain[1][0] = 0x20; 1782254a47ceSLohita Mudimela ram_table->bright_pos_gain[1][1] = 0x20; 1783254a47ceSLohita Mudimela ram_table->bright_pos_gain[1][2] = 0x20; 1784254a47ceSLohita Mudimela ram_table->bright_pos_gain[1][3] = 0x20; 1785254a47ceSLohita Mudimela ram_table->bright_pos_gain[2][0] = 0x20; 1786254a47ceSLohita Mudimela ram_table->bright_pos_gain[2][1] = 0x20; 1787254a47ceSLohita Mudimela ram_table->bright_pos_gain[2][2] = 0x20; 1788254a47ceSLohita Mudimela ram_table->bright_pos_gain[2][3] = 0x20; 1789254a47ceSLohita Mudimela ram_table->bright_pos_gain[3][0] = 0x20; 1790254a47ceSLohita Mudimela ram_table->bright_pos_gain[3][1] = 0x20; 1791254a47ceSLohita Mudimela ram_table->bright_pos_gain[3][2] = 0x20; 1792254a47ceSLohita Mudimela ram_table->bright_pos_gain[3][3] = 0x20; 1793254a47ceSLohita Mudimela ram_table->bright_pos_gain[4][0] = 0x20; 1794254a47ceSLohita Mudimela ram_table->bright_pos_gain[4][1] = 0x20; 1795254a47ceSLohita Mudimela ram_table->bright_pos_gain[4][2] = 0x20; 1796254a47ceSLohita Mudimela ram_table->bright_pos_gain[4][3] = 0x20; 1797254a47ceSLohita Mudimela 1798254a47ceSLohita Mudimela ram_table->dark_pos_gain[0][0] = 0x00; 1799254a47ceSLohita Mudimela ram_table->dark_pos_gain[0][1] = 0x00; 1800254a47ceSLohita Mudimela ram_table->dark_pos_gain[0][2] = 0x00; 1801254a47ceSLohita Mudimela ram_table->dark_pos_gain[0][3] = 0x00; 1802254a47ceSLohita Mudimela ram_table->dark_pos_gain[1][0] = 0x00; 1803254a47ceSLohita Mudimela ram_table->dark_pos_gain[1][1] = 0x00; 1804254a47ceSLohita Mudimela ram_table->dark_pos_gain[1][2] = 0x00; 1805254a47ceSLohita Mudimela ram_table->dark_pos_gain[1][3] = 0x00; 1806254a47ceSLohita Mudimela ram_table->dark_pos_gain[2][0] = 0x00; 1807254a47ceSLohita Mudimela ram_table->dark_pos_gain[2][1] = 0x00; 1808254a47ceSLohita Mudimela ram_table->dark_pos_gain[2][2] = 0x00; 1809254a47ceSLohita Mudimela ram_table->dark_pos_gain[2][3] = 0x00; 1810254a47ceSLohita Mudimela ram_table->dark_pos_gain[3][0] = 0x00; 1811254a47ceSLohita Mudimela ram_table->dark_pos_gain[3][1] = 0x00; 1812254a47ceSLohita Mudimela ram_table->dark_pos_gain[3][2] = 0x00; 1813254a47ceSLohita Mudimela ram_table->dark_pos_gain[3][3] = 0x00; 1814254a47ceSLohita Mudimela ram_table->dark_pos_gain[4][0] = 0x00; 1815254a47ceSLohita Mudimela ram_table->dark_pos_gain[4][1] = 0x00; 1816254a47ceSLohita Mudimela ram_table->dark_pos_gain[4][2] = 0x00; 1817254a47ceSLohita Mudimela ram_table->dark_pos_gain[4][3] = 0x00; 1818254a47ceSLohita Mudimela 1819254a47ceSLohita Mudimela ram_table->hybrid_factor[0] = 0xff; 1820254a47ceSLohita Mudimela ram_table->hybrid_factor[1] = 0xff; 1821254a47ceSLohita Mudimela ram_table->hybrid_factor[2] = 0xff; 1822254a47ceSLohita Mudimela ram_table->hybrid_factor[3] = 0xc0; 1823254a47ceSLohita Mudimela 1824254a47ceSLohita Mudimela ram_table->contrast_factor[0] = 0x99; 1825254a47ceSLohita Mudimela ram_table->contrast_factor[1] = 0x99; 1826254a47ceSLohita Mudimela ram_table->contrast_factor[2] = 0x90; 1827254a47ceSLohita Mudimela ram_table->contrast_factor[3] = 0x80; 1828254a47ceSLohita Mudimela 1829254a47ceSLohita Mudimela ram_table->iir_curve[0] = 0x65; 1830254a47ceSLohita Mudimela ram_table->iir_curve[1] = 0x65; 1831254a47ceSLohita Mudimela ram_table->iir_curve[2] = 0x65; 1832254a47ceSLohita Mudimela ram_table->iir_curve[3] = 0x65; 1833254a47ceSLohita Mudimela ram_table->iir_curve[4] = 0x65; 1834254a47ceSLohita Mudimela 1835254a47ceSLohita Mudimela //Gamma 2.2 1836254a47ceSLohita Mudimela ram_table->crgb_thresh[0] = cpu_to_be16(0x127c); 1837254a47ceSLohita Mudimela ram_table->crgb_thresh[1] = cpu_to_be16(0x151b); 1838254a47ceSLohita Mudimela ram_table->crgb_thresh[2] = cpu_to_be16(0x17d5); 1839254a47ceSLohita Mudimela ram_table->crgb_thresh[3] = cpu_to_be16(0x1a56); 1840254a47ceSLohita Mudimela ram_table->crgb_thresh[4] = cpu_to_be16(0x1c83); 1841254a47ceSLohita Mudimela ram_table->crgb_thresh[5] = cpu_to_be16(0x1e72); 1842254a47ceSLohita Mudimela ram_table->crgb_thresh[6] = cpu_to_be16(0x20f0); 1843254a47ceSLohita Mudimela ram_table->crgb_thresh[7] = cpu_to_be16(0x232b); 1844254a47ceSLohita Mudimela ram_table->crgb_offset[0] = cpu_to_be16(0x2999); 1845254a47ceSLohita Mudimela ram_table->crgb_offset[1] = cpu_to_be16(0x3999); 1846254a47ceSLohita Mudimela ram_table->crgb_offset[2] = cpu_to_be16(0x4666); 1847254a47ceSLohita Mudimela ram_table->crgb_offset[3] = cpu_to_be16(0x5999); 1848254a47ceSLohita Mudimela ram_table->crgb_offset[4] = cpu_to_be16(0x6333); 1849254a47ceSLohita Mudimela ram_table->crgb_offset[5] = cpu_to_be16(0x7800); 1850254a47ceSLohita Mudimela ram_table->crgb_offset[6] = cpu_to_be16(0x8c00); 1851254a47ceSLohita Mudimela ram_table->crgb_offset[7] = cpu_to_be16(0xa000); 1852254a47ceSLohita Mudimela ram_table->crgb_slope[0] = cpu_to_be16(0x3609); 1853254a47ceSLohita Mudimela ram_table->crgb_slope[1] = cpu_to_be16(0x2dfa); 1854254a47ceSLohita Mudimela ram_table->crgb_slope[2] = cpu_to_be16(0x27ea); 1855254a47ceSLohita Mudimela ram_table->crgb_slope[3] = cpu_to_be16(0x235d); 1856254a47ceSLohita Mudimela ram_table->crgb_slope[4] = cpu_to_be16(0x2042); 1857254a47ceSLohita Mudimela ram_table->crgb_slope[5] = cpu_to_be16(0x1dc3); 1858254a47ceSLohita Mudimela ram_table->crgb_slope[6] = cpu_to_be16(0x1b1a); 1859254a47ceSLohita Mudimela ram_table->crgb_slope[7] = cpu_to_be16(0x1910); 1860254a47ceSLohita Mudimela 1861254a47ceSLohita Mudimela fill_backlight_transform_table_v_2_2( 1862254a47ceSLohita Mudimela params, ram_table, true); 1863254a47ceSLohita Mudimela } 1864254a47ceSLohita Mudimela 1865254a47ceSLohita Mudimela static void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parameters params, bool big_endian) 1866254a47ceSLohita Mudimela { 1867254a47ceSLohita Mudimela unsigned int i, j; 1868254a47ceSLohita Mudimela unsigned int set = params.set; 1869254a47ceSLohita Mudimela 1870254a47ceSLohita Mudimela ram_table->flags = 0x0; 1871254a47ceSLohita Mudimela ram_table->min_abm_backlight = (uint16_t)((big_endian) ? 1872254a47ceSLohita Mudimela cpu_to_be16(params.min_abm_backlight) : 1873254a47ceSLohita Mudimela cpu_to_le16(params.min_abm_backlight)); 1874254a47ceSLohita Mudimela 1875254a47ceSLohita Mudimela for (i = 0; i < NUM_AGGR_LEVEL; i++) { 1876254a47ceSLohita Mudimela ram_table->hybrid_factor[i] = (uint8_t)abm_settings[set][i].brightness_gain; 1877254a47ceSLohita Mudimela ram_table->contrast_factor[i] = abm_settings[set][i].contrast_factor; 1878254a47ceSLohita Mudimela ram_table->deviation_gain[i] = abm_settings[set][i].deviation_gain; 1879254a47ceSLohita Mudimela ram_table->min_knee[i] = abm_settings[set][i].min_knee; 1880254a47ceSLohita Mudimela ram_table->max_knee[i] = abm_settings[set][i].max_knee; 1881254a47ceSLohita Mudimela 1882254a47ceSLohita Mudimela for (j = 0; j < NUM_AMBI_LEVEL; j++) { 1883254a47ceSLohita Mudimela ram_table->min_reduction[j][i] = abm_settings[set][i].min_reduction; 1884254a47ceSLohita Mudimela ram_table->max_reduction[j][i] = abm_settings[set][i].max_reduction; 1885254a47ceSLohita Mudimela ram_table->bright_pos_gain[j][i] = abm_settings[set][i].bright_pos_gain; 1886254a47ceSLohita Mudimela ram_table->dark_pos_gain[j][i] = abm_settings[set][i].dark_pos_gain; 1887254a47ceSLohita Mudimela } 1888254a47ceSLohita Mudimela } 1889254a47ceSLohita Mudimela 1890254a47ceSLohita Mudimela ram_table->iir_curve[0] = 0x65; 1891254a47ceSLohita Mudimela ram_table->iir_curve[1] = 0x65; 1892254a47ceSLohita Mudimela ram_table->iir_curve[2] = 0x65; 1893254a47ceSLohita Mudimela ram_table->iir_curve[3] = 0x65; 1894254a47ceSLohita Mudimela ram_table->iir_curve[4] = 0x65; 1895254a47ceSLohita Mudimela 1896254a47ceSLohita Mudimela //Gamma 2.2 1897254a47ceSLohita Mudimela ram_table->crgb_thresh[0] = bswap16_based_on_endian(big_endian, 0x127c); 1898254a47ceSLohita Mudimela ram_table->crgb_thresh[1] = bswap16_based_on_endian(big_endian, 0x151b); 1899254a47ceSLohita Mudimela ram_table->crgb_thresh[2] = bswap16_based_on_endian(big_endian, 0x17d5); 1900254a47ceSLohita Mudimela ram_table->crgb_thresh[3] = bswap16_based_on_endian(big_endian, 0x1a56); 1901254a47ceSLohita Mudimela ram_table->crgb_thresh[4] = bswap16_based_on_endian(big_endian, 0x1c83); 1902254a47ceSLohita Mudimela ram_table->crgb_thresh[5] = bswap16_based_on_endian(big_endian, 0x1e72); 1903254a47ceSLohita Mudimela ram_table->crgb_thresh[6] = bswap16_based_on_endian(big_endian, 0x20f0); 1904254a47ceSLohita Mudimela ram_table->crgb_thresh[7] = bswap16_based_on_endian(big_endian, 0x232b); 1905254a47ceSLohita Mudimela ram_table->crgb_offset[0] = bswap16_based_on_endian(big_endian, 0x2999); 1906254a47ceSLohita Mudimela ram_table->crgb_offset[1] = bswap16_based_on_endian(big_endian, 0x3999); 1907254a47ceSLohita Mudimela ram_table->crgb_offset[2] = bswap16_based_on_endian(big_endian, 0x4666); 1908254a47ceSLohita Mudimela ram_table->crgb_offset[3] = bswap16_based_on_endian(big_endian, 0x5999); 1909254a47ceSLohita Mudimela ram_table->crgb_offset[4] = bswap16_based_on_endian(big_endian, 0x6333); 1910254a47ceSLohita Mudimela ram_table->crgb_offset[5] = bswap16_based_on_endian(big_endian, 0x7800); 1911254a47ceSLohita Mudimela ram_table->crgb_offset[6] = bswap16_based_on_endian(big_endian, 0x8c00); 1912254a47ceSLohita Mudimela ram_table->crgb_offset[7] = bswap16_based_on_endian(big_endian, 0xa000); 1913254a47ceSLohita Mudimela ram_table->crgb_slope[0] = bswap16_based_on_endian(big_endian, 0x3609); 1914254a47ceSLohita Mudimela ram_table->crgb_slope[1] = bswap16_based_on_endian(big_endian, 0x2dfa); 1915254a47ceSLohita Mudimela ram_table->crgb_slope[2] = bswap16_based_on_endian(big_endian, 0x27ea); 1916254a47ceSLohita Mudimela ram_table->crgb_slope[3] = bswap16_based_on_endian(big_endian, 0x235d); 1917254a47ceSLohita Mudimela ram_table->crgb_slope[4] = bswap16_based_on_endian(big_endian, 0x2042); 1918254a47ceSLohita Mudimela ram_table->crgb_slope[5] = bswap16_based_on_endian(big_endian, 0x1dc3); 1919254a47ceSLohita Mudimela ram_table->crgb_slope[6] = bswap16_based_on_endian(big_endian, 0x1b1a); 1920254a47ceSLohita Mudimela ram_table->crgb_slope[7] = bswap16_based_on_endian(big_endian, 0x1910); 1921254a47ceSLohita Mudimela 1922254a47ceSLohita Mudimela fill_backlight_transform_table_v_2_2( 1923254a47ceSLohita Mudimela params, ram_table, big_endian); 1924254a47ceSLohita Mudimela } 1925254a47ceSLohita Mudimela 1926254a47ceSLohita Mudimela bool dmub_init_abm_config(struct resource_pool *res_pool, 1927254a47ceSLohita Mudimela struct dmcu_iram_parameters params, 1928254a47ceSLohita Mudimela unsigned int inst) 1929254a47ceSLohita Mudimela { 1930254a47ceSLohita Mudimela struct iram_table_v_2_2 ram_table; 1931254a47ceSLohita Mudimela struct abm_config_table config; 1932254a47ceSLohita Mudimela unsigned int set = params.set; 1933254a47ceSLohita Mudimela bool result = false; 1934254a47ceSLohita Mudimela uint32_t i, j = 0; 1935254a47ceSLohita Mudimela 1936254a47ceSLohita Mudimela if (res_pool->abm == NULL && res_pool->multiple_abms[inst] == NULL) 1937254a47ceSLohita Mudimela return false; 1938254a47ceSLohita Mudimela 1939254a47ceSLohita Mudimela memset(&ram_table, 0, sizeof(ram_table)); 1940254a47ceSLohita Mudimela memset(&config, 0, sizeof(config)); 1941254a47ceSLohita Mudimela 1942254a47ceSLohita Mudimela fill_iram_v_2_3(&ram_table, params, false); 1943254a47ceSLohita Mudimela 1944254a47ceSLohita Mudimela // We must copy to structure that is aligned to 32-bit 1945254a47ceSLohita Mudimela for (i = 0; i < NUM_POWER_FN_SEGS; i++) { 1946254a47ceSLohita Mudimela config.crgb_thresh[i] = ram_table.crgb_thresh[i]; 1947254a47ceSLohita Mudimela config.crgb_offset[i] = ram_table.crgb_offset[i]; 1948254a47ceSLohita Mudimela config.crgb_slope[i] = ram_table.crgb_slope[i]; 1949254a47ceSLohita Mudimela } 1950254a47ceSLohita Mudimela 1951254a47ceSLohita Mudimela for (i = 0; i < NUM_BL_CURVE_SEGS; i++) { 1952254a47ceSLohita Mudimela config.backlight_thresholds[i] = ram_table.backlight_thresholds[i]; 1953254a47ceSLohita Mudimela config.backlight_offsets[i] = ram_table.backlight_offsets[i]; 1954254a47ceSLohita Mudimela } 1955254a47ceSLohita Mudimela 1956254a47ceSLohita Mudimela for (i = 0; i < NUM_AMBI_LEVEL; i++) 1957254a47ceSLohita Mudimela config.iir_curve[i] = ram_table.iir_curve[i]; 1958254a47ceSLohita Mudimela 1959254a47ceSLohita Mudimela for (i = 0; i < NUM_AMBI_LEVEL; i++) { 1960254a47ceSLohita Mudimela for (j = 0; j < NUM_AGGR_LEVEL; j++) { 1961254a47ceSLohita Mudimela config.min_reduction[i][j] = ram_table.min_reduction[i][j]; 1962254a47ceSLohita Mudimela config.max_reduction[i][j] = ram_table.max_reduction[i][j]; 1963254a47ceSLohita Mudimela config.bright_pos_gain[i][j] = ram_table.bright_pos_gain[i][j]; 1964254a47ceSLohita Mudimela config.dark_pos_gain[i][j] = ram_table.dark_pos_gain[i][j]; 1965254a47ceSLohita Mudimela } 1966254a47ceSLohita Mudimela } 1967254a47ceSLohita Mudimela 1968254a47ceSLohita Mudimela for (i = 0; i < NUM_AGGR_LEVEL; i++) { 1969254a47ceSLohita Mudimela config.hybrid_factor[i] = ram_table.hybrid_factor[i]; 1970254a47ceSLohita Mudimela config.contrast_factor[i] = ram_table.contrast_factor[i]; 1971254a47ceSLohita Mudimela config.deviation_gain[i] = ram_table.deviation_gain[i]; 1972254a47ceSLohita Mudimela config.min_knee[i] = ram_table.min_knee[i]; 1973254a47ceSLohita Mudimela config.max_knee[i] = ram_table.max_knee[i]; 1974254a47ceSLohita Mudimela } 1975254a47ceSLohita Mudimela 1976254a47ceSLohita Mudimela if (params.backlight_ramping_override) { 1977254a47ceSLohita Mudimela 1978254a47ceSLohita Mudimela ASSERT(params.backlight_ramping_reduction <= 0xFFFF); 1979254a47ceSLohita Mudimela ASSERT(params.backlight_ramping_start <= 0xFFFF); 1980254a47ceSLohita Mudimela for (i = 0; i < NUM_AGGR_LEVEL; i++) { 1981254a47ceSLohita Mudimela config.blRampReduction[i] = (uint16_t)params.backlight_ramping_reduction; 1982254a47ceSLohita Mudimela config.blRampStart[i] = (uint16_t)params.backlight_ramping_start; 1983254a47ceSLohita Mudimela } 1984254a47ceSLohita Mudimela } else { 1985254a47ceSLohita Mudimela for (i = 0; i < NUM_AGGR_LEVEL; i++) { 1986254a47ceSLohita Mudimela config.blRampReduction[i] = abm_settings[set][i].blRampReduction; 1987254a47ceSLohita Mudimela config.blRampStart[i] = abm_settings[set][i].blRampStart; 1988254a47ceSLohita Mudimela } 1989254a47ceSLohita Mudimela } 1990254a47ceSLohita Mudimela 1991254a47ceSLohita Mudimela config.min_abm_backlight = ram_table.min_abm_backlight; 1992254a47ceSLohita Mudimela 1993254a47ceSLohita Mudimela if (res_pool->multiple_abms[inst]) { 1994254a47ceSLohita Mudimela result = res_pool->multiple_abms[inst]->funcs->init_abm_config( 1995254a47ceSLohita Mudimela res_pool->multiple_abms[inst], (char *)(&config), sizeof(struct abm_config_table), inst); 1996254a47ceSLohita Mudimela } else 1997254a47ceSLohita Mudimela result = res_pool->abm->funcs->init_abm_config( 1998254a47ceSLohita Mudimela res_pool->abm, (char *)(&config), sizeof(struct abm_config_table), 0); 1999254a47ceSLohita Mudimela 2000254a47ceSLohita Mudimela return result; 2001254a47ceSLohita Mudimela } 2002254a47ceSLohita Mudimela 2003254a47ceSLohita Mudimela bool dmcu_load_iram(struct dmcu *dmcu, 2004254a47ceSLohita Mudimela struct dmcu_iram_parameters params) 2005254a47ceSLohita Mudimela { 2006254a47ceSLohita Mudimela unsigned char ram_table[IRAM_SIZE]; 2007254a47ceSLohita Mudimela bool result = false; 2008254a47ceSLohita Mudimela 2009254a47ceSLohita Mudimela if (dmcu == NULL) 2010254a47ceSLohita Mudimela return false; 2011254a47ceSLohita Mudimela 2012254a47ceSLohita Mudimela if (dmcu && !dmcu->funcs->is_dmcu_initialized(dmcu)) 2013254a47ceSLohita Mudimela return true; 2014254a47ceSLohita Mudimela 2015254a47ceSLohita Mudimela memset(&ram_table, 0, sizeof(ram_table)); 2016254a47ceSLohita Mudimela 2017254a47ceSLohita Mudimela if (dmcu->dmcu_version.abm_version == 0x24) { 2018254a47ceSLohita Mudimela fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params, true); 2019254a47ceSLohita Mudimela result = dmcu->funcs->load_iram(dmcu, 0, (char *)(&ram_table), 2020254a47ceSLohita Mudimela IRAM_RESERVE_AREA_START_V2_2); 2021254a47ceSLohita Mudimela } else if (dmcu->dmcu_version.abm_version == 0x23) { 2022254a47ceSLohita Mudimela fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params, true); 2023254a47ceSLohita Mudimela 2024254a47ceSLohita Mudimela result = dmcu->funcs->load_iram( 2025254a47ceSLohita Mudimela dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2); 2026254a47ceSLohita Mudimela } else if (dmcu->dmcu_version.abm_version == 0x22) { 2027254a47ceSLohita Mudimela fill_iram_v_2_2((struct iram_table_v_2_2 *)ram_table, params); 2028254a47ceSLohita Mudimela 2029254a47ceSLohita Mudimela result = dmcu->funcs->load_iram( 2030254a47ceSLohita Mudimela dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2); 2031254a47ceSLohita Mudimela } else { 2032254a47ceSLohita Mudimela fill_iram_v_2((struct iram_table_v_2 *)ram_table, params); 2033254a47ceSLohita Mudimela 2034254a47ceSLohita Mudimela result = dmcu->funcs->load_iram( 2035254a47ceSLohita Mudimela dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2); 2036254a47ceSLohita Mudimela 2037254a47ceSLohita Mudimela if (result) 2038254a47ceSLohita Mudimela result = dmcu->funcs->load_iram( 2039254a47ceSLohita Mudimela dmcu, IRAM_RESERVE_AREA_END_V2 + 1, 2040254a47ceSLohita Mudimela (char *)(&ram_table) + IRAM_RESERVE_AREA_END_V2 + 1, 2041254a47ceSLohita Mudimela sizeof(ram_table) - IRAM_RESERVE_AREA_END_V2 - 1); 2042254a47ceSLohita Mudimela } 2043254a47ceSLohita Mudimela 2044254a47ceSLohita Mudimela return result; 2045254a47ceSLohita Mudimela } 2046254a47ceSLohita Mudimela 2047254a47ceSLohita Mudimela bool fill_custom_backlight_caps(unsigned int config_no, struct dm_acpi_atif_backlight_caps *caps) 2048254a47ceSLohita Mudimela { 2049254a47ceSLohita Mudimela unsigned int data_points_size; 2050254a47ceSLohita Mudimela uint64_t caps_size; 2051254a47ceSLohita Mudimela 2052254a47ceSLohita Mudimela if (config_no >= ARRAY_SIZE(custom_backlight_profiles)) 2053254a47ceSLohita Mudimela return false; 2054254a47ceSLohita Mudimela 2055254a47ceSLohita Mudimela data_points_size = custom_backlight_profiles[config_no].num_data_points 2056254a47ceSLohita Mudimela * sizeof(custom_backlight_profiles[config_no].data_points[0]); 2057254a47ceSLohita Mudimela 2058254a47ceSLohita Mudimela caps_size = sizeof(struct dm_acpi_atif_backlight_caps) - sizeof(caps->data_points) + data_points_size; 2059254a47ceSLohita Mudimela ASSERT(caps_size <= 0xFFFF); 2060254a47ceSLohita Mudimela caps->size = (uint16_t)caps_size; 2061254a47ceSLohita Mudimela caps->flags = 0; 2062254a47ceSLohita Mudimela caps->error_code = 0; 2063254a47ceSLohita Mudimela caps->ac_level_percentage = custom_backlight_profiles[config_no].ac_level_percentage; 2064254a47ceSLohita Mudimela caps->dc_level_percentage = custom_backlight_profiles[config_no].dc_level_percentage; 2065254a47ceSLohita Mudimela caps->min_input_signal = custom_backlight_profiles[config_no].min_input_signal; 2066254a47ceSLohita Mudimela caps->max_input_signal = custom_backlight_profiles[config_no].max_input_signal; 2067254a47ceSLohita Mudimela caps->num_data_points = (uint8_t)custom_backlight_profiles[config_no].num_data_points; 2068254a47ceSLohita Mudimela memcpy(caps->data_points, custom_backlight_profiles[config_no].data_points, data_points_size); 2069254a47ceSLohita Mudimela return true; 2070254a47ceSLohita Mudimela } 2071