Back to home page

OSCL-LXR

 
 

    


0001 /* Copyright 2018 Advanced Micro Devices, Inc.
0002  *
0003  * Permission is hereby granted, free of charge, to any person obtaining a
0004  * copy of this software and associated documentation files (the "Software"),
0005  * to deal in the Software without restriction, including without limitation
0006  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0007  * and/or sell copies of the Software, and to permit persons to whom the
0008  * Software is furnished to do so, subject to the following conditions:
0009  *
0010  * The above copyright notice and this permission notice shall be included in
0011  * all copies or substantial portions of the Software.
0012  *
0013  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0014  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0015  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0016  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0017  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0018  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0019  * OTHER DEALINGS IN THE SOFTWARE.
0020  *
0021  * Authors: AMD
0022  *
0023  */
0024 
0025 #include "power_helpers.h"
0026 #include "dc/inc/hw/dmcu.h"
0027 #include "dc/inc/hw/abm.h"
0028 #include "dc.h"
0029 #include "core_types.h"
0030 #include "dmub_cmd.h"
0031 
0032 #define DIV_ROUNDUP(a, b) (((a)+((b)/2))/(b))
0033 #define bswap16_based_on_endian(big_endian, value) \
0034     (big_endian) ? cpu_to_be16(value) : cpu_to_le16(value)
0035 
0036 /* Possible Min Reduction config from least aggressive to most aggressive
0037  *  0    1     2     3     4     5     6     7     8     9     10    11   12
0038  * 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 %
0039  */
0040 static const unsigned char min_reduction_table[13] = {
0041 0xff, 0xfa, 0xf0, 0xf0, 0xd9, 0xcd, 0xc0, 0xb1, 0x99, 0x93, 0x80, 0x82, 0x66};
0042 
0043 /* Possible Max Reduction configs from least aggressive to most aggressive
0044  *  0    1     2     3     4     5     6     7     8     9     10    11   12
0045  * 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 %
0046  */
0047 static const unsigned char max_reduction_table[13] = {
0048 0xf5, 0xe5, 0xd9, 0xcd, 0xb1, 0xa5, 0xa5, 0x80, 0x65, 0x4d, 0x4d, 0x4d, 0x32};
0049 
0050 /* Possible ABM 2.2 Min Reduction configs from least aggressive to most aggressive
0051  *  0    1     2     3     4     5     6     7     8     9     10    11   12
0052  * 100  100   100   100   100   100   100   100  100  92.2  83.1  75.3  75.3 %
0053  */
0054 static const unsigned char min_reduction_table_v_2_2[13] = {
0055 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xd4, 0xc0, 0xc0};
0056 
0057 /* Possible ABM 2.2 Max Reduction configs from least aggressive to most aggressive
0058  *  0    1     2     3     4     5     6     7     8     9     10    11   12
0059  * 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 %
0060  */
0061 static const unsigned char max_reduction_table_v_2_2[13] = {
0062 0xf5, 0xe5, 0xbf, 0xb1, 0xa5, 0x85, 0x7c, 0x65, 0x4d, 0x40, 0x32, 0x20, 0x20};
0063 
0064 /* Predefined ABM configuration sets. We may have different configuration sets
0065  * in order to satisfy different power/quality requirements.
0066  */
0067 static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_level] = {
0068 /*  ABM Level 1,    ABM Level 2,    ABM Level 3,    ABM Level 4 */
0069 {       2,              5,              7,              8       },  /* Default - Medium aggressiveness */
0070 {       2,              5,              8,              11      },  /* Alt #1  - Increased aggressiveness */
0071 {       0,              2,              4,              8       },  /* Alt #2  - Minimal aggressiveness */
0072 {       3,              6,              10,             12      },  /* Alt #3  - Super aggressiveness */
0073 };
0074 
0075 struct abm_parameters {
0076     unsigned char min_reduction;
0077     unsigned char max_reduction;
0078     unsigned char bright_pos_gain;
0079     unsigned char dark_pos_gain;
0080     unsigned char brightness_gain;
0081     unsigned char contrast_factor;
0082     unsigned char deviation_gain;
0083     unsigned char min_knee;
0084     unsigned char max_knee;
0085     unsigned short blRampReduction;
0086     unsigned short blRampStart;
0087 };
0088 
0089 static const struct abm_parameters abm_settings_config0[abm_defines_max_level] = {
0090 //  min_red  max_red  bright_pos  dark_pos  bright_gain  contrast  dev   min_knee  max_knee  blRed    blStart
0091     {0xff,   0xbf,    0x20,       0x00,     0xff,        0x99,     0xb3, 0x40,     0xe0,     0xf777,  0xcccc},
0092     {0xde,   0x85,    0x20,       0x00,     0xe0,        0x90,     0xa8, 0x40,     0xc8,     0xf777,  0xcccc},
0093     {0xb0,   0x50,    0x20,       0x00,     0xc0,        0x88,     0x78, 0x70,     0xa0,     0xeeee,  0x9999},
0094     {0x82,   0x40,    0x20,       0x00,     0x00,        0xb8,     0xb3, 0x70,     0x70,     0xe333,  0xb333},
0095 };
0096 
0097 static const struct abm_parameters abm_settings_config1[abm_defines_max_level] = {
0098 //  min_red  max_red  bright_pos  dark_pos  bright_gain  contrast  dev   min_knee  max_knee  blRed  blStart
0099     {0xf0,   0xd9,    0x20,       0x00,     0x00,        0xff,     0xb3, 0x70,     0x70,     0xcccc,  0xcccc},
0100     {0xcd,   0xa5,    0x20,       0x00,     0x00,        0xff,     0xb3, 0x70,     0x70,     0xcccc,  0xcccc},
0101     {0x99,   0x65,    0x20,       0x00,     0x00,        0xff,     0xb3, 0x70,     0x70,     0xcccc,  0xcccc},
0102     {0x82,   0x4d,    0x20,       0x00,     0x00,        0xff,     0xb3, 0x70,     0x70,     0xcccc,  0xcccc},
0103 };
0104 
0105 static const struct abm_parameters * const abm_settings[] = {
0106     abm_settings_config0,
0107     abm_settings_config1,
0108 };
0109 
0110 #define NUM_AMBI_LEVEL    5
0111 #define NUM_AGGR_LEVEL    4
0112 #define NUM_POWER_FN_SEGS 8
0113 #define NUM_BL_CURVE_SEGS 16
0114 #define IRAM_SIZE 256
0115 
0116 #define IRAM_RESERVE_AREA_START_V2 0xF0  // reserve 0xF0~0xF6 are write by DMCU only
0117 #define IRAM_RESERVE_AREA_END_V2 0xF6  // reserve 0xF0~0xF6 are write by DMCU only
0118 
0119 #define IRAM_RESERVE_AREA_START_V2_2 0xF0  // reserve 0xF0~0xFF are write by DMCU only
0120 #define IRAM_RESERVE_AREA_END_V2_2 0xFF  // reserve 0xF0~0xFF are write by DMCU only
0121 
0122 #pragma pack(push, 1)
0123 /* NOTE: iRAM is 256B in size */
0124 struct iram_table_v_2 {
0125     /* flags                      */
0126     uint16_t min_abm_backlight;                 /* 0x00 U16  */
0127 
0128     /* parameters for ABM2.0 algorithm */
0129     uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];      /* 0x02 U0.8 */
0130     uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];      /* 0x16 U0.8 */
0131     uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];    /* 0x2a U2.6 */
0132     uint8_t bright_neg_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];    /* 0x3e U2.6 */
0133     uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];      /* 0x52 U2.6 */
0134     uint8_t dark_neg_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];      /* 0x66 U2.6 */
0135     uint8_t iir_curve[NUM_AMBI_LEVEL];              /* 0x7a U0.8 */
0136     uint8_t deviation_gain;                     /* 0x7f U0.8 */
0137 
0138     /* parameters for crgb conversion */
0139     uint16_t crgb_thresh[NUM_POWER_FN_SEGS];            /* 0x80 U3.13 */
0140     uint16_t crgb_offset[NUM_POWER_FN_SEGS];            /* 0x90 U1.15 */
0141     uint16_t crgb_slope[NUM_POWER_FN_SEGS];             /* 0xa0 U4.12 */
0142 
0143     /* parameters for custom curve */
0144     /* thresholds for brightness --> backlight */
0145     uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS];       /* 0xb0 U16.0 */
0146     /* offsets for brightness --> backlight */
0147     uint16_t backlight_offsets[NUM_BL_CURVE_SEGS];          /* 0xd0 U16.0 */
0148 
0149     /* For reading PSR State directly from IRAM */
0150     uint8_t psr_state;                      /* 0xf0       */
0151     uint8_t dmcu_mcp_interface_version;             /* 0xf1       */
0152     uint8_t dmcu_abm_feature_version;               /* 0xf2       */
0153     uint8_t dmcu_psr_feature_version;               /* 0xf3       */
0154     uint16_t dmcu_version;                      /* 0xf4       */
0155     uint8_t dmcu_state;                     /* 0xf6       */
0156 
0157     uint16_t blRampReduction;                   /* 0xf7       */
0158     uint16_t blRampStart;                       /* 0xf9       */
0159     uint8_t dummy5;                         /* 0xfb       */
0160     uint8_t dummy6;                         /* 0xfc       */
0161     uint8_t dummy7;                         /* 0xfd       */
0162     uint8_t dummy8;                         /* 0xfe       */
0163     uint8_t dummy9;                         /* 0xff       */
0164 };
0165 
0166 struct iram_table_v_2_2 {
0167     /* flags                      */
0168     uint16_t flags;                         /* 0x00 U16  */
0169 
0170     /* parameters for ABM2.2 algorithm */
0171     uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];      /* 0x02 U0.8 */
0172     uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];      /* 0x16 U0.8 */
0173     uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];    /* 0x2a U2.6 */
0174     uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];      /* 0x3e U2.6 */
0175     uint8_t hybrid_factor[NUM_AGGR_LEVEL];              /* 0x52 U0.8 */
0176     uint8_t contrast_factor[NUM_AGGR_LEVEL];            /* 0x56 U0.8 */
0177     uint8_t deviation_gain[NUM_AGGR_LEVEL];             /* 0x5a U0.8 */
0178     uint8_t iir_curve[NUM_AMBI_LEVEL];              /* 0x5e U0.8 */
0179     uint8_t min_knee[NUM_AGGR_LEVEL];               /* 0x63 U0.8 */
0180     uint8_t max_knee[NUM_AGGR_LEVEL];               /* 0x67 U0.8 */
0181     uint16_t min_abm_backlight;                 /* 0x6b U16  */
0182     uint8_t pad[19];                        /* 0x6d U0.8 */
0183 
0184     /* parameters for crgb conversion */
0185     uint16_t crgb_thresh[NUM_POWER_FN_SEGS];            /* 0x80 U3.13 */
0186     uint16_t crgb_offset[NUM_POWER_FN_SEGS];            /* 0x90 U1.15 */
0187     uint16_t crgb_slope[NUM_POWER_FN_SEGS];             /* 0xa0 U4.12 */
0188 
0189     /* parameters for custom curve */
0190     /* thresholds for brightness --> backlight */
0191     uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS];       /* 0xb0 U16.0 */
0192     /* offsets for brightness --> backlight */
0193     uint16_t backlight_offsets[NUM_BL_CURVE_SEGS];          /* 0xd0 U16.0 */
0194 
0195     /* For reading PSR State directly from IRAM */
0196     uint8_t psr_state;                      /* 0xf0       */
0197     uint8_t dmcu_mcp_interface_version;             /* 0xf1       */
0198     uint8_t dmcu_abm_feature_version;               /* 0xf2       */
0199     uint8_t dmcu_psr_feature_version;               /* 0xf3       */
0200     uint16_t dmcu_version;                      /* 0xf4       */
0201     uint8_t dmcu_state;                     /* 0xf6       */
0202 
0203     uint8_t dummy1;                         /* 0xf7       */
0204     uint8_t dummy2;                         /* 0xf8       */
0205     uint8_t dummy3;                         /* 0xf9       */
0206     uint8_t dummy4;                         /* 0xfa       */
0207     uint8_t dummy5;                         /* 0xfb       */
0208     uint8_t dummy6;                         /* 0xfc       */
0209     uint8_t dummy7;                         /* 0xfd       */
0210     uint8_t dummy8;                         /* 0xfe       */
0211     uint8_t dummy9;                         /* 0xff       */
0212 };
0213 #pragma pack(pop)
0214 
0215 static void fill_backlight_transform_table(struct dmcu_iram_parameters params,
0216         struct iram_table_v_2 *table)
0217 {
0218     unsigned int i;
0219     unsigned int num_entries = NUM_BL_CURVE_SEGS;
0220     unsigned int lut_index;
0221 
0222     table->backlight_thresholds[0] = 0;
0223     table->backlight_offsets[0] = params.backlight_lut_array[0];
0224     table->backlight_thresholds[num_entries-1] = 0xFFFF;
0225     table->backlight_offsets[num_entries-1] =
0226         params.backlight_lut_array[params.backlight_lut_array_size - 1];
0227 
0228     /* Setup all brightness levels between 0% and 100% exclusive
0229      * Fills brightness-to-backlight transform table. Backlight custom curve
0230      * describes transform from brightness to backlight. It will be defined
0231      * as set of thresholds and set of offsets, together, implying
0232      * extrapolation of custom curve into 16 uniformly spanned linear
0233      * segments.  Each threshold/offset represented by 16 bit entry in
0234      * format U4.10.
0235      */
0236     for (i = 1; i+1 < num_entries; i++) {
0237         lut_index = (params.backlight_lut_array_size - 1) * i / (num_entries - 1);
0238         ASSERT(lut_index < params.backlight_lut_array_size);
0239 
0240         table->backlight_thresholds[i] =
0241             cpu_to_be16(DIV_ROUNDUP((i * 65536), num_entries));
0242         table->backlight_offsets[i] =
0243             cpu_to_be16(params.backlight_lut_array[lut_index]);
0244     }
0245 }
0246 
0247 static void fill_backlight_transform_table_v_2_2(struct dmcu_iram_parameters params,
0248         struct iram_table_v_2_2 *table, bool big_endian)
0249 {
0250     unsigned int i;
0251     unsigned int num_entries = NUM_BL_CURVE_SEGS;
0252     unsigned int lut_index;
0253 
0254     table->backlight_thresholds[0] = 0;
0255     table->backlight_offsets[0] = params.backlight_lut_array[0];
0256     table->backlight_thresholds[num_entries-1] = 0xFFFF;
0257     table->backlight_offsets[num_entries-1] =
0258         params.backlight_lut_array[params.backlight_lut_array_size - 1];
0259 
0260     /* Setup all brightness levels between 0% and 100% exclusive
0261      * Fills brightness-to-backlight transform table. Backlight custom curve
0262      * describes transform from brightness to backlight. It will be defined
0263      * as set of thresholds and set of offsets, together, implying
0264      * extrapolation of custom curve into 16 uniformly spanned linear
0265      * segments.  Each threshold/offset represented by 16 bit entry in
0266      * format U4.10.
0267      */
0268     for (i = 1; i+1 < num_entries; i++) {
0269         lut_index = DIV_ROUNDUP((i * params.backlight_lut_array_size), num_entries);
0270         ASSERT(lut_index < params.backlight_lut_array_size);
0271 
0272         table->backlight_thresholds[i] = (big_endian) ?
0273             cpu_to_be16(DIV_ROUNDUP((i * 65536), num_entries)) :
0274             cpu_to_le16(DIV_ROUNDUP((i * 65536), num_entries));
0275         table->backlight_offsets[i] = (big_endian) ?
0276             cpu_to_be16(params.backlight_lut_array[lut_index]) :
0277             cpu_to_le16(params.backlight_lut_array[lut_index]);
0278     }
0279 }
0280 
0281 static void fill_iram_v_2(struct iram_table_v_2 *ram_table, struct dmcu_iram_parameters params)
0282 {
0283     unsigned int set = params.set;
0284 
0285     ram_table->min_abm_backlight =
0286             cpu_to_be16(params.min_abm_backlight);
0287     ram_table->deviation_gain = 0xb3;
0288 
0289     ram_table->blRampReduction =
0290         cpu_to_be16(params.backlight_ramping_reduction);
0291     ram_table->blRampStart =
0292         cpu_to_be16(params.backlight_ramping_start);
0293 
0294     ram_table->min_reduction[0][0] = min_reduction_table[abm_config[set][0]];
0295     ram_table->min_reduction[1][0] = min_reduction_table[abm_config[set][0]];
0296     ram_table->min_reduction[2][0] = min_reduction_table[abm_config[set][0]];
0297     ram_table->min_reduction[3][0] = min_reduction_table[abm_config[set][0]];
0298     ram_table->min_reduction[4][0] = min_reduction_table[abm_config[set][0]];
0299     ram_table->max_reduction[0][0] = max_reduction_table[abm_config[set][0]];
0300     ram_table->max_reduction[1][0] = max_reduction_table[abm_config[set][0]];
0301     ram_table->max_reduction[2][0] = max_reduction_table[abm_config[set][0]];
0302     ram_table->max_reduction[3][0] = max_reduction_table[abm_config[set][0]];
0303     ram_table->max_reduction[4][0] = max_reduction_table[abm_config[set][0]];
0304 
0305     ram_table->min_reduction[0][1] = min_reduction_table[abm_config[set][1]];
0306     ram_table->min_reduction[1][1] = min_reduction_table[abm_config[set][1]];
0307     ram_table->min_reduction[2][1] = min_reduction_table[abm_config[set][1]];
0308     ram_table->min_reduction[3][1] = min_reduction_table[abm_config[set][1]];
0309     ram_table->min_reduction[4][1] = min_reduction_table[abm_config[set][1]];
0310     ram_table->max_reduction[0][1] = max_reduction_table[abm_config[set][1]];
0311     ram_table->max_reduction[1][1] = max_reduction_table[abm_config[set][1]];
0312     ram_table->max_reduction[2][1] = max_reduction_table[abm_config[set][1]];
0313     ram_table->max_reduction[3][1] = max_reduction_table[abm_config[set][1]];
0314     ram_table->max_reduction[4][1] = max_reduction_table[abm_config[set][1]];
0315 
0316     ram_table->min_reduction[0][2] = min_reduction_table[abm_config[set][2]];
0317     ram_table->min_reduction[1][2] = min_reduction_table[abm_config[set][2]];
0318     ram_table->min_reduction[2][2] = min_reduction_table[abm_config[set][2]];
0319     ram_table->min_reduction[3][2] = min_reduction_table[abm_config[set][2]];
0320     ram_table->min_reduction[4][2] = min_reduction_table[abm_config[set][2]];
0321     ram_table->max_reduction[0][2] = max_reduction_table[abm_config[set][2]];
0322     ram_table->max_reduction[1][2] = max_reduction_table[abm_config[set][2]];
0323     ram_table->max_reduction[2][2] = max_reduction_table[abm_config[set][2]];
0324     ram_table->max_reduction[3][2] = max_reduction_table[abm_config[set][2]];
0325     ram_table->max_reduction[4][2] = max_reduction_table[abm_config[set][2]];
0326 
0327     ram_table->min_reduction[0][3] = min_reduction_table[abm_config[set][3]];
0328     ram_table->min_reduction[1][3] = min_reduction_table[abm_config[set][3]];
0329     ram_table->min_reduction[2][3] = min_reduction_table[abm_config[set][3]];
0330     ram_table->min_reduction[3][3] = min_reduction_table[abm_config[set][3]];
0331     ram_table->min_reduction[4][3] = min_reduction_table[abm_config[set][3]];
0332     ram_table->max_reduction[0][3] = max_reduction_table[abm_config[set][3]];
0333     ram_table->max_reduction[1][3] = max_reduction_table[abm_config[set][3]];
0334     ram_table->max_reduction[2][3] = max_reduction_table[abm_config[set][3]];
0335     ram_table->max_reduction[3][3] = max_reduction_table[abm_config[set][3]];
0336     ram_table->max_reduction[4][3] = max_reduction_table[abm_config[set][3]];
0337 
0338     ram_table->bright_pos_gain[0][0] = 0x20;
0339     ram_table->bright_pos_gain[0][1] = 0x20;
0340     ram_table->bright_pos_gain[0][2] = 0x20;
0341     ram_table->bright_pos_gain[0][3] = 0x20;
0342     ram_table->bright_pos_gain[1][0] = 0x20;
0343     ram_table->bright_pos_gain[1][1] = 0x20;
0344     ram_table->bright_pos_gain[1][2] = 0x20;
0345     ram_table->bright_pos_gain[1][3] = 0x20;
0346     ram_table->bright_pos_gain[2][0] = 0x20;
0347     ram_table->bright_pos_gain[2][1] = 0x20;
0348     ram_table->bright_pos_gain[2][2] = 0x20;
0349     ram_table->bright_pos_gain[2][3] = 0x20;
0350     ram_table->bright_pos_gain[3][0] = 0x20;
0351     ram_table->bright_pos_gain[3][1] = 0x20;
0352     ram_table->bright_pos_gain[3][2] = 0x20;
0353     ram_table->bright_pos_gain[3][3] = 0x20;
0354     ram_table->bright_pos_gain[4][0] = 0x20;
0355     ram_table->bright_pos_gain[4][1] = 0x20;
0356     ram_table->bright_pos_gain[4][2] = 0x20;
0357     ram_table->bright_pos_gain[4][3] = 0x20;
0358     ram_table->bright_neg_gain[0][0] = 0x00;
0359     ram_table->bright_neg_gain[0][1] = 0x00;
0360     ram_table->bright_neg_gain[0][2] = 0x00;
0361     ram_table->bright_neg_gain[0][3] = 0x00;
0362     ram_table->bright_neg_gain[1][0] = 0x00;
0363     ram_table->bright_neg_gain[1][1] = 0x00;
0364     ram_table->bright_neg_gain[1][2] = 0x00;
0365     ram_table->bright_neg_gain[1][3] = 0x00;
0366     ram_table->bright_neg_gain[2][0] = 0x00;
0367     ram_table->bright_neg_gain[2][1] = 0x00;
0368     ram_table->bright_neg_gain[2][2] = 0x00;
0369     ram_table->bright_neg_gain[2][3] = 0x00;
0370     ram_table->bright_neg_gain[3][0] = 0x00;
0371     ram_table->bright_neg_gain[3][1] = 0x00;
0372     ram_table->bright_neg_gain[3][2] = 0x00;
0373     ram_table->bright_neg_gain[3][3] = 0x00;
0374     ram_table->bright_neg_gain[4][0] = 0x00;
0375     ram_table->bright_neg_gain[4][1] = 0x00;
0376     ram_table->bright_neg_gain[4][2] = 0x00;
0377     ram_table->bright_neg_gain[4][3] = 0x00;
0378     ram_table->dark_pos_gain[0][0] = 0x00;
0379     ram_table->dark_pos_gain[0][1] = 0x00;
0380     ram_table->dark_pos_gain[0][2] = 0x00;
0381     ram_table->dark_pos_gain[0][3] = 0x00;
0382     ram_table->dark_pos_gain[1][0] = 0x00;
0383     ram_table->dark_pos_gain[1][1] = 0x00;
0384     ram_table->dark_pos_gain[1][2] = 0x00;
0385     ram_table->dark_pos_gain[1][3] = 0x00;
0386     ram_table->dark_pos_gain[2][0] = 0x00;
0387     ram_table->dark_pos_gain[2][1] = 0x00;
0388     ram_table->dark_pos_gain[2][2] = 0x00;
0389     ram_table->dark_pos_gain[2][3] = 0x00;
0390     ram_table->dark_pos_gain[3][0] = 0x00;
0391     ram_table->dark_pos_gain[3][1] = 0x00;
0392     ram_table->dark_pos_gain[3][2] = 0x00;
0393     ram_table->dark_pos_gain[3][3] = 0x00;
0394     ram_table->dark_pos_gain[4][0] = 0x00;
0395     ram_table->dark_pos_gain[4][1] = 0x00;
0396     ram_table->dark_pos_gain[4][2] = 0x00;
0397     ram_table->dark_pos_gain[4][3] = 0x00;
0398     ram_table->dark_neg_gain[0][0] = 0x00;
0399     ram_table->dark_neg_gain[0][1] = 0x00;
0400     ram_table->dark_neg_gain[0][2] = 0x00;
0401     ram_table->dark_neg_gain[0][3] = 0x00;
0402     ram_table->dark_neg_gain[1][0] = 0x00;
0403     ram_table->dark_neg_gain[1][1] = 0x00;
0404     ram_table->dark_neg_gain[1][2] = 0x00;
0405     ram_table->dark_neg_gain[1][3] = 0x00;
0406     ram_table->dark_neg_gain[2][0] = 0x00;
0407     ram_table->dark_neg_gain[2][1] = 0x00;
0408     ram_table->dark_neg_gain[2][2] = 0x00;
0409     ram_table->dark_neg_gain[2][3] = 0x00;
0410     ram_table->dark_neg_gain[3][0] = 0x00;
0411     ram_table->dark_neg_gain[3][1] = 0x00;
0412     ram_table->dark_neg_gain[3][2] = 0x00;
0413     ram_table->dark_neg_gain[3][3] = 0x00;
0414     ram_table->dark_neg_gain[4][0] = 0x00;
0415     ram_table->dark_neg_gain[4][1] = 0x00;
0416     ram_table->dark_neg_gain[4][2] = 0x00;
0417     ram_table->dark_neg_gain[4][3] = 0x00;
0418 
0419     ram_table->iir_curve[0] = 0x65;
0420     ram_table->iir_curve[1] = 0x65;
0421     ram_table->iir_curve[2] = 0x65;
0422     ram_table->iir_curve[3] = 0x65;
0423     ram_table->iir_curve[4] = 0x65;
0424 
0425     //Gamma 2.4
0426     ram_table->crgb_thresh[0] = cpu_to_be16(0x13b6);
0427     ram_table->crgb_thresh[1] = cpu_to_be16(0x1648);
0428     ram_table->crgb_thresh[2] = cpu_to_be16(0x18e3);
0429     ram_table->crgb_thresh[3] = cpu_to_be16(0x1b41);
0430     ram_table->crgb_thresh[4] = cpu_to_be16(0x1d46);
0431     ram_table->crgb_thresh[5] = cpu_to_be16(0x1f21);
0432     ram_table->crgb_thresh[6] = cpu_to_be16(0x2167);
0433     ram_table->crgb_thresh[7] = cpu_to_be16(0x2384);
0434     ram_table->crgb_offset[0] = cpu_to_be16(0x2999);
0435     ram_table->crgb_offset[1] = cpu_to_be16(0x3999);
0436     ram_table->crgb_offset[2] = cpu_to_be16(0x4666);
0437     ram_table->crgb_offset[3] = cpu_to_be16(0x5999);
0438     ram_table->crgb_offset[4] = cpu_to_be16(0x6333);
0439     ram_table->crgb_offset[5] = cpu_to_be16(0x7800);
0440     ram_table->crgb_offset[6] = cpu_to_be16(0x8c00);
0441     ram_table->crgb_offset[7] = cpu_to_be16(0xa000);
0442     ram_table->crgb_slope[0]  = cpu_to_be16(0x3147);
0443     ram_table->crgb_slope[1]  = cpu_to_be16(0x2978);
0444     ram_table->crgb_slope[2]  = cpu_to_be16(0x23a2);
0445     ram_table->crgb_slope[3]  = cpu_to_be16(0x1f55);
0446     ram_table->crgb_slope[4]  = cpu_to_be16(0x1c63);
0447     ram_table->crgb_slope[5]  = cpu_to_be16(0x1a0f);
0448     ram_table->crgb_slope[6]  = cpu_to_be16(0x178d);
0449     ram_table->crgb_slope[7]  = cpu_to_be16(0x15ab);
0450 
0451     fill_backlight_transform_table(
0452             params, ram_table);
0453 }
0454 
0455 static void fill_iram_v_2_2(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parameters params)
0456 {
0457     unsigned int set = params.set;
0458 
0459     ram_table->flags = 0x0;
0460 
0461     ram_table->min_abm_backlight =
0462             cpu_to_be16(params.min_abm_backlight);
0463 
0464     ram_table->deviation_gain[0] = 0xb3;
0465     ram_table->deviation_gain[1] = 0xa8;
0466     ram_table->deviation_gain[2] = 0x98;
0467     ram_table->deviation_gain[3] = 0x68;
0468 
0469     ram_table->min_reduction[0][0] = min_reduction_table_v_2_2[abm_config[set][0]];
0470     ram_table->min_reduction[1][0] = min_reduction_table_v_2_2[abm_config[set][0]];
0471     ram_table->min_reduction[2][0] = min_reduction_table_v_2_2[abm_config[set][0]];
0472     ram_table->min_reduction[3][0] = min_reduction_table_v_2_2[abm_config[set][0]];
0473     ram_table->min_reduction[4][0] = min_reduction_table_v_2_2[abm_config[set][0]];
0474     ram_table->max_reduction[0][0] = max_reduction_table_v_2_2[abm_config[set][0]];
0475     ram_table->max_reduction[1][0] = max_reduction_table_v_2_2[abm_config[set][0]];
0476     ram_table->max_reduction[2][0] = max_reduction_table_v_2_2[abm_config[set][0]];
0477     ram_table->max_reduction[3][0] = max_reduction_table_v_2_2[abm_config[set][0]];
0478     ram_table->max_reduction[4][0] = max_reduction_table_v_2_2[abm_config[set][0]];
0479 
0480     ram_table->min_reduction[0][1] = min_reduction_table_v_2_2[abm_config[set][1]];
0481     ram_table->min_reduction[1][1] = min_reduction_table_v_2_2[abm_config[set][1]];
0482     ram_table->min_reduction[2][1] = min_reduction_table_v_2_2[abm_config[set][1]];
0483     ram_table->min_reduction[3][1] = min_reduction_table_v_2_2[abm_config[set][1]];
0484     ram_table->min_reduction[4][1] = min_reduction_table_v_2_2[abm_config[set][1]];
0485     ram_table->max_reduction[0][1] = max_reduction_table_v_2_2[abm_config[set][1]];
0486     ram_table->max_reduction[1][1] = max_reduction_table_v_2_2[abm_config[set][1]];
0487     ram_table->max_reduction[2][1] = max_reduction_table_v_2_2[abm_config[set][1]];
0488     ram_table->max_reduction[3][1] = max_reduction_table_v_2_2[abm_config[set][1]];
0489     ram_table->max_reduction[4][1] = max_reduction_table_v_2_2[abm_config[set][1]];
0490 
0491     ram_table->min_reduction[0][2] = min_reduction_table_v_2_2[abm_config[set][2]];
0492     ram_table->min_reduction[1][2] = min_reduction_table_v_2_2[abm_config[set][2]];
0493     ram_table->min_reduction[2][2] = min_reduction_table_v_2_2[abm_config[set][2]];
0494     ram_table->min_reduction[3][2] = min_reduction_table_v_2_2[abm_config[set][2]];
0495     ram_table->min_reduction[4][2] = min_reduction_table_v_2_2[abm_config[set][2]];
0496     ram_table->max_reduction[0][2] = max_reduction_table_v_2_2[abm_config[set][2]];
0497     ram_table->max_reduction[1][2] = max_reduction_table_v_2_2[abm_config[set][2]];
0498     ram_table->max_reduction[2][2] = max_reduction_table_v_2_2[abm_config[set][2]];
0499     ram_table->max_reduction[3][2] = max_reduction_table_v_2_2[abm_config[set][2]];
0500     ram_table->max_reduction[4][2] = max_reduction_table_v_2_2[abm_config[set][2]];
0501 
0502     ram_table->min_reduction[0][3] = min_reduction_table_v_2_2[abm_config[set][3]];
0503     ram_table->min_reduction[1][3] = min_reduction_table_v_2_2[abm_config[set][3]];
0504     ram_table->min_reduction[2][3] = min_reduction_table_v_2_2[abm_config[set][3]];
0505     ram_table->min_reduction[3][3] = min_reduction_table_v_2_2[abm_config[set][3]];
0506     ram_table->min_reduction[4][3] = min_reduction_table_v_2_2[abm_config[set][3]];
0507     ram_table->max_reduction[0][3] = max_reduction_table_v_2_2[abm_config[set][3]];
0508     ram_table->max_reduction[1][3] = max_reduction_table_v_2_2[abm_config[set][3]];
0509     ram_table->max_reduction[2][3] = max_reduction_table_v_2_2[abm_config[set][3]];
0510     ram_table->max_reduction[3][3] = max_reduction_table_v_2_2[abm_config[set][3]];
0511     ram_table->max_reduction[4][3] = max_reduction_table_v_2_2[abm_config[set][3]];
0512 
0513     ram_table->bright_pos_gain[0][0] = 0x20;
0514     ram_table->bright_pos_gain[0][1] = 0x20;
0515     ram_table->bright_pos_gain[0][2] = 0x20;
0516     ram_table->bright_pos_gain[0][3] = 0x20;
0517     ram_table->bright_pos_gain[1][0] = 0x20;
0518     ram_table->bright_pos_gain[1][1] = 0x20;
0519     ram_table->bright_pos_gain[1][2] = 0x20;
0520     ram_table->bright_pos_gain[1][3] = 0x20;
0521     ram_table->bright_pos_gain[2][0] = 0x20;
0522     ram_table->bright_pos_gain[2][1] = 0x20;
0523     ram_table->bright_pos_gain[2][2] = 0x20;
0524     ram_table->bright_pos_gain[2][3] = 0x20;
0525     ram_table->bright_pos_gain[3][0] = 0x20;
0526     ram_table->bright_pos_gain[3][1] = 0x20;
0527     ram_table->bright_pos_gain[3][2] = 0x20;
0528     ram_table->bright_pos_gain[3][3] = 0x20;
0529     ram_table->bright_pos_gain[4][0] = 0x20;
0530     ram_table->bright_pos_gain[4][1] = 0x20;
0531     ram_table->bright_pos_gain[4][2] = 0x20;
0532     ram_table->bright_pos_gain[4][3] = 0x20;
0533 
0534     ram_table->dark_pos_gain[0][0] = 0x00;
0535     ram_table->dark_pos_gain[0][1] = 0x00;
0536     ram_table->dark_pos_gain[0][2] = 0x00;
0537     ram_table->dark_pos_gain[0][3] = 0x00;
0538     ram_table->dark_pos_gain[1][0] = 0x00;
0539     ram_table->dark_pos_gain[1][1] = 0x00;
0540     ram_table->dark_pos_gain[1][2] = 0x00;
0541     ram_table->dark_pos_gain[1][3] = 0x00;
0542     ram_table->dark_pos_gain[2][0] = 0x00;
0543     ram_table->dark_pos_gain[2][1] = 0x00;
0544     ram_table->dark_pos_gain[2][2] = 0x00;
0545     ram_table->dark_pos_gain[2][3] = 0x00;
0546     ram_table->dark_pos_gain[3][0] = 0x00;
0547     ram_table->dark_pos_gain[3][1] = 0x00;
0548     ram_table->dark_pos_gain[3][2] = 0x00;
0549     ram_table->dark_pos_gain[3][3] = 0x00;
0550     ram_table->dark_pos_gain[4][0] = 0x00;
0551     ram_table->dark_pos_gain[4][1] = 0x00;
0552     ram_table->dark_pos_gain[4][2] = 0x00;
0553     ram_table->dark_pos_gain[4][3] = 0x00;
0554 
0555     ram_table->hybrid_factor[0] = 0xff;
0556     ram_table->hybrid_factor[1] = 0xff;
0557     ram_table->hybrid_factor[2] = 0xff;
0558     ram_table->hybrid_factor[3] = 0xc0;
0559 
0560     ram_table->contrast_factor[0] = 0x99;
0561     ram_table->contrast_factor[1] = 0x99;
0562     ram_table->contrast_factor[2] = 0x90;
0563     ram_table->contrast_factor[3] = 0x80;
0564 
0565     ram_table->iir_curve[0] = 0x65;
0566     ram_table->iir_curve[1] = 0x65;
0567     ram_table->iir_curve[2] = 0x65;
0568     ram_table->iir_curve[3] = 0x65;
0569     ram_table->iir_curve[4] = 0x65;
0570 
0571     //Gamma 2.2
0572     ram_table->crgb_thresh[0] = cpu_to_be16(0x127c);
0573     ram_table->crgb_thresh[1] = cpu_to_be16(0x151b);
0574     ram_table->crgb_thresh[2] = cpu_to_be16(0x17d5);
0575     ram_table->crgb_thresh[3] = cpu_to_be16(0x1a56);
0576     ram_table->crgb_thresh[4] = cpu_to_be16(0x1c83);
0577     ram_table->crgb_thresh[5] = cpu_to_be16(0x1e72);
0578     ram_table->crgb_thresh[6] = cpu_to_be16(0x20f0);
0579     ram_table->crgb_thresh[7] = cpu_to_be16(0x232b);
0580     ram_table->crgb_offset[0] = cpu_to_be16(0x2999);
0581     ram_table->crgb_offset[1] = cpu_to_be16(0x3999);
0582     ram_table->crgb_offset[2] = cpu_to_be16(0x4666);
0583     ram_table->crgb_offset[3] = cpu_to_be16(0x5999);
0584     ram_table->crgb_offset[4] = cpu_to_be16(0x6333);
0585     ram_table->crgb_offset[5] = cpu_to_be16(0x7800);
0586     ram_table->crgb_offset[6] = cpu_to_be16(0x8c00);
0587     ram_table->crgb_offset[7] = cpu_to_be16(0xa000);
0588     ram_table->crgb_slope[0]  = cpu_to_be16(0x3609);
0589     ram_table->crgb_slope[1]  = cpu_to_be16(0x2dfa);
0590     ram_table->crgb_slope[2]  = cpu_to_be16(0x27ea);
0591     ram_table->crgb_slope[3]  = cpu_to_be16(0x235d);
0592     ram_table->crgb_slope[4]  = cpu_to_be16(0x2042);
0593     ram_table->crgb_slope[5]  = cpu_to_be16(0x1dc3);
0594     ram_table->crgb_slope[6]  = cpu_to_be16(0x1b1a);
0595     ram_table->crgb_slope[7]  = cpu_to_be16(0x1910);
0596 
0597     fill_backlight_transform_table_v_2_2(
0598             params, ram_table, true);
0599 }
0600 
0601 static void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parameters params, bool big_endian)
0602 {
0603     unsigned int i, j;
0604     unsigned int set = params.set;
0605 
0606     ram_table->flags = 0x0;
0607     ram_table->min_abm_backlight = (big_endian) ?
0608         cpu_to_be16(params.min_abm_backlight) :
0609         cpu_to_le16(params.min_abm_backlight);
0610 
0611     for (i = 0; i < NUM_AGGR_LEVEL; i++) {
0612         ram_table->hybrid_factor[i] = abm_settings[set][i].brightness_gain;
0613         ram_table->contrast_factor[i] = abm_settings[set][i].contrast_factor;
0614         ram_table->deviation_gain[i] = abm_settings[set][i].deviation_gain;
0615         ram_table->min_knee[i] = abm_settings[set][i].min_knee;
0616         ram_table->max_knee[i] = abm_settings[set][i].max_knee;
0617 
0618         for (j = 0; j < NUM_AMBI_LEVEL; j++) {
0619             ram_table->min_reduction[j][i] = abm_settings[set][i].min_reduction;
0620             ram_table->max_reduction[j][i] = abm_settings[set][i].max_reduction;
0621             ram_table->bright_pos_gain[j][i] = abm_settings[set][i].bright_pos_gain;
0622             ram_table->dark_pos_gain[j][i] = abm_settings[set][i].dark_pos_gain;
0623         }
0624     }
0625 
0626     ram_table->iir_curve[0] = 0x65;
0627     ram_table->iir_curve[1] = 0x65;
0628     ram_table->iir_curve[2] = 0x65;
0629     ram_table->iir_curve[3] = 0x65;
0630     ram_table->iir_curve[4] = 0x65;
0631 
0632     //Gamma 2.2
0633     ram_table->crgb_thresh[0] = bswap16_based_on_endian(big_endian, 0x127c);
0634     ram_table->crgb_thresh[1] = bswap16_based_on_endian(big_endian, 0x151b);
0635     ram_table->crgb_thresh[2] = bswap16_based_on_endian(big_endian, 0x17d5);
0636     ram_table->crgb_thresh[3] = bswap16_based_on_endian(big_endian, 0x1a56);
0637     ram_table->crgb_thresh[4] = bswap16_based_on_endian(big_endian, 0x1c83);
0638     ram_table->crgb_thresh[5] = bswap16_based_on_endian(big_endian, 0x1e72);
0639     ram_table->crgb_thresh[6] = bswap16_based_on_endian(big_endian, 0x20f0);
0640     ram_table->crgb_thresh[7] = bswap16_based_on_endian(big_endian, 0x232b);
0641     ram_table->crgb_offset[0] = bswap16_based_on_endian(big_endian, 0x2999);
0642     ram_table->crgb_offset[1] = bswap16_based_on_endian(big_endian, 0x3999);
0643     ram_table->crgb_offset[2] = bswap16_based_on_endian(big_endian, 0x4666);
0644     ram_table->crgb_offset[3] = bswap16_based_on_endian(big_endian, 0x5999);
0645     ram_table->crgb_offset[4] = bswap16_based_on_endian(big_endian, 0x6333);
0646     ram_table->crgb_offset[5] = bswap16_based_on_endian(big_endian, 0x7800);
0647     ram_table->crgb_offset[6] = bswap16_based_on_endian(big_endian, 0x8c00);
0648     ram_table->crgb_offset[7] = bswap16_based_on_endian(big_endian, 0xa000);
0649     ram_table->crgb_slope[0]  = bswap16_based_on_endian(big_endian, 0x3609);
0650     ram_table->crgb_slope[1]  = bswap16_based_on_endian(big_endian, 0x2dfa);
0651     ram_table->crgb_slope[2]  = bswap16_based_on_endian(big_endian, 0x27ea);
0652     ram_table->crgb_slope[3]  = bswap16_based_on_endian(big_endian, 0x235d);
0653     ram_table->crgb_slope[4]  = bswap16_based_on_endian(big_endian, 0x2042);
0654     ram_table->crgb_slope[5]  = bswap16_based_on_endian(big_endian, 0x1dc3);
0655     ram_table->crgb_slope[6]  = bswap16_based_on_endian(big_endian, 0x1b1a);
0656     ram_table->crgb_slope[7]  = bswap16_based_on_endian(big_endian, 0x1910);
0657 
0658     fill_backlight_transform_table_v_2_2(
0659             params, ram_table, big_endian);
0660 }
0661 
0662 bool dmub_init_abm_config(struct resource_pool *res_pool,
0663     struct dmcu_iram_parameters params,
0664     unsigned int inst)
0665 {
0666     struct iram_table_v_2_2 ram_table;
0667     struct abm_config_table config;
0668     unsigned int set = params.set;
0669     bool result = false;
0670     uint32_t i, j = 0;
0671 
0672 #if defined(CONFIG_DRM_AMD_DC_DCN)
0673     if (res_pool->abm == NULL && res_pool->multiple_abms[inst] == NULL)
0674         return false;
0675 #else
0676     if (res_pool->abm == NULL)
0677         return false;
0678 #endif
0679 
0680     memset(&ram_table, 0, sizeof(ram_table));
0681     memset(&config, 0, sizeof(config));
0682 
0683     fill_iram_v_2_3(&ram_table, params, false);
0684 
0685     // We must copy to structure that is aligned to 32-bit
0686     for (i = 0; i < NUM_POWER_FN_SEGS; i++) {
0687         config.crgb_thresh[i] = ram_table.crgb_thresh[i];
0688         config.crgb_offset[i] = ram_table.crgb_offset[i];
0689         config.crgb_slope[i] = ram_table.crgb_slope[i];
0690     }
0691 
0692     for (i = 0; i < NUM_BL_CURVE_SEGS; i++) {
0693         config.backlight_thresholds[i] = ram_table.backlight_thresholds[i];
0694         config.backlight_offsets[i] = ram_table.backlight_offsets[i];
0695     }
0696 
0697     for (i = 0; i < NUM_AMBI_LEVEL; i++)
0698         config.iir_curve[i] = ram_table.iir_curve[i];
0699 
0700     for (i = 0; i < NUM_AMBI_LEVEL; i++) {
0701         for (j = 0; j < NUM_AGGR_LEVEL; j++) {
0702             config.min_reduction[i][j] = ram_table.min_reduction[i][j];
0703             config.max_reduction[i][j] = ram_table.max_reduction[i][j];
0704             config.bright_pos_gain[i][j] = ram_table.bright_pos_gain[i][j];
0705             config.dark_pos_gain[i][j] = ram_table.dark_pos_gain[i][j];
0706         }
0707     }
0708 
0709     for (i = 0; i < NUM_AGGR_LEVEL; i++) {
0710         config.hybrid_factor[i] = ram_table.hybrid_factor[i];
0711         config.contrast_factor[i] = ram_table.contrast_factor[i];
0712         config.deviation_gain[i] = ram_table.deviation_gain[i];
0713         config.min_knee[i] = ram_table.min_knee[i];
0714         config.max_knee[i] = ram_table.max_knee[i];
0715     }
0716 
0717     if (params.backlight_ramping_override) {
0718         for (i = 0; i < NUM_AGGR_LEVEL; i++) {
0719             config.blRampReduction[i] = params.backlight_ramping_reduction;
0720             config.blRampStart[i] = params.backlight_ramping_start;
0721             }
0722         } else {
0723             for (i = 0; i < NUM_AGGR_LEVEL; i++) {
0724                 config.blRampReduction[i] = abm_settings[set][i].blRampReduction;
0725                 config.blRampStart[i] = abm_settings[set][i].blRampStart;
0726                 }
0727             }
0728 
0729     config.min_abm_backlight = ram_table.min_abm_backlight;
0730 
0731 #if defined(CONFIG_DRM_AMD_DC_DCN)
0732     if (res_pool->multiple_abms[inst]) {
0733         result = res_pool->multiple_abms[inst]->funcs->init_abm_config(
0734             res_pool->multiple_abms[inst], (char *)(&config), sizeof(struct abm_config_table), inst);
0735     } else
0736 #endif
0737         result = res_pool->abm->funcs->init_abm_config(
0738             res_pool->abm, (char *)(&config), sizeof(struct abm_config_table), 0);
0739 
0740     return result;
0741 }
0742 
0743 bool dmcu_load_iram(struct dmcu *dmcu,
0744     struct dmcu_iram_parameters params)
0745 {
0746     unsigned char ram_table[IRAM_SIZE];
0747     bool result = false;
0748 
0749     if (dmcu == NULL)
0750         return false;
0751 
0752     if (dmcu && !dmcu->funcs->is_dmcu_initialized(dmcu))
0753         return true;
0754 
0755     memset(&ram_table, 0, sizeof(ram_table));
0756 
0757     if (dmcu->dmcu_version.abm_version == 0x24) {
0758         fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params, true);
0759             result = dmcu->funcs->load_iram(
0760                     dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2);
0761     } else if (dmcu->dmcu_version.abm_version == 0x23) {
0762         fill_iram_v_2_3((struct iram_table_v_2_2 *)ram_table, params, true);
0763 
0764         result = dmcu->funcs->load_iram(
0765                 dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2);
0766     } else if (dmcu->dmcu_version.abm_version == 0x22) {
0767         fill_iram_v_2_2((struct iram_table_v_2_2 *)ram_table, params);
0768 
0769         result = dmcu->funcs->load_iram(
0770                 dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2);
0771     } else {
0772         fill_iram_v_2((struct iram_table_v_2 *)ram_table, params);
0773 
0774         result = dmcu->funcs->load_iram(
0775                 dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2);
0776 
0777         if (result)
0778             result = dmcu->funcs->load_iram(
0779                     dmcu, IRAM_RESERVE_AREA_END_V2 + 1,
0780                     (char *)(&ram_table) + IRAM_RESERVE_AREA_END_V2 + 1,
0781                     sizeof(ram_table) - IRAM_RESERVE_AREA_END_V2 - 1);
0782     }
0783 
0784     return result;
0785 }
0786 
0787 /*
0788  * is_psr_su_specific_panel() - check if sink is AMD vendor-specific PSR-SU
0789  * supported eDP device.
0790  *
0791  * @link: dc link pointer
0792  *
0793  * Return: true if AMDGPU vendor specific PSR-SU eDP panel
0794  */
0795 bool is_psr_su_specific_panel(struct dc_link *link)
0796 {
0797     bool isPSRSUSupported = false;
0798     struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
0799 
0800     if (dpcd_caps->edp_rev >= DP_EDP_14) {
0801         if (dpcd_caps->psr_info.psr_version >= DP_PSR2_WITH_Y_COORD_ET_SUPPORTED)
0802             isPSRSUSupported = true;
0803         /*
0804          * Some panels will report PSR capabilities over additional DPCD bits.
0805          * Such panels are approved despite reporting only PSR v3, as long as
0806          * the additional bits are reported.
0807          */
0808         if (dpcd_caps->sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8) {
0809             /*
0810              * This is the temporary workaround to disable PSRSU when system turned on
0811              * DSC function on the sepcific sink.
0812              */
0813             if (dpcd_caps->psr_info.psr_version < DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)
0814                 isPSRSUSupported = false;
0815             else if (dpcd_caps->dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT &&
0816                 ((dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x08) ||
0817                 (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x07)))
0818                 isPSRSUSupported = false;
0819             else if (dpcd_caps->psr_info.force_psrsu_cap == 0x1)
0820                 isPSRSUSupported = true;
0821         }
0822     }
0823 
0824     return isPSRSUSupported;
0825 }
0826 
0827 /**
0828  * mod_power_calc_psr_configs() - calculate/update generic psr configuration fields.
0829  * @psr_config: [output], psr configuration structure to be updated
0830  * @link: [input] dc link pointer
0831  * @stream: [input] dc stream state pointer
0832  *
0833  * calculate and update the psr configuration fields that are not DM specific, i.e. such
0834  * fields which are based on DPCD caps or timing information. To setup PSR in DMUB FW,
0835  * this helper is assumed to be called before the call of the DC helper dc_link_setup_psr().
0836  *
0837  * PSR config fields to be updated within the helper:
0838  * - psr_rfb_setup_time
0839  * - psr_sdp_transmit_line_num_deadline
0840  * - line_time_in_us
0841  * - su_y_granularity
0842  * - su_granularity_required
0843  * - psr_frame_capture_indication_req
0844  * - psr_exit_link_training_required
0845  *
0846  * PSR config fields that are DM specific and NOT updated within the helper:
0847  * - allow_smu_optimizations
0848  * - allow_multi_disp_optimizations
0849  */
0850 void mod_power_calc_psr_configs(struct psr_config *psr_config,
0851         struct dc_link *link,
0852         const struct dc_stream_state *stream)
0853 {
0854     unsigned int num_vblank_lines = 0;
0855     unsigned int vblank_time_in_us = 0;
0856     unsigned int sdp_tx_deadline_in_us = 0;
0857     unsigned int line_time_in_us = 0;
0858     struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
0859     const int psr_setup_time_step_in_us = 55;   /* refer to eDP spec DPCD 0x071h */
0860 
0861     /* timing parameters */
0862     num_vblank_lines = stream->timing.v_total -
0863              stream->timing.v_addressable -
0864              stream->timing.v_border_top -
0865              stream->timing.v_border_bottom;
0866 
0867     vblank_time_in_us = (stream->timing.h_total * num_vblank_lines * 1000) / (stream->timing.pix_clk_100hz / 10);
0868 
0869     line_time_in_us = ((stream->timing.h_total * 1000) / (stream->timing.pix_clk_100hz / 10)) + 1;
0870 
0871     /**
0872      * psr configuration fields
0873      *
0874      * as per eDP 1.5 pg. 377 of 459, DPCD 0x071h bits [3:1], psr setup time bits interpreted as below
0875      * 000b <--> 330 us (default)
0876      * 001b <--> 275 us
0877      * 010b <--> 220 us
0878      * 011b <--> 165 us
0879      * 100b <--> 110 us
0880      * 101b <--> 055 us
0881      * 110b <--> 000 us
0882      */
0883     psr_config->psr_rfb_setup_time =
0884         (6 - dpcd_caps->psr_info.psr_dpcd_caps.bits.PSR_SETUP_TIME) * psr_setup_time_step_in_us;
0885 
0886     if (psr_config->psr_rfb_setup_time > vblank_time_in_us) {
0887         link->psr_settings.psr_frame_capture_indication_req = true;
0888         link->psr_settings.psr_sdp_transmit_line_num_deadline = num_vblank_lines;
0889     } else {
0890         sdp_tx_deadline_in_us = vblank_time_in_us - psr_config->psr_rfb_setup_time;
0891 
0892         /* Set the last possible line SDP may be transmitted without violating the RFB setup time */
0893         link->psr_settings.psr_frame_capture_indication_req = false;
0894         link->psr_settings.psr_sdp_transmit_line_num_deadline = sdp_tx_deadline_in_us / line_time_in_us;
0895     }
0896 
0897     psr_config->psr_sdp_transmit_line_num_deadline = link->psr_settings.psr_sdp_transmit_line_num_deadline;
0898     psr_config->line_time_in_us = line_time_in_us;
0899     psr_config->su_y_granularity = dpcd_caps->psr_info.psr2_su_y_granularity_cap;
0900     psr_config->su_granularity_required = dpcd_caps->psr_info.psr_dpcd_caps.bits.SU_GRANULARITY_REQUIRED;
0901     psr_config->psr_frame_capture_indication_req = link->psr_settings.psr_frame_capture_indication_req;
0902     psr_config->psr_exit_link_training_required =
0903         !link->dpcd_caps.psr_info.psr_dpcd_caps.bits.LINK_TRAINING_ON_EXIT_NOT_REQUIRED;
0904 }
0905 
0906 bool mod_power_only_edp(const struct dc_state *context, const struct dc_stream_state *stream)
0907 {
0908     return context && context->stream_count == 1 && dc_is_embedded_signal(stream->signal);
0909 }