提交 a10beabb 编写于 作者: D Dave Airlie

Merge branch 'drm-next-4.17' of git://people.freedesktop.org/~agd5f/linux into drm-next

- Add a PX quirk for radeon
- Fix flickering and stability issues with DC on some platforms
- Fix HDMI audio regression
- Few other misc DC and base driver fixes

* 'drm-next-4.17' of git://people.freedesktop.org/~agd5f/linux:
  Revert "drm/amd/display: disable CRTCs with NULL FB on their primary plane (V2)"
  Revert "drm/amd/display: fix dereferencing possible ERR_PTR()"
  drm/amd/display: Fix regamma not affecting full-intensity color values
  drm/amd/display: Fix FBC text console corruption
  drm/amd/display: Only register backlight device if embedded panel connected
  drm/amd/display: fix brightness level after resume from suspend
  drm/amd/display: HDMI has no sound after Panel power off/on
  drm/amdgpu: add MP1 and THM hw ip base reg offset
  drm/amdgpu: fix null pointer panic with direct fw loading on gpu reset
  drm/radeon: add PX quirk for Asus K73TK
...@@ -1379,6 +1379,7 @@ enum amd_hw_ip_block_type { ...@@ -1379,6 +1379,7 @@ enum amd_hw_ip_block_type {
ATHUB_HWIP, ATHUB_HWIP,
NBIO_HWIP, NBIO_HWIP,
MP0_HWIP, MP0_HWIP,
MP1_HWIP,
UVD_HWIP, UVD_HWIP,
VCN_HWIP = UVD_HWIP, VCN_HWIP = UVD_HWIP,
VCE_HWIP, VCE_HWIP,
...@@ -1388,6 +1389,7 @@ enum amd_hw_ip_block_type { ...@@ -1388,6 +1389,7 @@ enum amd_hw_ip_block_type {
SMUIO_HWIP, SMUIO_HWIP,
PWR_HWIP, PWR_HWIP,
NBIF_HWIP, NBIF_HWIP,
THM_HWIP,
MAX_HWIP MAX_HWIP
}; };
......
...@@ -505,6 +505,9 @@ static int psp_resume(void *handle) ...@@ -505,6 +505,9 @@ static int psp_resume(void *handle)
int psp_gpu_reset(struct amdgpu_device *adev) 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); return psp_mode1_reset(&adev->psp);
} }
......
...@@ -38,6 +38,7 @@ int vega10_reg_base_init(struct amdgpu_device *adev) ...@@ -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[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_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[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[UVD_HWIP][i] = (uint32_t *)(&(UVD_BASE.instance[i]));
adev->reg_offset[VCE_HWIP][i] = (uint32_t *)(&(VCE_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])); 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) ...@@ -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[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
adev->reg_offset[PWR_HWIP][i] = (uint32_t *)(&(PWR_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[NBIF_HWIP][i] = (uint32_t *)(&(NBIF_BASE.instance[i]));
adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
} }
return 0; return 0;
} }
......
...@@ -1403,6 +1403,28 @@ static int initialize_plane(struct amdgpu_display_manager *dm, ...@@ -1403,6 +1403,28 @@ static int initialize_plane(struct amdgpu_display_manager *dm,
return ret; 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 /* In this architecture, the association
* connector -> encoder -> crtc * connector -> encoder -> crtc
* id not really requried. The crtc and connector will hold the * 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) ...@@ -1456,6 +1478,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
/* loops over all connectors on the board */ /* loops over all connectors on the board */
for (i = 0; i < link_cnt; i++) { for (i = 0; i < link_cnt; i++) {
struct dc_link *link = NULL;
if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) { if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) {
DRM_ERROR( DRM_ERROR(
...@@ -1482,9 +1505,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) ...@@ -1482,9 +1505,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
goto fail; goto fail;
} }
if (dc_link_detect(dc_get_link_at_index(dm->dc, i), link = dc_get_link_at_index(dm->dc, i);
DETECT_REASON_BOOT))
if (dc_link_detect(link, DETECT_REASON_BOOT)) {
amdgpu_dm_update_connector_after_detect(aconnector); amdgpu_dm_update_connector_after_detect(aconnector);
register_backlight_device(dm, link);
}
} }
/* Software is initialized. Now we can register interrupt handlers. */ /* Software is initialized. Now we can register interrupt handlers. */
...@@ -2685,7 +2713,8 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) ...@@ -2685,7 +2713,8 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector)
#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) 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); amdgpu_dm_register_backlight_device(dm);
if (dm->backlight_dev) { if (dm->backlight_dev) {
...@@ -3561,6 +3590,7 @@ create_i2c(struct ddc_service *ddc_service, ...@@ -3561,6 +3590,7 @@ create_i2c(struct ddc_service *ddc_service,
return i2c; return i2c;
} }
/* Note: this function assumes that dc_link_detect() was called for the /* Note: this function assumes that dc_link_detect() was called for the
* dc_link which will be represented by this aconnector. * dc_link which will be represented by this aconnector.
*/ */
...@@ -3630,28 +3660,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, ...@@ -3630,28 +3660,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
|| connector_type == DRM_MODE_CONNECTOR_eDP) || connector_type == DRM_MODE_CONNECTOR_eDP)
amdgpu_dm_initialize_dp_connector(dm, aconnector); 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: out_free:
if (res) { if (res) {
kfree(i2c); kfree(i2c);
...@@ -4840,33 +4848,6 @@ static int dm_update_planes_state(struct dc *dc, ...@@ -4840,33 +4848,6 @@ static int dm_update_planes_state(struct dc *dc,
return ret; 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, static int amdgpu_dm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state) struct drm_atomic_state *state)
{ {
...@@ -4890,10 +4871,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -4890,10 +4871,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
goto fail; goto fail;
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { 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) && if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
!new_crtc_state->color_mgmt_changed) !new_crtc_state->color_mgmt_changed)
continue; continue;
......
...@@ -1997,6 +1997,19 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level, ...@@ -1997,6 +1997,19 @@ bool dc_link_set_backlight_level(const struct dc_link *link, uint32_t level,
return true; 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) bool dc_link_set_psr_enable(const struct dc_link *link, bool enable, bool wait)
{ {
struct dc *core_dc = link->ctx->dc; struct dc *core_dc = link->ctx->dc;
......
...@@ -132,6 +132,8 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_ ...@@ -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, 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); 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_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); bool dc_link_get_psr_state(const struct dc_link *dc_link, uint32_t *psr_state);
......
...@@ -735,6 +735,8 @@ static void dce110_stream_encoder_update_hdmi_info_packets( ...@@ -735,6 +735,8 @@ static void dce110_stream_encoder_update_hdmi_info_packets(
if (info_frame->avi.valid) { if (info_frame->avi.valid) {
const uint32_t *content = const uint32_t *content =
(const uint32_t *) &info_frame->avi.sb[0]; (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]); REG_WRITE(AFMT_AVI_INFO0, content[0]);
......
...@@ -102,6 +102,43 @@ static uint32_t align_to_chunks_number_per_line(uint32_t pixels) ...@@ -102,6 +102,43 @@ static uint32_t align_to_chunks_number_per_line(uint32_t pixels)
return 256 * ((pixels + 255) / 256); 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( static void wait_for_fbc_state_changed(
struct dce110_compressor *cp110, struct dce110_compressor *cp110,
bool enabled) bool enabled)
...@@ -232,19 +269,23 @@ void dce110_compressor_disable_fbc(struct compressor *compressor) ...@@ -232,19 +269,23 @@ void dce110_compressor_disable_fbc(struct compressor *compressor)
{ {
struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor);
if (compressor->options.bits.FBC_SUPPORT && if (compressor->options.bits.FBC_SUPPORT) {
dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) { if (dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL)) {
uint32_t reg_data; uint32_t reg_data;
/* Turn off compression */ /* Turn off compression */
reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL); reg_data = dm_read_reg(compressor->ctx, mmFBC_CNTL);
set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN); set_reg_field_value(reg_data, 0, FBC_CNTL, FBC_GRPH_COMP_EN);
dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data); dm_write_reg(compressor->ctx, mmFBC_CNTL, reg_data);
/* Reset enum controller_id to undefined */ /* Reset enum controller_id to undefined */
compressor->attached_inst = 0; compressor->attached_inst = 0;
compressor->is_enabled = false; 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);
} }
} }
......
...@@ -453,10 +453,13 @@ dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, ...@@ -453,10 +453,13 @@ dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
} else { } else {
/* 10 segments /* 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_start = -10;
region_end = 0; region_end = 1;
seg_distr[0] = 4; seg_distr[0] = 4;
seg_distr[1] = 4; seg_distr[1] = 4;
...@@ -468,7 +471,7 @@ dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf, ...@@ -468,7 +471,7 @@ dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
seg_distr[7] = 4; seg_distr[7] = 4;
seg_distr[8] = 4; seg_distr[8] = 4;
seg_distr[9] = 4; seg_distr[9] = 4;
seg_distr[10] = -1; seg_distr[10] = 0;
seg_distr[11] = -1; seg_distr[11] = -1;
seg_distr[12] = -1; seg_distr[12] = -1;
seg_distr[13] = -1; seg_distr[13] = -1;
...@@ -1016,8 +1019,10 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) ...@@ -1016,8 +1019,10 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
struct dc_stream_state *stream = pipe_ctx->stream; struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->sink->link; 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); link->dc->hwss.edp_backlight_control(link, false);
dc_link_set_abm_disable(link);
}
if (dc_is_dp_signal(pipe_ctx->stream->signal)) if (dc_is_dp_signal(pipe_ctx->stream->signal))
pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
......
...@@ -140,6 +140,10 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = { ...@@ -140,6 +140,10 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = {
* https://bugs.freedesktop.org/show_bug.cgi?id=101491 * https://bugs.freedesktop.org/show_bug.cgi?id=101491
*/ */
{ PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX }, { 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 }, { 0, 0, 0, 0, 0 },
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册