cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dce_opp.c (19973B)


      1/*
      2 * Copyright 2012-15 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25
     26#include <linux/slab.h>
     27
     28#include "dm_services.h"
     29#include "basics/conversion.h"
     30
     31#include "dce_opp.h"
     32
     33#include "reg_helper.h"
     34
     35#define REG(reg)\
     36	(opp110->regs->reg)
     37
     38#undef FN
     39#define FN(reg_name, field_name) \
     40	opp110->opp_shift->field_name, opp110->opp_mask->field_name
     41
     42#define CTX \
     43	opp110->base.ctx
     44
     45enum {
     46	MAX_PWL_ENTRY = 128,
     47	MAX_REGIONS_NUMBER = 16
     48};
     49
     50enum {
     51	MAX_LUT_ENTRY = 256,
     52	MAX_NUMBER_OF_ENTRIES = 256
     53};
     54
     55
     56enum {
     57	OUTPUT_CSC_MATRIX_SIZE = 12
     58};
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81/*
     82 *****************************************************************************
     83 *  Function: regamma_config_regions_and_segments
     84 *
     85 *     build regamma curve by using predefined hw points
     86 *     uses interface parameters ,like EDID coeff.
     87 *
     88 * @param   : parameters   interface parameters
     89 *  @return void
     90 *
     91 *  @note
     92 *
     93 *  @see
     94 *
     95 *****************************************************************************
     96 */
     97
     98
     99
    100/*
    101 *	set_truncation
    102 *	1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
    103 *	2) enable truncation
    104 *	3) HW remove 12bit FMT support for DCE11 power saving reason.
    105 */
    106static void set_truncation(
    107		struct dce110_opp *opp110,
    108		const struct bit_depth_reduction_params *params)
    109{
    110	/*Disable truncation*/
    111	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    112			FMT_TRUNCATE_EN, 0,
    113			FMT_TRUNCATE_DEPTH, 0,
    114			FMT_TRUNCATE_MODE, 0);
    115
    116
    117	if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
    118		/*  8bpc trunc on YCbCr422*/
    119		if (params->flags.TRUNCATE_DEPTH == 1)
    120			REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    121					FMT_TRUNCATE_EN, 1,
    122					FMT_TRUNCATE_DEPTH, 1,
    123					FMT_TRUNCATE_MODE, 0);
    124		else if (params->flags.TRUNCATE_DEPTH == 2)
    125			/*  10bpc trunc on YCbCr422*/
    126			REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    127					FMT_TRUNCATE_EN, 1,
    128					FMT_TRUNCATE_DEPTH, 2,
    129					FMT_TRUNCATE_MODE, 0);
    130		return;
    131	}
    132	/* on other format-to do */
    133	if (params->flags.TRUNCATE_ENABLED == 0)
    134		return;
    135	/*Set truncation depth and Enable truncation*/
    136	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    137				FMT_TRUNCATE_EN, 1,
    138				FMT_TRUNCATE_DEPTH,
    139				params->flags.TRUNCATE_DEPTH,
    140				FMT_TRUNCATE_MODE,
    141				params->flags.TRUNCATE_MODE);
    142}
    143
    144#if defined(CONFIG_DRM_AMD_DC_SI)
    145/*
    146 *	dce60_set_truncation
    147 *	1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
    148 *	2) enable truncation
    149 *	3) HW remove 12bit FMT support for DCE11 power saving reason.
    150 */
    151static void dce60_set_truncation(
    152		struct dce110_opp *opp110,
    153		const struct bit_depth_reduction_params *params)
    154{
    155	/* DCE6 has no FMT_TRUNCATE_MODE bit in FMT_BIT_DEPTH_CONTROL reg */
    156
    157	/*Disable truncation*/
    158	REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
    159			FMT_TRUNCATE_EN, 0,
    160			FMT_TRUNCATE_DEPTH, 0);
    161
    162	if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
    163		/*  8bpc trunc on YCbCr422*/
    164		if (params->flags.TRUNCATE_DEPTH == 1)
    165			REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
    166					FMT_TRUNCATE_EN, 1,
    167					FMT_TRUNCATE_DEPTH, 1);
    168		else if (params->flags.TRUNCATE_DEPTH == 2)
    169			/*  10bpc trunc on YCbCr422*/
    170			REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
    171					FMT_TRUNCATE_EN, 1,
    172					FMT_TRUNCATE_DEPTH, 2);
    173		return;
    174	}
    175	/* on other format-to do */
    176	if (params->flags.TRUNCATE_ENABLED == 0)
    177		return;
    178	/*Set truncation depth and Enable truncation*/
    179	REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
    180				FMT_TRUNCATE_EN, 1,
    181				FMT_TRUNCATE_DEPTH,
    182				params->flags.TRUNCATE_DEPTH);
    183}
    184#endif
    185
    186/*
    187 *	set_spatial_dither
    188 *	1) set spatial dithering mode: pattern of seed
    189 *	2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp
    190 *	3) set random seed
    191 *	4) set random mode
    192 *		lfsr is reset every frame or not reset
    193 *		RGB dithering method
    194 *		0: RGB data are all dithered with x^28+x^3+1
    195 *		1: R data is dithered with x^28+x^3+1
    196 *		G data is dithered with x^28+X^9+1
    197 *		B data is dithered with x^28+x^13+1
    198 *		enable high pass filter or not
    199 *	5) enable spatical dithering
    200 */
    201static void set_spatial_dither(
    202	struct dce110_opp *opp110,
    203	const struct bit_depth_reduction_params *params)
    204{
    205	/*Disable spatial (random) dithering*/
    206	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    207		FMT_SPATIAL_DITHER_EN, 0,
    208		FMT_SPATIAL_DITHER_DEPTH, 0,
    209		FMT_SPATIAL_DITHER_MODE, 0);
    210
    211	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    212		FMT_HIGHPASS_RANDOM_ENABLE, 0,
    213		FMT_FRAME_RANDOM_ENABLE, 0,
    214		FMT_RGB_RANDOM_ENABLE, 0);
    215
    216	REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
    217		FMT_TEMPORAL_DITHER_EN, 0);
    218
    219	if (params->flags.SPATIAL_DITHER_ENABLED == 0)
    220		return;
    221
    222	/* only use FRAME_COUNTER_MAX if frameRandom == 1*/
    223
    224	if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX &&
    225			opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) {
    226		if (params->flags.FRAME_RANDOM == 1) {
    227			if (params->flags.SPATIAL_DITHER_DEPTH == 0 ||
    228			params->flags.SPATIAL_DITHER_DEPTH == 1) {
    229				REG_UPDATE_2(FMT_CONTROL,
    230					FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
    231					FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
    232			} else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
    233				REG_UPDATE_2(FMT_CONTROL,
    234					FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
    235					FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
    236			} else
    237				return;
    238		} else {
    239			REG_UPDATE_2(FMT_CONTROL,
    240					FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
    241					FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
    242		}
    243	}
    244	/* Set seed for random values for
    245	 * spatial dithering for R,G,B channels
    246	 */
    247	REG_UPDATE(FMT_DITHER_RAND_R_SEED,
    248			FMT_RAND_R_SEED, params->r_seed_value);
    249
    250	REG_UPDATE(FMT_DITHER_RAND_G_SEED,
    251			FMT_RAND_G_SEED, params->g_seed_value);
    252
    253	REG_UPDATE(FMT_DITHER_RAND_B_SEED,
    254			FMT_RAND_B_SEED, params->b_seed_value);
    255
    256	/* FMT_OFFSET_R_Cr  31:16 0x0 Setting the zero
    257	 * offset for the R/Cr channel, lower 4LSB
    258	 * is forced to zeros. Typically set to 0
    259	 * RGB and 0x80000 YCbCr.
    260	 */
    261	/* FMT_OFFSET_G_Y   31:16 0x0 Setting the zero
    262	 * offset for the G/Y  channel, lower 4LSB is
    263	 * forced to zeros. Typically set to 0 RGB
    264	 * and 0x80000 YCbCr.
    265	 */
    266	/* FMT_OFFSET_B_Cb  31:16 0x0 Setting the zero
    267	 * offset for the B/Cb channel, lower 4LSB is
    268	 * forced to zeros. Typically set to 0 RGB and
    269	 * 0x80000 YCbCr.
    270	 */
    271
    272	/* Disable High pass filter
    273	 * Reset only at startup
    274	 * Set RGB data dithered with x^28+x^3+1
    275	 */
    276	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    277		FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
    278		FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
    279		FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
    280
    281	/* Set spatial dithering bit depth
    282	 * Set spatial dithering mode
    283	 * (default is Seed patterrn AAAA...)
    284	 * Enable spatial dithering
    285	 */
    286	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    287		FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
    288		FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
    289		FMT_SPATIAL_DITHER_EN, 1);
    290}
    291
    292/*
    293 *	SetTemporalDither (Frame Modulation)
    294 *	1) set temporal dither depth
    295 *	2) select pattern: from hard-coded pattern or programmable pattern
    296 *	3) select optimized strips for BGR or RGB LCD sub-pixel
    297 *	4) set s matrix
    298 *	5) set t matrix
    299 *	6) set grey level for 0.25, 0.5, 0.75
    300 *	7) enable temporal dithering
    301 */
    302
    303static void set_temporal_dither(
    304	struct dce110_opp *opp110,
    305	const struct bit_depth_reduction_params *params)
    306{
    307	/*Disable temporal (frame modulation) dithering first*/
    308	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    309		FMT_TEMPORAL_DITHER_EN, 0,
    310		FMT_TEMPORAL_DITHER_RESET, 0,
    311		FMT_TEMPORAL_DITHER_OFFSET, 0);
    312
    313	REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL,
    314		FMT_TEMPORAL_DITHER_DEPTH, 0,
    315		FMT_TEMPORAL_LEVEL, 0);
    316
    317	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    318		FMT_25FRC_SEL, 0,
    319		FMT_50FRC_SEL, 0,
    320		FMT_75FRC_SEL, 0);
    321
    322	/* no 10bpc dither on DCE11*/
    323	if (params->flags.FRAME_MODULATION_ENABLED == 0 ||
    324		params->flags.FRAME_MODULATION_DEPTH == 2)
    325		return;
    326
    327	/* Set temporal dithering depth*/
    328	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    329		FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH,
    330		FMT_TEMPORAL_DITHER_RESET, 0,
    331		FMT_TEMPORAL_DITHER_OFFSET, 0);
    332
    333	/*Select legacy pattern based on FRC and Temporal level*/
    334	if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) {
    335		REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0);
    336		/*Set s matrix*/
    337		REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0);
    338		/*Set t matrix*/
    339		REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0);
    340	}
    341
    342	/*Select patterns for 0.25, 0.5 and 0.75 grey level*/
    343	REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
    344		FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL);
    345
    346	REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
    347		FMT_25FRC_SEL, params->flags.FRC25,
    348		FMT_50FRC_SEL, params->flags.FRC50,
    349		FMT_75FRC_SEL, params->flags.FRC75);
    350
    351	/*Enable bit reduction by temporal (frame modulation) dithering*/
    352	REG_UPDATE(FMT_BIT_DEPTH_CONTROL,
    353		FMT_TEMPORAL_DITHER_EN, 1);
    354}
    355
    356/*
    357 *	Set Clamping
    358 *	1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
    359 *		1 for 8 bpc
    360 *		2 for 10 bpc
    361 *		3 for 12 bpc
    362 *		7 for programable
    363 *	2) Enable clamp if Limited range requested
    364 */
    365void dce110_opp_set_clamping(
    366	struct dce110_opp *opp110,
    367	const struct clamping_and_pixel_encoding_params *params)
    368{
    369	REG_SET_2(FMT_CLAMP_CNTL, 0,
    370		FMT_CLAMP_DATA_EN, 0,
    371		FMT_CLAMP_COLOR_FORMAT, 0);
    372
    373	switch (params->clamping_level) {
    374	case CLAMPING_FULL_RANGE:
    375		break;
    376	case CLAMPING_LIMITED_RANGE_8BPC:
    377		REG_SET_2(FMT_CLAMP_CNTL, 0,
    378			FMT_CLAMP_DATA_EN, 1,
    379			FMT_CLAMP_COLOR_FORMAT, 1);
    380		break;
    381	case CLAMPING_LIMITED_RANGE_10BPC:
    382		REG_SET_2(FMT_CLAMP_CNTL, 0,
    383			FMT_CLAMP_DATA_EN, 1,
    384			FMT_CLAMP_COLOR_FORMAT, 2);
    385		break;
    386	case CLAMPING_LIMITED_RANGE_12BPC:
    387		REG_SET_2(FMT_CLAMP_CNTL, 0,
    388			FMT_CLAMP_DATA_EN, 1,
    389			FMT_CLAMP_COLOR_FORMAT, 3);
    390		break;
    391	case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
    392		/*Set clamp control*/
    393		REG_SET_2(FMT_CLAMP_CNTL, 0,
    394			FMT_CLAMP_DATA_EN, 1,
    395			FMT_CLAMP_COLOR_FORMAT, 7);
    396
    397		/*set the defaults*/
    398		REG_SET_2(FMT_CLAMP_COMPONENT_R, 0,
    399			FMT_CLAMP_LOWER_R, 0x10,
    400			FMT_CLAMP_UPPER_R, 0xFEF);
    401
    402		REG_SET_2(FMT_CLAMP_COMPONENT_G, 0,
    403			FMT_CLAMP_LOWER_G, 0x10,
    404			FMT_CLAMP_UPPER_G, 0xFEF);
    405
    406		REG_SET_2(FMT_CLAMP_COMPONENT_B, 0,
    407			FMT_CLAMP_LOWER_B, 0x10,
    408			FMT_CLAMP_UPPER_B, 0xFEF);
    409		break;
    410	default:
    411		break;
    412	}
    413}
    414
    415#if defined(CONFIG_DRM_AMD_DC_SI)
    416/*
    417 *	Set Clamping for DCE6 parts
    418 *	1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
    419 *		1 for 8 bpc
    420 *		2 for 10 bpc
    421 *		3 for 12 bpc
    422 *		7 for programable
    423 *	2) Enable clamp if Limited range requested
    424 */
    425static void dce60_opp_set_clamping(
    426	struct dce110_opp *opp110,
    427	const struct clamping_and_pixel_encoding_params *params)
    428{
    429	REG_SET_2(FMT_CLAMP_CNTL, 0,
    430		FMT_CLAMP_DATA_EN, 0,
    431		FMT_CLAMP_COLOR_FORMAT, 0);
    432
    433	switch (params->clamping_level) {
    434	case CLAMPING_FULL_RANGE:
    435		break;
    436	case CLAMPING_LIMITED_RANGE_8BPC:
    437		REG_SET_2(FMT_CLAMP_CNTL, 0,
    438			FMT_CLAMP_DATA_EN, 1,
    439			FMT_CLAMP_COLOR_FORMAT, 1);
    440		break;
    441	case CLAMPING_LIMITED_RANGE_10BPC:
    442		REG_SET_2(FMT_CLAMP_CNTL, 0,
    443			FMT_CLAMP_DATA_EN, 1,
    444			FMT_CLAMP_COLOR_FORMAT, 2);
    445		break;
    446	case CLAMPING_LIMITED_RANGE_12BPC:
    447		REG_SET_2(FMT_CLAMP_CNTL, 0,
    448			FMT_CLAMP_DATA_EN, 1,
    449			FMT_CLAMP_COLOR_FORMAT, 3);
    450		break;
    451	case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
    452		/*Set clamp control*/
    453		REG_SET_2(FMT_CLAMP_CNTL, 0,
    454			FMT_CLAMP_DATA_EN, 1,
    455			FMT_CLAMP_COLOR_FORMAT, 7);
    456
    457		/* DCE6 does have FMT_CLAMP_COMPONENT_{R,G,B} registers */
    458
    459		break;
    460	default:
    461		break;
    462	}
    463}
    464#endif
    465
    466/*
    467 *	set_pixel_encoding
    468 *
    469 *	Set Pixel Encoding
    470 *		0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
    471 *		1: YCbCr 4:2:2
    472 */
    473static void set_pixel_encoding(
    474	struct dce110_opp *opp110,
    475	const struct clamping_and_pixel_encoding_params *params)
    476{
    477	if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
    478		REG_UPDATE_3(FMT_CONTROL,
    479				FMT_PIXEL_ENCODING, 0,
    480				FMT_SUBSAMPLING_MODE, 0,
    481				FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
    482	else
    483		REG_UPDATE_2(FMT_CONTROL,
    484				FMT_PIXEL_ENCODING, 0,
    485				FMT_SUBSAMPLING_MODE, 0);
    486
    487	if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
    488		REG_UPDATE_2(FMT_CONTROL,
    489				FMT_PIXEL_ENCODING, 1,
    490				FMT_SUBSAMPLING_ORDER, 0);
    491	}
    492	if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
    493		REG_UPDATE_3(FMT_CONTROL,
    494				FMT_PIXEL_ENCODING, 2,
    495				FMT_SUBSAMPLING_MODE, 2,
    496				FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
    497	}
    498
    499}
    500
    501#if defined(CONFIG_DRM_AMD_DC_SI)
    502/*
    503 *	dce60_set_pixel_encoding
    504 *	DCE6 has no FMT_SUBSAMPLING_{MODE,ORDER} bits in FMT_CONTROL reg
    505 *	Set Pixel Encoding
    506 *		0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
    507 *		1: YCbCr 4:2:2
    508 */
    509static void dce60_set_pixel_encoding(
    510	struct dce110_opp *opp110,
    511	const struct clamping_and_pixel_encoding_params *params)
    512{
    513	if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS)
    514		REG_UPDATE_2(FMT_CONTROL,
    515				FMT_PIXEL_ENCODING, 0,
    516				FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
    517	else
    518		REG_UPDATE(FMT_CONTROL,
    519				FMT_PIXEL_ENCODING, 0);
    520
    521	if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
    522		REG_UPDATE(FMT_CONTROL,
    523				FMT_PIXEL_ENCODING, 1);
    524	}
    525	if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
    526		REG_UPDATE_2(FMT_CONTROL,
    527				FMT_PIXEL_ENCODING, 2,
    528				FMT_CBCR_BIT_REDUCTION_BYPASS, 1);
    529	}
    530
    531}
    532#endif
    533
    534void dce110_opp_program_bit_depth_reduction(
    535	struct output_pixel_processor *opp,
    536	const struct bit_depth_reduction_params *params)
    537{
    538	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
    539
    540	set_truncation(opp110, params);
    541	set_spatial_dither(opp110, params);
    542	set_temporal_dither(opp110, params);
    543}
    544
    545#if defined(CONFIG_DRM_AMD_DC_SI)
    546static void dce60_opp_program_bit_depth_reduction(
    547	struct output_pixel_processor *opp,
    548	const struct bit_depth_reduction_params *params)
    549{
    550	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
    551
    552	dce60_set_truncation(opp110, params);
    553	set_spatial_dither(opp110, params);
    554	set_temporal_dither(opp110, params);
    555}
    556#endif
    557
    558void dce110_opp_program_clamping_and_pixel_encoding(
    559	struct output_pixel_processor *opp,
    560	const struct clamping_and_pixel_encoding_params *params)
    561{
    562	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
    563
    564	dce110_opp_set_clamping(opp110, params);
    565	set_pixel_encoding(opp110, params);
    566}
    567
    568#if defined(CONFIG_DRM_AMD_DC_SI)
    569static void dce60_opp_program_clamping_and_pixel_encoding(
    570	struct output_pixel_processor *opp,
    571	const struct clamping_and_pixel_encoding_params *params)
    572{
    573	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
    574
    575	dce60_opp_set_clamping(opp110, params);
    576	dce60_set_pixel_encoding(opp110, params);
    577}
    578#endif
    579
    580
    581static void program_formatter_420_memory(struct output_pixel_processor *opp)
    582{
    583	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
    584	uint32_t fmt_mem_cntl_value;
    585
    586	/* Program source select*/
    587	/* Use HW default source select for FMT_MEMORYx_CONTROL */
    588	/* Use that value for FMT_SRC_SELECT as well*/
    589	REG_GET(CONTROL,
    590			FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value);
    591
    592	REG_UPDATE(FMT_CONTROL,
    593			FMT_SRC_SELECT, fmt_mem_cntl_value);
    594
    595	/* Turn on the memory */
    596	REG_UPDATE(CONTROL,
    597			FMT420_MEM0_PWR_FORCE, 0);
    598}
    599
    600void dce110_opp_set_dyn_expansion(
    601	struct output_pixel_processor *opp,
    602	enum dc_color_space color_sp,
    603	enum dc_color_depth color_dpth,
    604	enum signal_type signal)
    605{
    606	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
    607
    608	REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
    609			FMT_DYNAMIC_EXP_EN, 0,
    610			FMT_DYNAMIC_EXP_MODE, 0);
    611
    612	/*00 - 10-bit -> 12-bit dynamic expansion*/
    613	/*01 - 8-bit  -> 12-bit dynamic expansion*/
    614	if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
    615		signal == SIGNAL_TYPE_DISPLAY_PORT ||
    616		signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
    617		switch (color_dpth) {
    618		case COLOR_DEPTH_888:
    619			REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
    620				FMT_DYNAMIC_EXP_EN, 1,
    621				FMT_DYNAMIC_EXP_MODE, 1);
    622			break;
    623		case COLOR_DEPTH_101010:
    624			REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
    625				FMT_DYNAMIC_EXP_EN, 1,
    626				FMT_DYNAMIC_EXP_MODE, 0);
    627			break;
    628		case COLOR_DEPTH_121212:
    629			REG_UPDATE_2(
    630				FMT_DYNAMIC_EXP_CNTL,
    631				FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/
    632				FMT_DYNAMIC_EXP_MODE, 0);
    633			break;
    634		default:
    635			break;
    636		}
    637	}
    638}
    639
    640static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp)
    641{
    642	struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
    643
    644	/* clear previous phase lock status*/
    645	REG_UPDATE(FMT_CONTROL,
    646			FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1);
    647
    648	/* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/
    649	REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10);
    650
    651}
    652
    653void dce110_opp_program_fmt(
    654	struct output_pixel_processor *opp,
    655	struct bit_depth_reduction_params *fmt_bit_depth,
    656	struct clamping_and_pixel_encoding_params *clamping)
    657{
    658	/* dithering is affected by <CrtcSourceSelect>, hence should be
    659	 * programmed afterwards */
    660
    661	if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
    662		program_formatter_420_memory(opp);
    663
    664	dce110_opp_program_bit_depth_reduction(
    665		opp,
    666		fmt_bit_depth);
    667
    668	dce110_opp_program_clamping_and_pixel_encoding(
    669		opp,
    670		clamping);
    671
    672	if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
    673		program_formatter_reset_dig_resync_fifo(opp);
    674
    675	return;
    676}
    677
    678#if defined(CONFIG_DRM_AMD_DC_SI)
    679static void dce60_opp_program_fmt(
    680	struct output_pixel_processor *opp,
    681	struct bit_depth_reduction_params *fmt_bit_depth,
    682	struct clamping_and_pixel_encoding_params *clamping)
    683{
    684	/* dithering is affected by <CrtcSourceSelect>, hence should be
    685	 * programmed afterwards */
    686
    687	if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
    688		program_formatter_420_memory(opp);
    689
    690	dce60_opp_program_bit_depth_reduction(
    691		opp,
    692		fmt_bit_depth);
    693
    694	dce60_opp_program_clamping_and_pixel_encoding(
    695		opp,
    696		clamping);
    697
    698	if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
    699		program_formatter_reset_dig_resync_fifo(opp);
    700
    701	return;
    702}
    703#endif
    704
    705
    706
    707/*****************************************/
    708/* Constructor, Destructor               */
    709/*****************************************/
    710
    711static const struct opp_funcs funcs = {
    712	.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
    713	.opp_destroy = dce110_opp_destroy,
    714	.opp_program_fmt = dce110_opp_program_fmt,
    715	.opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction
    716};
    717
    718#if defined(CONFIG_DRM_AMD_DC_SI)
    719static const struct opp_funcs dce60_opp_funcs = {
    720	.opp_set_dyn_expansion = dce110_opp_set_dyn_expansion,
    721	.opp_destroy = dce110_opp_destroy,
    722	.opp_program_fmt = dce60_opp_program_fmt,
    723	.opp_program_bit_depth_reduction = dce60_opp_program_bit_depth_reduction
    724};
    725#endif
    726
    727void dce110_opp_construct(struct dce110_opp *opp110,
    728	struct dc_context *ctx,
    729	uint32_t inst,
    730	const struct dce_opp_registers *regs,
    731	const struct dce_opp_shift *opp_shift,
    732	const struct dce_opp_mask *opp_mask)
    733{
    734	opp110->base.funcs = &funcs;
    735
    736	opp110->base.ctx = ctx;
    737
    738	opp110->base.inst = inst;
    739
    740	opp110->regs = regs;
    741	opp110->opp_shift = opp_shift;
    742	opp110->opp_mask = opp_mask;
    743}
    744
    745#if defined(CONFIG_DRM_AMD_DC_SI)
    746void dce60_opp_construct(struct dce110_opp *opp110,
    747	struct dc_context *ctx,
    748	uint32_t inst,
    749	const struct dce_opp_registers *regs,
    750	const struct dce_opp_shift *opp_shift,
    751	const struct dce_opp_mask *opp_mask)
    752{
    753	opp110->base.funcs = &dce60_opp_funcs;
    754
    755	opp110->base.ctx = ctx;
    756
    757	opp110->base.inst = inst;
    758
    759	opp110->regs = regs;
    760	opp110->opp_shift = opp_shift;
    761	opp110->opp_mask = opp_mask;
    762}
    763#endif
    764
    765void dce110_opp_destroy(struct output_pixel_processor **opp)
    766{
    767	if (*opp)
    768		kfree(FROM_DCE11_OPP(*opp));
    769	*opp = NULL;
    770}
    771