// SPDX-License-Identifier: MIT // // Copyright 2024 Advanced Micro Devices, Inc. #include "dcn401_optc.h" #include "dcn30/dcn30_optc.h" #include "dcn31/dcn31_optc.h" #include "dcn32/dcn32_optc.h" #include "reg_helper.h" #include "dc.h" #include "dcn_calc_math.h" #include "dc_dmub_srv.h" #define REG(reg) … #define CTX … #undef FN #define FN(reg_name, field_name) … /* * OPTC uses ODM_MEM sub block to merge pixel data coming from different OPPs * into unified memory location per horizontal line. ODM_MEM contains shared * memory resources global to the ASIC. Each memory resource is capable of * storing 2048 pixels independent from actual pixel data size. Total number of * memory allocated must be even. The memory resource allocation is described in * a memory bit map per OPTC instance. Driver has to make sure that there is no * double allocation across different OPTC instances. Bit offset in the map * represents memory instance id. Driver allocates a memory instance to the * current OPTC by setting the bit with offset associated with the desired * memory instance to 1 in the current OPTC memory map register. * * It is upto software to decide how to allocate the shared memory resources * across different OPTC instances. Driver understands that the total number * of memory available is always 2 times the max number of OPP pipes. So each * OPP pipe can be mapped 2 pieces of memory. However there exists cases such as * 11520x2160 which could use 6 pieces of memory for 2 OPP pipes i.e. 3 pieces * for each OPP pipe. * * Driver will reserve the first and second preferred memory instances for each * OPP pipe. For example, OPP0's first and second preferred memory is ODM_MEM0 * and ODM_MEM1. OPP1's first and second preferred memory is ODM_MEM2 and * ODM_MEM3 so on so forth. * * Driver will first allocate from first preferred memory instances associated * with current OPP pipes in use. If needed driver will then allocate from * second preferred memory instances associated with current OPP pipes in use. * Finally if still needed, driver will allocate from second preferred memory * instances not associated with current OPP pipes. So if memory instances are * enough other OPTCs can still allocate from their OPPs' first preferred memory * instances without worrying about double allocation. */ static uint32_t decide_odm_mem_bit_map(int *opp_id, int opp_cnt, int h_active) { … } static void optc401_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, int segment_width, int last_segment_width) { … } static void optc401_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode) { … } /** * optc401_enable_crtc() - Enable CRTC * @optc: Pointer to the timing generator structure * * This function calls ASIC Control Object to enable Timing generator. * * Return: Always returns true */ static bool optc401_enable_crtc(struct timing_generator *optc) { … } /* disable_crtc */ static bool optc401_disable_crtc(struct timing_generator *optc) { … } static void optc401_phantom_crtc_post_enable(struct timing_generator *optc) { … } static void optc401_disable_phantom_otg(struct timing_generator *optc) { … } static void optc401_set_odm_bypass(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing) { … } /* only to be used when FAMS2 is disabled or unsupported */ void optc401_setup_manual_trigger(struct timing_generator *optc) { … } void optc401_set_drr( struct timing_generator *optc, const struct drr_params *params) { … } static void optc401_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest) { … } void optc401_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max) { … } static struct timing_generator_funcs dcn401_tg_funcs = …; void dcn401_timing_generator_init(struct optc *optc1) { … }