1289 lines · c
1/*2* Copyright 2012-15 Advanced Micro Devices, Inc.cls3*4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice shall be included in13 * all copies or substantial portions of the Software.14 *15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR19 * 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 OR21 * OTHER DEALINGS IN THE SOFTWARE.22 *23 * Authors: AMD24 *25 */26 27#include "dm_services.h"28 29 30#include "stream_encoder.h"31#include "resource.h"32#include "include/irq_service_interface.h"33#include "dce120_resource.h"34 35#include "dce112/dce112_resource.h"36 37#include "dce110/dce110_resource.h"38#include "virtual/virtual_stream_encoder.h"39#include "dce120/dce120_timing_generator.h"40#include "irq/dce120/irq_service_dce120.h"41#include "dce/dce_opp.h"42#include "dce/dce_clock_source.h"43#include "dce/dce_ipp.h"44#include "dce/dce_mem_input.h"45#include "dce/dce_panel_cntl.h"46 47#include "dce110/dce110_hwseq.h"48#include "dce120/dce120_hwseq.h"49#include "dce/dce_transform.h"50#include "clk_mgr.h"51#include "dce/dce_audio.h"52#include "dce/dce_link_encoder.h"53#include "dce/dce_stream_encoder.h"54#include "dce/dce_hwseq.h"55#include "dce/dce_abm.h"56#include "dce/dce_dmcu.h"57#include "dce/dce_aux.h"58#include "dce/dce_i2c.h"59 60#include "dce/dce_12_0_offset.h"61#include "dce/dce_12_0_sh_mask.h"62#include "soc15_hw_ip.h"63#include "vega10_ip_offset.h"64#include "nbio/nbio_6_1_offset.h"65#include "mmhub/mmhub_1_0_offset.h"66#include "mmhub/mmhub_1_0_sh_mask.h"67#include "reg_helper.h"68 69#include "dce100/dce100_resource.h"70 71#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL72 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f73 #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 274 #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f75 #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 276 #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f77 #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 278 #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f79 #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 280 #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f81 #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 282 #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f83 #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 284 #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f85 #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 286#endif87 88enum dce120_clk_src_array_id {89 DCE120_CLK_SRC_PLL0,90 DCE120_CLK_SRC_PLL1,91 DCE120_CLK_SRC_PLL2,92 DCE120_CLK_SRC_PLL3,93 DCE120_CLK_SRC_PLL4,94 DCE120_CLK_SRC_PLL5,95 96 DCE120_CLK_SRC_TOTAL97};98 99static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = {100 {101 .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL),102 },103 {104 .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL),105 },106 {107 .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL),108 },109 {110 .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL),111 },112 {113 .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL),114 },115 {116 .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC0_CRTC_CONTROL),117 }118};119 120/* begin *********************121 * macros to expend register list macro defined in HW object header file */122 123#define BASE_INNER(seg) \124 DCE_BASE__INST0_SEG ## seg125 126#define NBIO_BASE_INNER(seg) \127 NBIF_BASE__INST0_SEG ## seg128 129#define NBIO_BASE(seg) \130 NBIO_BASE_INNER(seg)131 132/* compile time expand base address. */133#define BASE(seg) \134 BASE_INNER(seg)135 136#define SR(reg_name)\137 .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \138 mm ## reg_name139 140#define SRI(reg_name, block, id)\141 .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \142 mm ## block ## id ## _ ## reg_name143 144/* MMHUB */145#define MMHUB_BASE_INNER(seg) \146 MMHUB_BASE__INST0_SEG ## seg147 148#define MMHUB_BASE(seg) \149 MMHUB_BASE_INNER(seg)150 151#define MMHUB_SR(reg_name)\152 .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \153 mm ## reg_name154 155/* macros to expend register list macro defined in HW object header file156 * end *********************/157 158 159static const struct dce_dmcu_registers dmcu_regs = {160 DMCU_DCE110_COMMON_REG_LIST()161};162 163static const struct dce_dmcu_shift dmcu_shift = {164 DMCU_MASK_SH_LIST_DCE110(__SHIFT)165};166 167static const struct dce_dmcu_mask dmcu_mask = {168 DMCU_MASK_SH_LIST_DCE110(_MASK)169};170 171static const struct dce_abm_registers abm_regs = {172 ABM_DCE110_COMMON_REG_LIST()173};174 175static const struct dce_abm_shift abm_shift = {176 ABM_MASK_SH_LIST_DCE110(__SHIFT)177};178 179static const struct dce_abm_mask abm_mask = {180 ABM_MASK_SH_LIST_DCE110(_MASK)181};182 183#define ipp_regs(id)\184[id] = {\185 IPP_DCE110_REG_LIST_DCE_BASE(id)\186}187 188static const struct dce_ipp_registers ipp_regs[] = {189 ipp_regs(0),190 ipp_regs(1),191 ipp_regs(2),192 ipp_regs(3),193 ipp_regs(4),194 ipp_regs(5)195};196 197static const struct dce_ipp_shift ipp_shift = {198 IPP_DCE120_MASK_SH_LIST_SOC_BASE(__SHIFT)199};200 201static const struct dce_ipp_mask ipp_mask = {202 IPP_DCE120_MASK_SH_LIST_SOC_BASE(_MASK)203};204 205#define transform_regs(id)\206[id] = {\207 XFM_COMMON_REG_LIST_DCE110(id)\208}209 210static const struct dce_transform_registers xfm_regs[] = {211 transform_regs(0),212 transform_regs(1),213 transform_regs(2),214 transform_regs(3),215 transform_regs(4),216 transform_regs(5)217};218 219static const struct dce_transform_shift xfm_shift = {220 XFM_COMMON_MASK_SH_LIST_SOC_BASE(__SHIFT)221};222 223static const struct dce_transform_mask xfm_mask = {224 XFM_COMMON_MASK_SH_LIST_SOC_BASE(_MASK)225};226 227#define aux_regs(id)\228[id] = {\229 AUX_REG_LIST(id)\230}231 232static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = {233 aux_regs(0),234 aux_regs(1),235 aux_regs(2),236 aux_regs(3),237 aux_regs(4),238 aux_regs(5)239};240 241#define hpd_regs(id)\242[id] = {\243 HPD_REG_LIST(id)\244}245 246static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = {247 hpd_regs(0),248 hpd_regs(1),249 hpd_regs(2),250 hpd_regs(3),251 hpd_regs(4),252 hpd_regs(5)253};254 255#define link_regs(id)\256[id] = {\257 LE_DCE120_REG_LIST(id), \258 SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \259}260 261static const struct dce110_link_enc_registers link_enc_regs[] = {262 link_regs(0),263 link_regs(1),264 link_regs(2),265 link_regs(3),266 link_regs(4),267 link_regs(5),268 link_regs(6),269};270 271 272#define stream_enc_regs(id)\273[id] = {\274 SE_COMMON_REG_LIST(id),\275 .TMDS_CNTL = 0,\276}277 278static const struct dce110_stream_enc_registers stream_enc_regs[] = {279 stream_enc_regs(0),280 stream_enc_regs(1),281 stream_enc_regs(2),282 stream_enc_regs(3),283 stream_enc_regs(4),284 stream_enc_regs(5)285};286 287static const struct dce_stream_encoder_shift se_shift = {288 SE_COMMON_MASK_SH_LIST_DCE120(__SHIFT)289};290 291static const struct dce_stream_encoder_mask se_mask = {292 SE_COMMON_MASK_SH_LIST_DCE120(_MASK)293};294 295static const struct dce_panel_cntl_registers panel_cntl_regs[] = {296 { DCE_PANEL_CNTL_REG_LIST() }297};298 299static const struct dce_panel_cntl_shift panel_cntl_shift = {300 DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT)301};302 303static const struct dce_panel_cntl_mask panel_cntl_mask = {304 DCE_PANEL_CNTL_MASK_SH_LIST(_MASK)305};306 307static const struct dce110_aux_registers_shift aux_shift = {308 DCE12_AUX_MASK_SH_LIST(__SHIFT)309};310 311static const struct dce110_aux_registers_mask aux_mask = {312 DCE12_AUX_MASK_SH_LIST(_MASK)313};314 315#define opp_regs(id)\316[id] = {\317 OPP_DCE_120_REG_LIST(id),\318}319 320static const struct dce_opp_registers opp_regs[] = {321 opp_regs(0),322 opp_regs(1),323 opp_regs(2),324 opp_regs(3),325 opp_regs(4),326 opp_regs(5)327};328 329static const struct dce_opp_shift opp_shift = {330 OPP_COMMON_MASK_SH_LIST_DCE_120(__SHIFT)331};332 333static const struct dce_opp_mask opp_mask = {334 OPP_COMMON_MASK_SH_LIST_DCE_120(_MASK)335};336 #define aux_engine_regs(id)\337[id] = {\338 AUX_COMMON_REG_LIST(id), \339 .AUX_RESET_MASK = 0 \340}341 342static const struct dce110_aux_registers aux_engine_regs[] = {343 aux_engine_regs(0),344 aux_engine_regs(1),345 aux_engine_regs(2),346 aux_engine_regs(3),347 aux_engine_regs(4),348 aux_engine_regs(5)349};350 351#define audio_regs(id)\352[id] = {\353 AUD_COMMON_REG_LIST(id)\354}355 356static const struct dce_audio_registers audio_regs[] = {357 audio_regs(0),358 audio_regs(1),359 audio_regs(2),360 audio_regs(3),361 audio_regs(4),362 audio_regs(5),363 audio_regs(6),364};365 366#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\367 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\368 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\369 AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)370 371static const struct dce_audio_shift audio_shift = {372 DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT)373};374 375static const struct dce_audio_mask audio_mask = {376 DCE120_AUD_COMMON_MASK_SH_LIST(_MASK)377};378 379static int map_transmitter_id_to_phy_instance(380 enum transmitter transmitter)381{382 switch (transmitter) {383 case TRANSMITTER_UNIPHY_A:384 return 0;385 case TRANSMITTER_UNIPHY_B:386 return 1;387 case TRANSMITTER_UNIPHY_C:388 return 2;389 case TRANSMITTER_UNIPHY_D:390 return 3;391 case TRANSMITTER_UNIPHY_E:392 return 4;393 case TRANSMITTER_UNIPHY_F:394 return 5;395 case TRANSMITTER_UNIPHY_G:396 return 6;397 default:398 ASSERT(0);399 return 0;400 }401}402 403#define clk_src_regs(index, id)\404[index] = {\405 CS_COMMON_REG_LIST_DCE_112(id),\406}407 408static const struct dce110_clk_src_regs clk_src_regs[] = {409 clk_src_regs(0, A),410 clk_src_regs(1, B),411 clk_src_regs(2, C),412 clk_src_regs(3, D),413 clk_src_regs(4, E),414 clk_src_regs(5, F)415};416 417static const struct dce110_clk_src_shift cs_shift = {418 CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT)419};420 421static const struct dce110_clk_src_mask cs_mask = {422 CS_COMMON_MASK_SH_LIST_DCE_112(_MASK)423};424 425static struct output_pixel_processor *dce120_opp_create(426 struct dc_context *ctx,427 uint32_t inst)428{429 struct dce110_opp *opp =430 kzalloc(sizeof(struct dce110_opp), GFP_KERNEL);431 432 if (!opp)433 return NULL;434 435 dce110_opp_construct(opp,436 ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask);437 return &opp->base;438}439static struct dce_aux *dce120_aux_engine_create(440 struct dc_context *ctx,441 uint32_t inst)442{443 struct aux_engine_dce110 *aux_engine =444 kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL);445 446 if (!aux_engine)447 return NULL;448 449 dce110_aux_engine_construct(aux_engine, ctx, inst,450 SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,451 &aux_engine_regs[inst],452 &aux_mask,453 &aux_shift,454 ctx->dc->caps.extended_aux_timeout_support);455 456 return &aux_engine->base;457}458#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) }459 460static const struct dce_i2c_registers i2c_hw_regs[] = {461 i2c_inst_regs(1),462 i2c_inst_regs(2),463 i2c_inst_regs(3),464 i2c_inst_regs(4),465 i2c_inst_regs(5),466 i2c_inst_regs(6),467};468 469static const struct dce_i2c_shift i2c_shifts = {470 I2C_COMMON_MASK_SH_LIST_DCE110(__SHIFT)471};472 473static const struct dce_i2c_mask i2c_masks = {474 I2C_COMMON_MASK_SH_LIST_DCE110(_MASK)475};476 477static struct dce_i2c_hw *dce120_i2c_hw_create(478 struct dc_context *ctx,479 uint32_t inst)480{481 struct dce_i2c_hw *dce_i2c_hw =482 kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL);483 484 if (!dce_i2c_hw)485 return NULL;486 487 dce112_i2c_hw_construct(dce_i2c_hw, ctx, inst,488 &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);489 490 return dce_i2c_hw;491}492static const struct bios_registers bios_regs = {493 .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3 + NBIO_BASE(mmBIOS_SCRATCH_3_BASE_IDX),494 .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 + NBIO_BASE(mmBIOS_SCRATCH_6_BASE_IDX)495};496 497static const struct resource_caps res_cap = {498 .num_timing_generator = 6,499 .num_audio = 7,500 .num_stream_encoder = 6,501 .num_pll = 6,502 .num_ddc = 6,503};504 505static const struct dc_plane_cap plane_cap = {506 .type = DC_PLANE_TYPE_DCE_RGB,507 508 .pixel_format_support = {509 .argb8888 = true,510 .nv12 = false,511 .fp16 = true512 },513 514 .max_upscale_factor = {515 .argb8888 = 16000,516 .nv12 = 1,517 .fp16 = 1518 },519 520 .max_downscale_factor = {521 .argb8888 = 250,522 .nv12 = 1,523 .fp16 = 1524 }525};526 527static const struct dc_debug_options debug_defaults = {528 .disable_clock_gate = true,529 .enable_legacy_fast_update = true,530};531 532static struct clock_source *dce120_clock_source_create(533 struct dc_context *ctx,534 struct dc_bios *bios,535 enum clock_source_id id,536 const struct dce110_clk_src_regs *regs,537 bool dp_clk_src)538{539 struct dce110_clk_src *clk_src =540 kzalloc(sizeof(*clk_src), GFP_KERNEL);541 542 if (!clk_src)543 return NULL;544 545 if (dce112_clk_src_construct(clk_src, ctx, bios, id,546 regs, &cs_shift, &cs_mask)) {547 clk_src->base.dp_clk_src = dp_clk_src;548 return &clk_src->base;549 }550 551 kfree(clk_src);552 BREAK_TO_DEBUGGER();553 return NULL;554}555 556static void dce120_clock_source_destroy(struct clock_source **clk_src)557{558 kfree(TO_DCE110_CLK_SRC(*clk_src));559 *clk_src = NULL;560}561 562 563static bool dce120_hw_sequencer_create(struct dc *dc)564{565 /* All registers used by dce11.2 match those in dce11 in offset and566 * structure567 */568 dce120_hw_sequencer_construct(dc);569 570 /*TODO Move to separate file and Override what is needed */571 572 return true;573}574 575static struct timing_generator *dce120_timing_generator_create(576 struct dc_context *ctx,577 uint32_t instance,578 const struct dce110_timing_generator_offsets *offsets)579{580 struct dce110_timing_generator *tg110 =581 kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL);582 583 if (!tg110)584 return NULL;585 586 dce120_timing_generator_construct(tg110, ctx, instance, offsets);587 return &tg110->base;588}589 590static void dce120_transform_destroy(struct transform **xfm)591{592 kfree(TO_DCE_TRANSFORM(*xfm));593 *xfm = NULL;594}595 596static void dce120_resource_destruct(struct dce110_resource_pool *pool)597{598 unsigned int i;599 600 for (i = 0; i < pool->base.pipe_count; i++) {601 if (pool->base.opps[i] != NULL)602 dce110_opp_destroy(&pool->base.opps[i]);603 604 if (pool->base.transforms[i] != NULL)605 dce120_transform_destroy(&pool->base.transforms[i]);606 607 if (pool->base.ipps[i] != NULL)608 dce_ipp_destroy(&pool->base.ipps[i]);609 610 if (pool->base.mis[i] != NULL) {611 kfree(TO_DCE_MEM_INPUT(pool->base.mis[i]));612 pool->base.mis[i] = NULL;613 }614 615 if (pool->base.irqs != NULL) {616 dal_irq_service_destroy(&pool->base.irqs);617 }618 619 if (pool->base.timing_generators[i] != NULL) {620 kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i]));621 pool->base.timing_generators[i] = NULL;622 }623 }624 625 for (i = 0; i < pool->base.res_cap->num_ddc; i++) {626 if (pool->base.engines[i] != NULL)627 dce110_engine_destroy(&pool->base.engines[i]);628 if (pool->base.hw_i2cs[i] != NULL) {629 kfree(pool->base.hw_i2cs[i]);630 pool->base.hw_i2cs[i] = NULL;631 }632 if (pool->base.sw_i2cs[i] != NULL) {633 kfree(pool->base.sw_i2cs[i]);634 pool->base.sw_i2cs[i] = NULL;635 }636 }637 638 for (i = 0; i < pool->base.audio_count; i++) {639 if (pool->base.audios[i])640 dce_aud_destroy(&pool->base.audios[i]);641 }642 643 for (i = 0; i < pool->base.stream_enc_count; i++) {644 if (pool->base.stream_enc[i] != NULL)645 kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i]));646 }647 648 for (i = 0; i < pool->base.clk_src_count; i++) {649 if (pool->base.clock_sources[i] != NULL)650 dce120_clock_source_destroy(651 &pool->base.clock_sources[i]);652 }653 654 if (pool->base.dp_clock_source != NULL)655 dce120_clock_source_destroy(&pool->base.dp_clock_source);656 657 if (pool->base.abm != NULL)658 dce_abm_destroy(&pool->base.abm);659 660 if (pool->base.dmcu != NULL)661 dce_dmcu_destroy(&pool->base.dmcu);662}663 664static void read_dce_straps(665 struct dc_context *ctx,666 struct resource_straps *straps)667{668 uint32_t reg_val = dm_read_reg_soc15(ctx, mmCC_DC_MISC_STRAPS, 0);669 670 straps->audio_stream_number = get_reg_field_value(reg_val,671 CC_DC_MISC_STRAPS,672 AUDIO_STREAM_NUMBER);673 straps->hdmi_disable = get_reg_field_value(reg_val,674 CC_DC_MISC_STRAPS,675 HDMI_DISABLE);676 677 reg_val = dm_read_reg_soc15(ctx, mmDC_PINSTRAPS, 0);678 straps->dc_pinstraps_audio = get_reg_field_value(reg_val,679 DC_PINSTRAPS,680 DC_PINSTRAPS_AUDIO);681}682 683static struct audio *create_audio(684 struct dc_context *ctx, unsigned int inst)685{686 return dce_audio_create(ctx, inst,687 &audio_regs[inst], &audio_shift, &audio_mask);688}689 690static const struct encoder_feature_support link_enc_feature = {691 .max_hdmi_deep_color = COLOR_DEPTH_121212,692 .max_hdmi_pixel_clock = 600000,693 .hdmi_ycbcr420_supported = true,694 .dp_ycbcr420_supported = false,695 .flags.bits.IS_HBR2_CAPABLE = true,696 .flags.bits.IS_HBR3_CAPABLE = true,697 .flags.bits.IS_TPS3_CAPABLE = true,698 .flags.bits.IS_TPS4_CAPABLE = true,699};700 701static struct link_encoder *dce120_link_encoder_create(702 struct dc_context *ctx,703 const struct encoder_init_data *enc_init_data)704{705 struct dce110_link_encoder *enc110 =706 kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL);707 int link_regs_id;708 709 if (!enc110)710 return NULL;711 712 link_regs_id =713 map_transmitter_id_to_phy_instance(enc_init_data->transmitter);714 715 dce110_link_encoder_construct(enc110,716 enc_init_data,717 &link_enc_feature,718 &link_enc_regs[link_regs_id],719 &link_enc_aux_regs[enc_init_data->channel - 1],720 &link_enc_hpd_regs[enc_init_data->hpd_source]);721 722 return &enc110->base;723}724 725static struct panel_cntl *dce120_panel_cntl_create(const struct panel_cntl_init_data *init_data)726{727 struct dce_panel_cntl *panel_cntl =728 kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL);729 730 if (!panel_cntl)731 return NULL;732 733 dce_panel_cntl_construct(panel_cntl,734 init_data,735 &panel_cntl_regs[init_data->inst],736 &panel_cntl_shift,737 &panel_cntl_mask);738 739 return &panel_cntl->base;740}741 742static struct input_pixel_processor *dce120_ipp_create(743 struct dc_context *ctx, uint32_t inst)744{745 struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL);746 747 if (!ipp) {748 BREAK_TO_DEBUGGER();749 return NULL;750 }751 752 dce_ipp_construct(ipp, ctx, inst,753 &ipp_regs[inst], &ipp_shift, &ipp_mask);754 return &ipp->base;755}756 757static struct stream_encoder *dce120_stream_encoder_create(758 enum engine_id eng_id,759 struct dc_context *ctx)760{761 struct dce110_stream_encoder *enc110 =762 kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL);763 764 if (!enc110)765 return NULL;766 767 dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id,768 &stream_enc_regs[eng_id],769 &se_shift, &se_mask);770 return &enc110->base;771}772 773#define SRII(reg_name, block, id)\774 .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \775 mm ## block ## id ## _ ## reg_name776 777static const struct dce_hwseq_registers hwseq_reg = {778 HWSEQ_DCE120_REG_LIST()779};780 781static const struct dce_hwseq_shift hwseq_shift = {782 HWSEQ_DCE12_MASK_SH_LIST(__SHIFT)783};784 785static const struct dce_hwseq_mask hwseq_mask = {786 HWSEQ_DCE12_MASK_SH_LIST(_MASK)787};788 789/* HWSEQ regs for VG20 */790static const struct dce_hwseq_registers dce121_hwseq_reg = {791 HWSEQ_VG20_REG_LIST()792};793 794static const struct dce_hwseq_shift dce121_hwseq_shift = {795 HWSEQ_VG20_MASK_SH_LIST(__SHIFT)796};797 798static const struct dce_hwseq_mask dce121_hwseq_mask = {799 HWSEQ_VG20_MASK_SH_LIST(_MASK)800};801 802static struct dce_hwseq *dce120_hwseq_create(803 struct dc_context *ctx)804{805 struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);806 807 if (hws) {808 hws->ctx = ctx;809 hws->regs = &hwseq_reg;810 hws->shifts = &hwseq_shift;811 hws->masks = &hwseq_mask;812 }813 return hws;814}815 816static struct dce_hwseq *dce121_hwseq_create(817 struct dc_context *ctx)818{819 struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);820 821 if (hws) {822 hws->ctx = ctx;823 hws->regs = &dce121_hwseq_reg;824 hws->shifts = &dce121_hwseq_shift;825 hws->masks = &dce121_hwseq_mask;826 }827 return hws;828}829 830static const struct resource_create_funcs res_create_funcs = {831 .read_dce_straps = read_dce_straps,832 .create_audio = create_audio,833 .create_stream_encoder = dce120_stream_encoder_create,834 .create_hwseq = dce120_hwseq_create,835};836 837static const struct resource_create_funcs dce121_res_create_funcs = {838 .read_dce_straps = read_dce_straps,839 .create_audio = create_audio,840 .create_stream_encoder = dce120_stream_encoder_create,841 .create_hwseq = dce121_hwseq_create,842};843 844 845#define mi_inst_regs(id) { MI_DCE12_REG_LIST(id) }846static const struct dce_mem_input_registers mi_regs[] = {847 mi_inst_regs(0),848 mi_inst_regs(1),849 mi_inst_regs(2),850 mi_inst_regs(3),851 mi_inst_regs(4),852 mi_inst_regs(5),853};854 855static const struct dce_mem_input_shift mi_shifts = {856 MI_DCE12_MASK_SH_LIST(__SHIFT)857};858 859static const struct dce_mem_input_mask mi_masks = {860 MI_DCE12_MASK_SH_LIST(_MASK)861};862 863static struct mem_input *dce120_mem_input_create(864 struct dc_context *ctx,865 uint32_t inst)866{867 struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input),868 GFP_KERNEL);869 870 if (!dce_mi) {871 BREAK_TO_DEBUGGER();872 return NULL;873 }874 875 dce120_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks);876 return &dce_mi->base;877}878 879static struct transform *dce120_transform_create(880 struct dc_context *ctx,881 uint32_t inst)882{883 struct dce_transform *transform =884 kzalloc(sizeof(struct dce_transform), GFP_KERNEL);885 886 if (!transform)887 return NULL;888 889 dce_transform_construct(transform, ctx, inst,890 &xfm_regs[inst], &xfm_shift, &xfm_mask);891 transform->lb_memory_size = 0x1404; /*5124*/892 return &transform->base;893}894 895static void dce120_destroy_resource_pool(struct resource_pool **pool)896{897 struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool);898 899 dce120_resource_destruct(dce110_pool);900 kfree(dce110_pool);901 *pool = NULL;902}903 904static const struct resource_funcs dce120_res_pool_funcs = {905 .destroy = dce120_destroy_resource_pool,906 .link_enc_create = dce120_link_encoder_create,907 .panel_cntl_create = dce120_panel_cntl_create,908 .validate_bandwidth = dce112_validate_bandwidth,909 .validate_plane = dce100_validate_plane,910 .add_stream_to_ctx = dce112_add_stream_to_ctx,911 .find_first_free_match_stream_enc_for_link = dce110_find_first_free_match_stream_enc_for_link912};913 914static void bw_calcs_data_update_from_pplib(struct dc *dc)915{916 struct dm_pp_clock_levels_with_latency eng_clks = {0};917 struct dm_pp_clock_levels_with_latency mem_clks = {0};918 struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0};919 int i;920 unsigned int clk;921 unsigned int latency;922 /*original logic in dal3*/923 int memory_type_multiplier = MEMORY_TYPE_MULTIPLIER_CZ;924 925 /*do system clock*/926 if (!dm_pp_get_clock_levels_by_type_with_latency(927 dc->ctx,928 DM_PP_CLOCK_TYPE_ENGINE_CLK,929 &eng_clks) || eng_clks.num_levels == 0) {930 931 eng_clks.num_levels = 8;932 clk = 300000;933 934 for (i = 0; i < eng_clks.num_levels; i++) {935 eng_clks.data[i].clocks_in_khz = clk;936 clk += 100000;937 }938 }939 940 /* convert all the clock fro kHz to fix point mHz TODO: wloop data */941 dc->bw_vbios->high_sclk = bw_frc_to_fixed(942 eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000);943 dc->bw_vbios->mid1_sclk = bw_frc_to_fixed(944 eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000);945 dc->bw_vbios->mid2_sclk = bw_frc_to_fixed(946 eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000);947 dc->bw_vbios->mid3_sclk = bw_frc_to_fixed(948 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000);949 dc->bw_vbios->mid4_sclk = bw_frc_to_fixed(950 eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000);951 dc->bw_vbios->mid5_sclk = bw_frc_to_fixed(952 eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000);953 dc->bw_vbios->mid6_sclk = bw_frc_to_fixed(954 eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000);955 dc->bw_vbios->low_sclk = bw_frc_to_fixed(956 eng_clks.data[0].clocks_in_khz, 1000);957 958 /*do memory clock*/959 if (!dm_pp_get_clock_levels_by_type_with_latency(960 dc->ctx,961 DM_PP_CLOCK_TYPE_MEMORY_CLK,962 &mem_clks) || mem_clks.num_levels == 0) {963 964 mem_clks.num_levels = 3;965 clk = 250000;966 latency = 45;967 968 for (i = 0; i < eng_clks.num_levels; i++) {969 mem_clks.data[i].clocks_in_khz = clk;970 mem_clks.data[i].latency_in_us = latency;971 clk += 500000;972 latency -= 5;973 }974 975 }976 977 /* we don't need to call PPLIB for validation clock since they978 * also give us the highest sclk and highest mclk (UMA clock).979 * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula):980 * YCLK = UMACLK*m_memoryTypeMultiplier981 */982 if (dc->bw_vbios->memory_type == bw_def_hbm)983 memory_type_multiplier = MEMORY_TYPE_HBM;984 985 dc->bw_vbios->low_yclk = bw_frc_to_fixed(986 mem_clks.data[0].clocks_in_khz * memory_type_multiplier, 1000);987 dc->bw_vbios->mid_yclk = bw_frc_to_fixed(988 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * memory_type_multiplier,989 1000);990 dc->bw_vbios->high_yclk = bw_frc_to_fixed(991 mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * memory_type_multiplier,992 1000);993 994 /* Now notify PPLib/SMU about which Watermarks sets they should select995 * depending on DPM state they are in. And update BW MGR GFX Engine and996 * Memory clock member variables for Watermarks calculations for each997 * Watermark Set998 */999 clk_ranges.num_wm_sets = 4;1000 clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A;1001 clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz =1002 eng_clks.data[0].clocks_in_khz;1003 clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz =1004 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1;1005 clk_ranges.wm_clk_ranges[0].wm_min_mem_clk_in_khz =1006 mem_clks.data[0].clocks_in_khz;1007 clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz =1008 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1;1009 1010 clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B;1011 clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz =1012 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz;1013 /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */1014 clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000;1015 clk_ranges.wm_clk_ranges[1].wm_min_mem_clk_in_khz =1016 mem_clks.data[0].clocks_in_khz;1017 clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz =1018 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1;1019 1020 clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C;1021 clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz =1022 eng_clks.data[0].clocks_in_khz;1023 clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz =1024 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1;1025 clk_ranges.wm_clk_ranges[2].wm_min_mem_clk_in_khz =1026 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz;1027 /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */1028 clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000;1029 1030 clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D;1031 clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz =1032 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz;1033 /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */1034 clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000;1035 clk_ranges.wm_clk_ranges[3].wm_min_mem_clk_in_khz =1036 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz;1037 /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */1038 clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000;1039 1040 /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */1041 dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges);1042}1043 1044static uint32_t read_pipe_fuses(struct dc_context *ctx)1045{1046 uint32_t value = dm_read_reg_soc15(ctx, mmCC_DC_PIPE_DIS, 0);1047 /* VG20 support max 6 pipes */1048 value = value & 0x3f;1049 return value;1050}1051 1052static bool dce120_resource_construct(1053 uint8_t num_virtual_links,1054 struct dc *dc,1055 struct dce110_resource_pool *pool)1056{1057 unsigned int i;1058 int j;1059 struct dc_context *ctx = dc->ctx;1060 struct irq_service_init_data irq_init_data;1061 static const struct resource_create_funcs *res_funcs;1062 bool is_vg20 = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev);1063 uint32_t pipe_fuses = 0;1064 1065 ctx->dc_bios->regs = &bios_regs;1066 1067 pool->base.res_cap = &res_cap;1068 pool->base.funcs = &dce120_res_pool_funcs;1069 1070 /* TODO: Fill more data from GreenlandAsicCapability.cpp */1071 pool->base.pipe_count = res_cap.num_timing_generator;1072 pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;1073 pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;1074 1075 dc->caps.max_downscale_ratio = 200;1076 dc->caps.i2c_speed_in_khz = 100;1077 dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a not applied by default*/1078 dc->caps.max_cursor_size = 128;1079 dc->caps.min_horizontal_blanking_period = 80;1080 dc->caps.dual_link_dvi = true;1081 dc->caps.psp_setup_panel_mode = true;1082 dc->caps.extended_aux_timeout_support = false;1083 dc->debug = debug_defaults;1084 1085 /*************************************************1086 * Create resources *1087 *************************************************/1088 1089 pool->base.clock_sources[DCE120_CLK_SRC_PLL0] =1090 dce120_clock_source_create(ctx, ctx->dc_bios,1091 CLOCK_SOURCE_COMBO_PHY_PLL0,1092 &clk_src_regs[0], false);1093 pool->base.clock_sources[DCE120_CLK_SRC_PLL1] =1094 dce120_clock_source_create(ctx, ctx->dc_bios,1095 CLOCK_SOURCE_COMBO_PHY_PLL1,1096 &clk_src_regs[1], false);1097 pool->base.clock_sources[DCE120_CLK_SRC_PLL2] =1098 dce120_clock_source_create(ctx, ctx->dc_bios,1099 CLOCK_SOURCE_COMBO_PHY_PLL2,1100 &clk_src_regs[2], false);1101 pool->base.clock_sources[DCE120_CLK_SRC_PLL3] =1102 dce120_clock_source_create(ctx, ctx->dc_bios,1103 CLOCK_SOURCE_COMBO_PHY_PLL3,1104 &clk_src_regs[3], false);1105 pool->base.clock_sources[DCE120_CLK_SRC_PLL4] =1106 dce120_clock_source_create(ctx, ctx->dc_bios,1107 CLOCK_SOURCE_COMBO_PHY_PLL4,1108 &clk_src_regs[4], false);1109 pool->base.clock_sources[DCE120_CLK_SRC_PLL5] =1110 dce120_clock_source_create(ctx, ctx->dc_bios,1111 CLOCK_SOURCE_COMBO_PHY_PLL5,1112 &clk_src_regs[5], false);1113 pool->base.clk_src_count = DCE120_CLK_SRC_TOTAL;1114 1115 pool->base.dp_clock_source =1116 dce120_clock_source_create(ctx, ctx->dc_bios,1117 CLOCK_SOURCE_ID_DP_DTO,1118 &clk_src_regs[0], true);1119 1120 for (i = 0; i < pool->base.clk_src_count; i++) {1121 if (pool->base.clock_sources[i] == NULL) {1122 dm_error("DC: failed to create clock sources!\n");1123 BREAK_TO_DEBUGGER();1124 goto clk_src_create_fail;1125 }1126 }1127 1128 pool->base.dmcu = dce_dmcu_create(ctx,1129 &dmcu_regs,1130 &dmcu_shift,1131 &dmcu_mask);1132 if (pool->base.dmcu == NULL) {1133 dm_error("DC: failed to create dmcu!\n");1134 BREAK_TO_DEBUGGER();1135 goto res_create_fail;1136 }1137 1138 pool->base.abm = dce_abm_create(ctx,1139 &abm_regs,1140 &abm_shift,1141 &abm_mask);1142 if (pool->base.abm == NULL) {1143 dm_error("DC: failed to create abm!\n");1144 BREAK_TO_DEBUGGER();1145 goto res_create_fail;1146 }1147 1148 1149 irq_init_data.ctx = dc->ctx;1150 pool->base.irqs = dal_irq_service_dce120_create(&irq_init_data);1151 if (!pool->base.irqs)1152 goto irqs_create_fail;1153 1154 /* VG20: Pipe harvesting enabled, retrieve valid pipe fuses */1155 if (is_vg20)1156 pipe_fuses = read_pipe_fuses(ctx);1157 1158 /* index to valid pipe resource */1159 j = 0;1160 for (i = 0; i < pool->base.pipe_count; i++) {1161 if (is_vg20) {1162 if ((pipe_fuses & (1 << i)) != 0) {1163 dm_error("DC: skip invalid pipe %d!\n", i);1164 continue;1165 }1166 }1167 1168 pool->base.timing_generators[j] =1169 dce120_timing_generator_create(1170 ctx,1171 i,1172 &dce120_tg_offsets[i]);1173 if (pool->base.timing_generators[j] == NULL) {1174 BREAK_TO_DEBUGGER();1175 dm_error("DC: failed to create tg!\n");1176 goto controller_create_fail;1177 }1178 1179 pool->base.mis[j] = dce120_mem_input_create(ctx, i);1180 1181 if (pool->base.mis[j] == NULL) {1182 BREAK_TO_DEBUGGER();1183 dm_error(1184 "DC: failed to create memory input!\n");1185 goto controller_create_fail;1186 }1187 1188 pool->base.ipps[j] = dce120_ipp_create(ctx, i);1189 if (pool->base.ipps[i] == NULL) {1190 BREAK_TO_DEBUGGER();1191 dm_error(1192 "DC: failed to create input pixel processor!\n");1193 goto controller_create_fail;1194 }1195 1196 pool->base.transforms[j] = dce120_transform_create(ctx, i);1197 if (pool->base.transforms[i] == NULL) {1198 BREAK_TO_DEBUGGER();1199 dm_error(1200 "DC: failed to create transform!\n");1201 goto res_create_fail;1202 }1203 1204 pool->base.opps[j] = dce120_opp_create(1205 ctx,1206 i);1207 if (pool->base.opps[j] == NULL) {1208 BREAK_TO_DEBUGGER();1209 dm_error(1210 "DC: failed to create output pixel processor!\n");1211 }1212 1213 /* check next valid pipe */1214 j++;1215 }1216 1217 for (i = 0; i < pool->base.res_cap->num_ddc; i++) {1218 pool->base.engines[i] = dce120_aux_engine_create(ctx, i);1219 if (pool->base.engines[i] == NULL) {1220 BREAK_TO_DEBUGGER();1221 dm_error(1222 "DC:failed to create aux engine!!\n");1223 goto res_create_fail;1224 }1225 pool->base.hw_i2cs[i] = dce120_i2c_hw_create(ctx, i);1226 if (pool->base.hw_i2cs[i] == NULL) {1227 BREAK_TO_DEBUGGER();1228 dm_error(1229 "DC:failed to create i2c engine!!\n");1230 goto res_create_fail;1231 }1232 pool->base.sw_i2cs[i] = NULL;1233 }1234 1235 /* valid pipe num */1236 pool->base.pipe_count = j;1237 pool->base.timing_generator_count = j;1238 1239 if (is_vg20)1240 res_funcs = &dce121_res_create_funcs;1241 else1242 res_funcs = &res_create_funcs;1243 1244 if (!resource_construct(num_virtual_links, dc, &pool->base, res_funcs))1245 goto res_create_fail;1246 1247 /* Create hardware sequencer */1248 if (!dce120_hw_sequencer_create(dc))1249 goto controller_create_fail;1250 1251 dc->caps.max_planes = pool->base.pipe_count;1252 1253 for (i = 0; i < dc->caps.max_planes; ++i)1254 dc->caps.planes[i] = plane_cap;1255 1256 bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id);1257 1258 bw_calcs_data_update_from_pplib(dc);1259 1260 return true;1261 1262irqs_create_fail:1263controller_create_fail:1264clk_src_create_fail:1265res_create_fail:1266 1267 dce120_resource_destruct(pool);1268 1269 return false;1270}1271 1272struct resource_pool *dce120_create_resource_pool(1273 uint8_t num_virtual_links,1274 struct dc *dc)1275{1276 struct dce110_resource_pool *pool =1277 kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL);1278 1279 if (!pool)1280 return NULL;1281 1282 if (dce120_resource_construct(num_virtual_links, dc, pool))1283 return &pool->base;1284 1285 kfree(pool);1286 BREAK_TO_DEBUGGER();1287 return NULL;1288}1289