Home | History | Annotate | Line # | Download | only in dce110
      1 /*	$NetBSD: amdgpu_dce110_opp_regamma_v.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2012-15 Advanced Micro Devices, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors: AMD
     25  *
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dce110_opp_regamma_v.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $");
     30 
     31 #include <linux/delay.h>
     32 
     33 #include "dm_services.h"
     34 
     35 /* include DCE11 register header files */
     36 #include "dce/dce_11_0_d.h"
     37 #include "dce/dce_11_0_sh_mask.h"
     38 
     39 #include "dce110_transform_v.h"
     40 
     41 static void power_on_lut(struct transform *xfm,
     42 	bool power_on, bool inputgamma, bool regamma)
     43 {
     44 	uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);
     45 	int i;
     46 
     47 	if (power_on) {
     48 		if (inputgamma)
     49 			set_reg_field_value(
     50 				value,
     51 				1,
     52 				DCFEV_MEM_PWR_CTRL,
     53 				COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
     54 		if (regamma)
     55 			set_reg_field_value(
     56 				value,
     57 				1,
     58 				DCFEV_MEM_PWR_CTRL,
     59 				COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
     60 	} else {
     61 		if (inputgamma)
     62 			set_reg_field_value(
     63 				value,
     64 				0,
     65 				DCFEV_MEM_PWR_CTRL,
     66 				COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
     67 		if (regamma)
     68 			set_reg_field_value(
     69 				value,
     70 				0,
     71 				DCFEV_MEM_PWR_CTRL,
     72 				COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
     73 	}
     74 
     75 	dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value);
     76 
     77 	for (i = 0; i < 3; i++) {
     78 		value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);
     79 		if (get_reg_field_value(value,
     80 				DCFEV_MEM_PWR_CTRL,
     81 				COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) &&
     82 			get_reg_field_value(value,
     83 					DCFEV_MEM_PWR_CTRL,
     84 					COL_MAN_GAMMA_CORR_MEM_PWR_DIS))
     85 			break;
     86 
     87 		udelay(2);
     88 	}
     89 }
     90 
     91 static void set_bypass_input_gamma(struct dce_transform *xfm_dce)
     92 {
     93 	uint32_t value;
     94 
     95 	value = dm_read_reg(xfm_dce->base.ctx,
     96 			mmCOL_MAN_INPUT_GAMMA_CONTROL1);
     97 
     98 	set_reg_field_value(
     99 				value,
    100 				0,
    101 				COL_MAN_INPUT_GAMMA_CONTROL1,
    102 				INPUT_GAMMA_MODE);
    103 
    104 	dm_write_reg(xfm_dce->base.ctx,
    105 			mmCOL_MAN_INPUT_GAMMA_CONTROL1, value);
    106 }
    107 
    108 static void configure_regamma_mode(struct dce_transform *xfm_dce, uint32_t mode)
    109 {
    110 	uint32_t value = 0;
    111 
    112 	set_reg_field_value(
    113 				value,
    114 				mode,
    115 				GAMMA_CORR_CONTROL,
    116 				GAMMA_CORR_MODE);
    117 
    118 	dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CONTROL, 0);
    119 }
    120 
    121 /*
    122  *****************************************************************************
    123  *  Function: regamma_config_regions_and_segments
    124  *
    125  *     build regamma curve by using predefined hw points
    126  *     uses interface parameters ,like EDID coeff.
    127  *
    128  * @param   : parameters   interface parameters
    129  *  @return void
    130  *
    131  *  @note
    132  *
    133  *  @see
    134  *
    135  *****************************************************************************
    136  */
    137 static void regamma_config_regions_and_segments(
    138 	struct dce_transform *xfm_dce, const struct pwl_params *params)
    139 {
    140 	const struct gamma_curve *curve;
    141 	uint32_t value = 0;
    142 
    143 	{
    144 		set_reg_field_value(
    145 			value,
    146 			params->arr_points[0].custom_float_x,
    147 			GAMMA_CORR_CNTLA_START_CNTL,
    148 			GAMMA_CORR_CNTLA_EXP_REGION_START);
    149 
    150 		set_reg_field_value(
    151 			value,
    152 			0,
    153 			GAMMA_CORR_CNTLA_START_CNTL,
    154 			GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT);
    155 
    156 		dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL,
    157 				value);
    158 	}
    159 	{
    160 		value = 0;
    161 		set_reg_field_value(
    162 			value,
    163 			params->arr_points[0].custom_float_slope,
    164 			GAMMA_CORR_CNTLA_SLOPE_CNTL,
    165 			GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE);
    166 
    167 		dm_write_reg(xfm_dce->base.ctx,
    168 			mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value);
    169 	}
    170 	{
    171 		value = 0;
    172 		set_reg_field_value(
    173 			value,
    174 			params->arr_points[1].custom_float_x,
    175 			GAMMA_CORR_CNTLA_END_CNTL1,
    176 			GAMMA_CORR_CNTLA_EXP_REGION_END);
    177 
    178 		dm_write_reg(xfm_dce->base.ctx,
    179 			mmGAMMA_CORR_CNTLA_END_CNTL1, value);
    180 	}
    181 	{
    182 		value = 0;
    183 		set_reg_field_value(
    184 			value,
    185 			params->arr_points[1].custom_float_slope,
    186 			GAMMA_CORR_CNTLA_END_CNTL2,
    187 			GAMMA_CORR_CNTLA_EXP_REGION_END_BASE);
    188 
    189 		set_reg_field_value(
    190 			value,
    191 			params->arr_points[1].custom_float_y,
    192 			GAMMA_CORR_CNTLA_END_CNTL2,
    193 			GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE);
    194 
    195 		dm_write_reg(xfm_dce->base.ctx,
    196 			mmGAMMA_CORR_CNTLA_END_CNTL2, value);
    197 	}
    198 
    199 	curve = params->arr_curve_points;
    200 
    201 	{
    202 		value = 0;
    203 		set_reg_field_value(
    204 			value,
    205 			curve[0].offset,
    206 			GAMMA_CORR_CNTLA_REGION_0_1,
    207 			GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET);
    208 
    209 		set_reg_field_value(
    210 			value,
    211 			curve[0].segments_num,
    212 			GAMMA_CORR_CNTLA_REGION_0_1,
    213 			GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS);
    214 
    215 		set_reg_field_value(
    216 			value,
    217 			curve[1].offset,
    218 			GAMMA_CORR_CNTLA_REGION_0_1,
    219 			GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET);
    220 
    221 		set_reg_field_value(
    222 			value,
    223 			curve[1].segments_num,
    224 			GAMMA_CORR_CNTLA_REGION_0_1,
    225 			GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS);
    226 
    227 		dm_write_reg(
    228 				xfm_dce->base.ctx,
    229 			mmGAMMA_CORR_CNTLA_REGION_0_1,
    230 			value);
    231 	}
    232 
    233 	curve += 2;
    234 	{
    235 		value = 0;
    236 		set_reg_field_value(
    237 			value,
    238 			curve[0].offset,
    239 			GAMMA_CORR_CNTLA_REGION_2_3,
    240 			GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET);
    241 
    242 		set_reg_field_value(
    243 			value,
    244 			curve[0].segments_num,
    245 			GAMMA_CORR_CNTLA_REGION_2_3,
    246 			GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS);
    247 
    248 		set_reg_field_value(
    249 			value,
    250 			curve[1].offset,
    251 			GAMMA_CORR_CNTLA_REGION_2_3,
    252 			GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET);
    253 
    254 		set_reg_field_value(
    255 			value,
    256 			curve[1].segments_num,
    257 			GAMMA_CORR_CNTLA_REGION_2_3,
    258 			GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS);
    259 
    260 		dm_write_reg(xfm_dce->base.ctx,
    261 			mmGAMMA_CORR_CNTLA_REGION_2_3,
    262 			value);
    263 	}
    264 
    265 	curve += 2;
    266 	{
    267 		value = 0;
    268 		set_reg_field_value(
    269 			value,
    270 			curve[0].offset,
    271 			GAMMA_CORR_CNTLA_REGION_4_5,
    272 			GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET);
    273 
    274 		set_reg_field_value(
    275 			value,
    276 			curve[0].segments_num,
    277 			GAMMA_CORR_CNTLA_REGION_4_5,
    278 			GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS);
    279 
    280 		set_reg_field_value(
    281 			value,
    282 			curve[1].offset,
    283 			GAMMA_CORR_CNTLA_REGION_4_5,
    284 			GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET);
    285 
    286 		set_reg_field_value(
    287 			value,
    288 			curve[1].segments_num,
    289 			GAMMA_CORR_CNTLA_REGION_4_5,
    290 			GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS);
    291 
    292 		dm_write_reg(xfm_dce->base.ctx,
    293 			mmGAMMA_CORR_CNTLA_REGION_4_5,
    294 			value);
    295 	}
    296 
    297 	curve += 2;
    298 	{
    299 		value = 0;
    300 		set_reg_field_value(
    301 			value,
    302 			curve[0].offset,
    303 			GAMMA_CORR_CNTLA_REGION_6_7,
    304 			GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET);
    305 
    306 		set_reg_field_value(
    307 			value,
    308 			curve[0].segments_num,
    309 			GAMMA_CORR_CNTLA_REGION_6_7,
    310 			GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS);
    311 
    312 		set_reg_field_value(
    313 			value,
    314 			curve[1].offset,
    315 			GAMMA_CORR_CNTLA_REGION_6_7,
    316 			GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET);
    317 
    318 		set_reg_field_value(
    319 			value,
    320 			curve[1].segments_num,
    321 			GAMMA_CORR_CNTLA_REGION_6_7,
    322 			GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS);
    323 
    324 		dm_write_reg(xfm_dce->base.ctx,
    325 			mmGAMMA_CORR_CNTLA_REGION_6_7,
    326 			value);
    327 	}
    328 
    329 	curve += 2;
    330 	{
    331 		value = 0;
    332 		set_reg_field_value(
    333 			value,
    334 			curve[0].offset,
    335 			GAMMA_CORR_CNTLA_REGION_8_9,
    336 			GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET);
    337 
    338 		set_reg_field_value(
    339 			value,
    340 			curve[0].segments_num,
    341 			GAMMA_CORR_CNTLA_REGION_8_9,
    342 			GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS);
    343 
    344 		set_reg_field_value(
    345 			value,
    346 			curve[1].offset,
    347 			GAMMA_CORR_CNTLA_REGION_8_9,
    348 			GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET);
    349 
    350 		set_reg_field_value(
    351 			value,
    352 			curve[1].segments_num,
    353 			GAMMA_CORR_CNTLA_REGION_8_9,
    354 			GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS);
    355 
    356 		dm_write_reg(xfm_dce->base.ctx,
    357 			mmGAMMA_CORR_CNTLA_REGION_8_9,
    358 			value);
    359 	}
    360 
    361 	curve += 2;
    362 	{
    363 		value = 0;
    364 		set_reg_field_value(
    365 			value,
    366 			curve[0].offset,
    367 			GAMMA_CORR_CNTLA_REGION_10_11,
    368 			GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET);
    369 
    370 		set_reg_field_value(
    371 			value,
    372 			curve[0].segments_num,
    373 			GAMMA_CORR_CNTLA_REGION_10_11,
    374 			GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS);
    375 
    376 		set_reg_field_value(
    377 			value,
    378 			curve[1].offset,
    379 			GAMMA_CORR_CNTLA_REGION_10_11,
    380 			GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET);
    381 
    382 		set_reg_field_value(
    383 			value,
    384 			curve[1].segments_num,
    385 			GAMMA_CORR_CNTLA_REGION_10_11,
    386 			GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS);
    387 
    388 		dm_write_reg(xfm_dce->base.ctx,
    389 			mmGAMMA_CORR_CNTLA_REGION_10_11,
    390 			value);
    391 	}
    392 
    393 	curve += 2;
    394 	{
    395 		value = 0;
    396 		set_reg_field_value(
    397 			value,
    398 			curve[0].offset,
    399 			GAMMA_CORR_CNTLA_REGION_12_13,
    400 			GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET);
    401 
    402 		set_reg_field_value(
    403 			value,
    404 			curve[0].segments_num,
    405 			GAMMA_CORR_CNTLA_REGION_12_13,
    406 			GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS);
    407 
    408 		set_reg_field_value(
    409 			value,
    410 			curve[1].offset,
    411 			GAMMA_CORR_CNTLA_REGION_12_13,
    412 			GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET);
    413 
    414 		set_reg_field_value(
    415 			value,
    416 			curve[1].segments_num,
    417 			GAMMA_CORR_CNTLA_REGION_12_13,
    418 			GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS);
    419 
    420 		dm_write_reg(xfm_dce->base.ctx,
    421 			mmGAMMA_CORR_CNTLA_REGION_12_13,
    422 			value);
    423 	}
    424 
    425 	curve += 2;
    426 	{
    427 		value = 0;
    428 		set_reg_field_value(
    429 			value,
    430 			curve[0].offset,
    431 			GAMMA_CORR_CNTLA_REGION_14_15,
    432 			GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET);
    433 
    434 		set_reg_field_value(
    435 			value,
    436 			curve[0].segments_num,
    437 			GAMMA_CORR_CNTLA_REGION_14_15,
    438 			GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS);
    439 
    440 		set_reg_field_value(
    441 			value,
    442 			curve[1].offset,
    443 			GAMMA_CORR_CNTLA_REGION_14_15,
    444 			GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET);
    445 
    446 		set_reg_field_value(
    447 			value,
    448 			curve[1].segments_num,
    449 			GAMMA_CORR_CNTLA_REGION_14_15,
    450 			GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS);
    451 
    452 		dm_write_reg(xfm_dce->base.ctx,
    453 			mmGAMMA_CORR_CNTLA_REGION_14_15,
    454 			value);
    455 	}
    456 }
    457 
    458 static void program_pwl(struct dce_transform *xfm_dce,
    459 		const struct pwl_params *params)
    460 {
    461 	uint32_t value = 0;
    462 
    463 	set_reg_field_value(
    464 		value,
    465 		7,
    466 		GAMMA_CORR_LUT_WRITE_EN_MASK,
    467 		GAMMA_CORR_LUT_WRITE_EN_MASK);
    468 
    469 	dm_write_reg(xfm_dce->base.ctx,
    470 		mmGAMMA_CORR_LUT_WRITE_EN_MASK, value);
    471 
    472 	dm_write_reg(xfm_dce->base.ctx,
    473 		mmGAMMA_CORR_LUT_INDEX, 0);
    474 
    475 	/* Program REGAMMA_LUT_DATA */
    476 	{
    477 		const uint32_t addr = mmGAMMA_CORR_LUT_DATA;
    478 		uint32_t i = 0;
    479 		const struct pwl_result_data *rgb =
    480 				params->rgb_resulted;
    481 
    482 		while (i != params->hw_points_num) {
    483 			dm_write_reg(xfm_dce->base.ctx, addr, rgb->red_reg);
    484 			dm_write_reg(xfm_dce->base.ctx, addr, rgb->green_reg);
    485 			dm_write_reg(xfm_dce->base.ctx, addr, rgb->blue_reg);
    486 
    487 			dm_write_reg(xfm_dce->base.ctx, addr,
    488 				rgb->delta_red_reg);
    489 			dm_write_reg(xfm_dce->base.ctx, addr,
    490 				rgb->delta_green_reg);
    491 			dm_write_reg(xfm_dce->base.ctx, addr,
    492 				rgb->delta_blue_reg);
    493 
    494 			++rgb;
    495 			++i;
    496 		}
    497 	}
    498 }
    499 
    500 void dce110_opp_program_regamma_pwl_v(
    501 	struct transform *xfm,
    502 	const struct pwl_params *params)
    503 {
    504 	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
    505 
    506 	/* Setup regions */
    507 	regamma_config_regions_and_segments(xfm_dce, params);
    508 
    509 	set_bypass_input_gamma(xfm_dce);
    510 
    511 	/* Power on gamma LUT memory */
    512 	power_on_lut(xfm, true, false, true);
    513 
    514 	/* Program PWL */
    515 	program_pwl(xfm_dce, params);
    516 
    517 	/* program regamma config */
    518 	configure_regamma_mode(xfm_dce, 1);
    519 
    520 	/* Power return to auto back */
    521 	power_on_lut(xfm, false, false, true);
    522 }
    523 
    524 void dce110_opp_power_on_regamma_lut_v(
    525 	struct transform *xfm,
    526 	bool power_on)
    527 {
    528 	uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL);
    529 
    530 	set_reg_field_value(
    531 		value,
    532 		0,
    533 		DCFEV_MEM_PWR_CTRL,
    534 		COL_MAN_GAMMA_CORR_MEM_PWR_FORCE);
    535 
    536 	set_reg_field_value(
    537 		value,
    538 		power_on,
    539 		DCFEV_MEM_PWR_CTRL,
    540 		COL_MAN_GAMMA_CORR_MEM_PWR_DIS);
    541 
    542 	set_reg_field_value(
    543 		value,
    544 		0,
    545 		DCFEV_MEM_PWR_CTRL,
    546 		COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE);
    547 
    548 	set_reg_field_value(
    549 		value,
    550 		power_on,
    551 		DCFEV_MEM_PWR_CTRL,
    552 		COL_MAN_INPUT_GAMMA_MEM_PWR_DIS);
    553 
    554 	dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value);
    555 }
    556 
    557 void dce110_opp_set_regamma_mode_v(
    558 	struct transform *xfm,
    559 	enum opp_regamma mode)
    560 {
    561 	// TODO: need to implement the function
    562 }
    563