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

          Line data    Source code
       1             : // SPDX-License-Identifier: MIT
       2             : /*
       3             :  * Copyright 2022 Advanced Micro Devices, Inc.
       4             :  *
       5             :  * Permission is hereby granted, free of charge, to any person obtaining a
       6             :  * copy of this software and associated documentation files (the "Software"),
       7             :  * to deal in the Software without restriction, including without limitation
       8             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       9             :  * and/or sell copies of the Software, and to permit persons to whom the
      10             :  * Software is furnished to do so, subject to the following conditions:
      11             :  *
      12             :  * The above copyright notice and this permission notice shall be included in
      13             :  * all copies or substantial portions of the Software.
      14             :  *
      15             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      19             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      20             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      21             :  * OTHER DEALINGS IN THE SOFTWARE.
      22             :  *
      23             :  * Authors: AMD
      24             :  *
      25             :  */
      26             : 
      27             : #include "dcn314_optc.h"
      28             : 
      29             : #include "dcn30/dcn30_optc.h"
      30             : #include "dcn31/dcn31_optc.h"
      31             : #include "reg_helper.h"
      32             : #include "dc.h"
      33             : #include "dcn_calc_math.h"
      34             : 
      35             : #define REG(reg)\
      36             :         optc1->tg_regs->reg
      37             : 
      38             : #define CTX \
      39             :         optc1->base.ctx
      40             : 
      41             : #undef FN
      42             : #define FN(reg_name, field_name) \
      43             :         optc1->tg_shift->field_name, optc1->tg_mask->field_name
      44             : 
      45             : /*
      46             :  * Enable CRTC
      47             :  * Enable CRTC - call ASIC Control Object to enable Timing generator.
      48             :  */
      49             : 
      50           0 : static void optc314_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
      51             :                 struct dc_crtc_timing *timing)
      52             : {
      53           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
      54           0 :         uint32_t memory_mask = 0;
      55           0 :         int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right;
      56           0 :         int mpcc_hactive = h_active / opp_cnt;
      57             :         /* Each memory instance is 2048x(314x2) bits to support half line of 4096 */
      58           0 :         int odm_mem_count = (h_active + 2047) / 2048;
      59             : 
      60             :         /*
      61             :          * display <= 4k : 2 memories + 2 pipes
      62             :          * 4k < display <= 8k : 4 memories + 2 pipes
      63             :          * 8k < display <= 12k : 6 memories + 4 pipes
      64             :          */
      65           0 :         if (opp_cnt == 4) {
      66           0 :                 if (odm_mem_count <= 2)
      67             :                         memory_mask = 0x3;
      68           0 :                 else if (odm_mem_count <= 4)
      69             :                         memory_mask = 0xf;
      70             :                 else
      71           0 :                         memory_mask = 0x3f;
      72             :         } else {
      73           0 :                 if (odm_mem_count <= 2)
      74           0 :                         memory_mask = 0x1 << (opp_id[0] * 2) | 0x1 << (opp_id[1] * 2);
      75           0 :                 else if (odm_mem_count <= 4)
      76           0 :                         memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2);
      77             :                 else
      78             :                         memory_mask = 0x77;
      79             :         }
      80             : 
      81           0 :         REG_SET(OPTC_MEMORY_CONFIG, 0,
      82             :                 OPTC_MEM_SEL, memory_mask);
      83             : 
      84           0 :         if (opp_cnt == 2) {
      85           0 :                 REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0,
      86             :                                 OPTC_NUM_OF_INPUT_SEGMENT, 1,
      87             :                                 OPTC_SEG0_SRC_SEL, opp_id[0],
      88             :                                 OPTC_SEG1_SRC_SEL, opp_id[1]);
      89           0 :         } else if (opp_cnt == 4) {
      90           0 :                 REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
      91             :                                 OPTC_NUM_OF_INPUT_SEGMENT, 3,
      92             :                                 OPTC_SEG0_SRC_SEL, opp_id[0],
      93             :                                 OPTC_SEG1_SRC_SEL, opp_id[1],
      94             :                                 OPTC_SEG2_SRC_SEL, opp_id[2],
      95             :                                 OPTC_SEG3_SRC_SEL, opp_id[3]);
      96             :         }
      97             : 
      98           0 :         REG_UPDATE(OPTC_WIDTH_CONTROL,
      99             :                         OPTC_SEGMENT_WIDTH, mpcc_hactive);
     100             : 
     101           0 :         REG_UPDATE(OTG_H_TIMING_CNTL,
     102             :                         OTG_H_TIMING_DIV_MODE, opp_cnt - 1);
     103           0 :         optc1->opp_count = opp_cnt;
     104           0 : }
     105             : 
     106           0 : static bool optc314_enable_crtc(struct timing_generator *optc)
     107             : {
     108           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     109             : 
     110             :         /* opp instance for OTG, 1 to 1 mapping and odm will adjust */
     111           0 :         REG_UPDATE(OPTC_DATA_SOURCE_SELECT,
     112             :                         OPTC_SEG0_SRC_SEL, optc->inst);
     113             : 
     114             :         /* VTG enable first is for HW workaround */
     115           0 :         REG_UPDATE(CONTROL,
     116             :                         VTG0_ENABLE, 1);
     117             : 
     118           0 :         REG_SEQ_START();
     119             : 
     120             :         /* Enable CRTC */
     121           0 :         REG_UPDATE_2(OTG_CONTROL,
     122             :                         OTG_DISABLE_POINT_CNTL, 2,
     123             :                         OTG_MASTER_EN, 1);
     124             : 
     125           0 :         REG_SEQ_SUBMIT();
     126           0 :         REG_SEQ_WAIT_DONE();
     127             : 
     128           0 :         return true;
     129             : }
     130             : 
     131             : /* disable_crtc */
     132           0 : static bool optc314_disable_crtc(struct timing_generator *optc)
     133             : {
     134           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     135             : 
     136             :         /* disable otg request until end of the first line
     137             :          * in the vertical blank region
     138             :          */
     139           0 :         REG_UPDATE(OTG_CONTROL,
     140             :                         OTG_MASTER_EN, 0);
     141             : 
     142           0 :         REG_UPDATE(CONTROL,
     143             :                         VTG0_ENABLE, 0);
     144             : 
     145             :         /* CRTC disabled, so disable  clock. */
     146           0 :         REG_WAIT(OTG_CLOCK_CONTROL,
     147             :                         OTG_BUSY, 0,
     148             :                         1, 100000);
     149             : 
     150           0 :         return true;
     151             : }
     152             : 
     153           0 : void optc314_phantom_crtc_post_enable(struct timing_generator *optc)
     154             : {
     155           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     156             : 
     157             :         /* Disable immediately. */
     158           0 :         REG_UPDATE_2(OTG_CONTROL, OTG_DISABLE_POINT_CNTL, 0, OTG_MASTER_EN, 0);
     159             : 
     160             :         /* CRTC disabled, so disable  clock. */
     161           0 :         REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000);
     162           0 : }
     163             : 
     164           0 : static void optc314_set_odm_bypass(struct timing_generator *optc,
     165             :                 const struct dc_crtc_timing *dc_crtc_timing)
     166             : {
     167           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     168           0 :         enum h_timing_div_mode h_div = H_TIMING_NO_DIV;
     169             : 
     170           0 :         REG_SET_5(OPTC_DATA_SOURCE_SELECT, 0,
     171             :                         OPTC_NUM_OF_INPUT_SEGMENT, 0,
     172             :                         OPTC_SEG0_SRC_SEL, optc->inst,
     173             :                         OPTC_SEG1_SRC_SEL, 0xf,
     174             :                         OPTC_SEG2_SRC_SEL, 0xf,
     175             :                         OPTC_SEG3_SRC_SEL, 0xf
     176             :                         );
     177             : 
     178           0 :         h_div = optc1_is_two_pixels_per_containter(dc_crtc_timing);
     179           0 :         REG_UPDATE(OTG_H_TIMING_CNTL,
     180             :                         OTG_H_TIMING_DIV_MODE, h_div);
     181             : 
     182           0 :         REG_SET(OPTC_MEMORY_CONFIG, 0,
     183             :                         OPTC_MEM_SEL, 0);
     184           0 :         optc1->opp_count = 1;
     185           0 : }
     186             : 
     187           0 : static void optc314_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode)
     188             : {
     189           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     190             : 
     191           0 :         REG_UPDATE(OTG_H_TIMING_CNTL,
     192             :                         OTG_H_TIMING_DIV_MODE_MANUAL, manual_mode ? 1 : 0);
     193           0 : }
     194             : 
     195             : 
     196             : static struct timing_generator_funcs dcn314_tg_funcs = {
     197             :                 .validate_timing = optc1_validate_timing,
     198             :                 .program_timing = optc1_program_timing,
     199             :                 .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
     200             :                 .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
     201             :                 .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
     202             :                 .program_global_sync = optc1_program_global_sync,
     203             :                 .enable_crtc = optc314_enable_crtc,
     204             :                 .disable_crtc = optc314_disable_crtc,
     205             :                 .immediate_disable_crtc = optc31_immediate_disable_crtc,
     206             :                 .phantom_crtc_post_enable = optc314_phantom_crtc_post_enable,
     207             :                 /* used by enable_timing_synchronization. Not need for FPGA */
     208             :                 .is_counter_moving = optc1_is_counter_moving,
     209             :                 .get_position = optc1_get_position,
     210             :                 .get_frame_count = optc1_get_vblank_counter,
     211             :                 .get_scanoutpos = optc1_get_crtc_scanoutpos,
     212             :                 .get_otg_active_size = optc1_get_otg_active_size,
     213             :                 .set_early_control = optc1_set_early_control,
     214             :                 /* used by enable_timing_synchronization. Not need for FPGA */
     215             :                 .wait_for_state = optc1_wait_for_state,
     216             :                 .set_blank_color = optc3_program_blank_color,
     217             :                 .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
     218             :                 .triplebuffer_lock = optc3_triplebuffer_lock,
     219             :                 .triplebuffer_unlock = optc2_triplebuffer_unlock,
     220             :                 .enable_reset_trigger = optc1_enable_reset_trigger,
     221             :                 .enable_crtc_reset = optc1_enable_crtc_reset,
     222             :                 .disable_reset_trigger = optc1_disable_reset_trigger,
     223             :                 .lock = optc3_lock,
     224             :                 .unlock = optc1_unlock,
     225             :                 .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
     226             :                 .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
     227             :                 .enable_optc_clock = optc1_enable_optc_clock,
     228             :                 .set_drr = optc31_set_drr,
     229             :                 .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
     230             :                 .set_vtotal_min_max = optc1_set_vtotal_min_max,
     231             :                 .set_static_screen_control = optc1_set_static_screen_control,
     232             :                 .program_stereo = optc1_program_stereo,
     233             :                 .is_stereo_left_eye = optc1_is_stereo_left_eye,
     234             :                 .tg_init = optc3_tg_init,
     235             :                 .is_tg_enabled = optc1_is_tg_enabled,
     236             :                 .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
     237             :                 .clear_optc_underflow = optc1_clear_optc_underflow,
     238             :                 .setup_global_swap_lock = NULL,
     239             :                 .get_crc = optc1_get_crc,
     240             :                 .configure_crc = optc2_configure_crc,
     241             :                 .set_dsc_config = optc3_set_dsc_config,
     242             :                 .get_dsc_status = optc2_get_dsc_status,
     243             :                 .set_dwb_source = NULL,
     244             :                 .set_odm_bypass = optc3_set_odm_bypass,
     245             :                 .set_odm_combine = optc314_set_odm_combine,
     246             :                 .get_optc_source = optc2_get_optc_source,
     247             :                 .set_out_mux = optc3_set_out_mux,
     248             :                 .set_drr_trigger_window = optc3_set_drr_trigger_window,
     249             :                 .set_vtotal_change_limit = optc3_set_vtotal_change_limit,
     250             :                 .set_gsl = optc2_set_gsl,
     251             :                 .set_gsl_source_select = optc2_set_gsl_source_select,
     252             :                 .set_vtg_params = optc1_set_vtg_params,
     253             :                 .program_manual_trigger = optc2_program_manual_trigger,
     254             :                 .setup_manual_trigger = optc2_setup_manual_trigger,
     255             :                 .get_hw_timing = optc1_get_hw_timing,
     256             :                 .init_odm = optc3_init_odm,
     257             :                 .set_odm_bypass = optc314_set_odm_bypass,
     258             :                 .set_odm_combine = optc314_set_odm_combine,
     259             :                 .set_h_timing_div_manual_mode = optc314_set_h_timing_div_manual_mode,
     260             : };
     261             : 
     262           0 : void dcn314_timing_generator_init(struct optc *optc1)
     263             : {
     264           0 :         optc1->base.funcs = &dcn314_tg_funcs;
     265             : 
     266           0 :         optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
     267           0 :         optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
     268             : 
     269           0 :         optc1->min_h_blank = 32;
     270           0 :         optc1->min_v_blank = 3;
     271           0 :         optc1->min_v_blank_interlace = 5;
     272           0 :         optc1->min_h_sync_width = 4;
     273           0 :         optc1->min_v_sync_width = 1;
     274           0 : }
     275             : 

Generated by: LCOV version 1.14