xref: /linux/drivers/gpu/drm/amd/display/modules/power/power_abm.c (revision 9611c0ce215a66770ccbe5c126bf57ba8c31bcad)
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,	&current_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