diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 0193f6ced00b..c8b605f3dc05 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1379,6 +1379,7 @@ enum amd_hw_ip_block_type { ATHUB_HWIP, NBIO_HWIP, MP0_HWIP, + MP1_HWIP, UVD_HWIP, VCN_HWIP = UVD_HWIP, VCE_HWIP, @@ -1388,6 +1389,7 @@ enum amd_hw_ip_block_type { SMUIO_HWIP, PWR_HWIP, NBIF_HWIP, + THM_HWIP, MAX_HWIP }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 19e71f4a8ac2..c7d43e064fc7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -505,6 +505,9 @@ failed: int psp_gpu_reset(struct amdgpu_device *adev) { + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) + return 0; + return psp_mode1_reset(&adev->psp); } diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_reg_init.c b/drivers/gpu/drm/amd/amdgpu/vega10_reg_init.c index 4c45db7f1157..45aafca7f315 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_reg_init.c +++ b/drivers/gpu/drm/amd/amdgpu/vega10_reg_init.c @@ -38,6 +38,7 @@ int vega10_reg_base_init(struct amdgpu_device *adev) adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i])); adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i])); adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i])); + adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i])); adev->reg_offset[UVD_HWIP][i] = (uint32_t *)(&(UVD_BASE.instance[i])); adev->reg_offset[VCE_HWIP][i] = (uint32_t *)(&(VCE_BASE.instance[i])); adev->reg_offset[VCN_HWIP][i] = (uint32_t *)(&(VCN_BASE.instance[i])); @@ -49,7 +50,7 @@ int vega10_reg_base_init(struct amdgpu_device *adev) adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i])); adev->reg_offset[PWR_HWIP][i] = (uint32_t *)(&(PWR_BASE.instance[i])); adev->reg_offset[NBIF_HWIP][i] = (uint32_t *)(&(NBIF_BASE.instance[i])); - + adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i])); } return 0; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e42a28e3adc5..4e2f379ce217 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1403,6 +1403,28 @@ static int initialize_plane(struct amdgpu_display_manager *dm, return ret; } + +static void register_backlight_device(struct amdgpu_display_manager *dm, + struct dc_link *link) +{ +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + + if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) && + link->type != dc_connection_none) { + /* Event if registration failed, we should continue with + * DM initialization because not having a backlight control + * is better then a black screen. + */ + amdgpu_dm_register_backlight_device(dm); + + if (dm->backlight_dev) + dm->backlight_link = link; + } +#endif +} + + /* In this architecture, the association * connector -> encoder -> crtc * id not really requried. The crtc and connector will hold the @@ -1456,6 +1478,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) /* loops over all connectors on the board */ for (i = 0; i < link_cnt; i++) { + struct dc_link *link = NULL; if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) { DRM_ERROR( @@ -1482,9 +1505,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail; } - if (dc_link_detect(dc_get_link_at_index(dm->dc, i), - DETECT_REASON_BOOT)) + link = dc_get_link_at_index(dm->dc, i); + + if (dc_link_detect(link, DETECT_REASON_BOOT)) { amdgpu_dm_update_connector_after_detect(aconnector); + register_backlight_device(dm, link); + } + + } /* Software is initialized. Now we can register interrupt handlers. */ @@ -2685,7 +2713,8 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { + if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) && + link->type != dc_connection_none) { amdgpu_dm_register_backlight_device(dm); if (dm->backlight_dev) { @@ -3561,6 +3590,7 @@ create_i2c(struct ddc_service *ddc_service, return i2c; } + /* Note: this function assumes that dc_link_detect() was called for the * dc_link which will be represented by this aconnector. */ @@ -3630,28 +3660,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, || connector_type == DRM_MODE_CONNECTOR_eDP) amdgpu_dm_initialize_dp_connector(dm, aconnector); -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ - defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - - /* NOTE: this currently will create backlight device even if a panel - * is not connected to the eDP/LVDS connector. - * - * This is less than ideal but we don't have sink information at this - * stage since detection happens after. We can't do detection earlier - * since MST detection needs connectors to be created first. - */ - if (link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) { - /* Event if registration failed, we should continue with - * DM initialization because not having a backlight control - * is better then a black screen. - */ - amdgpu_dm_register_backlight_device(dm); - - if (dm->backlight_dev) - dm->backlight_link = link; - } -#endif - out_free: if (res) { kfree(i2c); @@ -4840,33 +4848,6 @@ static int dm_update_planes_state(struct dc *dc, return ret; } -static int dm_atomic_check_plane_state_fb(struct drm_atomic_state *state, - struct drm_crtc *crtc) -{ - struct drm_plane *plane; - struct drm_crtc_state *crtc_state; - - WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc)); - - drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) { - struct drm_plane_state *plane_state = - drm_atomic_get_plane_state(state, plane); - - if (IS_ERR(plane_state)) - return -EDEADLK; - - crtc_state = drm_atomic_get_crtc_state(plane_state->state, crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); - - if (crtc->primary == plane && crtc_state->active) { - if (!plane_state->fb) - return -EINVAL; - } - } - return 0; -} - static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { @@ -4890,10 +4871,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - ret = dm_atomic_check_plane_state_fb(state, crtc); - if (ret) - goto fail; - if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->color_mgmt_changed) continue; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index eeb04471b2f5..6d1c4981a185 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1997,6 +1997,19 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, return true; } +bool dc_link_set_abm_disable(const struct dc_link *link) +{ + struct dc *core_dc = link->ctx->dc; + struct abm *abm = core_dc->res_pool->abm; + + if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL)) + return false; + + abm->funcs->set_abm_immediate_disable(abm); + + return true; +} + bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait) { struct dc *core_dc = link->ctx->dc; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index fb4d9eafdc6e..dc34515ef01f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -132,6 +132,8 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level, uint32_t frame_ramp, const struct dc_stream_state *stream); +bool dc_link_set_abm_disable(const struct dc_link *dc_link); + bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable, bool wait); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 444558ca6533..162f6a6c4208 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -735,6 +735,8 @@ static void dce110_stream_encoder_update_hdmi_info_packets( if (info_frame->avi.valid) { const uint32_t *content = (const uint32_t *) &info_frame->avi.sb[0]; + /*we need turn on clock before programming AFMT block*/ + REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); REG_WRITE(AFMT_AVI_INFO0, content[0]); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c index 775d3bf0bd39..9150d2694450 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c @@ -102,6 +102,43 @@ static uint32_t align_to_chunks_number_per_line(uint32_t pixels) return 256 * ((pixels + 255) / 256); } +static void reset_lb_on_vblank(struct dc_context *ctx) +{ + uint32_t value, frame_count; + uint32_t retry = 0; + uint32_t status_pos = + dm_read_reg(ctx, mmCRTC_STATUS_POSITION); + + + /* Only if CRTC is enabled and counter is moving we wait for one frame. */ + if (status_pos != dm_read_reg(ctx, mmCRTC_STATUS_POSITION)) { + /* Resetting LB on VBlank */ + value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL); + set_reg_field_value(value, 3, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); + set_reg_field_value(value, 1, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); + dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value); + + frame_count = dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT); + + + for (retry = 100; retry > 0; retry--) { + if (frame_count != dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT)) + break; + msleep(1); + } + if (!retry) + dm_error("Frame count did not increase for 100ms.\n"); + + /* Resetting LB on VBlank */ + value = dm_read_reg(ctx, mmLB_SYNC_RESET_SEL); + set_reg_field_value(value, 2, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL); + set_reg_field_value(value, 0, LB_SYNC_RESET_SEL, LB_SYNC_RESET_SEL2); + dm_write_reg(ctx, mmLB_SYNC_RESET_SEL, value); + + } + +} + static void wait_for_fbc_state_changed( struct dce110_compressor *cp110, bool enabled) @@ -232,19 +269,23 @@ void dce110_compressor_disable_fbc(struct compressor *compressor) { struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); - if (compressor->options.bits.FBC_SUPPORT && - dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { - uint32_t reg_data; - /* Turn off compression */ - reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); - set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); - dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); + if (compressor->options.bits.FBC_SUPPORT) { + if (dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { + uint32_t reg_data; + /* Turn off compression */ + reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); + set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); + dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); - /* Reset enum controller_id to undefined */ - compressor->attached_inst = 0; - compressor->is_enabled = false; + /* Reset enum controller_id to undefined */ + compressor->attached_inst = 0; + compressor->is_enabled = false; - wait_for_fbc_state_changed(cp110, false); + wait_for_fbc_state_changed(cp110, false); + } + + /* Sync line buffer - dce100/110 only*/ + reset_lb_on_vblank(compressor->ctx); } } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 30dd62f0f5fa..d0575999f172 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -453,10 +453,13 @@ dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, } else { /* 10 segments - * segment is from 2^-10 to 2^0 + * segment is from 2^-10 to 2^1 + * We include an extra segment for range [2^0, 2^1). This is to + * ensure that colors with normalized values of 1 don't miss the + * LUT. */ region_start = -10; - region_end = 0; + region_end = 1; seg_distr[0] = 4; seg_distr[1] = 4; @@ -468,7 +471,7 @@ dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, seg_distr[7] = 4; seg_distr[8] = 4; seg_distr[9] = 4; - seg_distr[10] = -1; + seg_distr[10] = 0; seg_distr[11] = -1; seg_distr[12] = -1; seg_distr[13] = -1; @@ -1016,8 +1019,10 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; - if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) + if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { link->dc->hwss.edp_backlight_control(link, false); + dc_link_set_abm_disable(link); + } if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index e415d2c097a7..48d0e6bd0508 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -140,6 +140,10 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = { * https://bugs.freedesktop.org/show_bug.cgi?id=101491 */ { PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX }, + /* Asus K73TK laptop with AMD A6-3420M APU and Radeon 7670m GPU + * https://bugzilla.kernel.org/show_bug.cgi?id=51381#c52 + */ + { PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2123, RADEON_PX_QUIRK_DISABLE_PX }, { 0, 0, 0, 0, 0 }, };