xref: /linux/drivers/gpu/drm/amd/display/modules/power/power_abm.c (revision 254a47ce0c8a52ff78a60f92a13b56db69f69096)
1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2026 Advanced Micro Devices, Inc.
4 
5 #include "dm_services.h"
6 #include "dc.h"
7 #include "mod_power.h"
8 #include "core_types.h"
9 #include "dmcu.h"
10 #include "abm.h"
11 #include "power_helpers.h"
12 #include "dce/dmub_psr.h"
13 #include "dal_asic_id.h"
14 #include "link_service.h"
15 #include <linux/math.h>
16 
17 #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
18 #define DC_TRACE_LEVEL_MESSAGEP(...) /* do nothing */
19 
20 #define DIV_ROUNDUP(a, b) (((a)+((b)/2))/(b))
21 #define bswap16_based_on_endian(big_endian, value) \
22 	((big_endian) ? cpu_to_be16(value) : cpu_to_le16(value))
23 
24 /* Possible Min Reduction config from least aggressive to most aggressive
25  *  0    1     2     3     4     5     6     7     8     9     10    11   12
26  * 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 %
27  */
28 static const unsigned char min_reduction_table[13] = {
29 0xff, 0xfa, 0xf0, 0xf0, 0xd9, 0xcd, 0xc0, 0xb1, 0x99, 0x93, 0x80, 0x82, 0x66};
30 
31 /* Possible Max Reduction configs from least aggressive to most aggressive
32  *  0    1     2     3     4     5     6     7     8     9     10    11   12
33  * 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 %
34  */
35 static const unsigned char max_reduction_table[13] = {
36 0xf5, 0xe5, 0xd9, 0xcd, 0xb1, 0xa5, 0xa5, 0x80, 0x65, 0x4d, 0x4d, 0x4d, 0x32};
37 
38 /* Possible ABM 2.2 Min Reduction configs from least aggressive to most aggressive
39  *  0    1     2     3     4     5     6     7     8     9     10    11   12
40  * 100  100   100   100   100   100   100   100  100  92.2  83.1  75.3  75.3 %
41  */
42 static const unsigned char min_reduction_table_v_2_2[13] = {
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xd4, 0xc0, 0xc0};
44 
45 /* Possible ABM 2.2 Max Reduction configs from least aggressive to most aggressive
46  *  0    1     2     3     4     5     6     7     8     9     10    11   12
47  * 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 %
48  */
49 static const unsigned char max_reduction_table_v_2_2[13] = {
50 0xf5, 0xe5, 0xbf, 0xb1, 0xa5, 0x85, 0x7c, 0x65, 0x4d, 0x40, 0x32, 0x20, 0x20};
51 
52 /* Predefined ABM configuration sets. We may have different configuration sets
53  * in order to satisfy different power/quality requirements.
54  */
55 static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_level] = {
56 /*  ABM Level 1,    ABM Level 2,    ABM Level 3,    ABM Level 4 */
57 {       2,              5,              7,              8       },	/* Default - Medium aggressiveness */
58 {       2,              5,              8,              11      },	/* Alt #1  - Increased aggressiveness */
59 {       0,              2,              4,              8       },	/* Alt #2  - Minimal aggressiveness */
60 {       3,              6,              10,             12      },	/* Alt #3  - Super aggressiveness */
61 };
62 
63 struct abm_parameters {
64 	unsigned char min_reduction;
65 	unsigned char max_reduction;
66 	unsigned char bright_pos_gain;
67 	unsigned char dark_pos_gain;
68 	unsigned char brightness_gain;
69 	unsigned char contrast_factor;
70 	unsigned char deviation_gain;
71 	unsigned char min_knee;
72 	unsigned char max_knee;
73 	unsigned short blRampReduction;
74 	unsigned short blRampStart;
75 };
76 
77 static const struct abm_parameters abm_settings_config0[abm_defines_max_level] = {
78 //  min_red  max_red  bright_pos  dark_pos  bright_gain  contrast  dev   min_knee  max_knee  blRed    blStart
79 	{0xff,   0xbf,    0x20,       0x00,     0xff,        0x99,     0xb3, 0x40,     0xe0,     0xf777,  0xcccc},
80 	{0xde,   0x85,    0x20,       0x00,     0xe0,        0x90,     0xa8, 0x40,     0xc8,     0xf777,  0xcccc},
81 	{0xb0,   0x50,    0x20,       0x00,     0xc0,        0x88,     0x78, 0x70,     0xa0,     0xeeee,  0x9999},
82 	{0x82,   0x40,    0x20,       0x00,     0x00,        0xb8,     0xb3, 0x70,     0x70,     0xe333,  0xb333},
83 };
84 
85 static const struct abm_parameters abm_settings_config1[abm_defines_max_level] = {
86 //  min_red  max_red  bright_pos  dark_pos  bright_gain  contrast  dev   min_knee  max_knee  blRed  blStart
87 	{0xf0,   0xd9,    0x20,       0x00,     0x00,        0xff,     0xb3, 0x70,     0x70,     0xcccc,  0xcccc},
88 	{0xcd,   0xa5,    0x20,       0x00,     0x00,        0xff,     0xb3, 0x70,     0x70,     0xcccc,  0xcccc},
89 	{0x99,   0x65,    0x20,       0x00,     0x00,        0xff,     0xb3, 0x70,     0x70,     0xcccc,  0xcccc},
90 	{0x82,   0x4d,    0x20,       0x00,     0x00,        0xff,     0xb3, 0x70,     0x70,     0xcccc,  0xcccc},
91 };
92 
93 static const struct abm_parameters abm_settings_config2[abm_defines_max_level] = {
94 //  min_red  max_red  bright_pos  dark_pos  bright_gain  contrast  dev   min_knee  max_knee  blRed    blStart
95 	{0xf0,   0xbf,    0x20,       0x00,     0x88,        0x99,     0xb3, 0x40,     0xe0,    0x0000,  0xcccc},
96 	{0xd8,   0x85,    0x20,       0x00,     0x70,        0x90,     0xa8, 0x40,     0xc8,    0x0700,  0xb333},
97 	{0xb8,   0x58,    0x20,       0x00,     0x64,        0x88,     0x78, 0x70,     0xa0,    0x7000,  0x9999},
98 	{0x82,   0x40,    0x20,       0x00,     0x00,        0xb8,     0xb3, 0x70,     0x70,    0xc333,  0xb333},
99 };
100 
101 static const struct abm_parameters * const abm_settings[] = {
102 	abm_settings_config0,
103 	abm_settings_config1,
104 	abm_settings_config2,
105 };
106 
107 static const struct dm_bl_data_point custom_backlight_curve0[] = {
108 		{2, 14}, {4, 16}, {6, 18}, {8, 21}, {10, 23}, {12, 26}, {14, 29}, {16, 32}, {18, 35},
109 		{20, 38}, {22, 41}, {24, 44}, {26, 48}, {28, 52}, {30, 55}, {32, 59}, {34, 62},
110 		{36, 67}, {38, 71}, {40, 75}, {42, 80}, {44, 84}, {46, 88}, {48, 93}, {50, 98},
111 		{52, 103}, {54, 108}, {56, 113}, {58, 118}, {60, 123}, {62, 129}, {64, 135}, {66, 140},
112 		{68, 146}, {70, 152}, {72, 158}, {74, 164}, {76, 171}, {78, 177}, {80, 183}, {82, 190},
113 		{84, 197}, {86, 204}, {88, 211}, {90, 218}, {92, 225}, {94, 232}, {96, 240}, {98, 247}};
114 
115 struct custom_backlight_profile {
116 	uint8_t  ac_level_percentage;
117 	uint8_t  dc_level_percentage;
118 	uint8_t  min_input_signal;
119 	uint8_t  max_input_signal;
120 	uint8_t  num_data_points;
121 	const struct dm_bl_data_point *data_points;
122 };
123 
124 static const struct custom_backlight_profile custom_backlight_profiles[] = {
125 		{100, 32, 12, 255, ARRAY_SIZE(custom_backlight_curve0), custom_backlight_curve0},
126 };
127 
128 #define NUM_AMBI_LEVEL    5
129 #define NUM_AGGR_LEVEL    4
130 #define NUM_POWER_FN_SEGS 8
131 #define NUM_BL_CURVE_SEGS 16
132 #define IRAM_SIZE 256
133 
134 #define IRAM_RESERVE_AREA_START_V2 0xF0  // reserve 0xF0~0xF6 are write by DMCU only
135 #define IRAM_RESERVE_AREA_END_V2 0xF6  // reserve 0xF0~0xF6 are write by DMCU only
136 
137 #define IRAM_RESERVE_AREA_START_V2_2 0xF0  // reserve 0xF0~0xFF are write by DMCU only
138 #define IRAM_RESERVE_AREA_END_V2_2 0xFF  // reserve 0xF0~0xFF are write by DMCU only
139 
140 #pragma pack(push, 1)
141 /* NOTE: iRAM is 256B in size */
142 struct iram_table_v_2 {
143 	/* flags                      */
144 	uint16_t min_abm_backlight;					/* 0x00 U16  */
145 
146 	/* parameters for ABM2.0 algorithm */
147 	uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x02 U0.8 */
148 	uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x16 U0.8 */
149 	uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];	/* 0x2a U2.6 */
150 	uint8_t bright_neg_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];	/* 0x3e U2.6 */
151 	uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x52 U2.6 */
152 	uint8_t dark_neg_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x66 U2.6 */
153 	uint8_t iir_curve[NUM_AMBI_LEVEL];				/* 0x7a U0.8 */
154 	uint8_t deviation_gain;						/* 0x7f U0.8 */
155 
156 	/* parameters for crgb conversion */
157 	uint16_t crgb_thresh[NUM_POWER_FN_SEGS];			/* 0x80 U3.13 */
158 	uint16_t crgb_offset[NUM_POWER_FN_SEGS];			/* 0x90 U1.15 */
159 	uint16_t crgb_slope[NUM_POWER_FN_SEGS];				/* 0xa0 U4.12 */
160 
161 	/* parameters for custom curve */
162 	/* thresholds for brightness --> backlight */
163 	uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS];		/* 0xb0 U16.0 */
164 	/* offsets for brightness --> backlight */
165 	uint16_t backlight_offsets[NUM_BL_CURVE_SEGS];			/* 0xd0 U16.0 */
166 
167 	/* For reading PSR State directly from IRAM */
168 	uint8_t psr_state;						/* 0xf0       */
169 	uint8_t dmcu_mcp_interface_version;				/* 0xf1       */
170 	uint8_t dmcu_abm_feature_version;				/* 0xf2       */
171 	uint8_t dmcu_psr_feature_version;				/* 0xf3       */
172 	uint16_t dmcu_version;						/* 0xf4       */
173 	uint8_t dmcu_state;						/* 0xf6       */
174 
175 	uint16_t blRampReduction;					/* 0xf7       */
176 	uint16_t blRampStart;						/* 0xf9       */
177 	uint8_t dummy5;							/* 0xfb       */
178 	uint8_t dummy6;							/* 0xfc       */
179 	uint8_t dummy7;							/* 0xfd       */
180 	uint8_t dummy8;							/* 0xfe       */
181 	uint8_t dummy9;							/* 0xff       */
182 };
183 
184 struct iram_table_v_2_2 {
185 	/* flags                      */
186 	uint16_t flags;							/* 0x00 U16  */
187 
188 	/* parameters for ABM2.2 algorithm */
189 	uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x02 U0.8 */
190 	uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x16 U0.8 */
191 	uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];	/* 0x2a U2.6 */
192 	uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x3e U2.6 */
193 	uint8_t hybrid_factor[NUM_AGGR_LEVEL];				/* 0x52 U0.8 */
194 	uint8_t contrast_factor[NUM_AGGR_LEVEL];			/* 0x56 U0.8 */
195 	uint8_t deviation_gain[NUM_AGGR_LEVEL];				/* 0x5a U0.8 */
196 	uint8_t iir_curve[NUM_AMBI_LEVEL];				/* 0x5e U0.8 */
197 	uint8_t min_knee[NUM_AGGR_LEVEL];				/* 0x63 U0.8 */
198 	uint8_t max_knee[NUM_AGGR_LEVEL];				/* 0x67 U0.8 */
199 	uint16_t min_abm_backlight;					/* 0x6b U16  */
200 	uint8_t pad[19];						/* 0x6d U0.8 */
201 
202 	/* parameters for crgb conversion */
203 	uint16_t crgb_thresh[NUM_POWER_FN_SEGS];			/* 0x80 U3.13 */
204 	uint16_t crgb_offset[NUM_POWER_FN_SEGS];			/* 0x90 U1.15 */
205 	uint16_t crgb_slope[NUM_POWER_FN_SEGS];				/* 0xa0 U4.12 */
206 
207 	/* parameters for custom curve */
208 	/* thresholds for brightness --> backlight */
209 	uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS];		/* 0xb0 U16.0 */
210 	/* offsets for brightness --> backlight */
211 	uint16_t backlight_offsets[NUM_BL_CURVE_SEGS];			/* 0xd0 U16.0 */
212 
213 	/* For reading PSR State directly from IRAM */
214 	uint8_t psr_state;						/* 0xf0       */
215 	uint8_t dmcu_mcp_interface_version;				/* 0xf1       */
216 	uint8_t dmcu_abm_feature_version;				/* 0xf2       */
217 	uint8_t dmcu_psr_feature_version;				/* 0xf3       */
218 	uint16_t dmcu_version;						/* 0xf4       */
219 	uint8_t dmcu_state;						/* 0xf6       */
220 
221 	uint8_t dummy1;							/* 0xf7       */
222 	uint8_t dummy2;							/* 0xf8       */
223 	uint8_t dummy3;							/* 0xf9       */
224 	uint8_t dummy4;							/* 0xfa       */
225 	uint8_t dummy5;							/* 0xfb       */
226 	uint8_t dummy6;							/* 0xfc       */
227 	uint8_t dummy7;							/* 0xfd       */
228 	uint8_t dummy8;							/* 0xfe       */
229 	uint8_t dummy9;							/* 0xff       */
230 };
231 #pragma pack(pop)
232 
233 #define MOD_POWER_MAX_CONCURRENT_STREAMS 32
234 #define SMOOTH_BRIGHTNESS_ADJUSTMENT_TIME_IN_MS 500
235 
236 
237 
238 struct backlight_state {
239 	/* HW uses u16.16 format for backlight PWM */
240 	unsigned int backlight_pwm;
241 	/* DM may call power module to set backlight
242 	 * targeting percent brightness
243 	 */
244 	unsigned int backlight_millipercent;
245 	/* DM may call power module to set backlight based on an explicit
246 	 * nits value.
247 	 */
248 	unsigned int backlight_millinit;
249 	unsigned int frame_ramp;
250 	bool smooth_brightness_enabled;
251 	bool isHDR;
252 };
253 struct power_entity {
254 	struct dc_stream_state *stream;
255 	struct psr_caps *caps;
256 	struct mod_power_psr_context *psr_context;
257 
258 	/*PSR cached properties*/
259 	bool psr_enabled;
260 	unsigned int psr_events;
261 	unsigned int psr_power_opt;
262 	unsigned int replay_events;
263 };
264 
265 struct pwr_backlight_properties {
266 	bool use_nits_based_brightness;
267 	bool disable_fractional_pwm;
268 
269 	unsigned int min_abm_backlight;
270 	unsigned int num_backlight_levels;
271 
272 	bool backlight_ramping_override;
273 	unsigned int backlight_ramping_reduction;
274 	unsigned int backlight_ramping_start;
275 
276 	/* Backlight cached properties */
277 	unsigned int ac_backlight_percent;
278 	unsigned int dc_backlight_percent;
279 
280 	/* backlight LUT stored in HW u16.16 format*/
281 	unsigned int *backlight_lut;
282 	unsigned int min_backlight_pwm;
283 	unsigned int max_backlight_pwm;
284 	unsigned int backlight_range;
285 
286 	/* Describes the panel's min and max luminance in millinits measured
287 	 * on full white screen, in min and max backlight settings.
288 	 */
289 	unsigned int min_brightness_millinits;
290 	unsigned int max_brightness_millinits;
291 	unsigned int nits_range;
292 
293 	bool backlight_caps_valid;
294 	bool use_custom_backlight_caps;
295 	unsigned int custom_backlight_caps_config_no;
296 	bool use_linear_backlight_curve;
297 };
298 
299 struct dmcu_varibright_cached_properties {
300 	unsigned int varibright_config_setting;
301 	unsigned int varibright_level;
302 	unsigned int varibright_hw_level;
303 	unsigned int def_varibright_level;
304 	bool varibright_user_enable;
305 	bool varibright_active;
306 };
307 
308 struct core_power {
309 	struct mod_power mod_public;
310 	struct dc *dc;
311 	struct power_entity *map;
312 	struct dmcu_varibright_cached_properties varibright_prop;
313 	struct pwr_backlight_properties bl_prop[MAX_NUM_EDP];
314 	struct backlight_state bl_state[MAX_NUM_EDP];
315 	unsigned int edp_num;
316 
317 	bool psr_smu_optimizations_support;
318 	bool multi_disp_optimizations_support;
319 
320 	unsigned int num_entities;
321 };
322 
323 union dmcu_abm_set_bl_params {
324 	struct {
325 		unsigned int gradual_change : 1; /* [0:0] */
326 		unsigned int reserved : 15; /* [15:1] */
327 		unsigned int frame_ramp : 16; /* [31:16] */
328 	} bits;
329 	unsigned int u32All;
330 };
331 
332 /* If system or panel does not report some sort of brightness percent to nits
333  * mapping, we will use following default values so backlight control using
334  * nits based interfaces will still work, but might not describe panel
335  * correctly. In this case percentage based backlight control should ideally
336  * be used.
337  * Min = 5 nits
338  * Max = 300 nits
339  */
340 
341 #define MOD_POWER_TO_CORE(mod_power)\
342 		container_of(mod_power, struct core_power, mod_public)
343 
344 
345 
346 static uint16_t backlight_8_to_16(unsigned int backlight_8bit)
347 {
348 	return (uint16_t)(backlight_8bit * 0x101);
349 }
350 
351 unsigned int backlight_millipercent_to_millinit(
352 		struct core_power *core_power, unsigned int millipercent, unsigned int inst)
353 {
354 	unsigned int millinit = 0;
355 	unsigned long long numerator = 0;
356 
357 	if (core_power == NULL)
358 		return 0;
359 
360 	numerator = ((unsigned long long)millipercent) *
361 				core_power->bl_prop[inst].nits_range;
362 	millinit = ((unsigned int)div_u64(numerator, 100000)) +
363 			core_power->bl_prop[inst].min_brightness_millinits;
364 
365 	return millinit;
366 }
367 
368 static unsigned int backlight_millinit_to_millipercent(
369 		struct core_power *core_power, unsigned int millinit, unsigned int inst)
370 {
371 	unsigned int millipercent = 0;
372 	unsigned long long numerator = 0;
373 
374 	if (core_power == NULL)
375 		return 0;
376 
377 	if (millinit <= core_power->bl_prop[inst].min_brightness_millinits)
378 		return 0;
379 
380 	if (millinit >= core_power->bl_prop[inst].max_brightness_millinits)
381 		return (100 * 1000);
382 
383 	numerator = (((unsigned long long)millinit) -
384 			core_power->bl_prop[inst].min_brightness_millinits) * 100000;
385 	millipercent = ((unsigned int)div_u64(numerator,
386 				core_power->bl_prop[inst].nits_range));
387 
388 	return millipercent;
389 }
390 
391 static unsigned int backlight_pwm_to_millipercent(
392 		struct core_power *core_power, unsigned int pwm, unsigned int inst)
393 {
394 	unsigned int millipercent = 0;
395 	unsigned int max_index = 0;
396 
397 	if (core_power == NULL)
398 		return 0;
399 
400 	if (!core_power->bl_prop[inst].backlight_caps_valid)
401 		return 0;
402 
403 	/* Doesn't really make sense to have one single backlight level
404 	 * possible...
405 	 */
406 	if (core_power->bl_prop[inst].num_backlight_levels < 2)
407 		return 0;
408 
409 	max_index = core_power->bl_prop[inst].num_backlight_levels - 1;
410 
411 	if (pwm <= core_power->bl_prop[inst].backlight_lut[0])
412 		return 0;
413 
414 	if (pwm > core_power->bl_prop[inst].backlight_lut[max_index])
415 		return (100 * 1000);
416 
417 	/* We need to do a binary search over the array for where the pwm level
418 	 * is in the lut. Based on the index we can determine percentage.
419 	 */
420 	unsigned int min = 0;
421 	unsigned int max = max_index;
422 	unsigned int mid = 0;
423 
424 	while (max >= min) {
425 		mid = (min + max) / 2; /* floor of half range */
426 
427 		if (core_power->bl_prop[inst].backlight_lut[mid] < pwm)
428 			min = mid + 1;
429 		else if (core_power->bl_prop[inst].backlight_lut[mid] > pwm)
430 			max = mid - 1;
431 		else
432 			break;
433 	}
434 
435 	/* In this case, exact match is not found. Check if mid/min/max
436 	 * value is actually closer.
437 	 */
438 	if (max < min) {
439 		unsigned int min_delta;
440 		unsigned int mid_delta;
441 		unsigned int max_delta;
442 
443 		min_delta = (core_power->bl_prop[inst].backlight_lut[min] > pwm) ?
444 				core_power->bl_prop[inst].backlight_lut[min] - pwm :
445 				pwm - core_power->bl_prop[inst].backlight_lut[min];
446 
447 		mid_delta = (core_power->bl_prop[inst].backlight_lut[mid] > pwm) ?
448 				core_power->bl_prop[inst].backlight_lut[mid] - pwm :
449 				pwm - core_power->bl_prop[inst].backlight_lut[mid];
450 
451 		max_delta = (core_power->bl_prop[inst].backlight_lut[max] > pwm) ?
452 				core_power->bl_prop[inst].backlight_lut[max] - pwm :
453 				pwm - core_power->bl_prop[inst].backlight_lut[max];
454 
455 		if ((min_delta < mid_delta) && (min_delta < max_delta))
456 			mid = min;
457 
458 		if ((max_delta < mid_delta) && (max_delta < min_delta))
459 			mid = max;
460 	}
461 
462 	/* No interpolation, just take closest index */
463 	millipercent = 1000 * 100 * mid / max_index;
464 
465 	return millipercent;
466 }
467 
468 static unsigned int backlight_pwm_to_millinit(
469 		struct core_power *core_power, unsigned int pwm, unsigned int inst)
470 {
471 	unsigned int millinit = 0;
472 
473 	if (core_power == NULL)
474 		return 0;
475 
476 	if (pwm <= core_power->bl_prop[inst].min_backlight_pwm)
477 		return core_power->bl_prop[inst].min_brightness_millinits;
478 
479 	if (pwm >= core_power->bl_prop[inst].max_backlight_pwm)
480 		return core_power->bl_prop[inst].max_brightness_millinits;
481 
482 	millinit = ((unsigned int)div_u64(((unsigned long long)pwm -
483 				core_power->bl_prop[inst].min_backlight_pwm) *
484 				core_power->bl_prop[inst].nits_range,
485 				core_power->bl_prop[inst].backlight_range));
486 
487 	millinit += core_power->bl_prop[inst].min_brightness_millinits;
488 
489 	if (millinit > core_power->bl_prop[inst].max_brightness_millinits)
490 		millinit = core_power->bl_prop[inst].max_brightness_millinits;
491 
492 	return millinit;
493 }
494 
495 unsigned int backlight_millipercent_to_pwm(
496 		struct core_power *core_power, unsigned int millipercent, unsigned int inst)
497 {
498 	unsigned int pwm = (unsigned int)-1;
499 	unsigned int index = 0;
500 
501 	if (core_power == NULL)
502 		return 0;
503 
504 	// Bypass the brightness mapping LUT
505 	if (core_power->bl_prop->use_linear_backlight_curve) {
506 		pwm = core_power->bl_prop[inst].min_backlight_pwm +
507 			(unsigned int) div_u64((unsigned long long) millipercent *
508 			core_power->bl_prop[inst].backlight_range,
509 			100000);
510 
511 		if (pwm > core_power->bl_prop[inst].max_backlight_pwm)
512 			pwm = core_power->bl_prop[inst].max_backlight_pwm;
513 
514 		return pwm;
515 	}
516 
517 	if (millipercent >= (100 * 1000))
518 		return core_power->bl_prop[inst].backlight_lut[core_power->bl_prop[inst].num_backlight_levels - 1];
519 
520 	/* This will give the floor index. */
521 	index = ((core_power->bl_prop[inst].num_backlight_levels - 1) *
522 						millipercent) / 100000;
523 	/* Null check otherwise eDP doesn't lightup when connected to DP1 */
524 	if (core_power->bl_prop[inst].backlight_lut == NULL)
525 		return pwm;
526 
527 	pwm = core_power->bl_prop[inst].backlight_lut[index];
528 
529 	return pwm;
530 }
531 
532 static unsigned int backlight_millinit_to_pwm(
533 		struct core_power *core_power, unsigned int millinit, unsigned int inst)
534 {
535 	unsigned int pwm = 0;
536 
537 	if (core_power == NULL)
538 		return 0;
539 
540 	/* For nits based brightness, the signal will be a value
541 	 * between the minimum and maximum value.
542 	 */
543 	if (millinit >= core_power->bl_prop[inst].max_brightness_millinits)
544 		return core_power->bl_prop[inst].max_backlight_pwm;
545 	else if (millinit <= core_power->bl_prop[inst].min_brightness_millinits)
546 		return core_power->bl_prop[inst].min_backlight_pwm;
547 
548 	pwm = ((unsigned int)div_u64(((unsigned long long)millinit -
549 			core_power->bl_prop[inst].min_brightness_millinits) *
550 			core_power->bl_prop[inst].backlight_range,
551 			core_power->bl_prop[inst].nits_range));
552 
553 	pwm += core_power->bl_prop[inst].min_backlight_pwm;
554 
555 	if (pwm > core_power->bl_prop[inst].max_backlight_pwm)
556 		pwm = core_power->bl_prop[inst].max_backlight_pwm;
557 
558 	return pwm;
559 }
560 
561 static bool validate_ext_backlight_caps(
562 		struct dm_acpi_atif_backlight_caps *ext_backlight_caps)
563 {
564 	unsigned int i;
565 	unsigned int num_of_data_points = 0;
566 	unsigned int last_signal_level = 0;
567 	unsigned int last_luminance = 0;
568 
569 	num_of_data_points = ext_backlight_caps->num_data_points;
570 
571 	/* Validation rules:
572 	 * 1. BIOS should carry customized data points and
573 	 * the number of data points should not be larger than 99.
574 	 * 2. The max_input_signal should be larger than min_input_signal.
575 	 * 3. For each data point:
576 	 *	a. luminance should be in ascending order and
577 	 *	should not be 0 or 100 since the corresponding signal_level
578 	 *	are assigned by min_input_signal and max_input_signal.
579 	 *	b. signal_level should be in ascending order and
580 	 *	be within the range of min/max_input_signal.
581 	 */
582 	if (num_of_data_points > BL_DATA_POINTS)
583 		return false;
584 
585 	if (ext_backlight_caps->min_input_signal >= ext_backlight_caps->max_input_signal)
586 		return false;
587 
588 	last_signal_level = ext_backlight_caps->min_input_signal;
589 	for (i = 0; i < num_of_data_points; i++) {
590 		unsigned int luminance = ext_backlight_caps->data_points[i].luminance;
591 		unsigned int signal_level = ext_backlight_caps->data_points[i].signal_level;
592 
593 		if ((luminance <= last_luminance) || (luminance > BL_DATA_POINTS))
594 			return false;
595 
596 		if ((signal_level <= last_signal_level) || (signal_level >= ext_backlight_caps->max_input_signal))
597 			return false;
598 
599 		last_signal_level = signal_level;
600 		last_luminance = luminance;
601 	}
602 
603 	return true;
604 }
605 
606 /* hard coded to default backlight curve. */
607 void initialize_backlight_caps(struct core_power *core_power, unsigned int inst)
608 {
609 	unsigned int i;
610 	struct dm_acpi_atif_backlight_caps *ext_backlight_caps = NULL;
611 	bool custom_curve_present = false;
612 	unsigned int num_levels = 0;
613 	struct dc *dc = NULL;
614 	enum dm_acpi_display_type acpi_display_type =
615 		(inst == 0) ? AcpiDisplayType_LCD1 : AcpiDisplayType_LCD2;
616 
617 	if (core_power == NULL)
618 		return;
619 	dc = core_power->dc;
620 
621 	num_levels = core_power->bl_prop[inst].num_backlight_levels;
622 
623 	/* Allocate memory for ATIF output
624 	 * (do not want to use 256 bytes on the stack)
625 	 */
626 	ext_backlight_caps = (struct dm_acpi_atif_backlight_caps *)
627 		(kzalloc(sizeof(struct dm_acpi_atif_backlight_caps),
628 				GFP_KERNEL));
629 
630 	if (ext_backlight_caps == NULL)
631 		return;
632 
633 	/* Retrieve ACPI extended brightness caps */
634 	if (dm_query_extended_brightness_caps
635 		(dc->ctx, acpi_display_type, ext_backlight_caps)) {
636 		custom_curve_present = validate_ext_backlight_caps(ext_backlight_caps);
637 	}
638 
639 	if (core_power->bl_prop[inst].use_custom_backlight_caps &&
640 			fill_custom_backlight_caps(
641 					core_power->bl_prop[inst].custom_backlight_caps_config_no,
642 					ext_backlight_caps)) {
643 		custom_curve_present = validate_ext_backlight_caps(ext_backlight_caps);
644 	}
645 
646 	if (custom_curve_present) {
647 		unsigned int index = 1;
648 		unsigned int num_of_data_points = ext_backlight_caps->num_data_points;
649 
650 		core_power->bl_prop[inst].ac_backlight_percent =
651 			ext_backlight_caps->ac_level_percentage;
652 		core_power->bl_prop[inst].dc_backlight_percent =
653 			ext_backlight_caps->dc_level_percentage;
654 		core_power->bl_prop[inst].backlight_lut[0] =
655 			backlight_8_to_16(
656 				ext_backlight_caps->min_input_signal);
657 		core_power->bl_prop[inst].backlight_lut[num_levels - 1] =
658 			backlight_8_to_16(
659 				ext_backlight_caps->max_input_signal);
660 
661 		/* Filling translation table from data points -
662 		 * between every two provided data points we
663 		 * lineary interpolate missing values
664 		 */
665 		for (i = 0; i < num_of_data_points; i++) {
666 			unsigned int luminance =
667 				ext_backlight_caps->data_points[i].luminance;
668 			unsigned int signal_level =
669 				backlight_8_to_16(
670 					ext_backlight_caps->data_points[i].signal_level);
671 
672 			/* Since luminance is a percentage, scale it by num_levels*/
673 			luminance = (luminance * num_levels) / 101;
674 
675 			/* Lineary interpolate missing values */
676 			if (index < luminance) {
677 				unsigned int base_value =
678 					core_power->bl_prop[inst].backlight_lut[index-1];
679 				unsigned int delta_signal =
680 					signal_level - base_value;
681 				unsigned int delta_luma =
682 					luminance - index + 1;
683 				unsigned int step  = delta_signal;
684 
685 				for (; index < luminance; index++) {
686 					core_power->bl_prop[inst].backlight_lut[index] =
687 						base_value + (step / delta_luma);
688 					step += delta_signal;
689 				}
690 			}
691 
692 			/* Now [index == luminance],
693 			 * so we can add data point to the translation table
694 			 */
695 			core_power->bl_prop[inst].backlight_lut[index++] = signal_level;
696 		}
697 
698 		/* Complete the final segment of interpolation -
699 		 * between last datapoint and maximum value
700 		 */
701 		if (index < num_levels - 1) {
702 			unsigned int base_value =
703 				core_power->bl_prop[inst].backlight_lut[index-1];
704 			unsigned int delta_signal =
705 				core_power->bl_prop[inst].backlight_lut[num_levels - 1] -
706 								base_value;
707 			unsigned int delta_luma = num_levels - index;
708 			unsigned int step = delta_signal;
709 
710 			for (; index < num_levels - 1; index++) {
711 				core_power->bl_prop[inst].backlight_lut[index] =
712 						base_value + (step / delta_luma);
713 				step += delta_signal;
714 			}
715 		}
716 	/* Build backlight translation table based on default curve */
717 	} else {
718 		/* Defines default backlight curve F(x) = A(x*x) + Bx + C.
719 		 *
720 		 * Backlight curve should always  satisfy:
721 		 * F(0) = min, F(100) = max,
722 		 * So polynom coefficients are:
723 		 * A is 0.0255 - B/100 - min/10000 - (255-max)/10000 =
724 		 * (max - min)/10000 - B/100
725 		 * B is adjustable factor to modify the curve.
726 		 * Bigger B results in less concave curve.
727 		 * B range is [0..(max-min)/100]
728 		 * C is backlight minimum
729 		 */
730 		unsigned int backlight_curve_coeff_a_factor =
731 				num_levels * num_levels;
732 		unsigned int backlight_curve_coeff_b = num_levels;
733 		unsigned int delta =
734 			core_power->bl_prop[inst].backlight_lut[num_levels - 1] -
735 				core_power->bl_prop[inst].backlight_lut[0];
736 		unsigned int coeffC = core_power->bl_prop[inst].backlight_lut[0];
737 		unsigned int coeffB =
738 				(backlight_curve_coeff_b < delta ?
739 					backlight_curve_coeff_b : delta);
740 		unsigned long long coeffA = delta - coeffB; /* coeffB is B*100 */
741 
742 		for (i = 1; i < num_levels - 1; i++) {
743 			uint64_t lut_val = div_u64(coeffA * i * i, backlight_curve_coeff_a_factor) +
744 				div_u64((uint64_t)coeffB * i, backlight_curve_coeff_b) + coeffC;
745 
746 			ASSERT(lut_val <= 0xFFFFFFFF);
747 			core_power->bl_prop[inst].backlight_lut[i] = (unsigned int)lut_val;
748 		}
749 	}
750 
751 	if (ext_backlight_caps != NULL)
752 		kfree(ext_backlight_caps);
753 
754 	/* Successfully initialized */
755 	core_power->bl_prop[inst].backlight_caps_valid = true;
756 }
757 
758 static void varibright_set_level(struct core_power *core_power)
759 {
760 	if (!core_power->varibright_prop.varibright_active ||
761 		!core_power->varibright_prop.varibright_user_enable)
762 		core_power->varibright_prop.varibright_hw_level = 0;
763 	else
764 		core_power->varibright_prop.varibright_hw_level =
765 			core_power->varibright_prop.varibright_level;
766 }
767 
768 bool mod_power_hw_init_backlight(struct mod_power *mod_power)
769 {
770 	struct core_power *core_power = NULL;
771 	struct dc *dc = NULL;
772 	struct dmcu *dmcu = NULL;
773 	struct dmcu_iram_parameters params;
774 	unsigned int i;
775 
776 	if (mod_power == NULL)
777 		return false;
778 
779 	core_power = MOD_POWER_TO_CORE(mod_power);
780 	dc = core_power->dc;
781 
782 	for (i = 0; i < core_power->edp_num; i++) {
783 		params.set = core_power->varibright_prop.varibright_config_setting;
784 		params.backlight_ramping_override = core_power->bl_prop[i].backlight_ramping_override;
785 		params.backlight_ramping_reduction = core_power->bl_prop[i].backlight_ramping_reduction;
786 		params.backlight_ramping_start = core_power->bl_prop[i].backlight_ramping_start;
787 		params.backlight_lut_array = core_power->bl_prop[i].backlight_lut;
788 		params.backlight_lut_array_size = core_power->bl_prop[i].num_backlight_levels;
789 		params.min_abm_backlight = core_power->bl_prop[i].min_abm_backlight;
790 
791 		dmcu = dc->res_pool->dmcu;
792 
793 		// In the case where abm is implemented on dmcub,
794 		// dmcu object will be null.
795 		// ABM 2.4 and up are implemented on dmcub.
796 		if (dmcu) {
797 			//DMCU does not support multiple eDP
798 			return dmcu_load_iram(dmcu, params);
799 		} else if (dc->ctx->dmub_srv) {
800 			if (!dmub_init_abm_config(dc->res_pool, params, i))
801 				return false;
802 		} else
803 			return false;
804 	}
805 	return true;
806 }
807 
808 void mod_power_update_backlight_on_mode_change(
809     struct core_power *core_power,
810     struct dc_link *link,
811     unsigned int panel_inst,
812     uint8_t aux_inst,
813     bool is_hdr)
814 {
815     struct set_backlight_level_params backlight_level_params = { 0 };
816 
817 		if (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
818 			link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)
819 			dc_link_set_backlight_level_nits(link, core_power->bl_state[panel_inst].isHDR,
820 				core_power->bl_state[panel_inst].backlight_millinit, 0);
821 
822 		backlight_level_params.frame_ramp = 0;
823 
824 		fill_backlight_level_params(core_power, &backlight_level_params, panel_inst, aux_inst,
825 			core_power->bl_state[panel_inst].backlight_pwm, link->backlight_control_type,
826 			core_power->bl_state[panel_inst].backlight_millinit, 0, is_hdr);
827 
828 		dc_link_set_backlight_level(link, &backlight_level_params);
829 }
830 
831 static bool set_backlight_millinits_aux(struct core_power *core_power,
832 		struct dc_stream_state *stream,
833 		unsigned int backlight_millinits,
834 		unsigned int transition_time_millisec,
835 		unsigned int inst)
836 {
837 	struct dc_link *link = NULL;
838 
839 	if (core_power == NULL)
840 		return false;
841 
842 	if (stream == NULL)
843 		return true;
844 
845 	link = dc_stream_get_link(stream);
846 
847 	return dc_link_set_backlight_level_nits(link, core_power->bl_state[inst].isHDR,
848 			backlight_millinits, transition_time_millisec);
849 }
850 
851 static bool set_backlight(struct core_power *core_power,
852 		struct dc_stream_state *stream,
853 		struct set_backlight_level_params *backlight_level_params,
854 		unsigned int inst)
855 {
856 	bool retv = false;
857 	unsigned int frame_ramp = 0;
858 	unsigned int vsync_rate_hz;
859 	union dmcu_abm_set_bl_params params;
860 	const struct dc_link *link = NULL;
861 	unsigned int backlight_pwm_u16_16 = backlight_level_params->backlight_pwm_u16_16;
862 	unsigned int transition_time_millisec = backlight_level_params->transition_time_in_ms;
863 
864 	if (core_power == NULL)
865 		return false;
866 
867 	core_power->bl_state[inst].backlight_pwm = backlight_pwm_u16_16;
868 
869 	if (stream == NULL)
870 		return true;
871 
872 	if (stream->link->connector_signal != SIGNAL_TYPE_EDP)
873 		return false;
874 
875 	if (transition_time_millisec != 0) {
876 		unsigned int v_total =
877 			(stream->adjust.v_total_max == 0) ? stream->timing.v_total : stream->adjust.v_total_max;
878 
879 		vsync_rate_hz = (unsigned int)div_u64(div_u64((stream->
880 			timing.pix_clk_100hz * 100),
881 			v_total),
882 			stream->timing.h_total);
883 
884 		if (core_power->bl_state[inst].smooth_brightness_enabled)
885 			frame_ramp = ((vsync_rate_hz *
886 				transition_time_millisec) + 500) / 1000;
887 	}
888 
889 	core_power->bl_state[inst].frame_ramp = frame_ramp;
890 	params.u32All = 0;
891 	params.bits.gradual_change = (frame_ramp > 0);
892 	params.bits.frame_ramp = frame_ramp;
893 	link = dc_stream_get_link(stream);
894 
895 	mod_power_set_psr_event(&core_power->mod_public, stream, true, psr_event_hw_programming, true);
896 	mod_power_set_replay_event(&core_power->mod_public, stream, true, replay_event_hw_programming, true);
897 
898 	backlight_level_params->frame_ramp = params.u32All;
899 	retv = dc_link_set_backlight_level(link, backlight_level_params);
900 
901 	mod_power_set_psr_event(&core_power->mod_public, stream, false, psr_event_hw_programming, false);
902 	mod_power_set_replay_event(&core_power->mod_public, stream, false, replay_event_hw_programming, false);
903 
904 	return retv;
905 }
906 
907 void fill_backlight_level_params(struct core_power *core_power,
908 	struct set_backlight_level_params *backlight_level_params,
909 	int panel_inst, uint8_t aux_inst, unsigned int backlight_pwm,
910 	enum backlight_control_type backlight_control_type,
911 	unsigned int backlight_millinit, unsigned int transition_time_millisec,
912 	bool is_hdr)
913 {
914 	struct pwr_backlight_properties *bl_prop = &core_power->bl_prop[panel_inst];
915 
916 	backlight_level_params->aux_inst = aux_inst;
917 	backlight_level_params->backlight_pwm_u16_16 = backlight_pwm;
918 	backlight_level_params->control_type = backlight_control_type;
919 	backlight_level_params->backlight_millinits = backlight_millinit;
920 	backlight_level_params->transition_time_in_ms = transition_time_millisec;
921 	backlight_level_params->min_luminance = bl_prop->min_brightness_millinits;
922 	backlight_level_params->max_luminance = bl_prop->max_brightness_millinits;
923 	backlight_level_params->min_backlight_pwm = bl_prop->min_backlight_pwm;
924 	backlight_level_params->max_backlight_pwm = bl_prop->max_backlight_pwm;
925 
926 	if (backlight_control_type == BACKLIGHT_CONTROL_AMD_AUX && !is_hdr)
927 		backlight_level_params->control_type = BACKLIGHT_CONTROL_PWM;
928 }
929 
930 bool mod_power_set_backlight_nits(struct mod_power *mod_power,
931 		struct dc_stream_state *stream,
932 		unsigned int backlight_millinit,
933 		unsigned int transition_time_millisec,
934 		bool skip_aux,
935 		bool is_hdr)
936 {
937 	struct core_power *core_power = NULL;
938 	unsigned int backlight_pwm;
939 	unsigned int panel_inst = 0;
940 	struct set_backlight_level_params backlight_level_params = { 0 };
941 	const struct dc_link *link = NULL;
942 	uint8_t aux_inst = 0;
943 
944 	if (mod_power == NULL)
945 		return false;
946 
947 	core_power = MOD_POWER_TO_CORE(mod_power);
948 	link = dc_stream_get_link(stream);
949 
950 	ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF);
951 	aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel;
952 
953 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &panel_inst))
954 		return false;
955 
956 	if (!skip_aux) {
957 		if (!set_backlight_millinits_aux(core_power, stream,
958 						backlight_millinit, transition_time_millisec, panel_inst))
959 			return false;
960 	}
961 // always send both AUX (above) and PWM (below)
962 	core_power->bl_state[panel_inst].backlight_millinit = backlight_millinit;
963 
964 	core_power->bl_state[panel_inst].backlight_millipercent =
965 		backlight_millinit_to_millipercent(
966 				core_power, backlight_millinit, panel_inst);
967 
968 	backlight_pwm = backlight_millinit_to_pwm(
969 				core_power, backlight_millinit, panel_inst);
970 
971 	fill_backlight_level_params(core_power, &backlight_level_params, panel_inst, aux_inst, backlight_pwm,
972 		link->backlight_control_type, backlight_millinit, transition_time_millisec, is_hdr);
973 
974 	return set_backlight(core_power, stream,
975 			&backlight_level_params, panel_inst);
976 }
977 
978 bool mod_power_backlight_percent_to_nits(struct mod_power *mod_power,
979 		struct dc_stream_state *stream,
980 		unsigned int backlight_millipercent,
981 		unsigned int *backlight_millinit)
982 {
983 	struct core_power *core_power = NULL;
984 	unsigned int inst = 0;
985 
986 	if (mod_power == NULL)
987 		return false;
988 
989 	core_power = MOD_POWER_TO_CORE(mod_power);
990 
991 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst))
992 		return false;
993 
994 	*backlight_millinit = backlight_millipercent_to_millinit(
995 			core_power, backlight_millipercent, inst);
996 	return true;
997 }
998 
999 bool mod_power_backlight_nits_to_percent(struct mod_power *mod_power,
1000 		struct dc_stream_state *stream,
1001 		unsigned int backlight_millinit,
1002 		unsigned int *backlight_millipercent)
1003 {
1004 	struct core_power *core_power = NULL;
1005 	unsigned int inst = 0;
1006 
1007 	if (mod_power == NULL)
1008 		return false;
1009 
1010 	core_power = MOD_POWER_TO_CORE(mod_power);
1011 
1012 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst))
1013 		return false;
1014 
1015 	*backlight_millipercent = backlight_millinit_to_millipercent(
1016 			core_power, backlight_millinit, inst);
1017 	return true;
1018 }
1019 
1020 bool mod_power_set_backlight_percent(struct mod_power *mod_power,
1021 		struct dc_stream_state *stream,
1022 		unsigned int backlight_millipercent,
1023 		unsigned int transition_time_millisec,
1024 		bool is_hdr)
1025 {
1026 	struct core_power *core_power = NULL;
1027 	struct set_backlight_level_params backlight_level_params = { 0 };
1028 	const struct dc_link *link = NULL;
1029 	unsigned int backlight_pwm;
1030 	unsigned int panel_inst = 0;
1031 	uint8_t aux_inst = 0;
1032 
1033 	if (mod_power == NULL)
1034 		return false;
1035 
1036 	core_power = MOD_POWER_TO_CORE(mod_power);
1037 	link = dc_stream_get_link(stream);
1038 	ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF);
1039 	aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel;
1040 
1041 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &panel_inst))
1042 		return false;
1043 	core_power->bl_state[panel_inst].backlight_millipercent = backlight_millipercent;
1044 
1045 	core_power->bl_state[panel_inst].backlight_millinit =
1046 		backlight_millipercent_to_millinit(
1047 				core_power, backlight_millipercent, panel_inst);
1048 
1049 	backlight_pwm = backlight_millipercent_to_pwm(
1050 				core_power, backlight_millipercent, panel_inst);
1051 
1052 	fill_backlight_level_params(core_power, &backlight_level_params, panel_inst,
1053 		aux_inst, backlight_pwm, link->backlight_control_type,
1054 		core_power->bl_state[panel_inst].backlight_millinit, transition_time_millisec, is_hdr);
1055 
1056 	return set_backlight(core_power, stream,
1057 			&backlight_level_params, panel_inst);
1058 }
1059 
1060 void mod_power_update_backlight(struct mod_power *mod_power,
1061 		struct dc_stream_state *stream,
1062 		unsigned int backlight_millipercent)
1063 {
1064 	struct core_power *core_power = NULL;
1065 	unsigned int inst = 0;
1066 
1067 	if (mod_power == NULL)
1068 		return;
1069 
1070 	core_power = MOD_POWER_TO_CORE(mod_power);
1071 
1072 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst))
1073 		return;
1074 	core_power->bl_state[inst].backlight_millipercent = backlight_millipercent;
1075 
1076 	core_power->bl_state[inst].backlight_millinit =
1077 		backlight_millipercent_to_millinit(
1078 			core_power, backlight_millipercent, inst);
1079 
1080 	core_power->bl_state[inst].backlight_pwm = backlight_millipercent_to_pwm(
1081 		core_power, backlight_millipercent, inst);
1082 }
1083 
1084 void mod_power_update_backlight_nits(struct mod_power *mod_power,
1085 		struct dc_stream_state *stream,
1086 		unsigned int backlight_millinit)
1087 {
1088 	struct core_power *core_power = NULL;
1089 	unsigned int inst = 0;
1090 
1091 	if (mod_power == NULL)
1092 		return;
1093 
1094 	core_power = MOD_POWER_TO_CORE(mod_power);
1095 
1096 	if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &inst))
1097 		return;
1098 
1099 	core_power->bl_state[inst].backlight_millinit = backlight_millinit;
1100 
1101 	core_power->bl_state[inst].backlight_millipercent = backlight_millinit_to_millipercent(
1102 		core_power, backlight_millinit, inst);
1103 	core_power->bl_state[inst].backlight_pwm = backlight_millinit_to_pwm(
1104 		core_power, backlight_millinit, inst);
1105 }
1106 
1107 bool mod_power_get_backlight_pwm(struct mod_power *mod_power,
1108 		unsigned int *backlight_pwm,
1109 		unsigned int inst)
1110 {
1111 	struct core_power *core_power = NULL;
1112 
1113 	if (mod_power == NULL)
1114 		return false;
1115 
1116 	core_power = MOD_POWER_TO_CORE(mod_power);
1117 
1118 	*backlight_pwm = core_power->bl_state[inst].backlight_pwm;
1119 
1120 	return true;
1121 }
1122 
1123 bool mod_power_get_backlight_nits(struct mod_power *mod_power,
1124 		unsigned int *backlight_millinit,
1125 		unsigned int inst)
1126 {
1127 	struct core_power *core_power = NULL;
1128 
1129 	if (mod_power == NULL)
1130 		return false;
1131 
1132 	core_power = MOD_POWER_TO_CORE(mod_power);
1133 
1134 	*backlight_millinit = core_power->bl_state[inst].backlight_millinit;
1135 
1136 	return true;
1137 }
1138 
1139 bool mod_power_get_backlight_percent(struct mod_power *mod_power,
1140 		unsigned int *backlight_millipercent,
1141 		unsigned int inst)
1142 {
1143 	struct core_power *core_power = NULL;
1144 
1145 	if (mod_power == NULL)
1146 		return false;
1147 
1148 	core_power = MOD_POWER_TO_CORE(mod_power);
1149 
1150 	*backlight_millipercent = core_power->bl_state[inst].backlight_millipercent;
1151 
1152 	return true;
1153 }
1154 
1155 bool mod_power_get_hw_target_backlight_pwm_nits(struct mod_power *mod_power,
1156 		const struct dc_link *link,
1157 		unsigned int *backlight_millinit,
1158 		unsigned int inst)
1159 {
1160 	struct core_power *core_power = NULL;
1161 	unsigned int backlight_u16_16 = 0;
1162 
1163 	if (mod_power == NULL)
1164 		return false;
1165 
1166 	core_power = MOD_POWER_TO_CORE(mod_power);
1167 
1168 	if (mod_power_get_hw_target_backlight_pwm(mod_power, link,
1169 							&backlight_u16_16)) {
1170 		*backlight_millinit =
1171 			backlight_pwm_to_millinit(core_power,
1172 					backlight_u16_16, inst);
1173 		return true;
1174 	}
1175 	return false;
1176 }
1177 
1178 bool mod_power_get_hw_target_backlight_pwm_percent(struct mod_power *mod_power,
1179 		const struct dc_link *link,
1180 		unsigned int *backlight_millipercent,
1181 		unsigned int inst)
1182 {
1183 	struct core_power *core_power = NULL;
1184 	unsigned int backlight_u16_16 = 0;
1185 
1186 	if (mod_power == NULL)
1187 		return false;
1188 
1189 	core_power = MOD_POWER_TO_CORE(mod_power);
1190 
1191 	if (mod_power_get_hw_target_backlight_pwm(mod_power, link,
1192 							&backlight_u16_16)) {
1193 		*backlight_millipercent =
1194 			backlight_pwm_to_millipercent(core_power,
1195 					backlight_u16_16, inst);
1196 		return true;
1197 	}
1198 	return false;
1199 }
1200 
1201 bool mod_power_get_hw_target_backlight_pwm(struct mod_power *mod_power,
1202 		const struct dc_link *link,
1203 		unsigned int *backlight_u16_16)
1204 {
1205 	if (mod_power == NULL)
1206 		return false;
1207 
1208 	*backlight_u16_16 = dc_link_get_target_backlight_pwm(link);
1209 
1210 	return true;
1211 }
1212 
1213 bool mod_power_get_hw_backlight_pwm_nits(struct mod_power *mod_power,
1214 		const struct dc_link *link,
1215 		unsigned int *backlight_millinit,
1216 		unsigned int inst)
1217 {
1218 	struct core_power *core_power = NULL;
1219 	unsigned int backlight_u16_16 = 0;
1220 
1221 	if (mod_power == NULL)
1222 		return false;
1223 
1224 	core_power = MOD_POWER_TO_CORE(mod_power);
1225 
1226 	if (mod_power_get_hw_backlight_pwm(mod_power, link, &backlight_u16_16)) {
1227 		*backlight_millinit =
1228 			backlight_pwm_to_millinit(core_power,
1229 					backlight_u16_16, inst);
1230 		return true;
1231 	}
1232 	return false;
1233 }
1234 
1235 bool mod_power_get_hw_backlight_aux_nits(struct mod_power *mod_power,
1236 		struct dc_stream_state **streams, int num_streams,
1237 		unsigned int *backlight_millinit_avg,
1238 		unsigned int *backlight_millinit_peak)
1239 {
1240 	struct core_power *core_power = NULL;
1241 	struct dc_link *link = NULL;
1242 	int stream_index;
1243 
1244 	if (mod_power == NULL)
1245 		return false;
1246 
1247 	core_power = MOD_POWER_TO_CORE(mod_power);
1248 
1249 	if (core_power == NULL)
1250 		return false;
1251 
1252 	if (num_streams < 1)
1253 		return true;
1254 
1255 	for (stream_index = 0; stream_index < num_streams; stream_index++)
1256 		if (streams[stream_index]->link->connector_signal == SIGNAL_TYPE_EDP ||
1257 				streams[stream_index]->link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT)
1258 			break;
1259 
1260 	if (stream_index == num_streams)
1261 		return false;
1262 
1263 	link = dc_stream_get_link(streams[stream_index]);
1264 	if (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 0)
1265 		return false;
1266 
1267 	return dc_link_get_backlight_level_nits(link, backlight_millinit_avg,
1268 			backlight_millinit_peak);
1269 }
1270 
1271 bool mod_power_get_hw_backlight_pwm_percent(struct mod_power *mod_power,
1272 		const struct dc_link *link,
1273 		unsigned int *backlight_millipercent,
1274 		unsigned int inst)
1275 {
1276 	struct core_power *core_power = NULL;
1277 	unsigned int backlight_u16_16 = 0;
1278 
1279 	if (mod_power == NULL)
1280 		return false;
1281 
1282 	core_power = MOD_POWER_TO_CORE(mod_power);
1283 
1284 	if (mod_power_get_hw_backlight_pwm(mod_power, link, &backlight_u16_16)) {
1285 		*backlight_millipercent =
1286 			backlight_pwm_to_millipercent(core_power,
1287 					backlight_u16_16, inst);
1288 		return true;
1289 	}
1290 	return false;
1291 }
1292 
1293 bool mod_power_get_hw_backlight_pwm(struct mod_power *mod_power,
1294 		const struct dc_link *link,
1295 		unsigned int *backlight_u16_16)
1296 {
1297 	if (mod_power == NULL)
1298 		return false;
1299 
1300 	*backlight_u16_16 = dc_link_get_backlight_level(link);
1301 
1302 	return true;
1303 }
1304 
1305 bool mod_power_get_panel_backlight_boundaries(
1306 				struct mod_power *mod_power,
1307 				unsigned int *out_min_backlight,
1308 				unsigned int *out_max_backlight,
1309 				unsigned int *out_ac_backlight_percent,
1310 				unsigned int *out_dc_backlight_percent,
1311 				unsigned int inst)
1312 {
1313 	struct core_power *core_power = NULL;
1314 
1315 	if (mod_power == NULL)
1316 		return false;
1317 
1318 	core_power = MOD_POWER_TO_CORE(mod_power);
1319 
1320 	/* If cache was successfully updated,
1321 	 * copy the values to output structure and return success
1322 	 */
1323 	if (core_power->bl_prop[inst].backlight_caps_valid) {
1324 		*out_min_backlight = core_power->bl_prop[inst].backlight_lut[0];
1325 		*out_max_backlight =
1326 			core_power->bl_prop[inst].backlight_lut[
1327 				core_power->bl_prop[inst].num_backlight_levels - 1];
1328 		*out_ac_backlight_percent =
1329 			core_power->bl_prop[inst].ac_backlight_percent;
1330 		*out_dc_backlight_percent =
1331 			core_power->bl_prop[inst].dc_backlight_percent;
1332 
1333 		return true;
1334 	}
1335 
1336 	return false;
1337 }
1338 
1339 bool mod_power_set_smooth_brightness(struct mod_power *mod_power,
1340 		bool enable_brightness,
1341 		unsigned int inst)
1342 {
1343 	struct core_power *core_power = NULL;
1344 
1345 	if (mod_power == NULL)
1346 		return false;
1347 
1348 	core_power = MOD_POWER_TO_CORE(mod_power);
1349 
1350 	core_power->bl_state[inst].smooth_brightness_enabled = enable_brightness;
1351 
1352 	return true;
1353 }
1354 
1355 bool mod_power_varibright_feature_enable(struct mod_power *mod_power, bool enable,
1356 		struct dc_stream_update *stream_update)
1357 {
1358 	struct core_power *core_power = NULL;
1359 
1360 	if (mod_power == NULL)
1361 		return false;
1362 
1363 	core_power = MOD_POWER_TO_CORE(mod_power);
1364 	core_power->varibright_prop.varibright_user_enable = enable;
1365 
1366 	/* find abm hw level to program, and save in stream update */
1367 	varibright_set_level(core_power);
1368 	*stream_update->abm_level = core_power->varibright_prop.varibright_hw_level;
1369 
1370 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1371 						WPP_BIT_FLAG_Backlight_ABM,
1372 						">ABM feature enable: enable=%u su->varibright_level=%u varibright_hw_level=%u",
1373 						(unsigned int) enable,
1374 						*stream_update->abm_level,
1375 						core_power->varibright_prop.varibright_hw_level);
1376 	return true;
1377 }
1378 
1379 bool mod_power_varibright_activate(struct mod_power *mod_power,
1380 		bool activate,
1381 		struct dc_stream_update *stream_update)
1382 {
1383 	struct core_power *core_power = NULL;
1384 
1385 	if (mod_power == NULL)
1386 		return false;
1387 
1388 	core_power = MOD_POWER_TO_CORE(mod_power);
1389 	core_power->varibright_prop.varibright_active = activate;
1390 
1391 	/* find abm hw level to program, and save in stream update */
1392 	varibright_set_level(core_power);
1393 	*stream_update->abm_level = core_power->varibright_prop.varibright_hw_level;
1394 
1395 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1396 						WPP_BIT_FLAG_Backlight_ABM,
1397 						">ABM activate: activate=%u su->varibright_level=%u",
1398 						(unsigned int) activate,
1399 						*stream_update->abm_level);
1400 	return true;
1401 }
1402 bool mod_power_varibright_set_level(struct mod_power *mod_power, unsigned int level,
1403 		struct dc_stream_update *stream_update)
1404 {
1405 	struct core_power *core_power = NULL;
1406 
1407 	if (mod_power == NULL)
1408 		return false;
1409 
1410 	core_power = MOD_POWER_TO_CORE(mod_power);
1411 	core_power->varibright_prop.varibright_level = level;
1412 	core_power->varibright_prop.varibright_hw_level = level;
1413 
1414 	/* find abm hw level to program, and save in stream update */
1415 	varibright_set_level(core_power);
1416 	*stream_update->abm_level = core_power->varibright_prop.varibright_hw_level;
1417 
1418 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1419 						WPP_BIT_FLAG_Backlight_ABM,
1420 						">ABM set level: level=%u -> (varibright_level=%u varibright_hw_level=%u) -> su->varibright_level=%u",
1421 						level,
1422 						core_power->varibright_prop.varibright_level,
1423 						core_power->varibright_prop.varibright_hw_level,
1424 						*stream_update->abm_level);
1425 	return true;
1426 }
1427 
1428 bool mod_power_varibright_set_hw_level(struct mod_power *mod_power, unsigned int level,
1429 		struct dc_stream_update *stream_update)
1430 {
1431 	struct core_power *core_power = NULL;
1432 
1433 	if (mod_power == NULL)
1434 		return false;
1435 
1436 	core_power = MOD_POWER_TO_CORE(mod_power);
1437 
1438 	if (level == 0 || level == ABM_LEVEL_IMMEDIATE_DISABLE)
1439 		core_power->varibright_prop.varibright_active = 0;
1440 	else
1441 		core_power->varibright_prop.varibright_active = 1;
1442 	core_power->varibright_prop.varibright_hw_level = level;
1443 	*stream_update->abm_level = core_power->varibright_prop.varibright_hw_level;
1444 
1445 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1446 						WPP_BIT_FLAG_Backlight_ABM,
1447 						">ABM set level: level=%u -> (varibright_level=%u varibright_hw_level=%u) -> su->varibright_level=%u",
1448 						level,
1449 						core_power->varibright_prop.varibright_level,
1450 						core_power->varibright_prop.varibright_hw_level,
1451 						*stream_update->abm_level);
1452 	return true;
1453 }
1454 
1455 bool mod_power_get_varibright_level(struct mod_power *mod_power,
1456 		unsigned int *varibright_level)
1457 {
1458 	struct core_power *core_power = NULL;
1459 
1460 	if (mod_power == NULL)
1461 		return false;
1462 
1463 	core_power = MOD_POWER_TO_CORE(mod_power);
1464 
1465 	*varibright_level = core_power->varibright_prop.varibright_level;
1466 
1467 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1468 						WPP_BIT_FLAG_Backlight_ABM,
1469 						">get varibright level: cp->varibright_level=%u",
1470 						*varibright_level);
1471 	return true;
1472 
1473 }
1474 
1475 bool mod_power_get_varibright_hw_level(struct mod_power *mod_power,
1476 		unsigned int *varibright_level)
1477 {
1478 	struct core_power *core_power = NULL;
1479 
1480 	if (mod_power == NULL)
1481 		return false;
1482 
1483 	core_power = MOD_POWER_TO_CORE(mod_power);
1484 
1485 	*varibright_level = core_power->varibright_prop.varibright_hw_level;
1486 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1487 						WPP_BIT_FLAG_Backlight_ABM,
1488 						">get varibright HW level: hw_level=%u",
1489 						*varibright_level);
1490 	return true;
1491 }
1492 
1493 bool mod_power_get_varibright_default_level(struct mod_power *mod_power,
1494 		unsigned int *varibright_level)
1495 {
1496 	struct core_power *core_power = NULL;
1497 
1498 	if (mod_power == NULL)
1499 		return false;
1500 
1501 	core_power = MOD_POWER_TO_CORE(mod_power);
1502 
1503 	*varibright_level = core_power->varibright_prop.def_varibright_level;
1504 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1505 						WPP_BIT_FLAG_Backlight_ABM,
1506 						">get varibright default level: def_varibright_level=%u",
1507 						*varibright_level);
1508 	return true;
1509 }
1510 
1511 bool mod_power_get_varibright_enable(struct mod_power *mod_power,
1512 		bool *varibright_enable)
1513 {
1514 	struct core_power *core_power = NULL;
1515 
1516 	if (mod_power == NULL)
1517 		return false;
1518 
1519 	core_power = MOD_POWER_TO_CORE(mod_power);
1520 
1521 	*varibright_enable = core_power->varibright_prop.varibright_user_enable;
1522 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1523 				WPP_BIT_FLAG_Backlight_ABM,
1524 				">get varibright enable state: varibright_user_enable=%u",
1525 				(unsigned int) (*varibright_enable));
1526 	return true;
1527 }
1528 
1529 bool mod_power_is_abm_active(struct mod_power *mod_power,
1530 		const struct dc_link *link,
1531 		unsigned int inst)
1532 {
1533 	unsigned int user_backlight = 0;
1534 	unsigned int current_backlight = 0;
1535 	bool is_active = false;
1536 
1537 	if (mod_power == NULL)
1538 		return false;
1539 
1540 	mod_power_get_backlight_pwm(mod_power, &user_backlight, inst);
1541 	mod_power_get_hw_backlight_pwm(mod_power, link,	&current_backlight);
1542 
1543 	if (user_backlight != current_backlight)
1544 		is_active = true;
1545 	else
1546 		is_active = false;
1547 	DC_TRACE_LEVEL_MESSAGEP(DAL_TRACE_LEVEL_INFORMATION,
1548 						WPP_BIT_FLAG_Backlight_ABM,
1549 						">get ABM active state: is_active=%u (user_backlight_pwm=%u, current_backlight_pwm=%u)",
1550 						(unsigned int)is_active,
1551 						user_backlight,
1552 						current_backlight);
1553 	return is_active;
1554 }
1555 
1556 static void fill_backlight_transform_table(struct dmcu_iram_parameters params,
1557 		struct iram_table_v_2 *table)
1558 {
1559 	unsigned int i;
1560 	unsigned int num_entries = NUM_BL_CURVE_SEGS;
1561 	unsigned int lut_index;
1562 
1563 	table->backlight_thresholds[0] = 0;
1564 	ASSERT(params.backlight_lut_array[0] <= 0xFFFF);
1565 	table->backlight_offsets[0] = (uint16_t)params.backlight_lut_array[0];
1566 	table->backlight_thresholds[num_entries-1] = 0xFFFF;
1567 	ASSERT(params.backlight_lut_array[params.backlight_lut_array_size - 1] <= 0xFFFF);
1568 	table->backlight_offsets[num_entries-1] =
1569 		(uint16_t)params.backlight_lut_array[params.backlight_lut_array_size - 1];
1570 
1571 	/* Setup all brightness levels between 0% and 100% exclusive
1572 	 * Fills brightness-to-backlight transform table. Backlight custom curve
1573 	 * describes transform from brightness to backlight. It will be defined
1574 	 * as set of thresholds and set of offsets, together, implying
1575 	 * extrapolation of custom curve into 16 uniformly spanned linear
1576 	 * segments.  Each threshold/offset represented by 16 bit entry in
1577 	 * format U4.10.
1578 	 */
1579 	for (i = 1; i+1 < num_entries; i++) {
1580 		lut_index = (params.backlight_lut_array_size - 1) * i / (num_entries - 1);
1581 
1582 		ASSERT(lut_index < params.backlight_lut_array_size);
1583 
1584 		unsigned int threshold_val = DIV_ROUNDUP((i * 65536), num_entries);
1585 		unsigned int offset_val = params.backlight_lut_array[lut_index];
1586 
1587 		ASSERT(threshold_val <= 0xFFFF);
1588 		ASSERT(offset_val <= 0xFFFF);
1589 
1590 		table->backlight_thresholds[i] = cpu_to_be16((uint16_t)threshold_val);
1591 		table->backlight_offsets[i]    = cpu_to_be16((uint16_t)offset_val);
1592 	}
1593 }
1594 
1595 static void fill_backlight_transform_table_v_2_2(struct dmcu_iram_parameters params,
1596 		struct iram_table_v_2_2 *table, bool big_endian)
1597 {
1598 	unsigned int i;
1599 	unsigned int num_entries = NUM_BL_CURVE_SEGS;
1600 	unsigned int lut_index;
1601 
1602 	table->backlight_thresholds[0] = 0;
1603 	ASSERT(params.backlight_lut_array[0] <= 0xFFFF);
1604 	table->backlight_offsets[0] = (uint16_t)params.backlight_lut_array[0];
1605 	table->backlight_thresholds[num_entries-1] = 0xFFFF;
1606 	ASSERT(params.backlight_lut_array[params.backlight_lut_array_size - 1] <= 0xFFFF);
1607 	table->backlight_offsets[num_entries-1] =
1608 		(uint16_t)params.backlight_lut_array[params.backlight_lut_array_size - 1];
1609 
1610 	/* Setup all brightness levels between 0% and 100% exclusive
1611 	 * Fills brightness-to-backlight transform table. Backlight custom curve
1612 	 * describes transform from brightness to backlight. It will be defined
1613 	 * as set of thresholds and set of offsets, together, implying
1614 	 * extrapolation of custom curve into 16 uniformly spanned linear
1615 	 * segments.  Each threshold/offset represented by 16 bit entry in
1616 	 * format U4.10.
1617 	 */
1618 	for (i = 1; i+1 < num_entries; i++) {
1619 		lut_index = DIV_ROUNDUP((i * params.backlight_lut_array_size), num_entries);
1620 		ASSERT(lut_index < params.backlight_lut_array_size);
1621 
1622 		unsigned int threshold_val = DIV_ROUNDUP((i * 65536), num_entries);
1623 		unsigned int offset_val = params.backlight_lut_array[lut_index];
1624 
1625 		ASSERT(threshold_val <= 0xFFFF);
1626 		ASSERT(offset_val <= 0xFFFF);
1627 
1628 		table->backlight_thresholds[i] = (big_endian) ?
1629 			cpu_to_be16((uint16_t)threshold_val) : cpu_to_le16((uint16_t)threshold_val);
1630 		table->backlight_offsets[i] = (big_endian) ?
1631 			cpu_to_be16((uint16_t)offset_val) : cpu_to_le16((uint16_t)offset_val);
1632 	}
1633 }
1634 
1635 static void fill_iram_v_2(struct iram_table_v_2 *ram_table, struct dmcu_iram_parameters params)
1636 {
1637 	unsigned int set = params.set;
1638 
1639 	ram_table->min_abm_backlight =
1640 			cpu_to_be16(params.min_abm_backlight);
1641 	ram_table->deviation_gain = 0xb3;
1642 
1643 	ram_table->blRampReduction =
1644 		cpu_to_be16(params.backlight_ramping_reduction);
1645 	ram_table->blRampStart =
1646 		cpu_to_be16(params.backlight_ramping_start);
1647 
1648 	ram_table->min_reduction[0][0] = min_reduction_table[abm_config[set][0]];
1649 	ram_table->min_reduction[1][0] = min_reduction_table[abm_config[set][0]];
1650 	ram_table->min_reduction[2][0] = min_reduction_table[abm_config[set][0]];
1651 	ram_table->min_reduction[3][0] = min_reduction_table[abm_config[set][0]];
1652 	ram_table->min_reduction[4][0] = min_reduction_table[abm_config[set][0]];
1653 	ram_table->max_reduction[0][0] = max_reduction_table[abm_config[set][0]];
1654 	ram_table->max_reduction[1][0] = max_reduction_table[abm_config[set][0]];
1655 	ram_table->max_reduction[2][0] = max_reduction_table[abm_config[set][0]];
1656 	ram_table->max_reduction[3][0] = max_reduction_table[abm_config[set][0]];
1657 	ram_table->max_reduction[4][0] = max_reduction_table[abm_config[set][0]];
1658 
1659 	ram_table->min_reduction[0][1] = min_reduction_table[abm_config[set][1]];
1660 	ram_table->min_reduction[1][1] = min_reduction_table[abm_config[set][1]];
1661 	ram_table->min_reduction[2][1] = min_reduction_table[abm_config[set][1]];
1662 	ram_table->min_reduction[3][1] = min_reduction_table[abm_config[set][1]];
1663 	ram_table->min_reduction[4][1] = min_reduction_table[abm_config[set][1]];
1664 	ram_table->max_reduction[0][1] = max_reduction_table[abm_config[set][1]];
1665 	ram_table->max_reduction[1][1] = max_reduction_table[abm_config[set][1]];
1666 	ram_table->max_reduction[2][1] = max_reduction_table[abm_config[set][1]];
1667 	ram_table->max_reduction[3][1] = max_reduction_table[abm_config[set][1]];
1668 	ram_table->max_reduction[4][1] = max_reduction_table[abm_config[set][1]];
1669 
1670 	ram_table->min_reduction[0][2] = min_reduction_table[abm_config[set][2]];
1671 	ram_table->min_reduction[1][2] = min_reduction_table[abm_config[set][2]];
1672 	ram_table->min_reduction[2][2] = min_reduction_table[abm_config[set][2]];
1673 	ram_table->min_reduction[3][2] = min_reduction_table[abm_config[set][2]];
1674 	ram_table->min_reduction[4][2] = min_reduction_table[abm_config[set][2]];
1675 	ram_table->max_reduction[0][2] = max_reduction_table[abm_config[set][2]];
1676 	ram_table->max_reduction[1][2] = max_reduction_table[abm_config[set][2]];
1677 	ram_table->max_reduction[2][2] = max_reduction_table[abm_config[set][2]];
1678 	ram_table->max_reduction[3][2] = max_reduction_table[abm_config[set][2]];
1679 	ram_table->max_reduction[4][2] = max_reduction_table[abm_config[set][2]];
1680 
1681 	ram_table->min_reduction[0][3] = min_reduction_table[abm_config[set][3]];
1682 	ram_table->min_reduction[1][3] = min_reduction_table[abm_config[set][3]];
1683 	ram_table->min_reduction[2][3] = min_reduction_table[abm_config[set][3]];
1684 	ram_table->min_reduction[3][3] = min_reduction_table[abm_config[set][3]];
1685 	ram_table->min_reduction[4][3] = min_reduction_table[abm_config[set][3]];
1686 	ram_table->max_reduction[0][3] = max_reduction_table[abm_config[set][3]];
1687 	ram_table->max_reduction[1][3] = max_reduction_table[abm_config[set][3]];
1688 	ram_table->max_reduction[2][3] = max_reduction_table[abm_config[set][3]];
1689 	ram_table->max_reduction[3][3] = max_reduction_table[abm_config[set][3]];
1690 	ram_table->max_reduction[4][3] = max_reduction_table[abm_config[set][3]];
1691 
1692 	ram_table->bright_pos_gain[0][0] = 0x20;
1693 	ram_table->bright_pos_gain[0][1] = 0x20;
1694 	ram_table->bright_pos_gain[0][2] = 0x20;
1695 	ram_table->bright_pos_gain[0][3] = 0x20;
1696 	ram_table->bright_pos_gain[1][0] = 0x20;
1697 	ram_table->bright_pos_gain[1][1] = 0x20;
1698 	ram_table->bright_pos_gain[1][2] = 0x20;
1699 	ram_table->bright_pos_gain[1][3] = 0x20;
1700 	ram_table->bright_pos_gain[2][0] = 0x20;
1701 	ram_table->bright_pos_gain[2][1] = 0x20;
1702 	ram_table->bright_pos_gain[2][2] = 0x20;
1703 	ram_table->bright_pos_gain[2][3] = 0x20;
1704 	ram_table->bright_pos_gain[3][0] = 0x20;
1705 	ram_table->bright_pos_gain[3][1] = 0x20;
1706 	ram_table->bright_pos_gain[3][2] = 0x20;
1707 	ram_table->bright_pos_gain[3][3] = 0x20;
1708 	ram_table->bright_pos_gain[4][0] = 0x20;
1709 	ram_table->bright_pos_gain[4][1] = 0x20;
1710 	ram_table->bright_pos_gain[4][2] = 0x20;
1711 	ram_table->bright_pos_gain[4][3] = 0x20;
1712 	ram_table->bright_neg_gain[0][0] = 0x00;
1713 	ram_table->bright_neg_gain[0][1] = 0x00;
1714 	ram_table->bright_neg_gain[0][2] = 0x00;
1715 	ram_table->bright_neg_gain[0][3] = 0x00;
1716 	ram_table->bright_neg_gain[1][0] = 0x00;
1717 	ram_table->bright_neg_gain[1][1] = 0x00;
1718 	ram_table->bright_neg_gain[1][2] = 0x00;
1719 	ram_table->bright_neg_gain[1][3] = 0x00;
1720 	ram_table->bright_neg_gain[2][0] = 0x00;
1721 	ram_table->bright_neg_gain[2][1] = 0x00;
1722 	ram_table->bright_neg_gain[2][2] = 0x00;
1723 	ram_table->bright_neg_gain[2][3] = 0x00;
1724 	ram_table->bright_neg_gain[3][0] = 0x00;
1725 	ram_table->bright_neg_gain[3][1] = 0x00;
1726 	ram_table->bright_neg_gain[3][2] = 0x00;
1727 	ram_table->bright_neg_gain[3][3] = 0x00;
1728 	ram_table->bright_neg_gain[4][0] = 0x00;
1729 	ram_table->bright_neg_gain[4][1] = 0x00;
1730 	ram_table->bright_neg_gain[4][2] = 0x00;
1731 	ram_table->bright_neg_gain[4][3] = 0x00;
1732 	ram_table->dark_pos_gain[0][0] = 0x00;
1733 	ram_table->dark_pos_gain[0][1] = 0x00;
1734 	ram_table->dark_pos_gain[0][2] = 0x00;
1735 	ram_table->dark_pos_gain[0][3] = 0x00;
1736 	ram_table->dark_pos_gain[1][0] = 0x00;
1737 	ram_table->dark_pos_gain[1][1] = 0x00;
1738 	ram_table->dark_pos_gain[1][2] = 0x00;
1739 	ram_table->dark_pos_gain[1][3] = 0x00;
1740 	ram_table->dark_pos_gain[2][0] = 0x00;
1741 	ram_table->dark_pos_gain[2][1] = 0x00;
1742 	ram_table->dark_pos_gain[2][2] = 0x00;
1743 	ram_table->dark_pos_gain[2][3] = 0x00;
1744 	ram_table->dark_pos_gain[3][0] = 0x00;
1745 	ram_table->dark_pos_gain[3][1] = 0x00;
1746 	ram_table->dark_pos_gain[3][2] = 0x00;
1747 	ram_table->dark_pos_gain[3][3] = 0x00;
1748 	ram_table->dark_pos_gain[4][0] = 0x00;
1749 	ram_table->dark_pos_gain[4][1] = 0x00;
1750 	ram_table->dark_pos_gain[4][2] = 0x00;
1751 	ram_table->dark_pos_gain[4][3] = 0x00;
1752 	ram_table->dark_neg_gain[0][0] = 0x00;
1753 	ram_table->dark_neg_gain[0][1] = 0x00;
1754 	ram_table->dark_neg_gain[0][2] = 0x00;
1755 	ram_table->dark_neg_gain[0][3] = 0x00;
1756 	ram_table->dark_neg_gain[1][0] = 0x00;
1757 	ram_table->dark_neg_gain[1][1] = 0x00;
1758 	ram_table->dark_neg_gain[1][2] = 0x00;
1759 	ram_table->dark_neg_gain[1][3] = 0x00;
1760 	ram_table->dark_neg_gain[2][0] = 0x00;
1761 	ram_table->dark_neg_gain[2][1] = 0x00;
1762 	ram_table->dark_neg_gain[2][2] = 0x00;
1763 	ram_table->dark_neg_gain[2][3] = 0x00;
1764 	ram_table->dark_neg_gain[3][0] = 0x00;
1765 	ram_table->dark_neg_gain[3][1] = 0x00;
1766 	ram_table->dark_neg_gain[3][2] = 0x00;
1767 	ram_table->dark_neg_gain[3][3] = 0x00;
1768 	ram_table->dark_neg_gain[4][0] = 0x00;
1769 	ram_table->dark_neg_gain[4][1] = 0x00;
1770 	ram_table->dark_neg_gain[4][2] = 0x00;
1771 	ram_table->dark_neg_gain[4][3] = 0x00;
1772 
1773 	ram_table->iir_curve[0] = 0x65;
1774 	ram_table->iir_curve[1] = 0x65;
1775 	ram_table->iir_curve[2] = 0x65;
1776 	ram_table->iir_curve[3] = 0x65;
1777 	ram_table->iir_curve[4] = 0x65;
1778 
1779 	//Gamma 2.4
1780 	ram_table->crgb_thresh[0] = cpu_to_be16(0x13b6);
1781 	ram_table->crgb_thresh[1] = cpu_to_be16(0x1648);
1782 	ram_table->crgb_thresh[2] = cpu_to_be16(0x18e3);
1783 	ram_table->crgb_thresh[3] = cpu_to_be16(0x1b41);
1784 	ram_table->crgb_thresh[4] = cpu_to_be16(0x1d46);
1785 	ram_table->crgb_thresh[5] = cpu_to_be16(0x1f21);
1786 	ram_table->crgb_thresh[6] = cpu_to_be16(0x2167);
1787 	ram_table->crgb_thresh[7] = cpu_to_be16(0x2384);
1788 	ram_table->crgb_offset[0] = cpu_to_be16(0x2999);
1789 	ram_table->crgb_offset[1] = cpu_to_be16(0x3999);
1790 	ram_table->crgb_offset[2] = cpu_to_be16(0x4666);
1791 	ram_table->crgb_offset[3] = cpu_to_be16(0x5999);
1792 	ram_table->crgb_offset[4] = cpu_to_be16(0x6333);
1793 	ram_table->crgb_offset[5] = cpu_to_be16(0x7800);
1794 	ram_table->crgb_offset[6] = cpu_to_be16(0x8c00);
1795 	ram_table->crgb_offset[7] = cpu_to_be16(0xa000);
1796 	ram_table->crgb_slope[0]  = cpu_to_be16(0x3147);
1797 	ram_table->crgb_slope[1]  = cpu_to_be16(0x2978);
1798 	ram_table->crgb_slope[2]  = cpu_to_be16(0x23a2);
1799 	ram_table->crgb_slope[3]  = cpu_to_be16(0x1f55);
1800 	ram_table->crgb_slope[4]  = cpu_to_be16(0x1c63);
1801 	ram_table->crgb_slope[5]  = cpu_to_be16(0x1a0f);
1802 	ram_table->crgb_slope[6]  = cpu_to_be16(0x178d);
1803 	ram_table->crgb_slope[7]  = cpu_to_be16(0x15ab);
1804 
1805 	fill_backlight_transform_table(
1806 			params, ram_table);
1807 }
1808 
1809 static void fill_iram_v_2_2(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parameters params)
1810 {
1811 	unsigned int set = params.set;
1812 
1813 	ram_table->flags = 0x0;
1814 
1815 	ram_table->min_abm_backlight =
1816 			cpu_to_be16(params.min_abm_backlight);
1817 
1818 	ram_table->deviation_gain[0] = 0xb3;
1819 	ram_table->deviation_gain[1] = 0xa8;
1820 	ram_table->deviation_gain[2] = 0x98;
1821 	ram_table->deviation_gain[3] = 0x68;
1822 
1823 	ram_table->min_reduction[0][0] = min_reduction_table_v_2_2[abm_config[set][0]];
1824 	ram_table->min_reduction[1][0] = min_reduction_table_v_2_2[abm_config[set][0]];
1825 	ram_table->min_reduction[2][0] = min_reduction_table_v_2_2[abm_config[set][0]];
1826 	ram_table->min_reduction[3][0] = min_reduction_table_v_2_2[abm_config[set][0]];
1827 	ram_table->min_reduction[4][0] = min_reduction_table_v_2_2[abm_config[set][0]];
1828 	ram_table->max_reduction[0][0] = max_reduction_table_v_2_2[abm_config[set][0]];
1829 	ram_table->max_reduction[1][0] = max_reduction_table_v_2_2[abm_config[set][0]];
1830 	ram_table->max_reduction[2][0] = max_reduction_table_v_2_2[abm_config[set][0]];
1831 	ram_table->max_reduction[3][0] = max_reduction_table_v_2_2[abm_config[set][0]];
1832 	ram_table->max_reduction[4][0] = max_reduction_table_v_2_2[abm_config[set][0]];
1833 
1834 	ram_table->min_reduction[0][1] = min_reduction_table_v_2_2[abm_config[set][1]];
1835 	ram_table->min_reduction[1][1] = min_reduction_table_v_2_2[abm_config[set][1]];
1836 	ram_table->min_reduction[2][1] = min_reduction_table_v_2_2[abm_config[set][1]];
1837 	ram_table->min_reduction[3][1] = min_reduction_table_v_2_2[abm_config[set][1]];
1838 	ram_table->min_reduction[4][1] = min_reduction_table_v_2_2[abm_config[set][1]];
1839 	ram_table->max_reduction[0][1] = max_reduction_table_v_2_2[abm_config[set][1]];
1840 	ram_table->max_reduction[1][1] = max_reduction_table_v_2_2[abm_config[set][1]];
1841 	ram_table->max_reduction[2][1] = max_reduction_table_v_2_2[abm_config[set][1]];
1842 	ram_table->max_reduction[3][1] = max_reduction_table_v_2_2[abm_config[set][1]];
1843 	ram_table->max_reduction[4][1] = max_reduction_table_v_2_2[abm_config[set][1]];
1844 
1845 	ram_table->min_reduction[0][2] = min_reduction_table_v_2_2[abm_config[set][2]];
1846 	ram_table->min_reduction[1][2] = min_reduction_table_v_2_2[abm_config[set][2]];
1847 	ram_table->min_reduction[2][2] = min_reduction_table_v_2_2[abm_config[set][2]];
1848 	ram_table->min_reduction[3][2] = min_reduction_table_v_2_2[abm_config[set][2]];
1849 	ram_table->min_reduction[4][2] = min_reduction_table_v_2_2[abm_config[set][2]];
1850 	ram_table->max_reduction[0][2] = max_reduction_table_v_2_2[abm_config[set][2]];
1851 	ram_table->max_reduction[1][2] = max_reduction_table_v_2_2[abm_config[set][2]];
1852 	ram_table->max_reduction[2][2] = max_reduction_table_v_2_2[abm_config[set][2]];
1853 	ram_table->max_reduction[3][2] = max_reduction_table_v_2_2[abm_config[set][2]];
1854 	ram_table->max_reduction[4][2] = max_reduction_table_v_2_2[abm_config[set][2]];
1855 
1856 	ram_table->min_reduction[0][3] = min_reduction_table_v_2_2[abm_config[set][3]];
1857 	ram_table->min_reduction[1][3] = min_reduction_table_v_2_2[abm_config[set][3]];
1858 	ram_table->min_reduction[2][3] = min_reduction_table_v_2_2[abm_config[set][3]];
1859 	ram_table->min_reduction[3][3] = min_reduction_table_v_2_2[abm_config[set][3]];
1860 	ram_table->min_reduction[4][3] = min_reduction_table_v_2_2[abm_config[set][3]];
1861 	ram_table->max_reduction[0][3] = max_reduction_table_v_2_2[abm_config[set][3]];
1862 	ram_table->max_reduction[1][3] = max_reduction_table_v_2_2[abm_config[set][3]];
1863 	ram_table->max_reduction[2][3] = max_reduction_table_v_2_2[abm_config[set][3]];
1864 	ram_table->max_reduction[3][3] = max_reduction_table_v_2_2[abm_config[set][3]];
1865 	ram_table->max_reduction[4][3] = max_reduction_table_v_2_2[abm_config[set][3]];
1866 
1867 	ram_table->bright_pos_gain[0][0] = 0x20;
1868 	ram_table->bright_pos_gain[0][1] = 0x20;
1869 	ram_table->bright_pos_gain[0][2] = 0x20;
1870 	ram_table->bright_pos_gain[0][3] = 0x20;
1871 	ram_table->bright_pos_gain[1][0] = 0x20;
1872 	ram_table->bright_pos_gain[1][1] = 0x20;
1873 	ram_table->bright_pos_gain[1][2] = 0x20;
1874 	ram_table->bright_pos_gain[1][3] = 0x20;
1875 	ram_table->bright_pos_gain[2][0] = 0x20;
1876 	ram_table->bright_pos_gain[2][1] = 0x20;
1877 	ram_table->bright_pos_gain[2][2] = 0x20;
1878 	ram_table->bright_pos_gain[2][3] = 0x20;
1879 	ram_table->bright_pos_gain[3][0] = 0x20;
1880 	ram_table->bright_pos_gain[3][1] = 0x20;
1881 	ram_table->bright_pos_gain[3][2] = 0x20;
1882 	ram_table->bright_pos_gain[3][3] = 0x20;
1883 	ram_table->bright_pos_gain[4][0] = 0x20;
1884 	ram_table->bright_pos_gain[4][1] = 0x20;
1885 	ram_table->bright_pos_gain[4][2] = 0x20;
1886 	ram_table->bright_pos_gain[4][3] = 0x20;
1887 
1888 	ram_table->dark_pos_gain[0][0] = 0x00;
1889 	ram_table->dark_pos_gain[0][1] = 0x00;
1890 	ram_table->dark_pos_gain[0][2] = 0x00;
1891 	ram_table->dark_pos_gain[0][3] = 0x00;
1892 	ram_table->dark_pos_gain[1][0] = 0x00;
1893 	ram_table->dark_pos_gain[1][1] = 0x00;
1894 	ram_table->dark_pos_gain[1][2] = 0x00;
1895 	ram_table->dark_pos_gain[1][3] = 0x00;
1896 	ram_table->dark_pos_gain[2][0] = 0x00;
1897 	ram_table->dark_pos_gain[2][1] = 0x00;
1898 	ram_table->dark_pos_gain[2][2] = 0x00;
1899 	ram_table->dark_pos_gain[2][3] = 0x00;
1900 	ram_table->dark_pos_gain[3][0] = 0x00;
1901 	ram_table->dark_pos_gain[3][1] = 0x00;
1902 	ram_table->dark_pos_gain[3][2] = 0x00;
1903 	ram_table->dark_pos_gain[3][3] = 0x00;
1904 	ram_table->dark_pos_gain[4][0] = 0x00;
1905 	ram_table->dark_pos_gain[4][1] = 0x00;
1906 	ram_table->dark_pos_gain[4][2] = 0x00;
1907 	ram_table->dark_pos_gain[4][3] = 0x00;
1908 
1909 	ram_table->hybrid_factor[0] = 0xff;
1910 	ram_table->hybrid_factor[1] = 0xff;
1911 	ram_table->hybrid_factor[2] = 0xff;
1912 	ram_table->hybrid_factor[3] = 0xc0;
1913 
1914 	ram_table->contrast_factor[0] = 0x99;
1915 	ram_table->contrast_factor[1] = 0x99;
1916 	ram_table->contrast_factor[2] = 0x90;
1917 	ram_table->contrast_factor[3] = 0x80;
1918 
1919 	ram_table->iir_curve[0] = 0x65;
1920 	ram_table->iir_curve[1] = 0x65;
1921 	ram_table->iir_curve[2] = 0x65;
1922 	ram_table->iir_curve[3] = 0x65;
1923 	ram_table->iir_curve[4] = 0x65;
1924 
1925 	//Gamma 2.2
1926 	ram_table->crgb_thresh[0] = cpu_to_be16(0x127c);
1927 	ram_table->crgb_thresh[1] = cpu_to_be16(0x151b);
1928 	ram_table->crgb_thresh[2] = cpu_to_be16(0x17d5);
1929 	ram_table->crgb_thresh[3] = cpu_to_be16(0x1a56);
1930 	ram_table->crgb_thresh[4] = cpu_to_be16(0x1c83);
1931 	ram_table->crgb_thresh[5] = cpu_to_be16(0x1e72);
1932 	ram_table->crgb_thresh[6] = cpu_to_be16(0x20f0);
1933 	ram_table->crgb_thresh[7] = cpu_to_be16(0x232b);
1934 	ram_table->crgb_offset[0] = cpu_to_be16(0x2999);
1935 	ram_table->crgb_offset[1] = cpu_to_be16(0x3999);
1936 	ram_table->crgb_offset[2] = cpu_to_be16(0x4666);
1937 	ram_table->crgb_offset[3] = cpu_to_be16(0x5999);
1938 	ram_table->crgb_offset[4] = cpu_to_be16(0x6333);
1939 	ram_table->crgb_offset[5] = cpu_to_be16(0x7800);
1940 	ram_table->crgb_offset[6] = cpu_to_be16(0x8c00);
1941 	ram_table->crgb_offset[7] = cpu_to_be16(0xa000);
1942 	ram_table->crgb_slope[0]  = cpu_to_be16(0x3609);
1943 	ram_table->crgb_slope[1]  = cpu_to_be16(0x2dfa);
1944 	ram_table->crgb_slope[2]  = cpu_to_be16(0x27ea);
1945 	ram_table->crgb_slope[3]  = cpu_to_be16(0x235d);
1946 	ram_table->crgb_slope[4]  = cpu_to_be16(0x2042);
1947 	ram_table->crgb_slope[5]  = cpu_to_be16(0x1dc3);
1948 	ram_table->crgb_slope[6]  = cpu_to_be16(0x1b1a);
1949 	ram_table->crgb_slope[7]  = cpu_to_be16(0x1910);
1950 
1951 	fill_backlight_transform_table_v_2_2(
1952 			params, ram_table, true);
1953 }
1954 
1955 static void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parameters params, bool big_endian)
1956 {
1957 	unsigned int i, j;
1958 	unsigned int set = params.set;
1959 
1960 	ram_table->flags = 0x0;
1961 	ram_table->min_abm_backlight = (uint16_t)((big_endian) ?
1962 		cpu_to_be16(params.min_abm_backlight) :
1963 		cpu_to_le16(params.min_abm_backlight));
1964 
1965 	for (i = 0; i < NUM_AGGR_LEVEL; i++) {
1966 		ram_table->hybrid_factor[i] = (uint8_t)abm_settings[set][i].brightness_gain;
1967 		ram_table->contrast_factor[i] = abm_settings[set][i].contrast_factor;
1968 		ram_table->deviation_gain[i] = abm_settings[set][i].deviation_gain;
1969 		ram_table->min_knee[i] = abm_settings[set][i].min_knee;
1970 		ram_table->max_knee[i] = abm_settings[set][i].max_knee;
1971 
1972 		for (j = 0; j < NUM_AMBI_LEVEL; j++) {
1973 			ram_table->min_reduction[j][i] = abm_settings[set][i].min_reduction;
1974 			ram_table->max_reduction[j][i] = abm_settings[set][i].max_reduction;
1975 			ram_table->bright_pos_gain[j][i] = abm_settings[set][i].bright_pos_gain;
1976 			ram_table->dark_pos_gain[j][i] = abm_settings[set][i].dark_pos_gain;
1977 		}
1978 	}
1979 
1980 	ram_table->iir_curve[0] = 0x65;
1981 	ram_table->iir_curve[1] = 0x65;
1982 	ram_table->iir_curve[2] = 0x65;
1983 	ram_table->iir_curve[3] = 0x65;
1984 	ram_table->iir_curve[4] = 0x65;
1985 
1986 	//Gamma 2.2
1987 	ram_table->crgb_thresh[0] = bswap16_based_on_endian(big_endian, 0x127c);
1988 	ram_table->crgb_thresh[1] = bswap16_based_on_endian(big_endian, 0x151b);
1989 	ram_table->crgb_thresh[2] = bswap16_based_on_endian(big_endian, 0x17d5);
1990 	ram_table->crgb_thresh[3] = bswap16_based_on_endian(big_endian, 0x1a56);
1991 	ram_table->crgb_thresh[4] = bswap16_based_on_endian(big_endian, 0x1c83);
1992 	ram_table->crgb_thresh[5] = bswap16_based_on_endian(big_endian, 0x1e72);
1993 	ram_table->crgb_thresh[6] = bswap16_based_on_endian(big_endian, 0x20f0);
1994 	ram_table->crgb_thresh[7] = bswap16_based_on_endian(big_endian, 0x232b);
1995 	ram_table->crgb_offset[0] = bswap16_based_on_endian(big_endian, 0x2999);
1996 	ram_table->crgb_offset[1] = bswap16_based_on_endian(big_endian, 0x3999);
1997 	ram_table->crgb_offset[2] = bswap16_based_on_endian(big_endian, 0x4666);
1998 	ram_table->crgb_offset[3] = bswap16_based_on_endian(big_endian, 0x5999);
1999 	ram_table->crgb_offset[4] = bswap16_based_on_endian(big_endian, 0x6333);
2000 	ram_table->crgb_offset[5] = bswap16_based_on_endian(big_endian, 0x7800);
2001 	ram_table->crgb_offset[6] = bswap16_based_on_endian(big_endian, 0x8c00);
2002 	ram_table->crgb_offset[7] = bswap16_based_on_endian(big_endian, 0xa000);
2003 	ram_table->crgb_slope[0]  = bswap16_based_on_endian(big_endian, 0x3609);
2004 	ram_table->crgb_slope[1]  = bswap16_based_on_endian(big_endian, 0x2dfa);
2005 	ram_table->crgb_slope[2]  = bswap16_based_on_endian(big_endian, 0x27ea);
2006 	ram_table->crgb_slope[3]  = bswap16_based_on_endian(big_endian, 0x235d);
2007 	ram_table->crgb_slope[4]  = bswap16_based_on_endian(big_endian, 0x2042);
2008 	ram_table->crgb_slope[5]  = bswap16_based_on_endian(big_endian, 0x1dc3);
2009 	ram_table->crgb_slope[6]  = bswap16_based_on_endian(big_endian, 0x1b1a);
2010 	ram_table->crgb_slope[7]  = bswap16_based_on_endian(big_endian, 0x1910);
2011 
2012 	fill_backlight_transform_table_v_2_2(
2013 			params, ram_table, big_endian);
2014 }
2015 
2016 bool dmub_init_abm_config(struct resource_pool *res_pool,
2017 	struct dmcu_iram_parameters params,
2018 	unsigned int inst)
2019 {
2020 	struct iram_table_v_2_2 ram_table;
2021 	struct abm_config_table config;
2022 	unsigned int set = params.set;
2023 	bool result = false;
2024 	uint32_t i, j = 0;
2025 
2026 	if (res_pool->abm == NULL && res_pool->multiple_abms[inst] == NULL)
2027 		return false;
2028 
2029 	memset(&ram_table, 0, sizeof(ram_table));
2030 	memset(&config, 0, sizeof(config));
2031 
2032 	fill_iram_v_2_3(&ram_table, params, false);
2033 
2034 	// We must copy to structure that is aligned to 32-bit
2035 	for (i = 0; i < NUM_POWER_FN_SEGS; i++) {
2036 		config.crgb_thresh[i] = ram_table.crgb_thresh[i];
2037 		config.crgb_offset[i] = ram_table.crgb_offset[i];
2038 		config.crgb_slope[i] = ram_table.crgb_slope[i];
2039 	}
2040 
2041 	for (i = 0; i < NUM_BL_CURVE_SEGS; i++) {
2042 		config.backlight_thresholds[i] = ram_table.backlight_thresholds[i];
2043 		config.backlight_offsets[i] = ram_table.backlight_offsets[i];
2044 	}
2045 
2046 	for (i = 0; i < NUM_AMBI_LEVEL; i++)
2047 		config.iir_curve[i] = ram_table.iir_curve[i];
2048 
2049 	for (i = 0; i < NUM_AMBI_LEVEL; i++) {
2050 		for (j = 0; j < NUM_AGGR_LEVEL; j++) {
2051 			config.min_reduction[i][j] = ram_table.min_reduction[i][j];
2052 			config.max_reduction[i][j] = ram_table.max_reduction[i][j];
2053 			config.bright_pos_gain[i][j] = ram_table.bright_pos_gain[i][j];
2054 			config.dark_pos_gain[i][j] = ram_table.dark_pos_gain[i][j];
2055 		}
2056 	}
2057 
2058 	for (i = 0; i < NUM_AGGR_LEVEL; i++) {
2059 		config.hybrid_factor[i] = ram_table.hybrid_factor[i];
2060 		config.contrast_factor[i] = ram_table.contrast_factor[i];
2061 		config.deviation_gain[i] = ram_table.deviation_gain[i];
2062 		config.min_knee[i] = ram_table.min_knee[i];
2063 		config.max_knee[i] = ram_table.max_knee[i];
2064 	}
2065 
2066 	if (params.backlight_ramping_override) {
2067 
2068 		ASSERT(params.backlight_ramping_reduction <= 0xFFFF);
2069 		ASSERT(params.backlight_ramping_start <= 0xFFFF);
2070 		for (i = 0; i < NUM_AGGR_LEVEL; i++) {
2071 			config.blRampReduction[i] = (uint16_t)params.backlight_ramping_reduction;
2072 			config.blRampStart[i]     = (uint16_t)params.backlight_ramping_start;
2073 		}
2074 	} else {
2075 		for (i = 0; i < NUM_AGGR_LEVEL; i++) {
2076 			config.blRampReduction[i] = abm_settings[set][i].blRampReduction;
2077 			config.blRampStart[i] = abm_settings[set][i].blRampStart;
2078 		}
2079 	}
2080 
2081 	config.min_abm_backlight = ram_table.min_abm_backlight;
2082 
2083 	if (res_pool->multiple_abms[inst]) {
2084 		result = res_pool->multiple_abms[inst]->funcs->init_abm_config(
2085 			res_pool->multiple_abms[inst], (char *)(&config), sizeof(struct abm_config_table), inst);
2086 	} else
2087 		result = res_pool->abm->funcs->init_abm_config(
2088 			res_pool->abm, (char *)(&config), sizeof(struct abm_config_table), 0);
2089 
2090 	return result;
2091 }
2092 
2093 bool dmcu_load_iram(struct dmcu *dmcu,
2094 	struct dmcu_iram_parameters params)
2095 {
2096 	unsigned char ram_table[IRAM_SIZE];
2097 	bool result = false;
2098 
2099 	if (dmcu == NULL)
2100 		return false;
2101 
2102 	if (dmcu && !dmcu->funcs->is_dmcu_initialized(dmcu))
2103 		return true;
2104 
2105 	memset(&ram_table, 0, sizeof(ram_table));
2106 
2107 	if (dmcu->dmcu_version.abm_version == 0x24) {
2108 		fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params, true);
2109 		result = dmcu->funcs->load_iram(dmcu, 0, (char *)(&ram_table),
2110 						IRAM_RESERVE_AREA_START_V2_2);
2111 	} else if (dmcu->dmcu_version.abm_version == 0x23) {
2112 		fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params, true);
2113 
2114 		result = dmcu->funcs->load_iram(
2115 				dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2);
2116 	} else if (dmcu->dmcu_version.abm_version == 0x22) {
2117 		fill_iram_v_2_2((struct iram_table_v_2_2 *)ram_table, params);
2118 
2119 		result = dmcu->funcs->load_iram(
2120 				dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2);
2121 	} else {
2122 		fill_iram_v_2((struct iram_table_v_2 *)ram_table, params);
2123 
2124 		result = dmcu->funcs->load_iram(
2125 				dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2);
2126 
2127 		if (result)
2128 			result = dmcu->funcs->load_iram(
2129 					dmcu, IRAM_RESERVE_AREA_END_V2 + 1,
2130 					(char *)(&ram_table) + IRAM_RESERVE_AREA_END_V2 + 1,
2131 					sizeof(ram_table) - IRAM_RESERVE_AREA_END_V2 - 1);
2132 	}
2133 
2134 	return result;
2135 }
2136 
2137 bool fill_custom_backlight_caps(unsigned int config_no, struct dm_acpi_atif_backlight_caps *caps)
2138 {
2139 	unsigned int data_points_size;
2140 	uint64_t caps_size;
2141 
2142 	if (config_no >= ARRAY_SIZE(custom_backlight_profiles))
2143 		return false;
2144 
2145 	data_points_size = custom_backlight_profiles[config_no].num_data_points
2146 			* sizeof(custom_backlight_profiles[config_no].data_points[0]);
2147 
2148 	caps_size = sizeof(struct dm_acpi_atif_backlight_caps) - sizeof(caps->data_points) + data_points_size;
2149 	ASSERT(caps_size <= 0xFFFF);
2150 	caps->size = (uint16_t)caps_size;
2151 	caps->flags = 0;
2152 	caps->error_code = 0;
2153 	caps->ac_level_percentage = custom_backlight_profiles[config_no].ac_level_percentage;
2154 	caps->dc_level_percentage = custom_backlight_profiles[config_no].dc_level_percentage;
2155 	caps->min_input_signal = custom_backlight_profiles[config_no].min_input_signal;
2156 	caps->max_input_signal = custom_backlight_profiles[config_no].max_input_signal;
2157 	caps->num_data_points = (uint8_t)custom_backlight_profiles[config_no].num_data_points;
2158 	memcpy(caps->data_points, custom_backlight_profiles[config_no].data_points, data_points_size);
2159 	return true;
2160 }
2161