LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dcn10 - dcn10_opp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 91 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 11 0.0 %

          Line data    Source code
       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 "dm_services.h"
      27             : #include "dcn10_opp.h"
      28             : #include "reg_helper.h"
      29             : 
      30             : #define REG(reg) \
      31             :         (oppn10->regs->reg)
      32             : 
      33             : #undef FN
      34             : #define FN(reg_name, field_name) \
      35             :         oppn10->opp_shift->field_name, oppn10->opp_mask->field_name
      36             : 
      37             : #define CTX \
      38             :         oppn10->base.ctx
      39             : 
      40             : 
      41             : /************* FORMATTER ************/
      42             : 
      43             : /**
      44             :  *      set_truncation
      45             :  *      1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp
      46             :  *      2) enable truncation
      47             :  *      3) HW remove 12bit FMT support for DCE11 power saving reason.
      48             :  */
      49           0 : static void opp1_set_truncation(
      50             :                 struct dcn10_opp *oppn10,
      51             :                 const struct bit_depth_reduction_params *params)
      52             : {
      53           0 :         REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL,
      54             :                 FMT_TRUNCATE_EN, params->flags.TRUNCATE_ENABLED,
      55             :                 FMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_DEPTH,
      56             :                 FMT_TRUNCATE_MODE, params->flags.TRUNCATE_MODE);
      57           0 : }
      58             : 
      59           0 : static void opp1_set_spatial_dither(
      60             :         struct dcn10_opp *oppn10,
      61             :         const struct bit_depth_reduction_params *params)
      62             : {
      63             :         /*Disable spatial (random) dithering*/
      64           0 :         REG_UPDATE_7(FMT_BIT_DEPTH_CONTROL,
      65             :                         FMT_SPATIAL_DITHER_EN, 0,
      66             :                         FMT_SPATIAL_DITHER_MODE, 0,
      67             :                         FMT_SPATIAL_DITHER_DEPTH, 0,
      68             :                         FMT_TEMPORAL_DITHER_EN, 0,
      69             :                         FMT_HIGHPASS_RANDOM_ENABLE, 0,
      70             :                         FMT_FRAME_RANDOM_ENABLE, 0,
      71             :                         FMT_RGB_RANDOM_ENABLE, 0);
      72             : 
      73             : 
      74             :         /* only use FRAME_COUNTER_MAX if frameRandom == 1*/
      75           0 :         if (params->flags.FRAME_RANDOM == 1) {
      76           0 :                 if (params->flags.SPATIAL_DITHER_DEPTH == 0 || params->flags.SPATIAL_DITHER_DEPTH == 1) {
      77           0 :                         REG_UPDATE_2(FMT_CONTROL,
      78             :                                         FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
      79             :                                         FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
      80           0 :                 } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
      81           0 :                         REG_UPDATE_2(FMT_CONTROL,
      82             :                                         FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
      83             :                                         FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
      84             :                 } else {
      85             :                         return;
      86             :                 }
      87             :         } else {
      88           0 :                 REG_UPDATE_2(FMT_CONTROL,
      89             :                                 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
      90             :                                 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
      91             :         }
      92             : 
      93             :         /*Set seed for random values for
      94             :          * spatial dithering for R,G,B channels*/
      95             : 
      96           0 :         REG_SET(FMT_DITHER_RAND_R_SEED, 0,
      97             :                         FMT_RAND_R_SEED, params->r_seed_value);
      98             : 
      99           0 :         REG_SET(FMT_DITHER_RAND_G_SEED, 0,
     100             :                         FMT_RAND_G_SEED, params->g_seed_value);
     101             : 
     102           0 :         REG_SET(FMT_DITHER_RAND_B_SEED, 0,
     103             :                         FMT_RAND_B_SEED, params->b_seed_value);
     104             : 
     105             :         /* FMT_OFFSET_R_Cr  31:16 0x0 Setting the zero
     106             :          * offset for the R/Cr channel, lower 4LSB
     107             :          * is forced to zeros. Typically set to 0
     108             :          * RGB and 0x80000 YCbCr.
     109             :          */
     110             :         /* FMT_OFFSET_G_Y   31:16 0x0 Setting the zero
     111             :          * offset for the G/Y  channel, lower 4LSB is
     112             :          * forced to zeros. Typically set to 0 RGB
     113             :          * and 0x80000 YCbCr.
     114             :          */
     115             :         /* FMT_OFFSET_B_Cb  31:16 0x0 Setting the zero
     116             :          * offset for the B/Cb channel, lower 4LSB is
     117             :          * forced to zeros. Typically set to 0 RGB and
     118             :          * 0x80000 YCbCr.
     119             :          */
     120             : 
     121           0 :         REG_UPDATE_6(FMT_BIT_DEPTH_CONTROL,
     122             :                         /*Enable spatial dithering*/
     123             :                         FMT_SPATIAL_DITHER_EN, params->flags.SPATIAL_DITHER_ENABLED,
     124             :                         /* Set spatial dithering mode
     125             :                          * (default is Seed patterrn AAAA...)
     126             :                          */
     127             :                         FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
     128             :                         /*Set spatial dithering bit depth*/
     129             :                         FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
     130             :                         /*Disable High pass filter*/
     131             :                         FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
     132             :                         /*Reset only at startup*/
     133             :                         FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
     134             :                         /*Set RGB data dithered with x^28+x^3+1*/
     135             :                         FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
     136             : }
     137             : 
     138           0 : void opp1_program_bit_depth_reduction(
     139             :         struct output_pixel_processor *opp,
     140             :         const struct bit_depth_reduction_params *params)
     141             : {
     142           0 :         struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
     143             : 
     144           0 :         opp1_set_truncation(oppn10, params);
     145           0 :         opp1_set_spatial_dither(oppn10, params);
     146             :         /* TODO
     147             :          * set_temporal_dither(oppn10, params);
     148             :          */
     149           0 : }
     150             : 
     151             : /**
     152             :  *      set_pixel_encoding
     153             :  *
     154             :  *      Set Pixel Encoding
     155             :  *              0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly
     156             :  *              1: YCbCr 4:2:2
     157             :  */
     158           0 : static void opp1_set_pixel_encoding(
     159             :         struct dcn10_opp *oppn10,
     160             :         const struct clamping_and_pixel_encoding_params *params)
     161             : {
     162           0 :         switch (params->pixel_encoding)      {
     163             : 
     164             :         case PIXEL_ENCODING_RGB:
     165             :         case PIXEL_ENCODING_YCBCR444:
     166           0 :                 REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 0);
     167             :                 break;
     168             :         case PIXEL_ENCODING_YCBCR422:
     169           0 :                 REG_UPDATE_3(FMT_CONTROL,
     170             :                                 FMT_PIXEL_ENCODING, 1,
     171             :                                 FMT_SUBSAMPLING_MODE, 2,
     172             :                                 FMT_CBCR_BIT_REDUCTION_BYPASS, 0);
     173             :                 break;
     174             :         case PIXEL_ENCODING_YCBCR420:
     175           0 :                 REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 2);
     176             :                 break;
     177             :         default:
     178             :                 break;
     179             :         }
     180           0 : }
     181             : 
     182             : /**
     183             :  *      Set Clamping
     184             :  *      1) Set clamping format based on bpc - 0 for 6bpc (No clamping)
     185             :  *              1 for 8 bpc
     186             :  *              2 for 10 bpc
     187             :  *              3 for 12 bpc
     188             :  *              7 for programable
     189             :  *      2) Enable clamp if Limited range requested
     190             :  */
     191           0 : static void opp1_set_clamping(
     192             :         struct dcn10_opp *oppn10,
     193             :         const struct clamping_and_pixel_encoding_params *params)
     194             : {
     195           0 :         REG_UPDATE_2(FMT_CLAMP_CNTL,
     196             :                         FMT_CLAMP_DATA_EN, 0,
     197             :                         FMT_CLAMP_COLOR_FORMAT, 0);
     198             : 
     199           0 :         switch (params->clamping_level) {
     200             :         case CLAMPING_FULL_RANGE:
     201           0 :                 REG_UPDATE_2(FMT_CLAMP_CNTL,
     202             :                                 FMT_CLAMP_DATA_EN, 1,
     203             :                                 FMT_CLAMP_COLOR_FORMAT, 0);
     204             :                 break;
     205             :         case CLAMPING_LIMITED_RANGE_8BPC:
     206           0 :                 REG_UPDATE_2(FMT_CLAMP_CNTL,
     207             :                                 FMT_CLAMP_DATA_EN, 1,
     208             :                                 FMT_CLAMP_COLOR_FORMAT, 1);
     209             :                 break;
     210             :         case CLAMPING_LIMITED_RANGE_10BPC:
     211           0 :                 REG_UPDATE_2(FMT_CLAMP_CNTL,
     212             :                                 FMT_CLAMP_DATA_EN, 1,
     213             :                                 FMT_CLAMP_COLOR_FORMAT, 2);
     214             : 
     215             :                 break;
     216             :         case CLAMPING_LIMITED_RANGE_12BPC:
     217           0 :                 REG_UPDATE_2(FMT_CLAMP_CNTL,
     218             :                                 FMT_CLAMP_DATA_EN, 1,
     219             :                                 FMT_CLAMP_COLOR_FORMAT, 3);
     220             :                 break;
     221             :         case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
     222             :                 /* TODO */
     223             :         default:
     224             :                 break;
     225             :         }
     226             : 
     227           0 : }
     228             : 
     229           0 : void opp1_set_dyn_expansion(
     230             :         struct output_pixel_processor *opp,
     231             :         enum dc_color_space color_sp,
     232             :         enum dc_color_depth color_dpth,
     233             :         enum signal_type signal)
     234             : {
     235           0 :         struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
     236             : 
     237           0 :         REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
     238             :                         FMT_DYNAMIC_EXP_EN, 0,
     239             :                         FMT_DYNAMIC_EXP_MODE, 0);
     240             : 
     241           0 :         if (opp->dyn_expansion == DYN_EXPANSION_DISABLE)
     242             :                 return;
     243             : 
     244             :         /*00 - 10-bit -> 12-bit dynamic expansion*/
     245             :         /*01 - 8-bit  -> 12-bit dynamic expansion*/
     246           0 :         if (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
     247           0 :                 signal == SIGNAL_TYPE_DISPLAY_PORT ||
     248           0 :                 signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
     249           0 :                 signal == SIGNAL_TYPE_VIRTUAL) {
     250           0 :                 switch (color_dpth) {
     251             :                 case COLOR_DEPTH_888:
     252           0 :                         REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
     253             :                                 FMT_DYNAMIC_EXP_EN, 1,
     254             :                                 FMT_DYNAMIC_EXP_MODE, 1);
     255           0 :                         break;
     256             :                 case COLOR_DEPTH_101010:
     257           0 :                         REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
     258             :                                 FMT_DYNAMIC_EXP_EN, 1,
     259             :                                 FMT_DYNAMIC_EXP_MODE, 0);
     260           0 :                         break;
     261             :                 case COLOR_DEPTH_121212:
     262           0 :                         REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
     263             :                                 FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/
     264             :                                 FMT_DYNAMIC_EXP_MODE, 0);
     265           0 :                         break;
     266             :                 default:
     267             :                         break;
     268             :                 }
     269             :         }
     270             : }
     271             : 
     272             : static void opp1_program_clamping_and_pixel_encoding(
     273             :         struct output_pixel_processor *opp,
     274             :         const struct clamping_and_pixel_encoding_params *params)
     275             : {
     276           0 :         struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
     277             : 
     278           0 :         opp1_set_clamping(oppn10, params);
     279           0 :         opp1_set_pixel_encoding(oppn10, params);
     280             : }
     281             : 
     282           0 : void opp1_program_fmt(
     283             :         struct output_pixel_processor *opp,
     284             :         struct bit_depth_reduction_params *fmt_bit_depth,
     285             :         struct clamping_and_pixel_encoding_params *clamping)
     286             : {
     287           0 :         struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
     288             : 
     289           0 :         if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420)
     290           0 :                 REG_UPDATE(FMT_MAP420_MEMORY_CONTROL, FMT_MAP420MEM_PWR_FORCE, 0);
     291             : 
     292             :         /* dithering is affected by <CrtcSourceSelect>, hence should be
     293             :          * programmed afterwards */
     294           0 :         opp1_program_bit_depth_reduction(
     295             :                 opp,
     296             :                 fmt_bit_depth);
     297             : 
     298           0 :         opp1_program_clamping_and_pixel_encoding(
     299             :                 opp,
     300             :                 clamping);
     301             : 
     302           0 :         return;
     303             : }
     304             : 
     305           0 : void opp1_program_stereo(
     306             :         struct output_pixel_processor *opp,
     307             :         bool enable,
     308             :         const struct dc_crtc_timing *timing)
     309             : {
     310           0 :         struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
     311             : 
     312           0 :         uint32_t active_width = timing->h_addressable - timing->h_border_right - timing->h_border_right;
     313           0 :         uint32_t space1_size = timing->v_total - timing->v_addressable;
     314             :         /* TODO: confirm computation of space2_size */
     315           0 :         uint32_t space2_size = timing->v_total - timing->v_addressable;
     316             : 
     317           0 :         if (!enable) {
     318           0 :                 active_width = 0;
     319           0 :                 space1_size = 0;
     320           0 :                 space2_size = 0;
     321             :         }
     322             : 
     323             :         /* TODO: for which cases should FMT_STEREOSYNC_OVERRIDE be set? */
     324           0 :         REG_UPDATE(FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, 0);
     325             : 
     326           0 :         REG_UPDATE(OPPBUF_CONTROL, OPPBUF_ACTIVE_WIDTH, active_width);
     327             : 
     328             :         /* Program OPPBUF_3D_VACT_SPACE1_SIZE and OPPBUF_VACT_SPACE2_SIZE registers
     329             :          * In 3D progressive frames, Vactive space happens only in between the 2 frames,
     330             :          * so only need to program OPPBUF_3D_VACT_SPACE1_SIZE
     331             :          * In 3D alternative frames, left and right frames, top and bottom field.
     332             :          */
     333           0 :         if (timing->timing_3d_format == TIMING_3D_FORMAT_FRAME_ALTERNATE)
     334           0 :                 REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE2_SIZE, space2_size);
     335             :         else
     336           0 :                 REG_UPDATE(OPPBUF_3D_PARAMETERS_0, OPPBUF_3D_VACT_SPACE1_SIZE, space1_size);
     337             : 
     338             :         /* TODO: Is programming of OPPBUF_DUMMY_DATA_R/G/B needed? */
     339             :         /*
     340             :         REG_UPDATE(OPPBUF_3D_PARAMETERS_0,
     341             :                         OPPBUF_DUMMY_DATA_R, data_r);
     342             :         REG_UPDATE(OPPBUF_3D_PARAMETERS_1,
     343             :                         OPPBUF_DUMMY_DATA_G, data_g);
     344             :         REG_UPDATE(OPPBUF_3D_PARAMETERS_1,
     345             :                         OPPBUF_DUMMY_DATA_B, _data_b);
     346             :         */
     347           0 : }
     348             : 
     349           0 : void opp1_pipe_clock_control(struct output_pixel_processor *opp, bool enable)
     350             : {
     351           0 :         struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
     352           0 :         uint32_t regval = enable ? 1 : 0;
     353             : 
     354           0 :         REG_UPDATE(OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, regval);
     355           0 : }
     356             : 
     357             : /*****************************************/
     358             : /* Constructor, Destructor               */
     359             : /*****************************************/
     360             : 
     361           0 : void opp1_destroy(struct output_pixel_processor **opp)
     362             : {
     363           0 :         kfree(TO_DCN10_OPP(*opp));
     364           0 :         *opp = NULL;
     365           0 : }
     366             : 
     367             : static const struct opp_funcs dcn10_opp_funcs = {
     368             :                 .opp_set_dyn_expansion = opp1_set_dyn_expansion,
     369             :                 .opp_program_fmt = opp1_program_fmt,
     370             :                 .opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction,
     371             :                 .opp_program_stereo = opp1_program_stereo,
     372             :                 .opp_pipe_clock_control = opp1_pipe_clock_control,
     373             :                 .opp_set_disp_pattern_generator = NULL,
     374             :                 .opp_program_dpg_dimensions = NULL,
     375             :                 .dpg_is_blanked = NULL,
     376             :                 .opp_destroy = opp1_destroy
     377             : };
     378             : 
     379           0 : void dcn10_opp_construct(struct dcn10_opp *oppn10,
     380             :         struct dc_context *ctx,
     381             :         uint32_t inst,
     382             :         const struct dcn10_opp_registers *regs,
     383             :         const struct dcn10_opp_shift *opp_shift,
     384             :         const struct dcn10_opp_mask *opp_mask)
     385             : {
     386             : 
     387           0 :         oppn10->base.ctx = ctx;
     388           0 :         oppn10->base.inst = inst;
     389           0 :         oppn10->base.funcs = &dcn10_opp_funcs;
     390             : 
     391           0 :         oppn10->regs = regs;
     392           0 :         oppn10->opp_shift = opp_shift;
     393           0 :         oppn10->opp_mask = opp_mask;
     394           0 : }

Generated by: LCOV version 1.14