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

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

Last batch of new stuff for DC. Highlights:
- Fix some memory leaks
- S3 fixes
- Hotplug fixes
- Fix some CX multi-display issues
- MST fixes
- DML updates from the hw team
- Various code cleanups
- Misc bug fixes

* 'drm-next-4.15-dc' of git://people.freedesktop.org/~agd5f/linux: (155 commits)
  drm/amd/display:: Fix NULL pointer in Raven hotplug
  drm/amd/display: Fix memoryleak during S3 resume.
  drm/amd/display: add hardware_planes_only to list of affected planes
  drm/amd/display: Fix brace style
  drm/amd/display: Remove needless cast in amdgpu_dm_connector_init()
  drm/amd/display: Fix brace style in amdgpu_dm_connector_ddc_get_modes()
  drm/amd/display: Tidy up dm_drm_plane_reset()
  drm/amd/display: Fix indentation in create_eml_sink()
  drm/amd/display: Replace block with strncpy() in fill_audio_info()
  drm/amd/display: Fix brace style in amdgpu_dm_initialize_drm_device()
  drm/amd/display: Simplify handle_hpd_rx_irq()
  drm/amd/display: Fix brace style in dm_handle_hpd_rx_irq()
  drm/amd/display: Fix brace style in amdgpu_dm_update_connector_after_detect()
  drm/amd/display: Fix indentation in dm_resume()
  drm/amd/display: Fix indentation in dm_suspend()
  drm/amd/display: Simplify dm_late_init()
  amdgpu/dc: inline dml_round_to_multiple
  amdgpu/dc: drop dml_util_is_420
  drm/amd/display: Add bunch of missing license headers in DML
  amdgpu/dc: inline a bunch of the dml wrappers.
  ...
...@@ -17,6 +17,16 @@ config DRM_AMD_DC_PRE_VEGA ...@@ -17,6 +17,16 @@ config DRM_AMD_DC_PRE_VEGA
by default. This includes Polaris, Carrizo, Tonga, Bonaire, by default. This includes Polaris, Carrizo, Tonga, Bonaire,
and Hawaii. and Hawaii.
config DRM_AMD_DC_FBC
bool "AMD FBC - Enable Frame Buffer Compression"
depends on DRM_AMD_DC
help
Choose this option if you want to use frame buffer compression
support.
This is a power optimisation feature, check its availability
on your hardware before enabling this option.
config DRM_AMD_DC_DCN1_0 config DRM_AMD_DC_DCN1_0
bool "DCN 1.0 Raven family" bool "DCN 1.0 Raven family"
depends on DRM_AMD_DC && X86 depends on DRM_AMD_DC && X86
......
...@@ -538,9 +538,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev) ...@@ -538,9 +538,8 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev)
static int dm_late_init(void *handle) static int dm_late_init(void *handle)
{ {
struct drm_device *dev = ((struct amdgpu_device *)handle)->ddev; struct drm_device *dev = ((struct amdgpu_device *)handle)->ddev;
int r = detect_mst_link_for_all_connectors(dev);
return r; return detect_mst_link_for_all_connectors(dev);
} }
static void s3_handle_mst(struct drm_device *dev, bool suspend) static void s3_handle_mst(struct drm_device *dev, bool suspend)
...@@ -599,10 +598,7 @@ static int dm_suspend(void *handle) ...@@ -599,10 +598,7 @@ static int dm_suspend(void *handle)
WARN_ON(adev->dm.cached_state); WARN_ON(adev->dm.cached_state);
adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev);
dc_set_power_state( dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);
dm->dc,
DC_ACPI_CM_POWER_STATE_D3
);
return ret; return ret;
} }
...@@ -632,10 +628,7 @@ static int dm_resume(void *handle) ...@@ -632,10 +628,7 @@ static int dm_resume(void *handle)
struct amdgpu_display_manager *dm = &adev->dm; struct amdgpu_display_manager *dm = &adev->dm;
/* power on hardware */ /* power on hardware */
dc_set_power_state( dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
dm->dc,
DC_ACPI_CM_POWER_STATE_D0
);
return 0; return 0;
} }
...@@ -648,6 +641,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) ...@@ -648,6 +641,11 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev)
struct drm_connector *connector; struct drm_connector *connector;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_crtc_state *new_crtc_state; struct drm_crtc_state *new_crtc_state;
struct dm_crtc_state *dm_crtc_state;
struct drm_plane *plane;
struct drm_plane_state *plane_state;
struct dm_plane_state *dm_plane_state;
struct dm_atomic_state *cached_state;
int ret = 0; int ret = 0;
int i; int i;
...@@ -686,6 +684,34 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev) ...@@ -686,6 +684,34 @@ int amdgpu_dm_display_resume(struct amdgpu_device *adev)
for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i)
new_crtc_state->active_changed = true; new_crtc_state->active_changed = true;
cached_state = to_dm_atomic_state(adev->dm.cached_state);
/*
* During suspend, the cached state is saved before all streams are
* disabled. Refresh cached state to match actual current state before
* restoring it.
*/
WARN_ON(kref_read(&cached_state->context->refcount) > 1);
dc_release_state(cached_state->context);
for_each_new_crtc_in_state(adev->dm.cached_state, crtc, new_crtc_state, i) {
dm_crtc_state = to_dm_crtc_state(new_crtc_state);
if (dm_crtc_state->stream) {
WARN_ON(kref_read(&dm_crtc_state->stream->refcount) > 1);
dc_stream_release(dm_crtc_state->stream);
dm_crtc_state->stream = NULL;
}
}
for_each_new_plane_in_state(adev->dm.cached_state, plane, plane_state, i) {
dm_plane_state = to_dm_plane_state(plane_state);
if (dm_plane_state->dc_state) {
WARN_ON(kref_read(&dm_plane_state->dc_state->refcount) > 1);
dc_plane_state_release(dm_plane_state->dc_state);
dm_plane_state->dc_state = NULL;
}
}
ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state); ret = drm_atomic_helper_resume(ddev, adev->dm.cached_state);
drm_atomic_state_put(adev->dm.cached_state); drm_atomic_state_put(adev->dm.cached_state);
...@@ -860,9 +886,9 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) ...@@ -860,9 +886,9 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector)
connector); connector);
aconnector->dc_sink = sink; aconnector->dc_sink = sink;
if (sink->dc_edid.length == 0) if (sink->dc_edid.length == 0) {
aconnector->edid = NULL; aconnector->edid = NULL;
else { } else {
aconnector->edid = aconnector->edid =
(struct edid *) sink->dc_edid.raw_edid; (struct edid *) sink->dc_edid.raw_edid;
...@@ -980,8 +1006,9 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) ...@@ -980,8 +1006,9 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector)
dpcd_bytes_to_read); dpcd_bytes_to_read);
new_irq_handled = false; new_irq_handled = false;
} else } else {
break; break;
}
} }
if (process_count == max_process_count) if (process_count == max_process_count)
...@@ -993,20 +1020,20 @@ static void handle_hpd_rx_irq(void *param) ...@@ -993,20 +1020,20 @@ static void handle_hpd_rx_irq(void *param)
struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param;
struct drm_connector *connector = &aconnector->base; struct drm_connector *connector = &aconnector->base;
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
const struct dc_link *dc_link = aconnector->dc_link; struct dc_link *dc_link = aconnector->dc_link;
bool is_mst_root_connector = aconnector->mst_mgr.mst_state; bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
/* TODO:Temporary add mutex to protect hpd interrupt not have a gpio /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio
* conflict, after implement i2c helper, this mutex should be * conflict, after implement i2c helper, this mutex should be
* retired. * retired.
*/ */
if (aconnector->dc_link->type != dc_connection_mst_branch) if (dc_link->type != dc_connection_mst_branch)
mutex_lock(&aconnector->hpd_lock); mutex_lock(&aconnector->hpd_lock);
if (dc_link_handle_hpd_rx_irq(aconnector->dc_link, NULL) && if (dc_link_handle_hpd_rx_irq(dc_link, NULL) &&
!is_mst_root_connector) { !is_mst_root_connector) {
/* Downstream Port status changed. */ /* Downstream Port status changed. */
if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPDRX)) { if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) {
amdgpu_dm_update_connector_after_detect(aconnector); amdgpu_dm_update_connector_after_detect(aconnector);
...@@ -1018,10 +1045,10 @@ static void handle_hpd_rx_irq(void *param) ...@@ -1018,10 +1045,10 @@ static void handle_hpd_rx_irq(void *param)
} }
} }
if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
(dc_link->type == dc_connection_mst_branch)) (dc_link->type == dc_connection_mst_branch))
dm_handle_hpd_rx_irq(aconnector); dm_handle_hpd_rx_irq(aconnector);
if (aconnector->dc_link->type != dc_connection_mst_branch) if (dc_link->type != dc_connection_mst_branch)
mutex_unlock(&aconnector->hpd_lock); mutex_unlock(&aconnector->hpd_lock);
} }
...@@ -1381,9 +1408,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) ...@@ -1381,9 +1408,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
goto fail_free_planes; goto fail_free_planes;
aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL); aencoder = kzalloc(sizeof(*aencoder), GFP_KERNEL);
if (!aencoder) { if (!aencoder)
goto fail_free_connector; goto fail_free_connector;
}
if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) { if (amdgpu_dm_encoder_init(dm->ddev, aencoder, i)) {
DRM_ERROR("KMS: Failed to initialize encoder\n"); DRM_ERROR("KMS: Failed to initialize encoder\n");
...@@ -1754,7 +1780,9 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, ...@@ -1754,7 +1780,9 @@ static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb,
int r = amdgpu_bo_reserve(rbo, false); int r = amdgpu_bo_reserve(rbo, false);
if (unlikely(r)) { if (unlikely(r)) {
DRM_ERROR("Unable to reserve buffer\n"); // Don't show error msg. when return -ERESTARTSYS
if (r != -ERESTARTSYS)
DRM_ERROR("Unable to reserve buffer: %d\n", r);
return r; return r;
} }
...@@ -2206,11 +2234,9 @@ static void fill_audio_info(struct audio_info *audio_info, ...@@ -2206,11 +2234,9 @@ static void fill_audio_info(struct audio_info *audio_info,
cea_revision = drm_connector->display_info.cea_rev; cea_revision = drm_connector->display_info.cea_rev;
while (i < AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS && strncpy(audio_info->display_name,
edid_caps->display_name[i]) { edid_caps->display_name,
audio_info->display_name[i] = edid_caps->display_name[i]; AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS - 1);
i++;
}
if (cea_revision >= 3) { if (cea_revision >= 3) {
audio_info->mode_count = edid_caps->audio_mode_count; audio_info->mode_count = edid_caps->audio_mode_count;
...@@ -2318,8 +2344,16 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, ...@@ -2318,8 +2344,16 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
drm_connector = &aconnector->base; drm_connector = &aconnector->base;
if (!aconnector->dc_sink) if (!aconnector->dc_sink) {
/*
* Exclude MST from creating fake_sink
* TODO: need to enable MST into fake_sink feature
*/
if (aconnector->mst_port)
goto stream_create_fail;
create_fake_sink(aconnector); create_fake_sink(aconnector);
}
stream = dc_create_stream_for_sink(aconnector->dc_sink); stream = dc_create_stream_for_sink(aconnector->dc_sink);
...@@ -2453,7 +2487,8 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) ...@@ -2453,7 +2487,8 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)
* 2. This interface *is called* in context of user-mode ioctl. Which * 2. This interface *is called* in context of user-mode ioctl. Which
* makes it a bad place for *any* MST-related activit. */ * makes it a bad place for *any* MST-related activit. */
if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) if (aconnector->base.force == DRM_FORCE_UNSPECIFIED &&
!aconnector->fake_enable)
connected = (aconnector->dc_sink != NULL); connected = (aconnector->dc_sink != NULL);
else else
connected = (aconnector->base.force == DRM_FORCE_ON); connected = (aconnector->base.force == DRM_FORCE_ON);
...@@ -2681,8 +2716,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) ...@@ -2681,8 +2716,7 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
(edid->extensions + 1) * EDID_LENGTH, (edid->extensions + 1) * EDID_LENGTH,
&init_params); &init_params);
if (aconnector->base.force if (aconnector->base.force == DRM_FORCE_ON)
== DRM_FORCE_ON)
aconnector->dc_sink = aconnector->dc_link->local_sink ? aconnector->dc_sink = aconnector->dc_link->local_sink ?
aconnector->dc_link->local_sink : aconnector->dc_link->local_sink :
aconnector->dc_em_sink; aconnector->dc_em_sink;
...@@ -2746,7 +2780,7 @@ int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, ...@@ -2746,7 +2780,7 @@ int amdgpu_dm_connector_mode_valid(struct drm_connector *connector,
stream->src.height = mode->vdisplay; stream->src.height = mode->vdisplay;
stream->dst = stream->src; stream->dst = stream->src;
if (dc_validate_stream(adev->dm.dc, stream)) if (dc_validate_stream(adev->dm.dc, stream) == DC_OK)
result = MODE_OK; result = MODE_OK;
dc_stream_release(stream); dc_stream_release(stream);
...@@ -2791,7 +2825,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, ...@@ -2791,7 +2825,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
if (!dm_crtc_state->stream) if (!dm_crtc_state->stream)
return 0; return 0;
if (dc_validate_stream(dc, dm_crtc_state->stream)) if (dc_validate_stream(dc, dm_crtc_state->stream) == DC_OK)
return 0; return 0;
return ret; return ret;
...@@ -2835,13 +2869,13 @@ static void dm_drm_plane_reset(struct drm_plane *plane) ...@@ -2835,13 +2869,13 @@ static void dm_drm_plane_reset(struct drm_plane *plane)
plane->funcs->atomic_destroy_state(plane, plane->state); plane->funcs->atomic_destroy_state(plane, plane->state);
amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL); amdgpu_state = kzalloc(sizeof(*amdgpu_state), GFP_KERNEL);
WARN_ON(amdgpu_state == NULL);
if (amdgpu_state) { if (amdgpu_state) {
plane->state = &amdgpu_state->base; plane->state = &amdgpu_state->base;
plane->state->plane = plane; plane->state->plane = plane;
plane->state->rotation = DRM_MODE_ROTATE_0; plane->state->rotation = DRM_MODE_ROTATE_0;
} else }
WARN_ON(1);
} }
static struct drm_plane_state * static struct drm_plane_state *
...@@ -2986,7 +3020,7 @@ static int dm_plane_atomic_check(struct drm_plane *plane, ...@@ -2986,7 +3020,7 @@ static int dm_plane_atomic_check(struct drm_plane *plane,
if (!dm_plane_state->dc_state) if (!dm_plane_state->dc_state)
return 0; return 0;
if (dc_validate_plane(dc, dm_plane_state->dc_state)) if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK)
return 0; return 0;
return -EINVAL; return -EINVAL;
...@@ -3272,8 +3306,9 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, ...@@ -3272,8 +3306,9 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector,
drm_edid_to_eld(connector, edid); drm_edid_to_eld(connector, edid);
amdgpu_dm_get_native_mode(connector); amdgpu_dm_get_native_mode(connector);
} else } else {
amdgpu_dm_connector->num_modes = 0; amdgpu_dm_connector->num_modes = 0;
}
} }
static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) static int amdgpu_dm_connector_get_modes(struct drm_connector *connector)
...@@ -3421,7 +3456,8 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm, ...@@ -3421,7 +3456,8 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
struct dc *dc = dm->dc; struct dc *dc = dm->dc;
struct dc_link *link = dc_get_link_at_index(dc, link_index); struct dc_link *link = dc_get_link_at_index(dc, link_index);
struct amdgpu_i2c_adapter *i2c; struct amdgpu_i2c_adapter *i2c;
((struct dc_link *)link)->priv = aconnector;
link->priv = aconnector;
DRM_DEBUG_DRIVER("%s()\n", __func__); DRM_DEBUG_DRIVER("%s()\n", __func__);
...@@ -3661,10 +3697,10 @@ static void handle_cursor_update(struct drm_plane *plane, ...@@ -3661,10 +3697,10 @@ static void handle_cursor_update(struct drm_plane *plane,
return; return;
DRM_DEBUG_DRIVER("%s: crtc_id=%d with size %d to %d\n", DRM_DEBUG_DRIVER("%s: crtc_id=%d with size %d to %d\n",
__func__, __func__,
amdgpu_crtc->crtc_id, amdgpu_crtc->crtc_id,
plane->state->crtc_w, plane->state->crtc_w,
plane->state->crtc_h); plane->state->crtc_h);
ret = get_cursor_position(plane, crtc, &position); ret = get_cursor_position(plane, crtc, &position);
if (ret) if (ret)
...@@ -3691,14 +3727,15 @@ static void handle_cursor_update(struct drm_plane *plane, ...@@ -3691,14 +3727,15 @@ static void handle_cursor_update(struct drm_plane *plane,
attributes.pitch = attributes.width; attributes.pitch = attributes.width;
if (!dc_stream_set_cursor_attributes(crtc_state->stream, if (crtc_state->stream) {
&attributes)) if (!dc_stream_set_cursor_attributes(crtc_state->stream,
DRM_ERROR("DC failed to set cursor attributes\n"); &attributes))
DRM_ERROR("DC failed to set cursor attributes\n");
if (crtc_state->stream)
if (!dc_stream_set_cursor_position(crtc_state->stream, if (!dc_stream_set_cursor_position(crtc_state->stream,
&position)) &position))
DRM_ERROR("DC failed to set cursor position\n"); DRM_ERROR("DC failed to set cursor position\n");
}
} }
static void prepare_flip_isr(struct amdgpu_crtc *acrtc) static void prepare_flip_isr(struct amdgpu_crtc *acrtc)
...@@ -3726,7 +3763,8 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc) ...@@ -3726,7 +3763,8 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc)
*/ */
static void amdgpu_dm_do_flip(struct drm_crtc *crtc, static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb, struct drm_framebuffer *fb,
uint32_t target) uint32_t target,
struct dc_state *state)
{ {
unsigned long flags; unsigned long flags;
uint32_t target_vblank; uint32_t target_vblank;
...@@ -3797,7 +3835,13 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, ...@@ -3797,7 +3835,13 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
surface_updates->flip_addr = &addr; surface_updates->flip_addr = &addr;
dc_update_planes_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); dc_commit_updates_for_stream(adev->dm.dc,
surface_updates,
1,
acrtc_state->stream,
NULL,
&surface_updates->surface,
state);
DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
__func__, __func__,
...@@ -3823,6 +3867,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, ...@@ -3823,6 +3867,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
struct drm_crtc_state *new_pcrtc_state = struct drm_crtc_state *new_pcrtc_state =
drm_atomic_get_new_crtc_state(state, pcrtc); drm_atomic_get_new_crtc_state(state, pcrtc);
struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state);
struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
int planes_count = 0; int planes_count = 0;
unsigned long flags; unsigned long flags;
...@@ -3880,7 +3925,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, ...@@ -3880,7 +3925,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
amdgpu_dm_do_flip( amdgpu_dm_do_flip(
crtc, crtc,
fb, fb,
drm_crtc_vblank_count(crtc) + *wait_for_vblank); drm_crtc_vblank_count(crtc) + *wait_for_vblank,
dm_state->context);
} }
} }
...@@ -3900,7 +3946,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, ...@@ -3900,7 +3946,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
if (false == dc_commit_planes_to_stream(dm->dc, if (false == dc_commit_planes_to_stream(dm->dc,
plane_states_constructed, plane_states_constructed,
planes_count, planes_count,
dc_stream_attach)) dc_stream_attach,
dm_state->context))
dm_error("%s: Failed to attach plane!\n", __func__); dm_error("%s: Failed to attach plane!\n", __func__);
} else { } else {
/*TODO BUG Here should go disable planes on CRTC. */ /*TODO BUG Here should go disable planes on CRTC. */
...@@ -3931,6 +3978,8 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, ...@@ -3931,6 +3978,8 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev,
if (drm_atomic_crtc_needs_modeset(new_crtc_state) && dm_old_crtc_state->stream) if (drm_atomic_crtc_needs_modeset(new_crtc_state) && dm_old_crtc_state->stream)
manage_dm_interrupts(adev, acrtc, false); manage_dm_interrupts(adev, acrtc, false);
} }
/* Add check here for SoC's that support hardware cursor plane, to
* unset legacy_cursor_update */
return drm_atomic_helper_commit(dev, state, nonblock); return drm_atomic_helper_commit(dev, state, nonblock);
...@@ -4120,7 +4169,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -4120,7 +4169,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
dm->dc, dm->dc,
status->plane_states, status->plane_states,
status->plane_count, status->plane_count,
dm_new_crtc_state->stream)) dm_new_crtc_state->stream,
dm_state->context))
dm_error("%s: Failed to update stream scaling!\n", __func__); dm_error("%s: Failed to update stream scaling!\n", __func__);
} }
...@@ -4339,7 +4389,8 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -4339,7 +4389,8 @@ static int dm_update_crtcs_state(struct dc *dc,
aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc); aconnector = amdgpu_dm_find_first_crtc_matching_connector(state, crtc);
/* TODO This hack should go away */ /* TODO This hack should go away */
if (aconnector) { if (aconnector && enable) {
// Make sure fake sink is created in plug-in scenario
new_con_state = drm_atomic_get_connector_state(state, new_con_state = drm_atomic_get_connector_state(state,
&aconnector->base); &aconnector->base);
...@@ -4368,12 +4419,13 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -4368,12 +4419,13 @@ static int dm_update_crtcs_state(struct dc *dc,
} }
} }
if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream)) { if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) {
new_crtc_state->mode_changed = false; new_crtc_state->mode_changed = false;
DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d", DRM_DEBUG_DRIVER("Mode change not required, setting mode_changed to %d",
new_crtc_state->mode_changed); new_crtc_state->mode_changed);
} }
...@@ -4402,10 +4454,10 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -4402,10 +4454,10 @@ static int dm_update_crtcs_state(struct dc *dc,
crtc->base.id); crtc->base.id);
/* i.e. reset mode */ /* i.e. reset mode */
if (!dc_remove_stream_from_ctx( if (dc_remove_stream_from_ctx(
dc, dc,
dm_state->context, dm_state->context,
dm_old_crtc_state->stream)) { dm_old_crtc_state->stream) != DC_OK) {
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
...@@ -4416,6 +4468,13 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -4416,6 +4468,13 @@ static int dm_update_crtcs_state(struct dc *dc,
*lock_and_validation_needed = true; *lock_and_validation_needed = true;
} else {/* Add stream for any updated/enabled CRTC */ } else {/* Add stream for any updated/enabled CRTC */
/*
* Quick fix to prevent NULL pointer on new_stream when
* added MST connectors not found in existing crtc_state in the chained mode
* TODO: need to dig out the root cause of that
*/
if (!aconnector || (!aconnector->dc_sink && aconnector->mst_port))
goto next_crtc;
if (modereset_required(new_crtc_state)) if (modereset_required(new_crtc_state))
goto next_crtc; goto next_crtc;
...@@ -4431,10 +4490,10 @@ static int dm_update_crtcs_state(struct dc *dc, ...@@ -4431,10 +4490,10 @@ static int dm_update_crtcs_state(struct dc *dc,
DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n", DRM_DEBUG_DRIVER("Enabling DRM crtc: %d\n",
crtc->base.id); crtc->base.id);
if (!dc_add_stream_to_ctx( if (dc_add_stream_to_ctx(
dc, dc,
dm_state->context, dm_state->context,
dm_new_crtc_state->stream)) { dm_new_crtc_state->stream) != DC_OK) {
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
...@@ -4586,7 +4645,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -4586,7 +4645,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_state *old_con_state, *new_con_state; struct drm_connector_state *old_con_state, *new_con_state;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_crtc_state *new_crtc_state; struct drm_crtc_state *old_crtc_state, *new_crtc_state;
/* /*
* This bool will be set for true for any modeset/reset * This bool will be set for true for any modeset/reset
...@@ -4595,18 +4654,34 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -4595,18 +4654,34 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
bool lock_and_validation_needed = false; bool lock_and_validation_needed = false;
ret = drm_atomic_helper_check_modeset(dev, state); ret = drm_atomic_helper_check_modeset(dev, state);
if (ret) { if (ret) {
DRM_ERROR("Atomic state validation failed with error :%d !\n", ret); DRM_ERROR("Atomic state validation failed with error :%d !\n", ret);
return ret; return ret;
} }
/* /*
* Hack: Commit needs planes right now, specifically for gamma * legacy_cursor_update should be made false for SoC's having
* TODO rework commit to check CRTC for gamma change * a dedicated hardware plane for cursor in amdgpu_dm_atomic_commit(),
* otherwise for software cursor plane,
* we should not add it to list of affected planes.
*/ */
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { if (state->legacy_cursor_update) {
if (new_crtc_state->color_mgmt_changed) { for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
if (new_crtc_state->color_mgmt_changed) {
ret = drm_atomic_add_affected_planes(state, crtc);
if (ret)
goto fail;
}
}
} else {
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
if (!new_crtc_state->enable)
continue;
ret = drm_atomic_add_affected_connectors(state, crtc);
if (ret)
return ret;
ret = drm_atomic_add_affected_planes(state, crtc); ret = drm_atomic_add_affected_planes(state, crtc);
if (ret) if (ret)
goto fail; goto fail;
...@@ -4684,7 +4759,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -4684,7 +4759,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
if (ret) if (ret)
goto fail; goto fail;
if (!dc_validate_global_state(dc, dm_state->context)) { if (dc_validate_global_state(dc, dm_state->context) != DC_OK) {
ret = -EINVAL; ret = -EINVAL;
goto fail; goto fail;
} }
......
...@@ -208,24 +208,21 @@ static void remove_timer_handler(struct amdgpu_device *adev, ...@@ -208,24 +208,21 @@ static void remove_timer_handler(struct amdgpu_device *adev,
DM_IRQ_TABLE_LOCK(adev, irq_table_flags); DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
} }
if (handler_in == NULL) { /* Remove ALL handlers. */
/* Remove ALL handlers. */ if (handler_in == NULL)
continue; continue;
}
if (handler_in == handler_temp) { /* Remove a SPECIFIC handler.
/* Remove a SPECIFIC handler. * Found our handler - we can stop here. */
* Found our handler - we can stop here. */ if (handler_in == handler_temp)
break; break;
}
} }
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
if (handler_in != NULL && handler_removed == false) { if (handler_in != NULL && handler_removed == false)
DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n", DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n",
handler_in); handler_in);
}
} }
static bool static bool
...@@ -435,7 +432,7 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) ...@@ -435,7 +432,7 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev)
* Disable HW interrupt for HPD and HPDRX only since FLIP and VBLANK * Disable HW interrupt for HPD and HPDRX only since FLIP and VBLANK
* will be disabled from manage_dm_interrupts on disable CRTC. * will be disabled from manage_dm_interrupts on disable CRTC.
*/ */
for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6RX; src++) { for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6RX; src++) {
hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
...@@ -462,7 +459,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev) ...@@ -462,7 +459,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev)
DRM_DEBUG_KMS("DM_IRQ: early resume\n"); DRM_DEBUG_KMS("DM_IRQ: early resume\n");
/* re-enable short pulse interrupts HW interrupt */ /* re-enable short pulse interrupts HW interrupt */
for (src = DC_IRQ_SOURCE_HPD1RX; src < DC_IRQ_SOURCE_HPD6RX + 1; src++) { for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX; src++) {
hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
...@@ -488,7 +485,7 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) ...@@ -488,7 +485,7 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev)
* Renable HW interrupt for HPD and only since FLIP and VBLANK * Renable HW interrupt for HPD and only since FLIP and VBLANK
* will be enabled from manage_dm_interrupts on enable CRTC. * will be enabled from manage_dm_interrupts on enable CRTC.
*/ */
for (src = DC_IRQ_SOURCE_HPD1; src < DC_IRQ_SOURCE_HPD6; src++) { for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6; src++) {
hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
......
...@@ -174,14 +174,60 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { ...@@ -174,14 +174,60 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
.atomic_get_property = amdgpu_dm_connector_atomic_get_property .atomic_get_property = amdgpu_dm_connector_atomic_get_property
}; };
static int dm_connector_update_modes(struct drm_connector *connector,
struct edid *edid)
{
int ret;
ret = drm_add_edid_modes(connector, edid);
drm_edid_to_eld(connector, edid);
return ret;
}
static int dm_dp_mst_get_modes(struct drm_connector *connector) static int dm_dp_mst_get_modes(struct drm_connector *connector)
{ {
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
int ret = 0; int ret = 0;
ret = drm_add_edid_modes(&aconnector->base, aconnector->edid); if (!aconnector)
return dm_connector_update_modes(connector, NULL);
if (!aconnector->edid) {
struct edid *edid;
struct dc_sink *dc_sink;
struct dc_sink_init_data init_params = {
.link = aconnector->dc_link,
.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST };
edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
drm_edid_to_eld(&aconnector->base, aconnector->edid); if (!edid) {
drm_mode_connector_update_edid_property(
&aconnector->base,
NULL);
return ret;
}
aconnector->edid = edid;
dc_sink = dc_link_add_remote_sink(
aconnector->dc_link,
(uint8_t *)edid,
(edid->extensions + 1) * EDID_LENGTH,
&init_params);
dc_sink->priv = aconnector;
aconnector->dc_sink = dc_sink;
if (aconnector->dc_sink)
amdgpu_dm_add_sink_to_freesync_module(
connector, edid);
drm_mode_connector_update_edid_property(
&aconnector->base, edid);
}
ret = dm_connector_update_modes(connector, aconnector->edid);
return ret; return ret;
} }
...@@ -241,9 +287,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, ...@@ -241,9 +287,10 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
struct amdgpu_device *adev = dev->dev_private; struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_dm_connector *aconnector; struct amdgpu_dm_connector *aconnector;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); drm_connector_list_iter_begin(dev, &conn_iter);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { drm_for_each_connector_iter(connector, &conn_iter) {
aconnector = to_amdgpu_dm_connector(connector); aconnector = to_amdgpu_dm_connector(connector);
if (aconnector->mst_port == master if (aconnector->mst_port == master
&& !aconnector->port) { && !aconnector->port) {
...@@ -253,11 +300,11 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, ...@@ -253,11 +300,11 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
aconnector->port = port; aconnector->port = port;
drm_mode_connector_set_path_property(connector, pathprop); drm_mode_connector_set_path_property(connector, pathprop);
drm_modeset_unlock(&dev->mode_config.connection_mutex); drm_connector_list_iter_end(&conn_iter);
return &aconnector->base; return &aconnector->base;
} }
} }
drm_modeset_unlock(&dev->mode_config.connection_mutex); drm_connector_list_iter_end(&conn_iter);
aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL); aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
if (!aconnector) if (!aconnector)
...@@ -343,92 +390,20 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) ...@@ -343,92 +390,20 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
{ {
struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
struct drm_device *dev = master->base.dev; struct drm_device *dev = master->base.dev;
struct amdgpu_device *adev = dev->dev_private;
struct drm_connector *connector;
struct amdgpu_dm_connector *aconnector;
struct edid *edid;
struct dc_sink *dc_sink;
drm_modeset_lock_all(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
aconnector = to_amdgpu_dm_connector(connector);
if (aconnector->port &&
aconnector->port->pdt != DP_PEER_DEVICE_NONE &&
aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING &&
!aconnector->dc_sink) {
/*
* This is plug in case, where port has been created but
* sink hasn't been created yet
*/
if (!aconnector->edid) {
struct dc_sink_init_data init_params = {
.link = aconnector->dc_link,
.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST};
edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
if (!edid) {
drm_mode_connector_update_edid_property(
&aconnector->base,
NULL);
continue;
}
aconnector->edid = edid;
dc_sink = dc_link_add_remote_sink(
aconnector->dc_link,
(uint8_t *)edid,
(edid->extensions + 1) * EDID_LENGTH,
&init_params);
dc_sink->priv = aconnector;
aconnector->dc_sink = dc_sink;
if (aconnector->dc_sink)
amdgpu_dm_add_sink_to_freesync_module(
connector,
edid);
dm_restore_drm_connector_state(connector->dev, connector);
} else
edid = aconnector->edid;
DRM_DEBUG_KMS("edid retrieved %p\n", edid);
drm_mode_connector_update_edid_property( drm_kms_helper_hotplug_event(dev);
&aconnector->base,
aconnector->edid);
}
}
drm_modeset_unlock_all(dev);
schedule_work(&adev->dm.mst_hotplug_work);
} }
static void dm_dp_mst_register_connector(struct drm_connector *connector) static void dm_dp_mst_register_connector(struct drm_connector *connector)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct amdgpu_device *adev = dev->dev_private; struct amdgpu_device *adev = dev->dev_private;
int i;
drm_modeset_lock_all(dev);
if (adev->mode_info.rfbdev) {
/*Do not add if already registered in past*/
for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) {
if (adev->mode_info.rfbdev->helper.connector_info[i]->connector
== connector) {
drm_modeset_unlock_all(dev);
return;
}
}
if (adev->mode_info.rfbdev)
drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector);
}
else else
DRM_ERROR("adev->mode_info.rfbdev is NULL\n"); DRM_ERROR("adev->mode_info.rfbdev is NULL\n");
drm_modeset_unlock_all(dev);
drm_connector_register(connector); drm_connector_register(connector);
} }
......
...@@ -35,6 +35,12 @@ ...@@ -35,6 +35,12 @@
#include "amdgpu_dm_irq.h" #include "amdgpu_dm_irq.h"
#include "amdgpu_pm.h" #include "amdgpu_pm.h"
unsigned long long dm_get_timestamp(struct dc_context *ctx)
{
/* TODO: return actual timestamp */
return 0;
}
bool dm_write_persistent_data(struct dc_context *ctx, bool dm_write_persistent_data(struct dc_context *ctx,
const struct dc_sink *sink, const struct dc_sink *sink,
const char *module_name, const char *module_name,
......
...@@ -80,8 +80,6 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger, ...@@ -80,8 +80,6 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger,
logger->buffer_read_offset = 0; logger->buffer_read_offset = 0;
logger->buffer_write_offset = 0; logger->buffer_write_offset = 0;
logger->write_wrap_count = 0;
logger->read_wrap_count = 0;
logger->open_count = 0; logger->open_count = 0;
logger->flags.bits.ENABLE_CONSOLE = 1; logger->flags.bits.ENABLE_CONSOLE = 1;
...@@ -162,23 +160,24 @@ static void log_to_debug_console(struct log_entry *entry) ...@@ -162,23 +160,24 @@ static void log_to_debug_console(struct log_entry *entry)
} }
/* Print everything unread existing in log_buffer to debug console*/ /* Print everything unread existing in log_buffer to debug console*/
static void flush_to_debug_console(struct dal_logger *logger) void dm_logger_flush_buffer(struct dal_logger *logger, bool should_warn)
{ {
int i = logger->buffer_read_offset; char *string_start = &logger->log_buffer[logger->buffer_read_offset];
char *string_start = &logger->log_buffer[i];
dm_output_to_console( if (should_warn)
"---------------- FLUSHING LOG BUFFER ----------------\n"); dm_output_to_console(
while (i < logger->buffer_write_offset) { "---------------- FLUSHING LOG BUFFER ----------------\n");
while (logger->buffer_read_offset < logger->buffer_write_offset) {
if (logger->log_buffer[i] == '\0') { if (logger->log_buffer[logger->buffer_read_offset] == '\0') {
dm_output_to_console("%s", string_start); dm_output_to_console("%s", string_start);
string_start = (char *)logger->log_buffer + i + 1; string_start = logger->log_buffer + logger->buffer_read_offset + 1;
} }
i++; logger->buffer_read_offset++;
} }
dm_output_to_console( if (should_warn)
"-------------- END FLUSHING LOG BUFFER --------------\n\n"); dm_output_to_console(
"-------------- END FLUSHING LOG BUFFER --------------\n\n");
} }
static void log_to_internal_buffer(struct log_entry *entry) static void log_to_internal_buffer(struct log_entry *entry)
...@@ -195,35 +194,17 @@ static void log_to_internal_buffer(struct log_entry *entry) ...@@ -195,35 +194,17 @@ static void log_to_internal_buffer(struct log_entry *entry)
if (size > 0 && size < logger->log_buffer_size) { if (size > 0 && size < logger->log_buffer_size) {
int total_free_space = 0; int buffer_space = logger->log_buffer_size -
int space_before_wrap = 0; logger->buffer_write_offset;
if (logger->buffer_write_offset > logger->buffer_read_offset) { if (logger->buffer_write_offset == logger->buffer_read_offset) {
total_free_space = logger->log_buffer_size -
logger->buffer_write_offset +
logger->buffer_read_offset;
space_before_wrap = logger->log_buffer_size -
logger->buffer_write_offset;
} else if (logger->buffer_write_offset <
logger->buffer_read_offset) {
total_free_space = logger->log_buffer_size -
logger->buffer_read_offset +
logger->buffer_write_offset;
space_before_wrap = total_free_space;
} else if (logger->write_wrap_count !=
logger->read_wrap_count) {
/* Buffer is completely full already */
total_free_space = 0;
space_before_wrap = 0;
} else {
/* Buffer is empty, start writing at beginning */ /* Buffer is empty, start writing at beginning */
total_free_space = logger->log_buffer_size; buffer_space = logger->log_buffer_size;
space_before_wrap = logger->log_buffer_size;
logger->buffer_write_offset = 0; logger->buffer_write_offset = 0;
logger->buffer_read_offset = 0; logger->buffer_read_offset = 0;
} }
if (space_before_wrap > size) { if (buffer_space > size) {
/* No wrap around, copy 'size' bytes /* No wrap around, copy 'size' bytes
* from 'entry->buf' to 'log_buffer' * from 'entry->buf' to 'log_buffer'
*/ */
...@@ -232,28 +213,12 @@ static void log_to_internal_buffer(struct log_entry *entry) ...@@ -232,28 +213,12 @@ static void log_to_internal_buffer(struct log_entry *entry)
entry->buf, size); entry->buf, size);
logger->buffer_write_offset += size; logger->buffer_write_offset += size;
} else if (total_free_space > size) {
/* We have enough room without flushing,
* but need to wrap around */
int space_after_wrap = total_free_space -
space_before_wrap;
memmove(logger->log_buffer +
logger->buffer_write_offset,
entry->buf, space_before_wrap);
memmove(logger->log_buffer, entry->buf +
space_before_wrap, space_after_wrap);
logger->buffer_write_offset = space_after_wrap;
logger->write_wrap_count++;
} else { } else {
/* Not enough room remaining, we should flush /* Not enough room remaining, we should flush
* existing logs */ * existing logs */
/* Flush existing unread logs to console */ /* Flush existing unread logs to console */
flush_to_debug_console(logger); dm_logger_flush_buffer(logger, true);
/* Start writing to beginning of buffer */ /* Start writing to beginning of buffer */
memmove(logger->log_buffer, entry->buf, size); memmove(logger->log_buffer, entry->buf, size);
...@@ -325,9 +290,10 @@ void dm_logger_write( ...@@ -325,9 +290,10 @@ void dm_logger_write(
log_heading(&entry); log_heading(&entry);
size = dm_log_to_buffer( size = dm_log_to_buffer(
buffer, LOG_MAX_LINE_SIZE, msg, args); buffer, LOG_MAX_LINE_SIZE - 1, msg, args);
entry.buf_offset += size; buffer[entry.buf_offset + size] = '\0';
entry.buf_offset += size + 1;
/* --Flush log_entry buffer-- */ /* --Flush log_entry buffer-- */
/* print to kernel console */ /* print to kernel console */
......
...@@ -26,42 +26,5 @@ ...@@ -26,42 +26,5 @@
#ifndef __DAL_LOGGER_H__ #ifndef __DAL_LOGGER_H__
#define __DAL_LOGGER_H__ #define __DAL_LOGGER_H__
/* Structure for keeping track of offsets, buffer, etc */
#define DAL_LOGGER_BUFFER_MAX_SIZE 2048
/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes,
* change log line size to 896 to meet the request.
*/
#define LOG_MAX_LINE_SIZE 896
#include "include/logger_types.h"
struct dal_logger {
/* How far into the circular buffer has been read by dsat
* Read offset should never cross write offset. Write \0's to
* read data just to be sure?
*/
uint32_t buffer_read_offset;
/* How far into the circular buffer we have written
* Write offset should never cross read offset
*/
uint32_t buffer_write_offset;
uint32_t write_wrap_count;
uint32_t read_wrap_count;
uint32_t open_count;
char *log_buffer; /* Pointer to malloc'ed buffer */
uint32_t log_buffer_size; /* Size of circular buffer */
uint32_t mask; /*array of masks for major elements*/
union logger_flags flags;
struct dc_context *ctx;
};
#endif /* __DAL_LOGGER_H__ */ #endif /* __DAL_LOGGER_H__ */
...@@ -1042,13 +1042,13 @@ static enum bp_result get_embedded_panel_info_v2_1( ...@@ -1042,13 +1042,13 @@ static enum bp_result get_embedded_panel_info_v2_1(
info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0; info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
info->lcd_timing.misc_info.H_REPLICATION_BY2 = info->lcd_timing.misc_info.H_REPLICATION_BY2 =
lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2; !!(lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2);
info->lcd_timing.misc_info.V_REPLICATION_BY2 = info->lcd_timing.misc_info.V_REPLICATION_BY2 =
lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2; !!(lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2);
info->lcd_timing.misc_info.COMPOSITE_SYNC = info->lcd_timing.misc_info.COMPOSITE_SYNC =
lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC; !!(lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC);
info->lcd_timing.misc_info.INTERLACE = info->lcd_timing.misc_info.INTERLACE =
lvds->lcd_timing.miscinfo & ATOM_INTERLACE; !!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);
/* not provided by VBIOS*/ /* not provided by VBIOS*/
info->lcd_timing.misc_info.DOUBLE_CLOCK = 0; info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;
...@@ -1056,7 +1056,7 @@ static enum bp_result get_embedded_panel_info_v2_1( ...@@ -1056,7 +1056,7 @@ static enum bp_result get_embedded_panel_info_v2_1(
info->ss_id = 0; info->ss_id = 0;
info->realtek_eDPToLVDS = info->realtek_eDPToLVDS =
(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID ? 1:0); !!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);
return BP_RESULT_OK; return BP_RESULT_OK;
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calcs.o := -mhard-float -msse -mpreferred-stack-boundary=4
CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_auto.o := -mhard-float -msse -mpreferred-stack-boundary=4
CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 CFLAGS_dcn_calc_math.o := -mhard-float -msse -mpreferred-stack-boundary=4 -Wno-tautological-compare
BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o
......
...@@ -25,6 +25,41 @@ ...@@ -25,6 +25,41 @@
#include "dcn_calc_math.h" #include "dcn_calc_math.h"
float dcn_bw_mod(const float arg1, const float arg2)
{
if (arg1 != arg1)
return arg2;
if (arg2 != arg2)
return arg1;
return arg1 - arg1 * ((int) (arg1 / arg2));
}
float dcn_bw_min2(const float arg1, const float arg2)
{
if (arg1 != arg1)
return arg2;
if (arg2 != arg2)
return arg1;
return arg1 < arg2 ? arg1 : arg2;
}
unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2)
{
if (arg1 != arg1)
return arg2;
if (arg2 != arg2)
return arg1;
return arg1 > arg2 ? arg1 : arg2;
}
float dcn_bw_max2(const float arg1, const float arg2)
{
if (arg1 != arg1)
return arg2;
if (arg2 != arg2)
return arg1;
return arg1 > arg2 ? arg1 : arg2;
}
float dcn_bw_floor2(const float arg, const float significance) float dcn_bw_floor2(const float arg, const float significance)
{ {
if (significance == 0) if (significance == 0)
...@@ -40,6 +75,16 @@ float dcn_bw_ceil2(const float arg, const float significance) ...@@ -40,6 +75,16 @@ float dcn_bw_ceil2(const float arg, const float significance)
return flr + 0.00001 >= arg ? arg : flr + significance; return flr + 0.00001 >= arg ? arg : flr + significance;
} }
float dcn_bw_max3(float v1, float v2, float v3)
{
return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2);
}
float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5)
{
return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5);
}
float dcn_bw_pow(float a, float exp) float dcn_bw_pow(float a, float exp)
{ {
float temp; float temp;
......
...@@ -26,38 +26,14 @@ ...@@ -26,38 +26,14 @@
#ifndef _DCN_CALC_MATH_H_ #ifndef _DCN_CALC_MATH_H_
#define _DCN_CALC_MATH_H_ #define _DCN_CALC_MATH_H_
static inline float dcn_bw_mod(const float arg1, const float arg2) float dcn_bw_mod(const float arg1, const float arg2);
{ float dcn_bw_min2(const float arg1, const float arg2);
return arg1 - arg1 * ((int) (arg1 / arg2)); unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2);
} float dcn_bw_max2(const float arg1, const float arg2);
static inline float dcn_bw_min2(const float arg1, const float arg2)
{
return arg1 < arg2 ? arg1 : arg2;
}
static inline unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2)
{
return arg1 > arg2 ? arg1 : arg2;
}
static inline float dcn_bw_max2(const float arg1, const float arg2)
{
return arg1 > arg2 ? arg1 : arg2;
}
static inline float dcn_bw_max3(float v1, float v2, float v3)
{
return v3 > dcn_bw_max2(v1, v2) ? v3 : dcn_bw_max2(v1, v2);
}
static inline float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5)
{
return dcn_bw_max3(v1, v2, v3) > dcn_bw_max2(v4, v5) ? dcn_bw_max3(v1, v2, v3) : dcn_bw_max2(v4, v5);
}
float dcn_bw_floor2(const float arg, const float significance); float dcn_bw_floor2(const float arg, const float significance);
float dcn_bw_ceil2(const float arg, const float significance); float dcn_bw_ceil2(const float arg, const float significance);
float dcn_bw_max3(float v1, float v2, float v3);
float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5);
float dcn_bw_pow(float a, float exp); float dcn_bw_pow(float a, float exp);
float dcn_bw_log(float a, float b); float dcn_bw_log(float a, float b);
......
...@@ -364,7 +364,8 @@ static void pipe_ctx_to_e2e_pipe_params ( ...@@ -364,7 +364,8 @@ static void pipe_ctx_to_e2e_pipe_params (
} }
input->dest.vactive = pipe->stream->timing.v_addressable; input->dest.vactive = pipe->stream->timing.v_addressable + pipe->stream->timing.v_border_top
+ pipe->stream->timing.v_border_bottom;
input->dest.recout_width = pipe->plane_res.scl_data.recout.width; input->dest.recout_width = pipe->plane_res.scl_data.recout.width;
input->dest.recout_height = pipe->plane_res.scl_data.recout.height; input->dest.recout_height = pipe->plane_res.scl_data.recout.height;
...@@ -385,10 +386,6 @@ static void pipe_ctx_to_e2e_pipe_params ( ...@@ -385,10 +386,6 @@ static void pipe_ctx_to_e2e_pipe_params (
- pipe->stream->timing.v_addressable - pipe->stream->timing.v_addressable
- pipe->stream->timing.v_border_bottom - pipe->stream->timing.v_border_bottom
- pipe->stream->timing.v_border_top; - pipe->stream->timing.v_border_top;
input->dest.vsync_plus_back_porch = pipe->stream->timing.v_total
- pipe->stream->timing.v_addressable
- pipe->stream->timing.v_front_porch;
input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0; input->dest.pixel_rate_mhz = pipe->stream->timing.pix_clk_khz/1000.0;
input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start; input->dest.vstartup_start = pipe->pipe_dlg_param.vstartup_start;
input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset; input->dest.vupdate_offset = pipe->pipe_dlg_param.vupdate_offset;
...@@ -458,9 +455,9 @@ static void dcn_bw_calc_rq_dlg_ttu( ...@@ -458,9 +455,9 @@ static void dcn_bw_calc_rq_dlg_ttu(
/*todo: soc->sr_enter_plus_exit_time??*/ /*todo: soc->sr_enter_plus_exit_time??*/
dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep;
dml_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); dml1_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src);
extract_rq_regs(dml, rq_regs, rq_param); dml1_extract_rq_regs(dml, rq_regs, rq_param);
dml_rq_dlg_get_dlg_params( dml1_rq_dlg_get_dlg_params(
dml, dml,
dlg_regs, dlg_regs,
ttu_regs, ttu_regs,
...@@ -473,96 +470,6 @@ static void dcn_bw_calc_rq_dlg_ttu( ...@@ -473,96 +470,6 @@ static void dcn_bw_calc_rq_dlg_ttu(
pipe->plane_state->flip_immediate); pipe->plane_state->flip_immediate);
} }
static void dcn_dml_wm_override(
const struct dcn_bw_internal_vars *v,
struct display_mode_lib *dml,
struct dc_state *context,
const struct resource_pool *pool)
{
int i, in_idx, active_count;
struct _vcs_dpi_display_e2e_pipe_params_st *input = kzalloc(pool->pipe_count * sizeof(struct _vcs_dpi_display_e2e_pipe_params_st),
GFP_KERNEL);
struct wm {
double urgent;
struct _vcs_dpi_cstate_pstate_watermarks_st cpstate;
double pte_meta_urgent;
} a;
for (i = 0, in_idx = 0; i < pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
if (!pipe->stream || !pipe->plane_state)
continue;
input[in_idx].clks_cfg.dcfclk_mhz = v->dcfclk;
input[in_idx].clks_cfg.dispclk_mhz = v->dispclk;
input[in_idx].clks_cfg.dppclk_mhz = v->dppclk;
input[in_idx].clks_cfg.refclk_mhz = pool->ref_clock_inKhz / 1000;
input[in_idx].clks_cfg.socclk_mhz = v->socclk;
input[in_idx].clks_cfg.voltage = v->voltage_level;
input[in_idx].dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444;
input[in_idx].dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp;
//input[in_idx].dout.output_standard;
switch (v->output_deep_color[in_idx]) {
case dcn_bw_encoder_12bpc:
input[in_idx].dout.output_bpc = dm_out_12;
break;
case dcn_bw_encoder_10bpc:
input[in_idx].dout.output_bpc = dm_out_10;
break;
case dcn_bw_encoder_8bpc:
default:
input[in_idx].dout.output_bpc = dm_out_8;
break;
}
pipe_ctx_to_e2e_pipe_params(pipe, &input[in_idx].pipe);
dml_rq_dlg_get_rq_reg(
dml,
&pipe->rq_regs,
input[in_idx].pipe.src);
in_idx++;
}
active_count = in_idx;
a.urgent = dml_wm_urgent_e2e(dml, input, active_count);
a.cpstate = dml_wm_cstate_pstate_e2e(dml, input, active_count);
a.pte_meta_urgent = dml_wm_pte_meta_urgent(dml, a.urgent);
context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns =
a.cpstate.cstate_exit_us * 1000;
context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
a.cpstate.cstate_enter_plus_exit_us * 1000;
context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns =
a.cpstate.pstate_change_us * 1000;
context->bw.dcn.watermarks.a.pte_meta_urgent_ns = a.pte_meta_urgent * 1000;
context->bw.dcn.watermarks.a.urgent_ns = a.urgent * 1000;
context->bw.dcn.watermarks.b = context->bw.dcn.watermarks.a;
context->bw.dcn.watermarks.c = context->bw.dcn.watermarks.a;
context->bw.dcn.watermarks.d = context->bw.dcn.watermarks.a;
for (i = 0, in_idx = 0; i < pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
if (!pipe->stream || !pipe->plane_state)
continue;
dml_rq_dlg_get_dlg_reg(dml,
&pipe->dlg_regs,
&pipe->ttu_regs,
input, active_count,
in_idx,
true,
true,
v->pte_enable == dcn_bw_yes,
pipe->plane_state->flip_immediate);
in_idx++;
}
kfree(input);
}
static void split_stream_across_pipes( static void split_stream_across_pipes(
struct resource_context *res_ctx, struct resource_context *res_ctx,
const struct resource_pool *pool, const struct resource_pool *pool,
...@@ -578,8 +485,10 @@ static void split_stream_across_pipes( ...@@ -578,8 +485,10 @@ static void split_stream_across_pipes(
secondary_pipe->pipe_idx = pipe_idx; secondary_pipe->pipe_idx = pipe_idx;
secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.mi = pool->mis[secondary_pipe->pipe_idx];
secondary_pipe->plane_res.hubp = pool->hubps[secondary_pipe->pipe_idx];
secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.ipp = pool->ipps[secondary_pipe->pipe_idx];
secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx]; secondary_pipe->plane_res.xfm = pool->transforms[secondary_pipe->pipe_idx];
secondary_pipe->plane_res.dpp = pool->dpps[secondary_pipe->pipe_idx];
if (primary_pipe->bottom_pipe) { if (primary_pipe->bottom_pipe) {
ASSERT(primary_pipe->bottom_pipe != secondary_pipe); ASSERT(primary_pipe->bottom_pipe != secondary_pipe);
secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe; secondary_pipe->bottom_pipe = primary_pipe->bottom_pipe;
...@@ -719,6 +628,49 @@ static bool dcn_bw_apply_registry_override(struct dc *dc) ...@@ -719,6 +628,49 @@ static bool dcn_bw_apply_registry_override(struct dc *dc)
return updated; return updated;
} }
void hack_disable_optional_pipe_split(struct dcn_bw_internal_vars *v)
{
/*
* disable optional pipe split by lower dispclk bounding box
* at DPM0
*/
v->max_dispclk[0] = v->max_dppclk_vmin0p65;
}
void hack_force_pipe_split(struct dcn_bw_internal_vars *v,
unsigned int pixel_rate_khz)
{
float pixel_rate_mhz = pixel_rate_khz / 1000;
/*
* force enabling pipe split by lower dpp clock for DPM0 to just
* below the specify pixel_rate, so bw calc would split pipe.
*/
if (pixel_rate_mhz < v->max_dppclk[0])
v->max_dppclk[0] = pixel_rate_mhz;
}
void hack_bounding_box(struct dcn_bw_internal_vars *v,
struct dc_debug *dbg,
struct dc_state *context)
{
if (dbg->pipe_split_policy == MPC_SPLIT_AVOID) {
hack_disable_optional_pipe_split(v);
}
if (dbg->pipe_split_policy == MPC_SPLIT_AVOID_MULT_DISP &&
context->stream_count >= 2) {
hack_disable_optional_pipe_split(v);
}
if (context->stream_count == 1 &&
dbg->force_single_disp_pipe_split) {
struct dc_stream_state *stream0 = context->streams[0];
hack_force_pipe_split(v, stream0->timing.pix_clk_khz);
}
}
bool dcn_validate_bandwidth( bool dcn_validate_bandwidth(
struct dc *dc, struct dc *dc,
struct dc_state *context) struct dc_state *context)
...@@ -730,6 +682,7 @@ bool dcn_validate_bandwidth( ...@@ -730,6 +682,7 @@ bool dcn_validate_bandwidth(
bool bw_limit_pass; bool bw_limit_pass;
float bw_limit; float bw_limit;
PERFORMANCE_TRACE_START();
if (dcn_bw_apply_registry_override(dc)) if (dcn_bw_apply_registry_override(dc))
dcn_bw_sync_calcs_and_dml(dc); dcn_bw_sync_calcs_and_dml(dc);
...@@ -850,9 +803,7 @@ bool dcn_validate_bandwidth( ...@@ -850,9 +803,7 @@ bool dcn_validate_bandwidth(
v->phyclk_per_state[1] = v->phyclkv_mid0p72; v->phyclk_per_state[1] = v->phyclkv_mid0p72;
v->phyclk_per_state[0] = v->phyclkv_min0p65; v->phyclk_per_state[0] = v->phyclkv_min0p65;
if (dc->debug.disable_pipe_split) { hack_bounding_box(v, &dc->debug, context);
v->max_dispclk[0] = v->max_dppclk_vmin0p65;
}
if (v->voltage_override == dcn_bw_v_max0p9) { if (v->voltage_override == dcn_bw_v_max0p9) {
v->voltage_override_level = number_of_states - 1; v->voltage_override_level = number_of_states - 1;
...@@ -882,10 +833,11 @@ bool dcn_validate_bandwidth( ...@@ -882,10 +833,11 @@ bool dcn_validate_bandwidth(
v->htotal[input_idx] = pipe->stream->timing.h_total; v->htotal[input_idx] = pipe->stream->timing.h_total;
v->vtotal[input_idx] = pipe->stream->timing.v_total; v->vtotal[input_idx] = pipe->stream->timing.v_total;
v->vactive[input_idx] = pipe->stream->timing.v_addressable +
pipe->stream->timing.v_border_top + pipe->stream->timing.v_border_bottom;
v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total v->v_sync_plus_back_porch[input_idx] = pipe->stream->timing.v_total
- pipe->stream->timing.v_addressable - v->vactive[input_idx]
- pipe->stream->timing.v_front_porch; - pipe->stream->timing.v_front_porch;
v->vactive[input_idx] = pipe->stream->timing.v_addressable;
v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f; v->pixel_clock[input_idx] = pipe->stream->timing.pix_clk_khz / 1000.0f;
if (!pipe->plane_state) { if (!pipe->plane_state) {
...@@ -1006,6 +958,10 @@ bool dcn_validate_bandwidth( ...@@ -1006,6 +958,10 @@ bool dcn_validate_bandwidth(
else else
bw_consumed = v->fabric_and_dram_bandwidth_vmax0p9; bw_consumed = v->fabric_and_dram_bandwidth_vmax0p9;
if (bw_consumed < v->fabric_and_dram_bandwidth)
if (dc->debug.voltage_align_fclk)
bw_consumed = v->fabric_and_dram_bandwidth;
display_pipe_configuration(v); display_pipe_configuration(v);
calc_wm_sets_and_perf_params(context, v); calc_wm_sets_and_perf_params(context, v);
context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 / context->bw.dcn.calc_clk.fclk_khz = (int)(bw_consumed * 1000000 /
...@@ -1018,9 +974,17 @@ bool dcn_validate_bandwidth( ...@@ -1018,9 +974,17 @@ bool dcn_validate_bandwidth(
context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin); context->bw.dcn.calc_clk.min_active_dram_ccm_us = (int)(v->min_active_dram_clock_change_margin);
context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000); context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz = (int)(v->dcf_clk_deep_sleep * 1000);
context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000); context->bw.dcn.calc_clk.dcfclk_khz = (int)(v->dcfclk * 1000);
context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000); context->bw.dcn.calc_clk.dispclk_khz = (int)(v->dispclk * 1000);
if (dc->debug.max_disp_clk == true) if (dc->debug.max_disp_clk == true)
context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000); context->bw.dcn.calc_clk.dispclk_khz = (int)(dc->dcn_soc->max_dispclk_vmax0p9 * 1000);
if (context->bw.dcn.calc_clk.dispclk_khz <
dc->debug.min_disp_clk_khz) {
context->bw.dcn.calc_clk.dispclk_khz =
dc->debug.min_disp_clk_khz;
}
context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2; context->bw.dcn.calc_clk.dppclk_div = (int)(v->dispclk_dppclk_ratio) == 2;
for (i = 0, input_idx = 0; i < pool->pipe_count; i++) { for (i = 0, input_idx = 0; i < pool->pipe_count; i++) {
...@@ -1108,9 +1072,6 @@ bool dcn_validate_bandwidth( ...@@ -1108,9 +1072,6 @@ bool dcn_validate_bandwidth(
input_idx++; input_idx++;
} }
if (dc->debug.use_dml_wm)
dcn_dml_wm_override(v, (struct display_mode_lib *)
&dc->dml, context, pool);
} }
if (v->voltage_level == 0) { if (v->voltage_level == 0) {
...@@ -1129,6 +1090,8 @@ bool dcn_validate_bandwidth( ...@@ -1129,6 +1090,8 @@ bool dcn_validate_bandwidth(
kernel_fpu_end(); kernel_fpu_end();
PERFORMANCE_TRACE_END();
if (bw_limit_pass && v->voltage_level != 5) if (bw_limit_pass && v->voltage_level != 5)
return true; return true;
else else
...@@ -1263,7 +1226,7 @@ unsigned int dcn_find_dcfclk_suits_all( ...@@ -1263,7 +1226,7 @@ unsigned int dcn_find_dcfclk_suits_all(
else else
dcf_clk = dc->dcn_soc->dcfclkv_min0p65*1000; dcf_clk = dc->dcn_soc->dcfclkv_min0p65*1000;
dm_logger_write(dc->ctx->logger, LOG_HW_MARKS, dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
"\tdcf_clk for voltage = %d\n", dcf_clk); "\tdcf_clk for voltage = %d\n", dcf_clk);
return dcf_clk; return dcf_clk;
} }
...@@ -1386,6 +1349,53 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc) ...@@ -1386,6 +1349,53 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc)
ranges.writer_wm_sets[3].min_drain_clk_khz = max_fclk_khz; ranges.writer_wm_sets[3].min_drain_clk_khz = max_fclk_khz;
ranges.writer_wm_sets[3].max_drain_clk_khz = max_fclk_khz; ranges.writer_wm_sets[3].max_drain_clk_khz = max_fclk_khz;
if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) {
ranges.reader_wm_sets[0].wm_inst = WM_A;
ranges.reader_wm_sets[0].min_drain_clk_khz = 300000;
ranges.reader_wm_sets[0].max_drain_clk_khz = 654000;
ranges.reader_wm_sets[0].min_fill_clk_khz = 800000;
ranges.reader_wm_sets[0].max_fill_clk_khz = 800000;
ranges.writer_wm_sets[0].wm_inst = WM_A;
ranges.writer_wm_sets[0].min_fill_clk_khz = 200000;
ranges.writer_wm_sets[0].max_fill_clk_khz = 757000;
ranges.writer_wm_sets[0].min_drain_clk_khz = 800000;
ranges.writer_wm_sets[0].max_drain_clk_khz = 800000;
ranges.reader_wm_sets[1].wm_inst = WM_B;
ranges.reader_wm_sets[1].min_drain_clk_khz = 300000;
ranges.reader_wm_sets[1].max_drain_clk_khz = 654000;
ranges.reader_wm_sets[1].min_fill_clk_khz = 933000;
ranges.reader_wm_sets[1].max_fill_clk_khz = 933000;
ranges.writer_wm_sets[1].wm_inst = WM_B;
ranges.writer_wm_sets[1].min_fill_clk_khz = 200000;
ranges.writer_wm_sets[1].max_fill_clk_khz = 757000;
ranges.writer_wm_sets[1].min_drain_clk_khz = 933000;
ranges.writer_wm_sets[1].max_drain_clk_khz = 933000;
ranges.reader_wm_sets[2].wm_inst = WM_C;
ranges.reader_wm_sets[2].min_drain_clk_khz = 300000;
ranges.reader_wm_sets[2].max_drain_clk_khz = 654000;
ranges.reader_wm_sets[2].min_fill_clk_khz = 1067000;
ranges.reader_wm_sets[2].max_fill_clk_khz = 1067000;
ranges.writer_wm_sets[2].wm_inst = WM_C;
ranges.writer_wm_sets[2].min_fill_clk_khz = 200000;
ranges.writer_wm_sets[2].max_fill_clk_khz = 757000;
ranges.writer_wm_sets[2].min_drain_clk_khz = 1067000;
ranges.writer_wm_sets[2].max_drain_clk_khz = 1067000;
ranges.reader_wm_sets[3].wm_inst = WM_D;
ranges.reader_wm_sets[3].min_drain_clk_khz = 300000;
ranges.reader_wm_sets[3].max_drain_clk_khz = 654000;
ranges.reader_wm_sets[3].min_fill_clk_khz = 1200000;
ranges.reader_wm_sets[3].max_fill_clk_khz = 1200000;
ranges.writer_wm_sets[3].wm_inst = WM_D;
ranges.writer_wm_sets[3].min_fill_clk_khz = 200000;
ranges.writer_wm_sets[3].max_fill_clk_khz = 757000;
ranges.writer_wm_sets[3].min_drain_clk_khz = 1200000;
ranges.writer_wm_sets[3].max_drain_clk_khz = 1200000;
}
/* Notify PP Lib/SMU which Watermarks to use for which clock ranges */ /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
pp->set_wm_ranges(&pp->pp_smu, &ranges); pp->set_wm_ranges(&pp->pp_smu, &ranges);
} }
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "bios_parser_interface.h" #include "bios_parser_interface.h"
#include "include/irq_service_interface.h" #include "include/irq_service_interface.h"
#include "transform.h" #include "transform.h"
#include "dpp.h"
#include "timing_generator.h" #include "timing_generator.h"
#include "virtual/virtual_link_encoder.h" #include "virtual/virtual_link_encoder.h"
...@@ -47,6 +48,7 @@ ...@@ -47,6 +48,7 @@
#include "dc_link_ddc.h" #include "dc_link_ddc.h"
#include "dm_helpers.h" #include "dm_helpers.h"
#include "mem_input.h" #include "mem_input.h"
#include "hubp.h"
/******************************************************************************* /*******************************************************************************
...@@ -332,10 +334,19 @@ static void set_dither_option(struct dc_stream_state *stream, ...@@ -332,10 +334,19 @@ static void set_dither_option(struct dc_stream_state *stream,
{ {
struct bit_depth_reduction_params params; struct bit_depth_reduction_params params;
struct dc_link *link = stream->status.link; struct dc_link *link = stream->status.link;
struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; struct pipe_ctx *pipes = NULL;
int i;
for (i = 0; i < MAX_PIPES; i++) {
if (link->dc->current_state->res_ctx.pipe_ctx[i].stream ==
stream) {
pipes = &link->dc->current_state->res_ctx.pipe_ctx[i];
break;
}
}
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
if (!stream) if (!pipes)
return; return;
if (option > DITHER_OPTION_MAX) if (option > DITHER_OPTION_MAX)
return; return;
...@@ -349,6 +360,36 @@ static void set_dither_option(struct dc_stream_state *stream, ...@@ -349,6 +360,36 @@ static void set_dither_option(struct dc_stream_state *stream,
opp_program_bit_depth_reduction(pipes->stream_res.opp, &params); opp_program_bit_depth_reduction(pipes->stream_res.opp, &params);
} }
void set_dpms(
struct dc *dc,
struct dc_stream_state *stream,
bool dpms_off)
{
struct pipe_ctx *pipe_ctx = NULL;
int i;
for (i = 0; i < MAX_PIPES; i++) {
if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) {
pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
break;
}
}
if (!pipe_ctx) {
ASSERT(0);
return;
}
if (stream->dpms_off != dpms_off) {
stream->dpms_off = dpms_off;
if (dpms_off)
core_link_disable_stream(pipe_ctx,
KEEP_ACQUIRED_RESOURCE);
else
core_link_enable_stream(dc->current_state, pipe_ctx);
}
}
static void allocate_dc_stream_funcs(struct dc *dc) static void allocate_dc_stream_funcs(struct dc *dc)
{ {
if (dc->hwss.set_drr != NULL) { if (dc->hwss.set_drr != NULL) {
...@@ -371,6 +412,9 @@ static void allocate_dc_stream_funcs(struct dc *dc) ...@@ -371,6 +412,9 @@ static void allocate_dc_stream_funcs(struct dc *dc)
dc->stream_funcs.set_dither_option = dc->stream_funcs.set_dither_option =
set_dither_option; set_dither_option;
dc->stream_funcs.set_dpms =
set_dpms;
dc->link_funcs.set_drive_settings = dc->link_funcs.set_drive_settings =
set_drive_settings; set_drive_settings;
...@@ -507,7 +551,7 @@ static bool construct(struct dc *dc, ...@@ -507,7 +551,7 @@ static bool construct(struct dc *dc,
dc_version = resource_parse_asic_id(init_params->asic_id); dc_version = resource_parse_asic_id(init_params->asic_id);
dc->ctx->dce_version = dc_version; dc->ctx->dce_version = dc_version;
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr; dc->ctx->fbc_gpu_addr = init_params->fbc_gpu_addr;
#endif #endif
/* Resource should construct all asic specific resources. /* Resource should construct all asic specific resources.
...@@ -749,7 +793,7 @@ bool dc_enable_stereo( ...@@ -749,7 +793,7 @@ bool dc_enable_stereo(
* Applies given context to HW and copy it into current context. * Applies given context to HW and copy it into current context.
* It's up to the user to release the src context afterwards. * It's up to the user to release the src context afterwards.
*/ */
static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context)
{ {
struct dc_bios *dcb = dc->ctx->dc_bios; struct dc_bios *dcb = dc->ctx->dc_bios;
enum dc_status result = DC_ERROR_UNEXPECTED; enum dc_status result = DC_ERROR_UNEXPECTED;
...@@ -763,41 +807,31 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) ...@@ -763,41 +807,31 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context)
if (!dcb->funcs->is_accelerated_mode(dcb)) if (!dcb->funcs->is_accelerated_mode(dcb))
dc->hwss.enable_accelerated_mode(dc); dc->hwss.enable_accelerated_mode(dc);
dc->hwss.ready_shared_resources(dc);
for (i = 0; i < dc->res_pool->pipe_count; i++) {
pipe = &context->res_ctx.pipe_ctx[i];
dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe);
}
result = dc->hwss.apply_ctx_to_hw(dc, context);
program_timing_sync(dc, context);
for (i = 0; i < context->stream_count; i++) { for (i = 0; i < context->stream_count; i++) {
const struct dc_sink *sink = context->streams[i]->sink; const struct dc_sink *sink = context->streams[i]->sink;
for (j = 0; j < context->stream_status[i].plane_count; j++) { dc->hwss.apply_ctx_for_surface(
dc->hwss.apply_ctx_for_surface( dc, context->streams[i],
dc, context->streams[i], context->stream_status[i].plane_count,
context->stream_status[i].plane_count, context);
context);
/* /*
* enable stereo * enable stereo
* TODO rework dc_enable_stereo call to work with validation sets? * TODO rework dc_enable_stereo call to work with validation sets?
*/ */
for (k = 0; k < MAX_PIPES; k++) { for (k = 0; k < MAX_PIPES; k++) {
pipe = &context->res_ctx.pipe_ctx[k]; pipe = &context->res_ctx.pipe_ctx[k];
for (l = 0 ; pipe && l < context->stream_count; l++) { for (l = 0 ; pipe && l < context->stream_count; l++) {
if (context->streams[l] && if (context->streams[l] &&
context->streams[l] == pipe->stream && context->streams[l] == pipe->stream &&
dc->hwss.setup_stereo) dc->hwss.setup_stereo)
dc->hwss.setup_stereo(pipe, dc); dc->hwss.setup_stereo(pipe, dc);
}
} }
} }
CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}", CONN_MSG_MODE(sink->link, "{%dx%d, %dx%d@%dKhz}",
context->streams[i]->timing.h_addressable, context->streams[i]->timing.h_addressable,
context->streams[i]->timing.v_addressable, context->streams[i]->timing.v_addressable,
...@@ -806,8 +840,27 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) ...@@ -806,8 +840,27 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context)
context->streams[i]->timing.pix_clk_khz); context->streams[i]->timing.pix_clk_khz);
} }
dc->hwss.ready_shared_resources(dc, context);
for (i = 0; i < dc->res_pool->pipe_count; i++) {
pipe = &context->res_ctx.pipe_ctx[i];
dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe);
}
result = dc->hwss.apply_ctx_to_hw(dc, context);
program_timing_sync(dc, context);
dc_enable_stereo(dc, context, dc_streams, context->stream_count); dc_enable_stereo(dc, context, dc_streams, context->stream_count);
for (i = 0; i < context->stream_count; i++) {
for (j = 0; j < MAX_PIPES; j++) {
pipe = &context->res_ctx.pipe_ctx[j];
if (!pipe->top_pipe && pipe->stream == context->streams[i])
dc->hwss.pipe_control_lock(dc, pipe, false);
}
}
dc_release_state(dc->current_state); dc_release_state(dc->current_state);
dc->current_state = context; dc->current_state = context;
...@@ -816,7 +869,7 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context) ...@@ -816,7 +869,7 @@ static bool dc_commit_state_no_check(struct dc *dc, struct dc_state *context)
dc->hwss.optimize_shared_resources(dc); dc->hwss.optimize_shared_resources(dc);
return (result == DC_OK); return result;
} }
bool dc_commit_state(struct dc *dc, struct dc_state *context) bool dc_commit_state(struct dc *dc, struct dc_state *context)
...@@ -865,16 +918,24 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) ...@@ -865,16 +918,24 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
return true; return true;
} }
/*
* TODO this whole function needs to go
*
* dc_surface_update is needlessly complex. See if we can just replace this
* with a dc_plane_state and follow the atomic model a bit more closely here.
*/
bool dc_commit_planes_to_stream( bool dc_commit_planes_to_stream(
struct dc *dc, struct dc *dc,
struct dc_plane_state **plane_states, struct dc_plane_state **plane_states,
uint8_t new_plane_count, uint8_t new_plane_count,
struct dc_stream_state *dc_stream) struct dc_stream_state *dc_stream,
struct dc_state *state)
{ {
/* no need to dynamically allocate this. it's pretty small */
struct dc_surface_update updates[MAX_SURFACES]; struct dc_surface_update updates[MAX_SURFACES];
struct dc_flip_addrs flip_addr[MAX_SURFACES]; struct dc_flip_addrs *flip_addr;
struct dc_plane_info plane_info[MAX_SURFACES]; struct dc_plane_info *plane_info;
struct dc_scaling_info scaling_info[MAX_SURFACES]; struct dc_scaling_info *scaling_info;
int i; int i;
struct dc_stream_update *stream_update = struct dc_stream_update *stream_update =
kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL); kzalloc(sizeof(struct dc_stream_update), GFP_KERNEL);
...@@ -884,10 +945,14 @@ bool dc_commit_planes_to_stream( ...@@ -884,10 +945,14 @@ bool dc_commit_planes_to_stream(
return false; return false;
} }
flip_addr = kcalloc(MAX_SURFACES, sizeof(struct dc_flip_addrs),
GFP_KERNEL);
plane_info = kcalloc(MAX_SURFACES, sizeof(struct dc_plane_info),
GFP_KERNEL);
scaling_info = kcalloc(MAX_SURFACES, sizeof(struct dc_scaling_info),
GFP_KERNEL);
memset(updates, 0, sizeof(updates)); memset(updates, 0, sizeof(updates));
memset(flip_addr, 0, sizeof(flip_addr));
memset(plane_info, 0, sizeof(plane_info));
memset(scaling_info, 0, sizeof(scaling_info));
stream_update->src = dc_stream->src; stream_update->src = dc_stream->src;
stream_update->dst = dc_stream->dst; stream_update->dst = dc_stream->dst;
...@@ -920,14 +985,15 @@ bool dc_commit_planes_to_stream( ...@@ -920,14 +985,15 @@ bool dc_commit_planes_to_stream(
updates[i].scaling_info = &scaling_info[i]; updates[i].scaling_info = &scaling_info[i];
} }
dc_update_planes_and_stream( dc_commit_updates_for_stream(
dc, dc,
updates, updates,
new_plane_count, new_plane_count,
dc_stream, stream_update); dc_stream, stream_update, plane_states, state);
dc_post_update_surfaces_to_stream(dc);
kfree(flip_addr);
kfree(plane_info);
kfree(scaling_info);
kfree(stream_update); kfree(stream_update);
return true; return true;
} }
...@@ -1030,7 +1096,6 @@ static enum surface_update_type get_plane_info_update_type( ...@@ -1030,7 +1096,6 @@ static enum surface_update_type get_plane_info_update_type(
temp_plane_info.plane_size = u->surface->plane_size; temp_plane_info.plane_size = u->surface->plane_size;
temp_plane_info.rotation = u->surface->rotation; temp_plane_info.rotation = u->surface->rotation;
temp_plane_info.stereo_format = u->surface->stereo_format; temp_plane_info.stereo_format = u->surface->stereo_format;
temp_plane_info.tiling_info = u->surface->tiling_info;
if (surface_index == 0) if (surface_index == 0)
temp_plane_info.visible = u->plane_info->visible; temp_plane_info.visible = u->plane_info->visible;
...@@ -1043,10 +1108,26 @@ static enum surface_update_type get_plane_info_update_type( ...@@ -1043,10 +1108,26 @@ static enum surface_update_type get_plane_info_update_type(
if (pixel_format_to_bpp(u->plane_info->format) != if (pixel_format_to_bpp(u->plane_info->format) !=
pixel_format_to_bpp(u->surface->format)) { pixel_format_to_bpp(u->surface->format)) {
/* different bytes per element will require full bandwidth
* and DML calculation
*/
return UPDATE_TYPE_FULL; return UPDATE_TYPE_FULL;
} else {
return UPDATE_TYPE_MED;
} }
if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info,
sizeof(union dc_tiling_info)) != 0) {
/* todo: below are HW dependent, we should add a hook to
* DCE/N resource and validated there.
*/
if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) {
/* swizzled mode requires RQ to be setup properly,
* thus need to run DML to calculate RQ settings
*/
return UPDATE_TYPE_FULL;
}
}
return UPDATE_TYPE_MED;
} }
static enum surface_update_type get_scaling_info_update_type( static enum surface_update_type get_scaling_info_update_type(
...@@ -1150,192 +1231,20 @@ static struct dc_stream_status *stream_get_status( ...@@ -1150,192 +1231,20 @@ static struct dc_stream_status *stream_get_status(
static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
void dc_update_planes_and_stream(struct dc *dc,
struct dc_surface_update *srf_updates, int surface_count, static void commit_planes_for_stream(struct dc *dc,
struct dc_surface_update *srf_updates,
int surface_count,
struct dc_stream_state *stream, struct dc_stream_state *stream,
struct dc_stream_update *stream_update) struct dc_stream_update *stream_update,
enum surface_update_type update_type,
struct dc_state *context)
{ {
struct dc_state *context;
int i, j; int i, j;
enum surface_update_type update_type;
const struct dc_stream_status *stream_status;
struct dc_context *dc_ctx = dc->ctx;
stream_status = dc_stream_get_status(stream);
ASSERT(stream_status);
if (!stream_status)
return; /* Cannot commit surface to stream that is not committed */
#ifdef ENABLE_FBC
if (srf_updates->flip_addr) {
if (srf_updates->flip_addr->address.grph.addr.low_part == 0)
ASSERT(0);
}
#endif
context = dc->current_state;
/* update current stream with the new updates */
if (stream_update) {
if ((stream_update->src.height != 0) &&
(stream_update->src.width != 0))
stream->src = stream_update->src;
if ((stream_update->dst.height != 0) &&
(stream_update->dst.width != 0))
stream->dst = stream_update->dst;
if (stream_update->out_transfer_func &&
stream_update->out_transfer_func !=
stream->out_transfer_func) {
if (stream->out_transfer_func != NULL)
dc_transfer_func_release(stream->out_transfer_func);
dc_transfer_func_retain(stream_update->out_transfer_func);
stream->out_transfer_func =
stream_update->out_transfer_func;
}
}
/* do not perform surface update if surface has invalid dimensions
* (all zero) and no scaling_info is provided
*/
if (surface_count > 0 &&
srf_updates->surface->src_rect.width == 0 &&
srf_updates->surface->src_rect.height == 0 &&
srf_updates->surface->dst_rect.width == 0 &&
srf_updates->surface->dst_rect.height == 0 &&
!srf_updates->scaling_info) {
ASSERT(false);
return;
}
update_type = dc_check_update_surfaces_for_stream(
dc, srf_updates, surface_count, stream_update, stream_status);
if (update_type >= update_surface_trace_level)
update_surface_trace(dc, srf_updates, surface_count);
if (update_type >= UPDATE_TYPE_FULL) {
struct dc_plane_state *new_planes[MAX_SURFACES] = {0};
for (i = 0; i < surface_count; i++)
new_planes[i] = srf_updates[i].surface;
/* initialize scratch memory for building context */
context = dc_create_state();
if (context == NULL) {
DC_ERROR("Failed to allocate new validate context!\n");
return;
}
dc_resource_state_copy_construct(
dc->current_state, context);
/*remove old surfaces from context */
if (!dc_rem_all_planes_for_stream(dc, stream, context)) {
BREAK_TO_DEBUGGER();
goto fail;
}
/* add surface to context */
if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) {
BREAK_TO_DEBUGGER();
goto fail;
}
}
/* save update parameters into surface */
for (i = 0; i < surface_count; i++) {
struct dc_plane_state *surface = srf_updates[i].surface;
if (srf_updates[i].flip_addr) {
surface->address = srf_updates[i].flip_addr->address;
surface->flip_immediate =
srf_updates[i].flip_addr->flip_immediate;
}
if (srf_updates[i].scaling_info) {
surface->scaling_quality =
srf_updates[i].scaling_info->scaling_quality;
surface->dst_rect =
srf_updates[i].scaling_info->dst_rect;
surface->src_rect =
srf_updates[i].scaling_info->src_rect;
surface->clip_rect =
srf_updates[i].scaling_info->clip_rect;
}
if (srf_updates[i].plane_info) {
surface->color_space =
srf_updates[i].plane_info->color_space;
surface->format =
srf_updates[i].plane_info->format;
surface->plane_size =
srf_updates[i].plane_info->plane_size;
surface->rotation =
srf_updates[i].plane_info->rotation;
surface->horizontal_mirror =
srf_updates[i].plane_info->horizontal_mirror;
surface->stereo_format =
srf_updates[i].plane_info->stereo_format;
surface->tiling_info =
srf_updates[i].plane_info->tiling_info;
surface->visible =
srf_updates[i].plane_info->visible;
surface->per_pixel_alpha =
srf_updates[i].plane_info->per_pixel_alpha;
surface->dcc =
srf_updates[i].plane_info->dcc;
}
if (update_type >= UPDATE_TYPE_MED) {
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
if (pipe_ctx->plane_state != surface)
continue;
resource_build_scaling_params(pipe_ctx);
}
}
if (srf_updates[i].gamma &&
srf_updates[i].gamma != surface->gamma_correction) {
if (surface->gamma_correction != NULL)
dc_gamma_release(&surface->gamma_correction);
dc_gamma_retain(srf_updates[i].gamma);
surface->gamma_correction = srf_updates[i].gamma;
}
if (srf_updates[i].in_transfer_func &&
srf_updates[i].in_transfer_func != surface->in_transfer_func) {
if (surface->in_transfer_func != NULL)
dc_transfer_func_release(
surface->
in_transfer_func);
dc_transfer_func_retain(
srf_updates[i].in_transfer_func);
surface->in_transfer_func =
srf_updates[i].in_transfer_func;
}
if (srf_updates[i].hdr_static_metadata)
surface->hdr_static_ctx =
*(srf_updates[i].hdr_static_metadata);
}
if (update_type == UPDATE_TYPE_FULL) { if (update_type == UPDATE_TYPE_FULL) {
if (!dc->res_pool->funcs->validate_bandwidth(dc, context)) { dc->hwss.set_bandwidth(dc, context, false);
BREAK_TO_DEBUGGER(); context_clock_trace(dc, context);
goto fail;
} else {
dc->hwss.set_bandwidth(dc, context, false);
context_clock_trace(dc, context);
}
} }
if (update_type > UPDATE_TYPE_FAST) { if (update_type > UPDATE_TYPE_FAST) {
...@@ -1346,8 +1255,14 @@ void dc_update_planes_and_stream(struct dc *dc, ...@@ -1346,8 +1255,14 @@ void dc_update_planes_and_stream(struct dc *dc,
} }
} }
if (surface_count == 0) if (surface_count == 0) {
/*
* In case of turning off screen, no need to program front end a second time.
* just return after program front end.
*/
dc->hwss.apply_ctx_for_surface(dc, stream, surface_count, context); dc->hwss.apply_ctx_for_surface(dc, stream, surface_count, context);
return;
}
/* Lock pipes for provided surfaces, or all active if full update*/ /* Lock pipes for provided surfaces, or all active if full update*/
for (i = 0; i < surface_count; i++) { for (i = 0; i < surface_count; i++) {
...@@ -1373,10 +1288,6 @@ void dc_update_planes_and_stream(struct dc *dc, ...@@ -1373,10 +1288,6 @@ void dc_update_planes_and_stream(struct dc *dc,
/* Full fe update*/ /* Full fe update*/
for (j = 0; j < dc->res_pool->pipe_count; j++) { for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
struct pipe_ctx *cur_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[j];
bool is_new_pipe_surface = cur_pipe_ctx->plane_state != pipe_ctx->plane_state;
struct dc_cursor_position position = { 0 };
if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state) if (update_type != UPDATE_TYPE_FULL || !pipe_ctx->plane_state)
continue; continue;
...@@ -1387,17 +1298,6 @@ void dc_update_planes_and_stream(struct dc *dc, ...@@ -1387,17 +1298,6 @@ void dc_update_planes_and_stream(struct dc *dc,
dc->hwss.apply_ctx_for_surface( dc->hwss.apply_ctx_for_surface(
dc, pipe_ctx->stream, stream_status->plane_count, context); dc, pipe_ctx->stream, stream_status->plane_count, context);
} }
/* TODO: this is a hack w/a for switching from mpo to pipe split */
dc_stream_set_cursor_position(pipe_ctx->stream, &position);
if (is_new_pipe_surface) {
dc->hwss.update_plane_addr(dc, pipe_ctx);
dc->hwss.set_input_transfer_func(
pipe_ctx, pipe_ctx->plane_state);
dc->hwss.set_output_transfer_func(
pipe_ctx, pipe_ctx->stream);
}
} }
if (update_type > UPDATE_TYPE_FAST) if (update_type > UPDATE_TYPE_FAST)
...@@ -1423,7 +1323,9 @@ void dc_update_planes_and_stream(struct dc *dc, ...@@ -1423,7 +1323,9 @@ void dc_update_planes_and_stream(struct dc *dc,
if (update_type == UPDATE_TYPE_FAST) if (update_type == UPDATE_TYPE_FAST)
continue; continue;
if (srf_updates[i].in_transfer_func) /* work around to program degamma regs for split pipe after set mode. */
if (srf_updates[i].in_transfer_func || (pipe_ctx->top_pipe &&
pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state))
dc->hwss.set_input_transfer_func( dc->hwss.set_input_transfer_func(
pipe_ctx, pipe_ctx->plane_state); pipe_ctx, pipe_ctx->plane_state);
...@@ -1459,16 +1361,79 @@ void dc_update_planes_and_stream(struct dc *dc, ...@@ -1459,16 +1361,79 @@ void dc_update_planes_and_stream(struct dc *dc,
break; break;
} }
} }
}
if (dc->current_state != context) { void dc_commit_updates_for_stream(struct dc *dc,
struct dc_surface_update *srf_updates,
int surface_count,
struct dc_stream_state *stream,
struct dc_stream_update *stream_update,
struct dc_plane_state **plane_states,
struct dc_state *state)
{
const struct dc_stream_status *stream_status;
enum surface_update_type update_type;
struct dc_state *context;
struct dc_context *dc_ctx = dc->ctx;
int i, j;
stream_status = dc_stream_get_status(stream);
context = dc->current_state;
update_type = dc_check_update_surfaces_for_stream(
dc, srf_updates, surface_count, stream_update, stream_status);
if (update_type >= update_surface_trace_level)
update_surface_trace(dc, srf_updates, surface_count);
if (update_type >= UPDATE_TYPE_FULL) {
/* initialize scratch memory for building context */
context = dc_create_state();
if (context == NULL) {
DC_ERROR("Failed to allocate new validate context!\n");
return;
}
dc_resource_state_copy_construct(state, context);
}
for (i = 0; i < surface_count; i++) {
struct dc_plane_state *surface = srf_updates[i].surface;
/* Since memory free requires elevated IRQL, an interrupt /* TODO: On flip we don't build the state, so it still has the
* request is generated by mem free. If this happens * old address. Which is why we are updating the address here
* between freeing and reassigning the context, our vsync
* interrupt will call into dc and cause a memory
* corruption BSOD. Hence, we first reassign the context,
* then free the old context.
*/ */
if (srf_updates[i].flip_addr)
surface->address = srf_updates[i].flip_addr->address;
if (update_type >= UPDATE_TYPE_MED) {
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
if (pipe_ctx->plane_state != surface)
continue;
resource_build_scaling_params(pipe_ctx);
}
}
}
commit_planes_for_stream(
dc,
srf_updates,
surface_count,
stream,
stream_update,
update_type,
context);
if (update_type >= UPDATE_TYPE_FULL)
dc_post_update_surfaces_to_stream(dc);
if (dc->current_state != context) {
struct dc_state *old = dc->current_state; struct dc_state *old = dc->current_state;
...@@ -1476,10 +1441,9 @@ void dc_update_planes_and_stream(struct dc *dc, ...@@ -1476,10 +1441,9 @@ void dc_update_planes_and_stream(struct dc *dc,
dc_release_state(old); dc_release_state(old);
} }
return; return;
fail:
dc_release_state(context);
} }
uint8_t dc_get_current_stream_count(struct dc *dc) uint8_t dc_get_current_stream_count(struct dc *dc)
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "dce/dce_11_0_enum.h" #include "dce/dce_11_0_enum.h"
#include "dce/dce_11_0_sh_mask.h" #include "dce/dce_11_0_sh_mask.h"
#define EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK 0x007C /* Copied from atombios.h */
#define LINK_INFO(...) \ #define LINK_INFO(...) \
dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \ dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \
__VA_ARGS__) __VA_ARGS__)
...@@ -78,14 +79,15 @@ static void destruct(struct dc_link *link) ...@@ -78,14 +79,15 @@ static void destruct(struct dc_link *link)
dc_sink_release(link->remote_sinks[i]); dc_sink_release(link->remote_sinks[i]);
} }
static struct gpio *get_hpd_gpio(const struct dc_link *link) struct gpio *get_hpd_gpio(struct dc_bios *dcb,
struct graphics_object_id link_id,
struct gpio_service *gpio_service)
{ {
enum bp_result bp_result; enum bp_result bp_result;
struct dc_bios *dcb = link->ctx->dc_bios;
struct graphics_object_hpd_info hpd_info; struct graphics_object_hpd_info hpd_info;
struct gpio_pin_info pin_info; struct gpio_pin_info pin_info;
if (dcb->funcs->get_hpd_info(dcb, link->link_id, &hpd_info) != BP_RESULT_OK) if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK)
return NULL; return NULL;
bp_result = dcb->funcs->get_gpio_pin_info(dcb, bp_result = dcb->funcs->get_gpio_pin_info(dcb,
...@@ -97,7 +99,7 @@ static struct gpio *get_hpd_gpio(const struct dc_link *link) ...@@ -97,7 +99,7 @@ static struct gpio *get_hpd_gpio(const struct dc_link *link)
} }
return dal_gpio_service_create_irq( return dal_gpio_service_create_irq(
link->ctx->gpio_service, gpio_service,
pin_info.offset, pin_info.offset,
pin_info.mask); pin_info.mask);
} }
...@@ -153,7 +155,7 @@ static bool program_hpd_filter( ...@@ -153,7 +155,7 @@ static bool program_hpd_filter(
} }
/* Obtain HPD handle */ /* Obtain HPD handle */
hpd = get_hpd_gpio(link); hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
if (!hpd) if (!hpd)
return result; return result;
...@@ -186,7 +188,7 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type) ...@@ -186,7 +188,7 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type)
struct gpio *hpd_pin; struct gpio *hpd_pin;
/* todo: may need to lock gpio access */ /* todo: may need to lock gpio access */
hpd_pin = get_hpd_gpio(link); hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
if (hpd_pin == NULL) if (hpd_pin == NULL)
goto hpd_gpio_failure; goto hpd_gpio_failure;
...@@ -496,6 +498,7 @@ static void detect_dp( ...@@ -496,6 +498,7 @@ static void detect_dp(
} }
if (is_mst_supported(link)) { if (is_mst_supported(link)) {
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST; sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
link->type = dc_connection_mst_branch;
/* /*
* This call will initiate MST topology discovery. Which * This call will initiate MST topology discovery. Which
...@@ -524,12 +527,11 @@ static void detect_dp( ...@@ -524,12 +527,11 @@ static void detect_dp(
if (reason == DETECT_REASON_BOOT) if (reason == DETECT_REASON_BOOT)
boot = true; boot = true;
if (dm_helpers_dp_mst_start_top_mgr( if (!dm_helpers_dp_mst_start_top_mgr(
link->ctx, link->ctx,
link, boot)) { link, boot)) {
link->type = dc_connection_mst_branch;
} else {
/* MST not supported */ /* MST not supported */
link->type = dc_connection_single;
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
} }
} }
...@@ -638,8 +640,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -638,8 +640,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
if (link->dpcd_caps.sink_count.bits.SINK_COUNT) if (link->dpcd_caps.sink_count.bits.SINK_COUNT)
link->dpcd_sink_count = link->dpcd_caps.sink_count. link->dpcd_sink_count = link->dpcd_caps.sink_count.
bits.SINK_COUNT; bits.SINK_COUNT;
else else
link->dpcd_sink_count = 1; link->dpcd_sink_count = 1;
dal_ddc_service_set_transaction_type( dal_ddc_service_set_transaction_type(
link->ddc, link->ddc,
...@@ -746,6 +748,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) ...@@ -746,6 +748,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
if (link->type == dc_connection_mst_branch) { if (link->type == dc_connection_mst_branch) {
LINK_INFO("link=%d, mst branch is now Disconnected\n", LINK_INFO("link=%d, mst branch is now Disconnected\n",
link->link_index); link->link_index);
dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
link->mst_stream_alloc_table.stream_count = 0; link->mst_stream_alloc_table.stream_count = 0;
...@@ -770,7 +773,7 @@ static enum hpd_source_id get_hpd_line( ...@@ -770,7 +773,7 @@ static enum hpd_source_id get_hpd_line(
struct gpio *hpd; struct gpio *hpd;
enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN; enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN;
hpd = get_hpd_gpio(link); hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
if (hpd) { if (hpd) {
switch (dal_irq_get_source(hpd)) { switch (dal_irq_get_source(hpd)) {
...@@ -940,7 +943,7 @@ static bool construct( ...@@ -940,7 +943,7 @@ static bool construct(
goto create_fail; goto create_fail;
} }
hpd_gpio = get_hpd_gpio(link); hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
if (hpd_gpio != NULL) if (hpd_gpio != NULL)
link->irq_source_hpd = dal_irq_get_source(hpd_gpio); link->irq_source_hpd = dal_irq_get_source(hpd_gpio);
...@@ -1343,7 +1346,18 @@ static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx, ...@@ -1343,7 +1346,18 @@ static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,
sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings)); sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings));
result = true; result = true;
break; break;
case ENGINE_ID_DIGD:
settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr;
settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num;
settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num;
memmove(settings->reg_settings,
integrated_info->dp3_ext_hdmi_reg_settings,
sizeof(integrated_info->dp3_ext_hdmi_reg_settings));
memmove(settings->reg_settings_6g,
integrated_info->dp3_ext_hdmi_6g_reg_settings,
sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings));
result = true;
break;
default: default:
break; break;
} }
...@@ -1680,7 +1694,9 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) ...@@ -1680,7 +1694,9 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
is_over_340mhz = true; is_over_340mhz = true;
if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x2) { unsigned short masked_chip_caps = pipe_ctx->stream->sink->link->chip_caps &
EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
if (masked_chip_caps == (0x2 << 2)) {
/* DP159, Retimer settings */ /* DP159, Retimer settings */
eng_id = pipe_ctx->stream_res.stream_enc->id; eng_id = pipe_ctx->stream_res.stream_enc->id;
...@@ -1691,7 +1707,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) ...@@ -1691,7 +1707,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
write_i2c_default_retimer_setting(pipe_ctx, write_i2c_default_retimer_setting(pipe_ctx,
is_vga_mode, is_over_340mhz); is_vga_mode, is_over_340mhz);
} }
} else if ((pipe_ctx->stream->sink->link->chip_caps >> 2) == 0x1) { } else if (masked_chip_caps == (0x1 << 2)) {
/* PI3EQX1204, Redriver settings */ /* PI3EQX1204, Redriver settings */
write_i2c_redriver_setting(pipe_ctx, is_over_340mhz); write_i2c_redriver_setting(pipe_ctx, is_over_340mhz);
} }
...@@ -1782,7 +1798,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal) ...@@ -1782,7 +1798,7 @@ static void disable_link(struct dc_link *link, enum signal_type signal)
else else
dp_disable_link_phy_mst(link, signal); dp_disable_link_phy_mst(link, signal);
} else } else
link->link_enc->funcs->disable_output(link->link_enc, signal); link->link_enc->funcs->disable_output(link->link_enc, signal, link);
} }
enum dc_status dc_link_validate_mode_timing( enum dc_status dc_link_validate_mode_timing(
...@@ -2319,16 +2335,20 @@ void core_link_enable_stream( ...@@ -2319,16 +2335,20 @@ void core_link_enable_stream(
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
allocate_mst_payload(pipe_ctx); allocate_mst_payload(pipe_ctx);
if (dc_is_dp_signal(pipe_ctx->stream->signal))
core_dc->hwss.unblank_stream(pipe_ctx,
&pipe_ctx->stream->sink->link->cur_link_settings);
} }
void core_link_disable_stream(struct pipe_ctx *pipe_ctx) void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
{ {
struct dc *core_dc = pipe_ctx->stream->ctx->dc; struct dc *core_dc = pipe_ctx->stream->ctx->dc;
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
deallocate_mst_payload(pipe_ctx); deallocate_mst_payload(pipe_ctx);
core_dc->hwss.disable_stream(pipe_ctx); core_dc->hwss.disable_stream(pipe_ctx, option);
disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal); disable_link(pipe_ctx->stream->sink->link, pipe_ctx->stream->signal);
} }
......
...@@ -1700,6 +1700,12 @@ static void dp_test_send_link_training(struct dc_link *link) ...@@ -1700,6 +1700,12 @@ static void dp_test_send_link_training(struct dc_link *link)
dp_retrain_link_dp_test(link, &link_settings, false); dp_retrain_link_dp_test(link, &link_settings, false);
} }
/* TODO hbr2 compliance eye output is unstable
* (toggling on and off) with debugger break
* This caueses intermittent PHY automation failure
* Need to look into the root cause */
static uint8_t force_tps4_for_cp2520 = 1;
static void dp_test_send_phy_test_pattern(struct dc_link *link) static void dp_test_send_phy_test_pattern(struct dc_link *link)
{ {
union phy_test_pattern dpcd_test_pattern; union phy_test_pattern dpcd_test_pattern;
...@@ -1758,10 +1764,16 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) ...@@ -1758,10 +1764,16 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM; test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
break; break;
case PHY_TEST_PATTERN_CP2520_1: case PHY_TEST_PATTERN_CP2520_1:
test_pattern = DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE; /* CP2520 pattern is unstable, temporarily use TPS4 instead */
test_pattern = (force_tps4_for_cp2520 == 1) ?
DP_TEST_PATTERN_TRAINING_PATTERN4 :
DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
break; break;
case PHY_TEST_PATTERN_CP2520_2: case PHY_TEST_PATTERN_CP2520_2:
test_pattern = DP_TEST_PATTERN_CP2520_2; /* CP2520 pattern is unstable, temporarily use TPS4 instead */
test_pattern = (force_tps4_for_cp2520 == 1) ?
DP_TEST_PATTERN_TRAINING_PATTERN4 :
DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
break; break;
case PHY_TEST_PATTERN_CP2520_3: case PHY_TEST_PATTERN_CP2520_3:
test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
......
...@@ -89,12 +89,12 @@ void dp_enable_link_phy( ...@@ -89,12 +89,12 @@ void dp_enable_link_phy(
if (dc_is_dp_sst_signal(signal)) { if (dc_is_dp_sst_signal(signal)) {
if (signal == SIGNAL_TYPE_EDP) { if (signal == SIGNAL_TYPE_EDP) {
link_enc->funcs->power_control(link_enc, true); link->dc->hwss.edp_power_control(link->link_enc, true);
link_enc->funcs->enable_dp_output( link_enc->funcs->enable_dp_output(
link_enc, link_enc,
link_settings, link_settings,
clock_source); clock_source);
link_enc->funcs->backlight_control(link_enc, true); link->dc->hwss.edp_backlight_control(link, true);
} else } else
link_enc->funcs->enable_dp_output( link_enc->funcs->enable_dp_output(
link_enc, link_enc,
...@@ -138,12 +138,12 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) ...@@ -138,12 +138,12 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
dp_receiver_power_ctrl(link, false); dp_receiver_power_ctrl(link, false);
if (signal == SIGNAL_TYPE_EDP) { if (signal == SIGNAL_TYPE_EDP) {
link->link_enc->funcs->backlight_control(link->link_enc, false); link->dc->hwss.edp_backlight_control(link, false);
edp_receiver_ready_T9(link); edp_receiver_ready_T9(link);
link->link_enc->funcs->disable_output(link->link_enc, signal); link->link_enc->funcs->disable_output(link->link_enc, signal, link);
link->link_enc->funcs->power_control(link->link_enc, false); link->dc->hwss.edp_power_control(link->link_enc, false);
} else } else
link->link_enc->funcs->disable_output(link->link_enc, signal); link->link_enc->funcs->disable_output(link->link_enc, signal, link);
/* Clear current link setting.*/ /* Clear current link setting.*/
memset(&link->cur_link_settings, 0, memset(&link->cur_link_settings, 0,
...@@ -282,11 +282,12 @@ void dp_retrain_link_dp_test(struct dc_link *link, ...@@ -282,11 +282,12 @@ void dp_retrain_link_dp_test(struct dc_link *link,
dp_receiver_power_ctrl(link, false); dp_receiver_power_ctrl(link, false);
link->dc->hwss.disable_stream(&pipes[i]); link->dc->hwss.disable_stream(&pipes[i], KEEP_ACQUIRED_RESOURCE);
link->link_enc->funcs->disable_output( link->link_enc->funcs->disable_output(
link->link_enc, link->link_enc,
SIGNAL_TYPE_DISPLAY_PORT); SIGNAL_TYPE_DISPLAY_PORT,
link);
/* Clear current link setting. */ /* Clear current link setting. */
memset(&link->cur_link_settings, 0, memset(&link->cur_link_settings, 0,
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "opp.h" #include "opp.h"
#include "timing_generator.h" #include "timing_generator.h"
#include "transform.h" #include "transform.h"
#include "dpp.h"
#include "core_types.h" #include "core_types.h"
#include "set_mode_types.h" #include "set_mode_types.h"
#include "virtual/virtual_stream_encoder.h" #include "virtual/virtual_stream_encoder.h"
...@@ -242,7 +243,10 @@ bool resource_construct( ...@@ -242,7 +243,10 @@ bool resource_construct(
pool->stream_enc_count++; pool->stream_enc_count++;
} }
} }
dc->caps.dynamic_audio = false;
if (pool->audio_count < pool->stream_enc_count) {
dc->caps.dynamic_audio = true;
}
for (i = 0; i < num_virtual_links; i++) { for (i = 0; i < num_virtual_links; i++) {
pool->stream_enc[pool->stream_enc_count] = pool->stream_enc[pool->stream_enc_count] =
virtual_stream_encoder_create( virtual_stream_encoder_create(
...@@ -846,12 +850,20 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) ...@@ -846,12 +850,20 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
*/ */
pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable; pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left;
pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable; pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top;
pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right;
pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom;
/* Taps calculations */ /* Taps calculations */
res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( if (pipe_ctx->plane_res.xfm != NULL)
pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
if (pipe_ctx->plane_res.dpp != NULL)
res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
if (!res) { if (!res) {
/* Try 24 bpp linebuffer */ /* Try 24 bpp linebuffer */
...@@ -859,6 +871,9 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) ...@@ -859,6 +871,9 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps(
pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
} }
if (res) if (res)
...@@ -1021,9 +1036,9 @@ static int acquire_first_split_pipe( ...@@ -1021,9 +1036,9 @@ static int acquire_first_split_pipe(
memset(pipe_ctx, 0, sizeof(*pipe_ctx)); memset(pipe_ctx, 0, sizeof(*pipe_ctx));
pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->stream_res.tg = pool->timing_generators[i];
pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.hubp = pool->hubps[i];
pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i];
pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->plane_res.dpp = pool->dpps[i];
pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->stream_res.opp = pool->opps[i];
pipe_ctx->pipe_idx = i; pipe_ctx->pipe_idx = i;
...@@ -1070,9 +1085,6 @@ bool dc_add_plane_to_context( ...@@ -1070,9 +1085,6 @@ bool dc_add_plane_to_context(
return false; return false;
} }
/* retain new surfaces */
dc_plane_state_retain(plane_state);
free_pipe = acquire_free_pipe_for_stream(context, pool, stream); free_pipe = acquire_free_pipe_for_stream(context, pool, stream);
#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
...@@ -1082,11 +1094,11 @@ bool dc_add_plane_to_context( ...@@ -1082,11 +1094,11 @@ bool dc_add_plane_to_context(
free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
} }
#endif #endif
if (!free_pipe) { if (!free_pipe)
stream_status->plane_states[i] = NULL;
return false; return false;
}
/* retain new surfaces */
dc_plane_state_retain(plane_state);
free_pipe->plane_state = plane_state; free_pipe->plane_state = plane_state;
if (head_pipe != free_pipe) { if (head_pipe != free_pipe) {
...@@ -1178,8 +1190,8 @@ bool dc_remove_plane_from_context( ...@@ -1178,8 +1190,8 @@ bool dc_remove_plane_from_context(
stream_status->plane_count--; stream_status->plane_count--;
/* Trim back arrays */ /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */
for (i = 0; i < stream_status->plane_count; i++) for (; i < stream_status->plane_count; i++)
stream_status->plane_states[i] = stream_status->plane_states[i + 1]; stream_status->plane_states[i] = stream_status->plane_states[i + 1];
stream_status->plane_states[stream_status->plane_count] = NULL; stream_status->plane_states[stream_status->plane_count] = NULL;
...@@ -1312,6 +1324,28 @@ bool dc_is_stream_unchanged( ...@@ -1312,6 +1324,28 @@ bool dc_is_stream_unchanged(
return true; return true;
} }
bool dc_is_stream_scaling_unchanged(
struct dc_stream_state *old_stream, struct dc_stream_state *stream)
{
if (old_stream == stream)
return true;
if (old_stream == NULL || stream == NULL)
return false;
if (memcmp(&old_stream->src,
&stream->src,
sizeof(struct rect)) != 0)
return false;
if (memcmp(&old_stream->dst,
&stream->dst,
sizeof(struct rect)) != 0)
return false;
return true;
}
/* Maximum TMDS single link pixel clock 165MHz */ /* Maximum TMDS single link pixel clock 165MHz */
#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
...@@ -1330,7 +1364,7 @@ static void update_stream_engine_usage( ...@@ -1330,7 +1364,7 @@ static void update_stream_engine_usage(
} }
/* TODO: release audio object */ /* TODO: release audio object */
static void update_audio_usage( void update_audio_usage(
struct resource_context *res_ctx, struct resource_context *res_ctx,
const struct resource_pool *pool, const struct resource_pool *pool,
struct audio *audio, struct audio *audio,
...@@ -1356,8 +1390,10 @@ static int acquire_first_free_pipe( ...@@ -1356,8 +1390,10 @@ static int acquire_first_free_pipe(
pipe_ctx->stream_res.tg = pool->timing_generators[i]; pipe_ctx->stream_res.tg = pool->timing_generators[i];
pipe_ctx->plane_res.mi = pool->mis[i]; pipe_ctx->plane_res.mi = pool->mis[i];
pipe_ctx->plane_res.hubp = pool->hubps[i];
pipe_ctx->plane_res.ipp = pool->ipps[i]; pipe_ctx->plane_res.ipp = pool->ipps[i];
pipe_ctx->plane_res.xfm = pool->transforms[i]; pipe_ctx->plane_res.xfm = pool->transforms[i];
pipe_ctx->plane_res.dpp = pool->dpps[i];
pipe_ctx->stream_res.opp = pool->opps[i]; pipe_ctx->stream_res.opp = pool->opps[i];
pipe_ctx->pipe_idx = i; pipe_ctx->pipe_idx = i;
...@@ -1414,12 +1450,17 @@ static struct audio *find_first_free_audio( ...@@ -1414,12 +1450,17 @@ static struct audio *find_first_free_audio(
const struct resource_pool *pool) const struct resource_pool *pool)
{ {
int i; int i;
for (i = 0; i < pool->audio_count; i++) {
if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) {
return pool->audios[i];
}
}
/*not found the matching one, first come first serve*/
for (i = 0; i < pool->audio_count; i++) { for (i = 0; i < pool->audio_count; i++) {
if (res_ctx->is_audio_acquired[i] == false) { if (res_ctx->is_audio_acquired[i] == false) {
return pool->audios[i]; return pool->audios[i];
} }
} }
return 0; return 0;
} }
...@@ -1438,7 +1479,7 @@ bool resource_is_stream_unchanged( ...@@ -1438,7 +1479,7 @@ bool resource_is_stream_unchanged(
return false; return false;
} }
bool dc_add_stream_to_ctx( enum dc_status dc_add_stream_to_ctx(
struct dc *dc, struct dc *dc,
struct dc_state *new_ctx, struct dc_state *new_ctx,
struct dc_stream_state *stream) struct dc_stream_state *stream)
...@@ -1459,10 +1500,10 @@ bool dc_add_stream_to_ctx( ...@@ -1459,10 +1500,10 @@ bool dc_add_stream_to_ctx(
if (res != DC_OK) if (res != DC_OK)
DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res); DC_ERROR("Adding stream %p to context failed with err %d!\n", stream, res);
return res == DC_OK; return res;
} }
bool dc_remove_stream_from_ctx( enum dc_status dc_remove_stream_from_ctx(
struct dc *dc, struct dc *dc,
struct dc_state *new_ctx, struct dc_state *new_ctx,
struct dc_stream_state *stream) struct dc_stream_state *stream)
...@@ -1632,10 +1673,11 @@ enum dc_status resource_map_pool_resources( ...@@ -1632,10 +1673,11 @@ enum dc_status resource_map_pool_resources(
/* acquire new resources */ /* acquire new resources */
pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #ifdef CONFIG_DRM_AMD_DC_DCN1_0
if (pipe_idx < 0) if (pipe_idx < 0)
acquire_first_split_pipe(&context->res_ctx, pool, stream); pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
#endif #endif
if (pipe_idx < 0) if (pipe_idx < 0)
return DC_NO_CONTROLLER_RESOURCE; return DC_NO_CONTROLLER_RESOURCE;
...@@ -1716,17 +1758,18 @@ void dc_resource_state_construct( ...@@ -1716,17 +1758,18 @@ void dc_resource_state_construct(
dst_ctx->dis_clk = dc->res_pool->display_clock; dst_ctx->dis_clk = dc->res_pool->display_clock;
} }
bool dc_validate_global_state( enum dc_status dc_validate_global_state(
struct dc *dc, struct dc *dc,
struct dc_state *new_ctx) struct dc_state *new_ctx)
{ {
enum dc_status result = DC_ERROR_UNEXPECTED; enum dc_status result = DC_ERROR_UNEXPECTED;
int i, j; int i, j;
if (dc->res_pool->funcs->validate_global && if (dc->res_pool->funcs->validate_global) {
dc->res_pool->funcs->validate_global( result = dc->res_pool->funcs->validate_global(dc, new_ctx);
dc, new_ctx) != DC_OK) if (result != DC_OK)
return false; return result;
}
for (i = 0; new_ctx && i < new_ctx->stream_count; i++) { for (i = 0; new_ctx && i < new_ctx->stream_count; i++) {
struct dc_stream_state *stream = new_ctx->streams[i]; struct dc_stream_state *stream = new_ctx->streams[i];
...@@ -2713,7 +2756,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, ...@@ -2713,7 +2756,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream,
fmt_bit_depth->pixel_encoding = pixel_encoding; fmt_bit_depth->pixel_encoding = pixel_encoding;
} }
bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
{ {
struct dc *core_dc = dc; struct dc *core_dc = dc;
struct dc_link *link = stream->sink->link; struct dc_link *link = stream->sink->link;
...@@ -2737,16 +2780,16 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) ...@@ -2737,16 +2780,16 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
link, link,
&stream->timing); &stream->timing);
return res == DC_OK; return res;
} }
bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state)
{ {
struct dc *core_dc = dc; enum dc_status res = DC_OK;
/* TODO For now validates pixel format only */ /* TODO For now validates pixel format only */
if (core_dc->res_pool->funcs->validate_plane) if (dc->res_pool->funcs->validate_plane)
return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK; return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps);
return true; return res;
} }
...@@ -173,7 +173,7 @@ struct dc_stream_status *dc_stream_get_status( ...@@ -173,7 +173,7 @@ struct dc_stream_status *dc_stream_get_status(
* Update the cursor attributes and set cursor surface address * Update the cursor attributes and set cursor surface address
*/ */
bool dc_stream_set_cursor_attributes( bool dc_stream_set_cursor_attributes(
const struct dc_stream_state *stream, struct dc_stream_state *stream,
const struct dc_cursor_attributes *attributes) const struct dc_cursor_attributes *attributes)
{ {
int i; int i;
...@@ -189,21 +189,51 @@ bool dc_stream_set_cursor_attributes( ...@@ -189,21 +189,51 @@ bool dc_stream_set_cursor_attributes(
return false; return false;
} }
if (attributes->address.quad_part == 0) {
dm_output_to_console("DC: Cursor address is 0!\n");
return false;
}
core_dc = stream->ctx->dc; core_dc = stream->ctx->dc;
res_ctx = &core_dc->current_state->res_ctx; res_ctx = &core_dc->current_state->res_ctx;
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
if (pipe_ctx->stream != stream || !pipe_ctx->plane_res.ipp) if (pipe_ctx->stream != stream || (!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
continue; continue;
if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
continue; continue;
pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
pipe_ctx->plane_res.ipp, attributes); if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL)
pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
pipe_ctx->plane_res.ipp, attributes);
if (pipe_ctx->plane_res.hubp != NULL &&
pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes != NULL)
pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
pipe_ctx->plane_res.hubp, attributes);
if (pipe_ctx->plane_res.mi != NULL &&
pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL)
pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
pipe_ctx->plane_res.mi, attributes);
if (pipe_ctx->plane_res.xfm != NULL &&
pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL)
pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
pipe_ctx->plane_res.xfm, attributes);
if (pipe_ctx->plane_res.dpp != NULL &&
pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL)
pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
pipe_ctx->plane_res.dpp, attributes);
} }
stream->cursor_attributes = *attributes;
return true; return true;
} }
...@@ -231,6 +261,10 @@ bool dc_stream_set_cursor_position( ...@@ -231,6 +261,10 @@ bool dc_stream_set_cursor_position(
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
struct mem_input *mi = pipe_ctx->plane_res.mi;
struct hubp *hubp = pipe_ctx->plane_res.hubp;
struct transform *xfm = pipe_ctx->plane_res.xfm;
struct dpp *dpp = pipe_ctx->plane_res.dpp;
struct dc_cursor_position pos_cpy = *position; struct dc_cursor_position pos_cpy = *position;
struct dc_cursor_mi_param param = { struct dc_cursor_mi_param param = {
.pixel_clk_khz = stream->timing.pix_clk_khz, .pixel_clk_khz = stream->timing.pix_clk_khz,
...@@ -241,7 +275,9 @@ bool dc_stream_set_cursor_position( ...@@ -241,7 +275,9 @@ bool dc_stream_set_cursor_position(
}; };
if (pipe_ctx->stream != stream || if (pipe_ctx->stream != stream ||
!pipe_ctx->plane_res.ipp || !pipe_ctx->plane_state) (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) ||
!pipe_ctx->plane_state ||
(!pipe_ctx->plane_res.xfm && !pipe_ctx->plane_res.dpp))
continue; continue;
if (pipe_ctx->plane_state->address.type if (pipe_ctx->plane_state->address.type
...@@ -251,7 +287,22 @@ bool dc_stream_set_cursor_position( ...@@ -251,7 +287,22 @@ bool dc_stream_set_cursor_position(
if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
pos_cpy.enable = false; pos_cpy.enable = false;
ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
if (ipp->funcs->ipp_cursor_set_position != NULL)
ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
if (mi != NULL && mi->funcs->set_cursor_position != NULL)
mi->funcs->set_cursor_position(mi, &pos_cpy, &param);
if (hubp != NULL && hubp->funcs->set_cursor_position != NULL)
hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
if (xfm != NULL && xfm->funcs->set_cursor_position != NULL)
xfm->funcs->set_cursor_position(xfm, &pos_cpy, &param, hubp->curs_attr.width);
if (dpp != NULL && dpp->funcs->set_cursor_position != NULL)
dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width);
} }
return true; return true;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
/* DC core (private) */ /* DC core (private) */
#include "core_types.h" #include "core_types.h"
#include "transform.h" #include "transform.h"
#include "dpp.h"
/******************************************************************************* /*******************************************************************************
* Private functions * Private functions
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include "inc/compressor.h" #include "inc/compressor.h"
#include "dml/display_mode_lib.h" #include "dml/display_mode_lib.h"
#define DC_VER "3.1.01" #define DC_VER "3.1.07"
#define MAX_SURFACES 3 #define MAX_SURFACES 3
#define MAX_STREAMS 6 #define MAX_STREAMS 6
...@@ -56,11 +56,12 @@ struct dc_caps { ...@@ -56,11 +56,12 @@ struct dc_caps {
uint32_t max_planes; uint32_t max_planes;
uint32_t max_downscale_ratio; uint32_t max_downscale_ratio;
uint32_t i2c_speed_in_khz; uint32_t i2c_speed_in_khz;
unsigned int max_cursor_size; unsigned int max_cursor_size;
unsigned int max_video_width;
bool dcc_const_color;
bool dynamic_audio;
}; };
struct dc_dcc_surface_param { struct dc_dcc_surface_param {
struct dc_size surface_size; struct dc_size surface_size;
enum surface_pixel_format format; enum surface_pixel_format format;
...@@ -132,6 +133,10 @@ struct dc_stream_state_funcs { ...@@ -132,6 +133,10 @@ struct dc_stream_state_funcs {
void (*set_dither_option)(struct dc_stream_state *stream, void (*set_dither_option)(struct dc_stream_state *stream,
enum dc_dither_option option); enum dc_dither_option option);
void (*set_dpms)(struct dc *dc,
struct dc_stream_state *stream,
bool dpms_off);
}; };
struct link_training_settings; struct link_training_settings;
...@@ -162,6 +167,23 @@ struct dc_config { ...@@ -162,6 +167,23 @@ struct dc_config {
bool disable_disp_pll_sharing; bool disable_disp_pll_sharing;
}; };
enum dcc_option {
DCC_ENABLE = 0,
DCC_DISABLE = 1,
DCC_HALF_REQ_DISALBE = 2,
};
enum pipe_split_policy {
MPC_SPLIT_DYNAMIC = 0,
MPC_SPLIT_AVOID = 1,
MPC_SPLIT_AVOID_MULT_DISP = 2,
};
enum wm_report_mode {
WM_REPORT_DEFAULT = 0,
WM_REPORT_OVERRIDE = 1,
};
struct dc_debug { struct dc_debug {
bool surface_visual_confirm; bool surface_visual_confirm;
bool sanity_checks; bool sanity_checks;
...@@ -170,14 +192,21 @@ struct dc_debug { ...@@ -170,14 +192,21 @@ struct dc_debug {
bool timing_trace; bool timing_trace;
bool clock_trace; bool clock_trace;
bool validation_trace; bool validation_trace;
/* stutter efficiency related */
bool disable_stutter; bool disable_stutter;
bool disable_dcc; bool use_max_lb;
enum dcc_option disable_dcc;
enum pipe_split_policy pipe_split_policy;
bool force_single_disp_pipe_split;
bool voltage_align_fclk;
bool disable_dfs_bypass; bool disable_dfs_bypass;
bool disable_dpp_power_gate; bool disable_dpp_power_gate;
bool disable_hubp_power_gate; bool disable_hubp_power_gate;
bool disable_pplib_wm_range; bool disable_pplib_wm_range;
bool use_dml_wm; enum wm_report_mode pplib_wm_report_mode;
bool disable_pipe_split; unsigned int min_disp_clk_khz;
int sr_exit_time_dpm0_ns; int sr_exit_time_dpm0_ns;
int sr_enter_plus_exit_time_dpm0_ns; int sr_enter_plus_exit_time_dpm0_ns;
int sr_exit_time_ns; int sr_exit_time_ns;
...@@ -191,6 +220,11 @@ struct dc_debug { ...@@ -191,6 +220,11 @@ struct dc_debug {
bool disable_dmcu; bool disable_dmcu;
bool disable_psr; bool disable_psr;
bool force_abm_enable; bool force_abm_enable;
bool disable_hbup_pg;
bool disable_dpp_pg;
bool disable_stereo_support;
bool vsr_support;
bool performance_trace;
}; };
struct dc_state; struct dc_state;
struct resource_pool; struct resource_pool;
...@@ -233,7 +267,7 @@ struct dc { ...@@ -233,7 +267,7 @@ struct dc {
struct dm_pp_display_configuration prev_display_config; struct dm_pp_display_configuration prev_display_config;
/* FBC compressor */ /* FBC compressor */
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
struct compressor *fbc_compressor; struct compressor *fbc_compressor;
#endif #endif
}; };
...@@ -268,7 +302,7 @@ struct dc_init_data { ...@@ -268,7 +302,7 @@ struct dc_init_data {
struct dc_config flags; struct dc_config flags;
uint32_t log_mask; uint32_t log_mask;
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
uint64_t fbc_gpu_addr; uint64_t fbc_gpu_addr;
#endif #endif
}; };
...@@ -285,6 +319,38 @@ enum { ...@@ -285,6 +319,38 @@ enum {
TRANSFER_FUNC_POINTS = 1025 TRANSFER_FUNC_POINTS = 1025
}; };
// Moved here from color module for linux
enum color_transfer_func {
transfer_func_unknown,
transfer_func_srgb,
transfer_func_bt709,
transfer_func_pq2084,
transfer_func_pq2084_interim,
transfer_func_linear_0_1,
transfer_func_linear_0_125,
transfer_func_dolbyvision,
transfer_func_gamma_22,
transfer_func_gamma_26
};
enum color_color_space {
color_space_unsupported,
color_space_srgb,
color_space_bt601,
color_space_bt709,
color_space_xv_ycc_bt601,
color_space_xv_ycc_bt709,
color_space_xr_rgb,
color_space_bt2020,
color_space_adobe,
color_space_dci_p3,
color_space_sc_rgb_ms_ref,
color_space_display_native,
color_space_app_ctrl,
color_space_dolby_vision,
color_space_custom_coordinates
};
struct dc_hdr_static_metadata { struct dc_hdr_static_metadata {
/* display chromaticities and white point in units of 0.00001 */ /* display chromaticities and white point in units of 0.00001 */
unsigned int chromaticity_green_x; unsigned int chromaticity_green_x;
...@@ -365,6 +431,12 @@ struct dc_plane_state { ...@@ -365,6 +431,12 @@ struct dc_plane_state {
struct dc_gamma *gamma_correction; struct dc_gamma *gamma_correction;
struct dc_transfer_func *in_transfer_func; struct dc_transfer_func *in_transfer_func;
// sourceContentAttribute cache
bool is_source_input_valid;
struct dc_hdr_static_metadata source_input_mastering_info;
enum color_color_space source_input_color_space;
enum color_transfer_func source_input_tf;
enum dc_color_space color_space; enum dc_color_space color_space;
enum surface_pixel_format format; enum surface_pixel_format format;
enum dc_rotation_angle rotation; enum dc_rotation_angle rotation;
...@@ -449,23 +521,6 @@ struct dc_flip_addrs { ...@@ -449,23 +521,6 @@ struct dc_flip_addrs {
/* TODO: add flip duration for FreeSync */ /* TODO: add flip duration for FreeSync */
}; };
/*
* Set up surface attributes and associate to a stream
* The surfaces parameter is an absolute set of all surface active for the stream.
* If no surfaces are provided, the stream will be blanked; no memory read.
* Any flip related attribute changes must be done through this interface.
*
* After this call:
* Surfaces attributes are programmed and configured to be composed into stream.
* This does not trigger a flip. No surface address is programmed.
*/
bool dc_commit_planes_to_stream(
struct dc *dc,
struct dc_plane_state **plane_states,
uint8_t new_plane_count,
struct dc_stream_state *stream);
bool dc_post_update_surfaces_to_stream( bool dc_post_update_surfaces_to_stream(
struct dc *dc); struct dc *dc);
...@@ -554,9 +609,12 @@ struct dc_stream_state { ...@@ -554,9 +609,12 @@ struct dc_stream_state {
int phy_pix_clk; int phy_pix_clk;
enum signal_type signal; enum signal_type signal;
bool dpms_off;
struct dc_stream_status status; struct dc_stream_status status;
struct dc_cursor_attributes cursor_attributes;
/* from stream struct */ /* from stream struct */
struct kref refcount; struct kref refcount;
}; };
...@@ -569,11 +627,10 @@ struct dc_stream_update { ...@@ -569,11 +627,10 @@ struct dc_stream_update {
bool dc_is_stream_unchanged( bool dc_is_stream_unchanged(
struct dc_stream_state *old_stream, struct dc_stream_state *stream); struct dc_stream_state *old_stream, struct dc_stream_state *stream);
bool dc_is_stream_scaling_unchanged(
struct dc_stream_state *old_stream, struct dc_stream_state *stream);
/* /*
* Setup stream attributes if no stream updates are provided
* there will be no impact on the stream parameters
*
* Set up surface attributes and associate to a stream * Set up surface attributes and associate to a stream
* The surfaces parameter is an absolute set of all surface active for the stream. * The surfaces parameter is an absolute set of all surface active for the stream.
* If no surfaces are provided, the stream will be blanked; no memory read. * If no surfaces are provided, the stream will be blanked; no memory read.
...@@ -582,14 +639,22 @@ bool dc_is_stream_unchanged( ...@@ -582,14 +639,22 @@ bool dc_is_stream_unchanged(
* After this call: * After this call:
* Surfaces attributes are programmed and configured to be composed into stream. * Surfaces attributes are programmed and configured to be composed into stream.
* This does not trigger a flip. No surface address is programmed. * This does not trigger a flip. No surface address is programmed.
*
*/ */
void dc_update_planes_and_stream(struct dc *dc, bool dc_commit_planes_to_stream(
struct dc_surface_update *surface_updates, int surface_count, struct dc *dc,
struct dc_plane_state **plane_states,
uint8_t new_plane_count,
struct dc_stream_state *dc_stream, struct dc_stream_state *dc_stream,
struct dc_stream_update *stream_update); struct dc_state *state);
void dc_commit_updates_for_stream(struct dc *dc,
struct dc_surface_update *srf_updates,
int surface_count,
struct dc_stream_state *stream,
struct dc_stream_update *stream_update,
struct dc_plane_state **plane_states,
struct dc_state *state);
/* /*
* Log the current stream state. * Log the current stream state.
*/ */
...@@ -616,12 +681,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, ...@@ -616,12 +681,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
uint32_t *h_position, uint32_t *h_position,
uint32_t *v_position); uint32_t *v_position);
bool dc_add_stream_to_ctx( enum dc_status dc_add_stream_to_ctx(
struct dc *dc, struct dc *dc,
struct dc_state *new_ctx, struct dc_state *new_ctx,
struct dc_stream_state *stream); struct dc_stream_state *stream);
bool dc_remove_stream_from_ctx( enum dc_status dc_remove_stream_from_ctx(
struct dc *dc, struct dc *dc,
struct dc_state *new_ctx, struct dc_state *new_ctx,
struct dc_stream_state *stream); struct dc_stream_state *stream);
...@@ -660,11 +725,11 @@ struct dc_validation_set { ...@@ -660,11 +725,11 @@ struct dc_validation_set {
uint8_t plane_count; uint8_t plane_count;
}; };
bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream);
bool dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state);
bool dc_validate_global_state( enum dc_status dc_validate_global_state(
struct dc *dc, struct dc *dc,
struct dc_state *new_ctx); struct dc_state *new_ctx);
...@@ -991,7 +1056,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params); ...@@ -991,7 +1056,7 @@ struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params);
******************************************************************************/ ******************************************************************************/
/* TODO: Deprecated once we switch to dc_set_cursor_position */ /* TODO: Deprecated once we switch to dc_set_cursor_position */
bool dc_stream_set_cursor_attributes( bool dc_stream_set_cursor_attributes(
const struct dc_stream_state *stream, struct dc_stream_state *stream,
const struct dc_cursor_attributes *attributes); const struct dc_cursor_attributes *attributes);
bool dc_stream_set_cursor_position( bool dc_stream_set_cursor_position(
......
...@@ -204,6 +204,8 @@ enum surface_pixel_format { ...@@ -204,6 +204,8 @@ enum surface_pixel_format {
/*grow 444 video here if necessary */ /*grow 444 video here if necessary */
}; };
/* Pixel format */ /* Pixel format */
enum pixel_format { enum pixel_format {
/*graph*/ /*graph*/
......
...@@ -92,7 +92,7 @@ struct dc_context { ...@@ -92,7 +92,7 @@ struct dc_context {
bool created_bios; bool created_bios;
struct gpio_service *gpio_service; struct gpio_service *gpio_service;
struct i2caux *i2caux; struct i2caux *i2caux;
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
uint64_t fbc_gpu_addr; uint64_t fbc_gpu_addr;
#endif #endif
}; };
...@@ -151,6 +151,7 @@ enum dc_edid_status { ...@@ -151,6 +151,7 @@ enum dc_edid_status {
EDID_BAD_INPUT, EDID_BAD_INPUT,
EDID_NO_RESPONSE, EDID_NO_RESPONSE,
EDID_BAD_CHECKSUM, EDID_BAD_CHECKSUM,
EDID_THE_SAME,
}; };
/* audio capability from EDID*/ /* audio capability from EDID*/
......
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
#include "hw_sequencer.h" #include "hw_sequencer.h"
#define BL_REG_LIST()\
SR(LVTMA_PWRSEQ_CNTL), \
SR(LVTMA_PWRSEQ_STATE)
#define HWSEQ_DCEF_REG_LIST_DCE8() \ #define HWSEQ_DCEF_REG_LIST_DCE8() \
.DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \ .DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \
.DCFE_CLOCK_CONTROL[1] = mmCRTC1_CRTC_DCFE_CLOCK_CONTROL, \ .DCFE_CLOCK_CONTROL[1] = mmCRTC1_CRTC_DCFE_CLOCK_CONTROL, \
...@@ -86,24 +90,27 @@ ...@@ -86,24 +90,27 @@
SRII(BLND_CONTROL, BLND, 0),\ SRII(BLND_CONTROL, BLND, 0),\
SRII(BLND_CONTROL, BLND, 1),\ SRII(BLND_CONTROL, BLND, 1),\
SR(BLNDV_CONTROL),\ SR(BLNDV_CONTROL),\
HWSEQ_PIXEL_RATE_REG_LIST(CRTC) HWSEQ_PIXEL_RATE_REG_LIST(CRTC),\
BL_REG_LIST()
#define HWSEQ_DCE8_REG_LIST() \ #define HWSEQ_DCE8_REG_LIST() \
HWSEQ_DCEF_REG_LIST_DCE8(), \ HWSEQ_DCEF_REG_LIST_DCE8(), \
HWSEQ_BLND_REG_LIST(), \ HWSEQ_BLND_REG_LIST(), \
HWSEQ_PIXEL_RATE_REG_LIST(CRTC) HWSEQ_PIXEL_RATE_REG_LIST(CRTC),\
BL_REG_LIST()
#define HWSEQ_DCE10_REG_LIST() \ #define HWSEQ_DCE10_REG_LIST() \
HWSEQ_DCEF_REG_LIST(), \ HWSEQ_DCEF_REG_LIST(), \
HWSEQ_BLND_REG_LIST(), \ HWSEQ_BLND_REG_LIST(), \
HWSEQ_PIXEL_RATE_REG_LIST(CRTC) HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \
BL_REG_LIST()
#define HWSEQ_ST_REG_LIST() \ #define HWSEQ_ST_REG_LIST() \
HWSEQ_DCE11_REG_LIST_BASE(), \ HWSEQ_DCE11_REG_LIST_BASE(), \
.DCFE_CLOCK_CONTROL[2] = mmDCFEV_CLOCK_CONTROL, \ .DCFE_CLOCK_CONTROL[2] = mmDCFEV_CLOCK_CONTROL, \
.CRTC_H_BLANK_START_END[2] = mmCRTCV_H_BLANK_START_END, \ .CRTC_H_BLANK_START_END[2] = mmCRTCV_H_BLANK_START_END, \
.BLND_V_UPDATE_LOCK[2] = mmBLNDV_V_UPDATE_LOCK, \ .BLND_V_UPDATE_LOCK[2] = mmBLNDV_V_UPDATE_LOCK, \
.BLND_CONTROL[2] = mmBLNDV_CONTROL, .BLND_CONTROL[2] = mmBLNDV_CONTROL
#define HWSEQ_CZ_REG_LIST() \ #define HWSEQ_CZ_REG_LIST() \
HWSEQ_DCE11_REG_LIST_BASE(), \ HWSEQ_DCE11_REG_LIST_BASE(), \
...@@ -123,16 +130,16 @@ ...@@ -123,16 +130,16 @@
SR(DCHUB_FB_LOCATION),\ SR(DCHUB_FB_LOCATION),\
SR(DCHUB_AGP_BASE),\ SR(DCHUB_AGP_BASE),\
SR(DCHUB_AGP_BOT),\ SR(DCHUB_AGP_BOT),\
SR(DCHUB_AGP_TOP) SR(DCHUB_AGP_TOP), \
BL_REG_LIST()
#define HWSEQ_DCE112_REG_LIST() \ #define HWSEQ_DCE112_REG_LIST() \
HWSEQ_DCE10_REG_LIST(), \ HWSEQ_DCE10_REG_LIST(), \
HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \ HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \
HWSEQ_PHYPLL_REG_LIST(CRTC) HWSEQ_PHYPLL_REG_LIST(CRTC), \
BL_REG_LIST()
#define HWSEQ_DCN_REG_LIST()\ #define HWSEQ_DCN_REG_LIST()\
HWSEQ_PIXEL_RATE_REG_LIST(OTG), \
HWSEQ_PHYPLL_REG_LIST(OTG), \
SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 0), \
SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 1), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 1), \
SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 2), \ SRII(OTG_GLOBAL_SYNC_STATUS, OTG, 2), \
...@@ -156,23 +163,15 @@ ...@@ -156,23 +163,15 @@
SR(REFCLK_CNTL), \ SR(REFCLK_CNTL), \
SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\
SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_A),\
SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\
SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\
SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A),\
SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\
SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_B),\
SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\
SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\
SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B),\
SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\
SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_C),\
SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\
SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\
SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C),\
SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\
SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\ SR(DCHUBBUB_ARB_PTE_META_URGENCY_WATERMARK_D),\
SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\
SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\
SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\ SR(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D),\
SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\ SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\
SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\ SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\
...@@ -181,32 +180,11 @@ ...@@ -181,32 +180,11 @@
SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
SR(DCHUBBUB_TEST_DEBUG_INDEX), \ SR(DCHUBBUB_TEST_DEBUG_INDEX), \
SR(DCHUBBUB_TEST_DEBUG_DATA), \ SR(DCHUBBUB_TEST_DEBUG_DATA), \
SR(DC_IP_REQUEST_CNTL), \
SR(DOMAIN0_PG_CONFIG), \
SR(DOMAIN1_PG_CONFIG), \
SR(DOMAIN2_PG_CONFIG), \
SR(DOMAIN3_PG_CONFIG), \
SR(DOMAIN4_PG_CONFIG), \
SR(DOMAIN5_PG_CONFIG), \
SR(DOMAIN6_PG_CONFIG), \
SR(DOMAIN7_PG_CONFIG), \
SR(DOMAIN0_PG_STATUS), \
SR(DOMAIN1_PG_STATUS), \
SR(DOMAIN2_PG_STATUS), \
SR(DOMAIN3_PG_STATUS), \
SR(DOMAIN4_PG_STATUS), \
SR(DOMAIN5_PG_STATUS), \
SR(DOMAIN6_PG_STATUS), \
SR(DOMAIN7_PG_STATUS), \
SR(DIO_MEM_PWR_CTRL), \ SR(DIO_MEM_PWR_CTRL), \
SR(DCCG_GATE_DISABLE_CNTL), \ SR(DCCG_GATE_DISABLE_CNTL), \
SR(DCCG_GATE_DISABLE_CNTL2), \ SR(DCCG_GATE_DISABLE_CNTL2), \
SR(DCFCLK_CNTL),\ SR(DCFCLK_CNTL),\
SR(DCFCLK_CNTL), \ SR(DCFCLK_CNTL), \
SR(D1VGA_CONTROL), \
SR(D2VGA_CONTROL), \
SR(D3VGA_CONTROL), \
SR(D4VGA_CONTROL), \
/* todo: get these from GVM instead of reading registers ourselves */\ /* todo: get these from GVM instead of reading registers ourselves */\
MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32),\
MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\ MMHUB_SR(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32),\
...@@ -221,17 +199,56 @@ ...@@ -221,17 +199,56 @@
MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\ MMHUB_SR(MC_VM_SYSTEM_APERTURE_LOW_ADDR),\
MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR) MMHUB_SR(MC_VM_SYSTEM_APERTURE_HIGH_ADDR)
#define HWSEQ_SR_WATERMARK_REG_LIST()\
SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\
SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\
SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\
SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\
SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\
SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\
SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\
SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D)
#define HWSEQ_DCN1_REG_LIST()\ #define HWSEQ_DCN1_REG_LIST()\
HWSEQ_DCN_REG_LIST(), \ HWSEQ_DCN_REG_LIST(), \
HWSEQ_SR_WATERMARK_REG_LIST(), \
HWSEQ_PIXEL_RATE_REG_LIST(OTG), \
HWSEQ_PHYPLL_REG_LIST(OTG), \
SR(DCHUBBUB_SDPIF_FB_TOP),\ SR(DCHUBBUB_SDPIF_FB_TOP),\
SR(DCHUBBUB_SDPIF_FB_BASE),\ SR(DCHUBBUB_SDPIF_FB_BASE),\
SR(DCHUBBUB_SDPIF_FB_OFFSET),\ SR(DCHUBBUB_SDPIF_FB_OFFSET),\
SR(DCHUBBUB_SDPIF_AGP_BASE),\ SR(DCHUBBUB_SDPIF_AGP_BASE),\
SR(DCHUBBUB_SDPIF_AGP_BOT),\ SR(DCHUBBUB_SDPIF_AGP_BOT),\
SR(DCHUBBUB_SDPIF_AGP_TOP) SR(DCHUBBUB_SDPIF_AGP_TOP),\
SR(DOMAIN0_PG_CONFIG), \
SR(DOMAIN1_PG_CONFIG), \
SR(DOMAIN2_PG_CONFIG), \
SR(DOMAIN3_PG_CONFIG), \
SR(DOMAIN4_PG_CONFIG), \
SR(DOMAIN5_PG_CONFIG), \
SR(DOMAIN6_PG_CONFIG), \
SR(DOMAIN7_PG_CONFIG), \
SR(DOMAIN0_PG_STATUS), \
SR(DOMAIN1_PG_STATUS), \
SR(DOMAIN2_PG_STATUS), \
SR(DOMAIN3_PG_STATUS), \
SR(DOMAIN4_PG_STATUS), \
SR(DOMAIN5_PG_STATUS), \
SR(DOMAIN6_PG_STATUS), \
SR(DOMAIN7_PG_STATUS), \
SR(D1VGA_CONTROL), \
SR(D2VGA_CONTROL), \
SR(D3VGA_CONTROL), \
SR(D4VGA_CONTROL), \
SR(DC_IP_REQUEST_CNTL), \
BL_REG_LIST()
struct dce_hwseq_registers { struct dce_hwseq_registers {
/* Backlight registers */
uint32_t LVTMA_PWRSEQ_CNTL;
uint32_t LVTMA_PWRSEQ_STATE;
uint32_t DCFE_CLOCK_CONTROL[6]; uint32_t DCFE_CLOCK_CONTROL[6];
uint32_t DCFEV_CLOCK_CONTROL; uint32_t DCFEV_CLOCK_CONTROL;
uint32_t DC_MEM_GLOBAL_PWR_REQ_CNTL; uint32_t DC_MEM_GLOBAL_PWR_REQ_CNTL;
...@@ -376,20 +393,28 @@ struct dce_hwseq_registers { ...@@ -376,20 +393,28 @@ struct dce_hwseq_registers {
HWS_SF(BLND_, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\
HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\ HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\
HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\ HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
#define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\ #define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\
HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\
HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\
HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_), \
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
#define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\ #define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\
HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\ SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
#define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\ #define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\
HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\ HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_) HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_)
#define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\ #define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\
...@@ -397,14 +422,18 @@ struct dce_hwseq_registers { ...@@ -397,14 +422,18 @@ struct dce_hwseq_registers {
SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\ SF(DCHUB_FB_LOCATION, FB_BASE, mask_sh),\
SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\ SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\
SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\ SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\
SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh) SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh), \
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
#define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\ #define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\
HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\ HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\
HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\ HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND0_BLND_),\
HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\
HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\ HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\
HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh) HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh), \
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
#define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\ #define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\
HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\ HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\
...@@ -416,35 +445,12 @@ struct dce_hwseq_registers { ...@@ -416,35 +445,12 @@ struct dce_hwseq_registers {
HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \ HWS_SF(DPP_TOP0_, DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \
HWS_SF(OPP_PIPE0_, OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh),\ HWS_SF(OPP_PIPE0_, OPP_PIPE_CONTROL, OPP_PIPE_CLOCK_EN, mask_sh),\
HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \
HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \
HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \
HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \
HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \
HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, mask_sh), \
HWS_SF(, DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, mask_sh), \
HWS_SF(, DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \
HWS_SF(, DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \ HWS_SF(, DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \
HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh) HWS_SF(, DCFCLK_CNTL, DCFCLK_GATE_DIS, mask_sh)
...@@ -468,7 +474,34 @@ struct dce_hwseq_registers { ...@@ -468,7 +474,34 @@ struct dce_hwseq_registers {
HWS_SF(, VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\ HWS_SF(, VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32, PHYSICAL_PAGE_ADDR_LO32, mask_sh),\
HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\ HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB, PHYSICAL_PAGE_NUMBER_MSB, mask_sh),\
HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\ HWS_SF(, MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB, PHYSICAL_PAGE_NUMBER_LSB, mask_sh),\
HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh) HWS_SF(, MC_VM_SYSTEM_APERTURE_LOW_ADDR, LOGICAL_ADDR, mask_sh),\
HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN0_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN1_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN2_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN3_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN4_PG_CONFIG, DOMAIN4_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN5_PG_CONFIG, DOMAIN5_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN6_PG_CONFIG, DOMAIN6_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, mask_sh), \
HWS_SF(, DOMAIN7_PG_CONFIG, DOMAIN7_POWER_GATE, mask_sh), \
HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN0_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN1_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN2_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN3_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN4_PG_STATUS, DOMAIN4_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN5_PG_STATUS, DOMAIN5_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \
HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)
#define HWSEQ_REG_FIELD_LIST(type) \ #define HWSEQ_REG_FIELD_LIST(type) \
type DCFE_CLOCK_ENABLE; \ type DCFE_CLOCK_ENABLE; \
...@@ -498,7 +531,9 @@ struct dce_hwseq_registers { ...@@ -498,7 +531,9 @@ struct dce_hwseq_registers {
type PHYSICAL_PAGE_NUMBER_LSB;\ type PHYSICAL_PAGE_NUMBER_LSB;\
type LOGICAL_ADDR; \ type LOGICAL_ADDR; \
type ENABLE_L1_TLB;\ type ENABLE_L1_TLB;\
type SYSTEM_ACCESS_MODE; type SYSTEM_ACCESS_MODE;\
type LVTMA_BLON;\
type LVTMA_PWRSEQ_TARGET_STATE_R;
#define HWSEQ_DCN_REG_FIELD_LIST(type) \ #define HWSEQ_DCN_REG_FIELD_LIST(type) \
type VUPDATE_NO_LOCK_EVENT_CLEAR; \ type VUPDATE_NO_LOCK_EVENT_CLEAR; \
...@@ -524,6 +559,8 @@ struct dce_hwseq_registers { ...@@ -524,6 +559,8 @@ struct dce_hwseq_registers {
type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\ type DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE;\
type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE;\
type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\ type DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE;\
type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE;\
type DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE;\
type DCHUBBUB_ARB_SAT_LEVEL;\ type DCHUBBUB_ARB_SAT_LEVEL;\
type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\ type DCHUBBUB_ARB_MIN_REQ_OUTSTAND;\
type OPP_PIPE_CLOCK_EN;\ type OPP_PIPE_CLOCK_EN;\
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define CTX \ #define CTX \
ipp_dce->base.ctx ipp_dce->base.ctx
static void dce_ipp_cursor_set_position( static void dce_ipp_cursor_set_position(
struct input_pixel_processor *ipp, struct input_pixel_processor *ipp,
const struct dc_cursor_position *position, const struct dc_cursor_position *position,
...@@ -133,6 +134,7 @@ static void dce_ipp_cursor_set_attributes( ...@@ -133,6 +134,7 @@ static void dce_ipp_cursor_set_attributes(
REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false); REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false);
} }
static void dce_ipp_program_prescale( static void dce_ipp_program_prescale(
struct input_pixel_processor *ipp, struct input_pixel_processor *ipp,
struct ipp_prescale_params *params) struct ipp_prescale_params *params)
......
...@@ -82,13 +82,6 @@ ...@@ -82,13 +82,6 @@
#define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20
#define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40 #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40
/* all values are in milliseconds */
/* For eDP, after power-up/power/down,
* 300/500 msec max. delay from LCDVCC to black video generation */
#define PANEL_POWER_UP_TIMEOUT 300
#define PANEL_POWER_DOWN_TIMEOUT 500
#define HPD_CHECK_INTERVAL 10
/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ /* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */
#define TMDS_MIN_PIXEL_CLOCK 25000 #define TMDS_MIN_PIXEL_CLOCK 25000
/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ /* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */
...@@ -122,8 +115,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { ...@@ -122,8 +115,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
.psr_program_dp_dphy_fast_training = .psr_program_dp_dphy_fast_training =
dce110_psr_program_dp_dphy_fast_training, dce110_psr_program_dp_dphy_fast_training,
.psr_program_secondary_packet = dce110_psr_program_secondary_packet, .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
.backlight_control = dce110_link_encoder_edp_backlight_control,
.power_control = dce110_link_encoder_edp_power_control,
.connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
.enable_hpd = dce110_link_encoder_enable_hpd, .enable_hpd = dce110_link_encoder_enable_hpd,
.disable_hpd = dce110_link_encoder_disable_hpd, .disable_hpd = dce110_link_encoder_disable_hpd,
...@@ -493,165 +484,6 @@ static void configure_encoder( ...@@ -493,165 +484,6 @@ static void configure_encoder(
REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1);
} }
static bool is_panel_powered_on(struct dce110_link_encoder *enc110)
{
bool ret;
uint32_t value;
REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value);
ret = value;
return ret == 1;
}
/* TODO duplicate of dc_link.c version */
static struct gpio *get_hpd_gpio(const struct link_encoder *enc)
{
enum bp_result bp_result;
struct dc_bios *dcb = enc->ctx->dc_bios;
struct graphics_object_hpd_info hpd_info;
struct gpio_pin_info pin_info;
if (dcb->funcs->get_hpd_info(dcb, enc->connector, &hpd_info) != BP_RESULT_OK)
return NULL;
bp_result = dcb->funcs->get_gpio_pin_info(dcb,
hpd_info.hpd_int_gpio_uid, &pin_info);
if (bp_result != BP_RESULT_OK) {
ASSERT(bp_result == BP_RESULT_NORECORD);
return NULL;
}
return dal_gpio_service_create_irq(
enc->ctx->gpio_service,
pin_info.offset,
pin_info.mask);
}
/*
* @brief
* eDP only.
*/
static void link_encoder_edp_wait_for_hpd_ready(
struct dce110_link_encoder *enc110,
bool power_up)
{
struct dc_context *ctx = enc110->base.ctx;
struct graphics_object_id connector = enc110->base.connector;
struct gpio *hpd;
bool edp_hpd_high = false;
uint32_t time_elapsed = 0;
uint32_t timeout = power_up ?
PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
if (dal_graphics_object_id_get_connector_id(connector) !=
CONNECTOR_ID_EDP) {
BREAK_TO_DEBUGGER();
return;
}
if (!power_up)
/* from KV, we will not HPD low after turning off VCC -
* instead, we will check the SW timer in power_up(). */
return;
/* when we power on/off the eDP panel,
* we need to wait until SENSE bit is high/low */
/* obtain HPD */
/* TODO what to do with this? */
hpd = get_hpd_gpio(&enc110->base);
if (!hpd) {
BREAK_TO_DEBUGGER();
return;
}
dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
/* wait until timeout or panel detected */
do {
uint32_t detected = 0;
dal_gpio_get_value(hpd, &detected);
if (!(detected ^ power_up)) {
edp_hpd_high = true;
break;
}
msleep(HPD_CHECK_INTERVAL);
time_elapsed += HPD_CHECK_INTERVAL;
} while (time_elapsed < timeout);
dal_gpio_close(hpd);
dal_gpio_destroy_irq(&hpd);
if (false == edp_hpd_high) {
dm_logger_write(ctx->logger, LOG_ERROR,
"%s: wait timed out!\n", __func__);
}
}
/*
* @brief
* eDP only. Control the power of the eDP panel.
*/
void dce110_link_encoder_edp_power_control(
struct link_encoder *enc,
bool power_up)
{
struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
struct dc_context *ctx = enc110->base.ctx;
struct bp_transmitter_control cntl = { 0 };
enum bp_result bp_result;
if (dal_graphics_object_id_get_connector_id(enc110->base.connector) !=
CONNECTOR_ID_EDP) {
BREAK_TO_DEBUGGER();
return;
}
if ((power_up && !is_panel_powered_on(enc110)) ||
(!power_up && is_panel_powered_on(enc110))) {
/* Send VBIOS command to prompt eDP panel power */
dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
"%s: Panel Power action: %s\n",
__func__, (power_up ? "On":"Off"));
cntl.action = power_up ?
TRANSMITTER_CONTROL_POWER_ON :
TRANSMITTER_CONTROL_POWER_OFF;
cntl.transmitter = enc110->base.transmitter;
cntl.connector_obj_id = enc110->base.connector;
cntl.coherent = false;
cntl.lanes_number = LANE_COUNT_FOUR;
cntl.hpd_sel = enc110->base.hpd_source;
bp_result = link_transmitter_control(enc110, &cntl);
if (BP_RESULT_OK != bp_result) {
dm_logger_write(ctx->logger, LOG_ERROR,
"%s: Panel Power bp_result: %d\n",
__func__, bp_result);
}
} else {
dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
"%s: Skipping Panel Power action: %s\n",
__func__, (power_up ? "On":"Off"));
}
link_encoder_edp_wait_for_hpd_ready(enc110, true);
}
static void aux_initialize( static void aux_initialize(
struct dce110_link_encoder *enc110) struct dce110_link_encoder *enc110)
{ {
...@@ -674,16 +506,6 @@ static void aux_initialize( ...@@ -674,16 +506,6 @@ static void aux_initialize(
} }
/*todo: cloned in stream enc, fix*/
static bool is_panel_backlight_on(struct dce110_link_encoder *enc110)
{
uint32_t value;
REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value);
return value;
}
void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc, void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc,
bool exit_link_training_required) bool exit_link_training_required)
{ {
...@@ -718,69 +540,6 @@ void dce110_psr_program_secondary_packet(struct link_encoder *enc, ...@@ -718,69 +540,6 @@ void dce110_psr_program_secondary_packet(struct link_encoder *enc,
DP_SEC_GSP0_PRIORITY, 1); DP_SEC_GSP0_PRIORITY, 1);
} }
/*todo: cloned in stream enc, fix*/
/*
* @brief
* eDP only. Control the backlight of the eDP panel
*/
void dce110_link_encoder_edp_backlight_control(
struct link_encoder *enc,
bool enable)
{
struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
struct dc_context *ctx = enc110->base.ctx;
struct bp_transmitter_control cntl = { 0 };
if (dal_graphics_object_id_get_connector_id(enc110->base.connector)
!= CONNECTOR_ID_EDP) {
BREAK_TO_DEBUGGER();
return;
}
if (enable && is_panel_backlight_on(enc110)) {
dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
"%s: panel already powered up. Do nothing.\n",
__func__);
return;
}
if (!enable && !is_panel_backlight_on(enc110)) {
dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
"%s: panel already powered down. Do nothing.\n",
__func__);
return;
}
/* Send VBIOS command to control eDP panel backlight */
dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
"%s: backlight action: %s\n",
__func__, (enable ? "On":"Off"));
cntl.action = enable ?
TRANSMITTER_CONTROL_BACKLIGHT_ON :
TRANSMITTER_CONTROL_BACKLIGHT_OFF;
/*cntl.engine_id = ctx->engine;*/
cntl.transmitter = enc110->base.transmitter;
cntl.connector_obj_id = enc110->base.connector;
/*todo: unhardcode*/
cntl.lanes_number = LANE_COUNT_FOUR;
cntl.hpd_sel = enc110->base.hpd_source;
/* For eDP, the following delays might need to be considered
* after link training completed:
* idle period - min. accounts for required BS-Idle pattern,
* max. allows for source frame synchronization);
* 50 msec max. delay from valid video data from source
* to video on dislpay or backlight enable.
*
* Disable the delay for now.
* Enable it in the future if necessary.
*/
/* dc_service_sleep_in_milliseconds(50); */
link_transmitter_control(enc110, &cntl);
}
static bool is_dig_enabled(const struct dce110_link_encoder *enc110) static bool is_dig_enabled(const struct dce110_link_encoder *enc110)
{ {
uint32_t value; uint32_t value;
...@@ -998,11 +757,6 @@ void dce110_link_encoder_construct( ...@@ -998,11 +757,6 @@ void dce110_link_encoder_construct(
enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
} }
dm_logger_write(init_data->ctx->logger, LOG_I2C_AUX,
"Using channel: %s [%d]\n",
DECODE_CHANNEL_ID(init_data->channel),
init_data->channel);
/* Override features with DCE-specific values */ /* Override features with DCE-specific values */
if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info(
enc110->base.ctx->dc_bios, enc110->base.id, enc110->base.ctx->dc_bios, enc110->base.id,
...@@ -1092,7 +846,7 @@ void dce110_link_encoder_hw_init( ...@@ -1092,7 +846,7 @@ void dce110_link_encoder_hw_init(
ASSERT(result == BP_RESULT_OK); ASSERT(result == BP_RESULT_OK);
} else if (enc110->base.connector.id == CONNECTOR_ID_EDP) { } else if (enc110->base.connector.id == CONNECTOR_ID_EDP) {
enc->funcs->power_control(&enc110->base, true); ctx->dc->hwss.edp_power_control(enc, true);
} }
aux_initialize(enc110); aux_initialize(enc110);
...@@ -1279,7 +1033,8 @@ void dce110_link_encoder_enable_dp_mst_output( ...@@ -1279,7 +1033,8 @@ void dce110_link_encoder_enable_dp_mst_output(
*/ */
void dce110_link_encoder_disable_output( void dce110_link_encoder_disable_output(
struct link_encoder *enc, struct link_encoder *enc,
enum signal_type signal) enum signal_type signal,
struct dc_link *link)
{ {
struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
struct dc_context *ctx = enc110->base.ctx; struct dc_context *ctx = enc110->base.ctx;
...@@ -1291,7 +1046,7 @@ void dce110_link_encoder_disable_output( ...@@ -1291,7 +1046,7 @@ void dce110_link_encoder_disable_output(
return; return;
} }
if (enc110->base.connector.id == CONNECTOR_ID_EDP) if (enc110->base.connector.id == CONNECTOR_ID_EDP)
dce110_link_encoder_edp_backlight_control(enc, false); ctx->dc->hwss.edp_backlight_control(link, false);
/* Power-down RX and disable GPU PHY should be paired. /* Power-down RX and disable GPU PHY should be paired.
* Disabling PHY without powering down RX may cause * Disabling PHY without powering down RX may cause
* symbol lock loss, on which we will get DP Sink interrupt. */ * symbol lock loss, on which we will get DP Sink interrupt. */
......
...@@ -44,8 +44,6 @@ ...@@ -44,8 +44,6 @@
SRI(DC_HPD_CONTROL, HPD, id) SRI(DC_HPD_CONTROL, HPD, id)
#define LE_COMMON_REG_LIST_BASE(id) \ #define LE_COMMON_REG_LIST_BASE(id) \
SR(LVTMA_PWRSEQ_CNTL), \
SR(LVTMA_PWRSEQ_STATE), \
SR(DMCU_RAM_ACCESS_CTRL), \ SR(DMCU_RAM_ACCESS_CTRL), \
SR(DMCU_IRAM_RD_CTRL), \ SR(DMCU_IRAM_RD_CTRL), \
SR(DMCU_IRAM_RD_DATA), \ SR(DMCU_IRAM_RD_DATA), \
...@@ -104,8 +102,7 @@ ...@@ -104,8 +102,7 @@
LE_COMMON_REG_LIST_BASE(id), \ LE_COMMON_REG_LIST_BASE(id), \
SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \ SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id)
SR(DMU_MEM_PWR_CNTL)
struct dce110_link_enc_aux_registers { struct dce110_link_enc_aux_registers {
uint32_t AUX_CONTROL; uint32_t AUX_CONTROL;
...@@ -117,10 +114,6 @@ struct dce110_link_enc_hpd_registers { ...@@ -117,10 +114,6 @@ struct dce110_link_enc_hpd_registers {
}; };
struct dce110_link_enc_registers { struct dce110_link_enc_registers {
/* Backlight registers */
uint32_t LVTMA_PWRSEQ_CNTL;
uint32_t LVTMA_PWRSEQ_STATE;
/* DMCU registers */ /* DMCU registers */
uint32_t MASTER_COMM_DATA_REG1; uint32_t MASTER_COMM_DATA_REG1;
uint32_t MASTER_COMM_DATA_REG2; uint32_t MASTER_COMM_DATA_REG2;
...@@ -236,7 +229,8 @@ void dce110_link_encoder_enable_dp_mst_output( ...@@ -236,7 +229,8 @@ void dce110_link_encoder_enable_dp_mst_output(
/* disable PHY output */ /* disable PHY output */
void dce110_link_encoder_disable_output( void dce110_link_encoder_disable_output(
struct link_encoder *link_enc, struct link_encoder *link_enc,
enum signal_type signal); enum signal_type signal,
struct dc_link *link);
/* set DP lane settings */ /* set DP lane settings */
void dce110_link_encoder_dp_set_lane_settings( void dce110_link_encoder_dp_set_lane_settings(
...@@ -252,14 +246,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table( ...@@ -252,14 +246,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table(
struct link_encoder *enc, struct link_encoder *enc,
const struct link_mst_stream_allocation_table *table); const struct link_mst_stream_allocation_table *table);
void dce110_link_encoder_edp_backlight_control(
struct link_encoder *enc,
bool enable);
void dce110_link_encoder_edp_power_control(
struct link_encoder *enc,
bool power_up);
void dce110_link_encoder_connect_dig_be_to_fe( void dce110_link_encoder_connect_dig_be_to_fe(
struct link_encoder *enc, struct link_encoder *enc,
enum engine_id engine, enum engine_id engine,
......
...@@ -361,7 +361,7 @@ static void program_grph_pixel_format( ...@@ -361,7 +361,7 @@ static void program_grph_pixel_format(
enum surface_pixel_format format) enum surface_pixel_format format)
{ {
uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */ uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */
uint32_t grph_depth, grph_format; uint32_t grph_depth = 0, grph_format = 0;
uint32_t sign = 0, floating = 0; uint32_t sign = 0, floating = 0;
if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 || if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 ||
...@@ -685,9 +685,6 @@ void dce_mem_input_construct( ...@@ -685,9 +685,6 @@ void dce_mem_input_construct(
dce_mi->regs = regs; dce_mi->regs = regs;
dce_mi->shifts = mi_shift; dce_mi->shifts = mi_shift;
dce_mi->masks = mi_mask; dce_mi->masks = mi_mask;
dce_mi->base.mpcc_id = 0xf;
dce_mi->base.opp_id = 0xf;
} }
void dce112_mem_input_construct( void dce112_mem_input_construct(
......
...@@ -743,7 +743,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool) ...@@ -743,7 +743,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool)
*pool = NULL; *pool = NULL;
} }
enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state) enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps)
{ {
if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
......
...@@ -16,7 +16,7 @@ struct resource_pool *dce100_create_resource_pool( ...@@ -16,7 +16,7 @@ struct resource_pool *dce100_create_resource_pool(
uint8_t num_virtual_links, uint8_t num_virtual_links,
struct dc *dc); struct dc *dc);
enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state); enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps);
enum dc_status dce100_add_stream_to_ctx( enum dc_status dce100_add_stream_to_ctx(
struct dc *dc, struct dc *dc,
......
...@@ -514,7 +514,7 @@ void dce110_compressor_construct(struct dce110_compressor *compressor, ...@@ -514,7 +514,7 @@ void dce110_compressor_construct(struct dce110_compressor *compressor,
compressor->base.lpt_channels_num = 0; compressor->base.lpt_channels_num = 0;
compressor->base.attached_inst = 0; compressor->base.attached_inst = 0;
compressor->base.is_enabled = false; compressor->base.is_enabled = false;
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
compressor->base.funcs = &dce110_compressor_funcs; compressor->base.funcs = &dce110_compressor_funcs;
#endif #endif
......
...@@ -32,8 +32,9 @@ ...@@ -32,8 +32,9 @@
#include "dce110_hw_sequencer.h" #include "dce110_hw_sequencer.h"
#include "dce110_timing_generator.h" #include "dce110_timing_generator.h"
#include "dce/dce_hwseq.h" #include "dce/dce_hwseq.h"
#include "gpio_service_interface.h"
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
#include "dce110_compressor.h" #include "dce110_compressor.h"
#endif #endif
...@@ -45,10 +46,10 @@ ...@@ -45,10 +46,10 @@
#include "transform.h" #include "transform.h"
#include "stream_encoder.h" #include "stream_encoder.h"
#include "link_encoder.h" #include "link_encoder.h"
#include "link_hwss.h"
#include "clock_source.h" #include "clock_source.h"
#include "abm.h" #include "abm.h"
#include "audio.h" #include "audio.h"
#include "dce/dce_hwseq.h"
#include "reg_helper.h" #include "reg_helper.h"
/* include DCE11 register header files */ /* include DCE11 register header files */
...@@ -56,6 +57,24 @@ ...@@ -56,6 +57,24 @@
#include "dce/dce_11_0_sh_mask.h" #include "dce/dce_11_0_sh_mask.h"
#include "custom_float.h" #include "custom_float.h"
/*
* All values are in milliseconds;
* For eDP, after power-up/power/down,
* 300/500 msec max. delay from LCDVCC to black video generation
*/
#define PANEL_POWER_UP_TIMEOUT 300
#define PANEL_POWER_DOWN_TIMEOUT 500
#define HPD_CHECK_INTERVAL 10
#define CTX \
hws->ctx
#define REG(reg)\
hws->regs->reg
#undef FN
#define FN(reg_name, field_name) \
hws->shifts->field_name, hws->masks->field_name
struct dce110_hw_seq_reg_offsets { struct dce110_hw_seq_reg_offsets {
uint32_t crtc; uint32_t crtc;
}; };
...@@ -761,10 +780,216 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) ...@@ -761,10 +780,216 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
} }
void dce110_disable_stream(struct pipe_ctx *pipe_ctx) /*todo: cloned in stream enc, fix*/
static bool is_panel_backlight_on(struct dce_hwseq *hws)
{
uint32_t value;
REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value);
return value;
}
static bool is_panel_powered_on(struct dce_hwseq *hws)
{
uint32_t value;
REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value);
return value == 1;
}
static enum bp_result link_transmitter_control(
struct dc_bios *bios,
struct bp_transmitter_control *cntl)
{
enum bp_result result;
result = bios->funcs->transmitter_control(bios, cntl);
return result;
}
/*
* @brief
* eDP only.
*/
void hwss_edp_wait_for_hpd_ready(
struct link_encoder *enc,
bool power_up)
{
struct dc_context *ctx = enc->ctx;
struct graphics_object_id connector = enc->connector;
struct gpio *hpd;
bool edp_hpd_high = false;
uint32_t time_elapsed = 0;
uint32_t timeout = power_up ?
PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
if (dal_graphics_object_id_get_connector_id(connector)
!= CONNECTOR_ID_EDP) {
BREAK_TO_DEBUGGER();
return;
}
if (!power_up)
/*
* From KV, we will not HPD low after turning off VCC -
* instead, we will check the SW timer in power_up().
*/
return;
/*
* When we power on/off the eDP panel,
* we need to wait until SENSE bit is high/low.
*/
/* obtain HPD */
/* TODO what to do with this? */
hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
if (!hpd) {
BREAK_TO_DEBUGGER();
return;
}
dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
/* wait until timeout or panel detected */
do {
uint32_t detected = 0;
dal_gpio_get_value(hpd, &detected);
if (!(detected ^ power_up)) {
edp_hpd_high = true;
break;
}
msleep(HPD_CHECK_INTERVAL);
time_elapsed += HPD_CHECK_INTERVAL;
} while (time_elapsed < timeout);
dal_gpio_close(hpd);
dal_gpio_destroy_irq(&hpd);
if (false == edp_hpd_high) {
dm_logger_write(ctx->logger, LOG_ERROR,
"%s: wait timed out!\n", __func__);
}
}
void hwss_edp_power_control(
struct link_encoder *enc,
bool power_up)
{
struct dc_context *ctx = enc->ctx;
struct dce_hwseq *hwseq = ctx->dc->hwseq;
struct bp_transmitter_control cntl = { 0 };
enum bp_result bp_result;
if (dal_graphics_object_id_get_connector_id(enc->connector)
!= CONNECTOR_ID_EDP) {
BREAK_TO_DEBUGGER();
return;
}
if (power_up != is_panel_powered_on(hwseq)) {
/* Send VBIOS command to prompt eDP panel power */
dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
"%s: Panel Power action: %s\n",
__func__, (power_up ? "On":"Off"));
cntl.action = power_up ?
TRANSMITTER_CONTROL_POWER_ON :
TRANSMITTER_CONTROL_POWER_OFF;
cntl.transmitter = enc->transmitter;
cntl.connector_obj_id = enc->connector;
cntl.coherent = false;
cntl.lanes_number = LANE_COUNT_FOUR;
cntl.hpd_sel = enc->hpd_source;
bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
if (bp_result != BP_RESULT_OK)
dm_logger_write(ctx->logger, LOG_ERROR,
"%s: Panel Power bp_result: %d\n",
__func__, bp_result);
} else {
dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
"%s: Skipping Panel Power action: %s\n",
__func__, (power_up ? "On":"Off"));
}
hwss_edp_wait_for_hpd_ready(enc, true);
}
/*todo: cloned in stream enc, fix*/
/*
* @brief
* eDP only. Control the backlight of the eDP panel
*/
void hwss_edp_backlight_control(
struct dc_link *link,
bool enable)
{
struct dce_hwseq *hws = link->dc->hwseq;
struct dc_context *ctx = link->dc->ctx;
struct bp_transmitter_control cntl = { 0 };
if (dal_graphics_object_id_get_connector_id(link->link_id)
!= CONNECTOR_ID_EDP) {
BREAK_TO_DEBUGGER();
return;
}
if (enable && is_panel_backlight_on(hws)) {
dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
"%s: panel already powered up. Do nothing.\n",
__func__);
return;
}
/* Send VBIOS command to control eDP panel backlight */
dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
"%s: backlight action: %s\n",
__func__, (enable ? "On":"Off"));
cntl.action = enable ?
TRANSMITTER_CONTROL_BACKLIGHT_ON :
TRANSMITTER_CONTROL_BACKLIGHT_OFF;
/*cntl.engine_id = ctx->engine;*/
cntl.transmitter = link->link_enc->transmitter;
cntl.connector_obj_id = link->link_enc->connector;
/*todo: unhardcode*/
cntl.lanes_number = LANE_COUNT_FOUR;
cntl.hpd_sel = link->link_enc->hpd_source;
/* For eDP, the following delays might need to be considered
* after link training completed:
* idle period - min. accounts for required BS-Idle pattern,
* max. allows for source frame synchronization);
* 50 msec max. delay from valid video data from source
* to video on dislpay or backlight enable.
*
* Disable the delay for now.
* Enable it in the future if necessary.
*/
/* dc_service_sleep_in_milliseconds(50); */
link_transmitter_control(link->dc->ctx->dc_bios, &cntl);
}
void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option)
{ {
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;
struct dc *dc = pipe_ctx->stream->ctx->dc;
if (pipe_ctx->stream_res.audio) { if (pipe_ctx->stream_res.audio) {
pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
...@@ -775,6 +1000,13 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) ...@@ -775,6 +1000,13 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
else else
pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc);
/*don't free audio if it is from retrain or internal disable stream*/
if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) {
/*we have to dynamic arbitrate the audio endpoints*/
pipe_ctx->stream_res.audio = NULL;
/*we free the resource, need reset is_audio_acquired*/
update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
}
/* TODO: notify audio driver for if audio modes list changed /* TODO: notify audio driver for if audio modes list changed
* add audio mode list change flag */ * add audio mode list change flag */
...@@ -798,7 +1030,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) ...@@ -798,7 +1030,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
/* blank at encoder level */ /* blank at encoder level */
if (dc_is_dp_signal(pipe_ctx->stream->signal)) { if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP) if (pipe_ctx->stream->sink->link->connector_signal == SIGNAL_TYPE_EDP)
link->link_enc->funcs->backlight_control(link->link_enc, false); hwss_edp_backlight_control(link, false);
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);
} }
link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc->funcs->connect_dig_be_to_fe(
...@@ -820,7 +1052,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, ...@@ -820,7 +1052,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
params.link_settings.link_rate = link_settings->link_rate; params.link_settings.link_rate = link_settings->link_rate;
pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, &params); pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, &params);
if (link->connector_signal == SIGNAL_TYPE_EDP) if (link->connector_signal == SIGNAL_TYPE_EDP)
link->link_enc->funcs->backlight_control(link->link_enc, true); hwss_edp_backlight_control(link, true);
} }
...@@ -1132,33 +1364,21 @@ static enum dc_status apply_single_controller_ctx_to_hw( ...@@ -1132,33 +1364,21 @@ static enum dc_status apply_single_controller_ctx_to_hw(
resource_build_info_frame(pipe_ctx); resource_build_info_frame(pipe_ctx);
dce110_update_info_frame(pipe_ctx); dce110_update_info_frame(pipe_ctx);
if (!pipe_ctx_old->stream) { if (!pipe_ctx_old->stream) {
core_link_enable_stream(context, pipe_ctx); if (!pipe_ctx->stream->dpms_off)
core_link_enable_stream(context, pipe_ctx);
if (dc_is_dp_signal(pipe_ctx->stream->signal))
dce110_unblank_stream(pipe_ctx,
&stream->sink->link->cur_link_settings);
} }
pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
/* program_scaler and allocate_mem_input are not new asic */
if ((!pipe_ctx_old ||
memcmp(&pipe_ctx_old->plane_res.scl_data, &pipe_ctx->plane_res.scl_data,
sizeof(struct scaler_data)) != 0) &&
pipe_ctx->plane_state) {
program_scaler(dc, pipe_ctx);
}
/* mst support - use total stream count */ /* mst support - use total stream count */
#if defined(CONFIG_DRM_AMD_DC_DCN1_0) if (pipe_ctx->plane_res.mi != NULL) {
if (pipe_ctx->plane_res.mi->funcs->allocate_mem_input != NULL)
#endif
pipe_ctx->plane_res.mi->funcs->allocate_mem_input( pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
pipe_ctx->plane_res.mi, pipe_ctx->plane_res.mi,
stream->timing.h_total, stream->timing.h_total,
stream->timing.v_total, stream->timing.v_total,
stream->timing.pix_clk_khz, stream->timing.pix_clk_khz,
context->stream_count); context->stream_count);
}
pipe_ctx->stream->sink->link->psr_enabled = false; pipe_ctx->stream->sink->link->psr_enabled = false;
...@@ -1171,6 +1391,16 @@ static void power_down_encoders(struct dc *dc) ...@@ -1171,6 +1391,16 @@ static void power_down_encoders(struct dc *dc)
{ {
int i; int i;
enum connector_id connector_id; enum connector_id connector_id;
enum signal_type signal = SIGNAL_TYPE_NONE;
/* do not know BIOS back-front mapping, simply blank all. It will not
* hurt for non-DP
*/
for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
dc->res_pool->stream_enc[i]->funcs->dp_blank(
dc->res_pool->stream_enc[i]);
}
for (i = 0; i < dc->link_count; i++) { for (i = 0; i < dc->link_count; i++) {
connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id); connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id);
if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
...@@ -1178,10 +1408,12 @@ static void power_down_encoders(struct dc *dc) ...@@ -1178,10 +1408,12 @@ static void power_down_encoders(struct dc *dc)
if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) if (!dc->links[i]->wa_flags.dp_keep_receiver_powered)
dp_receiver_power_ctrl(dc->links[i], false); dp_receiver_power_ctrl(dc->links[i], false);
if (connector_id == CONNECTOR_ID_EDP)
signal = SIGNAL_TYPE_EDP;
} }
dc->links[i]->link_enc->funcs->disable_output( dc->links[i]->link_enc->funcs->disable_output(
dc->links[i]->link_enc, SIGNAL_TYPE_NONE); dc->links[i]->link_enc, signal, dc->links[i]);
} }
} }
...@@ -1218,7 +1450,7 @@ static void power_down_all_hw_blocks(struct dc *dc) ...@@ -1218,7 +1450,7 @@ static void power_down_all_hw_blocks(struct dc *dc)
power_down_clock_sources(dc); power_down_clock_sources(dc);
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
if (dc->fbc_compressor) if (dc->fbc_compressor)
dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
#endif #endif
...@@ -1325,7 +1557,7 @@ static void set_safe_displaymarks( ...@@ -1325,7 +1557,7 @@ static void set_safe_displaymarks(
SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK }; SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
if (res_ctx->pipe_ctx[i].stream == NULL) if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL)
continue; continue;
res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks( res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks(
...@@ -1334,6 +1566,7 @@ static void set_safe_displaymarks( ...@@ -1334,6 +1566,7 @@ static void set_safe_displaymarks(
max_marks, max_marks,
max_marks, max_marks,
MAX_WATERMARK); MAX_WATERMARK);
if (i == underlay_idx) if (i == underlay_idx)
res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks( res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks(
res_ctx->pipe_ctx[i].plane_res.mi, res_ctx->pipe_ctx[i].plane_res.mi,
...@@ -1341,6 +1574,7 @@ static void set_safe_displaymarks( ...@@ -1341,6 +1574,7 @@ static void set_safe_displaymarks(
max_marks, max_marks,
max_marks, max_marks,
MAX_WATERMARK); MAX_WATERMARK);
} }
} }
...@@ -1391,7 +1625,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx, ...@@ -1391,7 +1625,7 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
if (events->cursor_update) if (events->cursor_update)
value |= 0x2; value |= 0x2;
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
value |= 0x84; value |= 0x84;
#endif #endif
...@@ -1521,7 +1755,7 @@ static void apply_min_clocks( ...@@ -1521,7 +1755,7 @@ static void apply_min_clocks(
} }
} }
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
/* /*
* Check if FBC can be enabled * Check if FBC can be enabled
...@@ -1644,7 +1878,10 @@ static void dce110_reset_hw_ctx_wrap( ...@@ -1644,7 +1878,10 @@ static void dce110_reset_hw_ctx_wrap(
pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) { pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
struct clock_source *old_clk = pipe_ctx_old->clock_source; struct clock_source *old_clk = pipe_ctx_old->clock_source;
core_link_disable_stream(pipe_ctx_old); /* disable already, no need to disable again */
if (pipe_ctx->stream && !pipe_ctx->stream->dpms_off)
core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE);
pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true);
if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) {
dm_error("DC: failed to blank crtc!\n"); dm_error("DC: failed to blank crtc!\n");
...@@ -1713,7 +1950,7 @@ enum dc_status dce110_apply_ctx_to_hw( ...@@ -1713,7 +1950,7 @@ enum dc_status dce110_apply_ctx_to_hw(
set_safe_displaymarks(&context->res_ctx, dc->res_pool); set_safe_displaymarks(&context->res_ctx, dc->res_pool);
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
if (dc->fbc_compressor) if (dc->fbc_compressor)
dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
#endif #endif
...@@ -1889,6 +2126,7 @@ enum dc_status dce110_apply_ctx_to_hw( ...@@ -1889,6 +2126,7 @@ enum dc_status dce110_apply_ctx_to_hw(
return status; return status;
} }
/* pplib is notified if disp_num changed */
dc->hwss.set_bandwidth(dc, context, true); dc->hwss.set_bandwidth(dc, context, true);
/* to save power */ /* to save power */
...@@ -1896,7 +2134,7 @@ enum dc_status dce110_apply_ctx_to_hw( ...@@ -1896,7 +2134,7 @@ enum dc_status dce110_apply_ctx_to_hw(
dcb->funcs->set_scratch_critical_state(dcb, false); dcb->funcs->set_scratch_critical_state(dcb, false);
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
if (dc->fbc_compressor) if (dc->fbc_compressor)
enable_fbc(dc, context); enable_fbc(dc, context);
...@@ -2305,7 +2543,7 @@ static void init_hw(struct dc *dc) ...@@ -2305,7 +2543,7 @@ static void init_hw(struct dc *dc)
abm->funcs->init_backlight(abm); abm->funcs->init_backlight(abm);
abm->funcs->abm_init(abm); abm->funcs->abm_init(abm);
} }
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
if (dc->fbc_compressor) if (dc->fbc_compressor)
dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor); dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor);
#endif #endif
...@@ -2490,6 +2728,8 @@ static void dce110_program_front_end_for_pipe( ...@@ -2490,6 +2728,8 @@ static void dce110_program_front_end_for_pipe(
struct dc_plane_state *plane_state = pipe_ctx->plane_state; struct dc_plane_state *plane_state = pipe_ctx->plane_state;
struct xfm_grph_csc_adjustment adjust; struct xfm_grph_csc_adjustment adjust;
struct out_csc_color_matrix tbl_entry; struct out_csc_color_matrix tbl_entry;
struct pipe_ctx *cur_pipe_ctx =
&dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
unsigned int i; unsigned int i;
memset(&tbl_entry, 0, sizeof(tbl_entry)); memset(&tbl_entry, 0, sizeof(tbl_entry));
...@@ -2553,6 +2793,15 @@ static void dce110_program_front_end_for_pipe( ...@@ -2553,6 +2793,15 @@ static void dce110_program_front_end_for_pipe(
program_scaler(dc, pipe_ctx); program_scaler(dc, pipe_ctx);
#if defined(CONFIG_DRM_AMD_DC_FBC)
if (dc->fbc_compressor && old_pipe->stream) {
if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
else
enable_fbc(dc, dc->current_state);
}
#endif
mi->funcs->mem_input_program_surface_config( mi->funcs->mem_input_program_surface_config(
mi, mi,
plane_state->format, plane_state->format,
...@@ -2571,6 +2820,14 @@ static void dce110_program_front_end_for_pipe( ...@@ -2571,6 +2820,14 @@ static void dce110_program_front_end_for_pipe(
&plane_state->tiling_info, &plane_state->tiling_info,
plane_state->rotation); plane_state->rotation);
/* Moved programming gamma from dc to hwss */
if (cur_pipe_ctx->plane_state != pipe_ctx->plane_state) {
dc->hwss.set_input_transfer_func(
pipe_ctx, pipe_ctx->plane_state);
dc->hwss.set_output_transfer_func(
pipe_ctx, pipe_ctx->stream);
}
dm_logger_write(dc->ctx->logger, LOG_SURFACE, dm_logger_write(dc->ctx->logger, LOG_SURFACE,
"Pipe:%d 0x%x: addr hi:0x%x, " "Pipe:%d 0x%x: addr hi:0x%x, "
"addr low:0x%x, " "addr low:0x%x, "
...@@ -2683,7 +2940,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, ...@@ -2683,7 +2940,7 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
} }
} }
static void ready_shared_resources(struct dc *dc) {} static void ready_shared_resources(struct dc *dc, struct dc_state *context) {}
static void optimize_shared_resources(struct dc *dc) {} static void optimize_shared_resources(struct dc *dc) {}
...@@ -2720,7 +2977,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { ...@@ -2720,7 +2977,8 @@ static const struct hw_sequencer_funcs dce110_funcs = {
.wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
.ready_shared_resources = ready_shared_resources, .ready_shared_resources = ready_shared_resources,
.optimize_shared_resources = optimize_shared_resources, .optimize_shared_resources = optimize_shared_resources,
.edp_backlight_control = hwss_edp_backlight_control,
.edp_power_control = hwss_edp_power_control,
}; };
void dce110_hw_sequencer_construct(struct dc *dc) void dce110_hw_sequencer_construct(struct dc *dc)
......
...@@ -47,7 +47,7 @@ void dce110_set_displaymarks( ...@@ -47,7 +47,7 @@ void dce110_set_displaymarks(
void dce110_enable_stream(struct pipe_ctx *pipe_ctx); void dce110_enable_stream(struct pipe_ctx *pipe_ctx);
void dce110_disable_stream(struct pipe_ctx *pipe_ctx); void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option);
void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link_settings *link_settings); struct dc_link_settings *link_settings);
...@@ -68,5 +68,14 @@ void dce110_fill_display_configs( ...@@ -68,5 +68,14 @@ void dce110_fill_display_configs(
uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context);
void dp_receiver_power_ctrl(struct dc_link *link, bool on); void dp_receiver_power_ctrl(struct dc_link *link, bool on);
void hwss_edp_power_control(
struct link_encoder *enc,
bool power_up);
void hwss_edp_backlight_control(
struct dc_link *link,
bool enable);
#endif /* __DC_HWSS_DCE110_H__ */ #endif /* __DC_HWSS_DCE110_H__ */
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#include "dce/dce_abm.h" #include "dce/dce_abm.h"
#include "dce/dce_dmcu.h" #include "dce/dce_dmcu.h"
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
#include "dce110/dce110_compressor.h" #include "dce110/dce110_compressor.h"
#endif #endif
...@@ -849,7 +849,7 @@ static bool dce110_validate_bandwidth( ...@@ -849,7 +849,7 @@ static bool dce110_validate_bandwidth(
static bool dce110_validate_surface_sets( static bool dce110_validate_surface_sets(
struct dc_state *context) struct dc_state *context)
{ {
int i; int i, j;
for (i = 0; i < context->stream_count; i++) { for (i = 0; i < context->stream_count; i++) {
if (context->stream_status[i].plane_count == 0) if (context->stream_status[i].plane_count == 0)
...@@ -858,14 +858,27 @@ static bool dce110_validate_surface_sets( ...@@ -858,14 +858,27 @@ static bool dce110_validate_surface_sets(
if (context->stream_status[i].plane_count > 2) if (context->stream_status[i].plane_count > 2)
return false; return false;
if ((context->stream_status[i].plane_states[i]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) && for (j = 0; j < context->stream_status[i].plane_count; j++) {
(context->stream_status[i].plane_states[i]->src_rect.width > 1920 || struct dc_plane_state *plane =
context->stream_status[i].plane_states[i]->src_rect.height > 1080)) context->stream_status[i].plane_states[j];
return false;
/* irrespective of plane format, stream should be RGB encoded */ /* underlay validation */
if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB) if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
return false;
if ((plane->src_rect.width > 1920 ||
plane->src_rect.height > 1080))
return false;
/* irrespective of plane format,
* stream should be RGB encoded
*/
if (context->streams[i]->timing.pixel_encoding
!= PIXEL_ENCODING_RGB)
return false;
}
}
} }
return true; return true;
...@@ -1266,7 +1279,7 @@ static bool construct( ...@@ -1266,7 +1279,7 @@ static bool construct(
} }
} }
#ifdef ENABLE_FBC #if defined(CONFIG_DRM_AMD_DC_FBC)
dc->fbc_compressor = dce110_compressor_create(ctx); dc->fbc_compressor = dce110_compressor_create(ctx);
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \
dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \ dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \
dcn10_mem_input.o dcn10_mpc.o \ dcn10_hubp.o dcn10_mpc.o \
dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_dpp_cm_helper.o dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o
AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10))
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include "reg_helper.h" #include "reg_helper.h"
#include "dcn10_dpp.h" #include "dcn10_dpp.h"
#include "dcn10_dpp_cm_helper.h" #include "dcn10_cm_common.h"
#define REG(reg) reg #define REG(reg) reg
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
* *
*/ */
#ifndef __DAL_DPP_DCN10_CM_HELPER_H__ #ifndef __DAL_DCN10_CM_COMMON_H__
#define __DAL_DPP_DCN10_CM_HELPER_H__ #define __DAL_DCN10_CM_COMMON_H__
#define TF_HELPER_REG_FIELD_LIST(type) \ #define TF_HELPER_REG_FIELD_LIST(type) \
type exp_region0_lut_offset; \ type exp_region0_lut_offset; \
......
...@@ -39,14 +39,14 @@ ...@@ -39,14 +39,14 @@
#define BLACK_OFFSET_CBCR 0x8000 #define BLACK_OFFSET_CBCR 0x8000
#define REG(reg)\ #define REG(reg)\
xfm->tf_regs->reg dpp->tf_regs->reg
#define CTX \ #define CTX \
xfm->base.ctx dpp->base.ctx
#undef FN #undef FN
#define FN(reg_name, field_name) \ #define FN(reg_name, field_name) \
xfm->tf_shift->field_name, xfm->tf_mask->field_name dpp->tf_shift->field_name, dpp->tf_mask->field_name
enum pixel_format_description { enum pixel_format_description {
PIXEL_FORMAT_FIXED = 0, PIXEL_FORMAT_FIXED = 0,
...@@ -99,7 +99,7 @@ enum gamut_remap_select { ...@@ -99,7 +99,7 @@ enum gamut_remap_select {
}; };
/* Program gamut remap in bypass mode */ /* Program gamut remap in bypass mode */
void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) void dpp_set_gamut_remap_bypass(struct dcn10_dpp *dpp)
{ {
REG_SET(CM_GAMUT_REMAP_CONTROL, 0, REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
CM_GAMUT_REMAP_MODE, 0); CM_GAMUT_REMAP_MODE, 0);
...@@ -110,7 +110,7 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm) ...@@ -110,7 +110,7 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm)
bool dpp_get_optimal_number_of_taps( bool dpp_get_optimal_number_of_taps(
struct transform *xfm, struct dpp *dpp,
struct scaler_data *scl_data, struct scaler_data *scl_data,
const struct scaling_taps *in_taps) const struct scaling_taps *in_taps)
{ {
...@@ -154,28 +154,29 @@ bool dpp_get_optimal_number_of_taps( ...@@ -154,28 +154,29 @@ bool dpp_get_optimal_number_of_taps(
else else
scl_data->taps.h_taps_c = in_taps->h_taps_c; scl_data->taps.h_taps_c = in_taps->h_taps_c;
if (!xfm->ctx->dc->debug.always_scale) { if (!dpp->ctx->dc->debug.always_scale) {
if (IDENTITY_RATIO(scl_data->ratios.horz)) if (IDENTITY_RATIO(scl_data->ratios.horz))
scl_data->taps.h_taps = 1; scl_data->taps.h_taps = 1;
if (IDENTITY_RATIO(scl_data->ratios.vert)) if (IDENTITY_RATIO(scl_data->ratios.vert))
scl_data->taps.v_taps = 1; scl_data->taps.v_taps = 1;
if (IDENTITY_RATIO(scl_data->ratios.horz_c)) /*
scl_data->taps.h_taps_c = 1; * Spreadsheet doesn't handle taps_c is one properly,
if (IDENTITY_RATIO(scl_data->ratios.vert_c)) * need to force Chroma to always be scaled to pass
scl_data->taps.v_taps_c = 1; * bandwidth validation.
*/
} }
return true; return true;
} }
void dpp_reset(struct transform *xfm_base) void dpp_reset(struct dpp *dpp_base)
{ {
struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
xfm->filter_h_c = NULL; dpp->filter_h_c = NULL;
xfm->filter_v_c = NULL; dpp->filter_v_c = NULL;
xfm->filter_h = NULL; dpp->filter_h = NULL;
xfm->filter_v = NULL; dpp->filter_v = NULL;
/* set boundary mode to 0 */ /* set boundary mode to 0 */
REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0); REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0);
...@@ -183,28 +184,28 @@ void dpp_reset(struct transform *xfm_base) ...@@ -183,28 +184,28 @@ void dpp_reset(struct transform *xfm_base)
static void dcn10_dpp_cm_set_regamma_pwl( static void dpp1_cm_set_regamma_pwl(
struct transform *xfm_base, const struct pwl_params *params) struct dpp *dpp_base, const struct pwl_params *params)
{ {
struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
dcn10_dpp_cm_power_on_regamma_lut(xfm_base, true); dpp1_cm_power_on_regamma_lut(dpp_base, true);
dcn10_dpp_cm_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe); dpp1_cm_configure_regamma_lut(dpp_base, dpp->is_write_to_ram_a_safe);
if (xfm->is_write_to_ram_a_safe) if (dpp->is_write_to_ram_a_safe)
dcn10_dpp_cm_program_regamma_luta_settings(xfm_base, params); dpp1_cm_program_regamma_luta_settings(dpp_base, params);
else else
dcn10_dpp_cm_program_regamma_lutb_settings(xfm_base, params); dpp1_cm_program_regamma_lutb_settings(dpp_base, params);
dcn10_dpp_cm_program_regamma_lut( dpp1_cm_program_regamma_lut(
xfm_base, params->rgb_resulted, params->hw_points_num); dpp_base, params->rgb_resulted, params->hw_points_num);
} }
static void dcn10_dpp_cm_set_regamma_mode( static void dpp1_cm_set_regamma_mode(
struct transform *xfm_base, struct dpp *dpp_base,
enum opp_regamma mode) enum opp_regamma mode)
{ {
struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
uint32_t re_mode = 0; uint32_t re_mode = 0;
uint32_t obuf_bypass = 0; /* need for pipe split */ uint32_t obuf_bypass = 0; /* need for pipe split */
uint32_t obuf_hupscale = 0; uint32_t obuf_hupscale = 0;
...@@ -220,8 +221,8 @@ static void dcn10_dpp_cm_set_regamma_mode( ...@@ -220,8 +221,8 @@ static void dcn10_dpp_cm_set_regamma_mode(
re_mode = 2; re_mode = 2;
break; break;
case OPP_REGAMMA_USER: case OPP_REGAMMA_USER:
re_mode = xfm->is_write_to_ram_a_safe ? 3 : 4; re_mode = dpp->is_write_to_ram_a_safe ? 3 : 4;
xfm->is_write_to_ram_a_safe = !xfm->is_write_to_ram_a_safe; dpp->is_write_to_ram_a_safe = !dpp->is_write_to_ram_a_safe;
break; break;
default: default:
break; break;
...@@ -233,7 +234,7 @@ static void dcn10_dpp_cm_set_regamma_mode( ...@@ -233,7 +234,7 @@ static void dcn10_dpp_cm_set_regamma_mode(
OBUF_H_2X_UPSCALE_EN, obuf_hupscale); OBUF_H_2X_UPSCALE_EN, obuf_hupscale);
} }
static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ static void dpp1_setup_format_flags(enum surface_pixel_format input_format,\
enum pixel_format_description *fmt) enum pixel_format_description *fmt)
{ {
...@@ -246,11 +247,11 @@ static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\ ...@@ -246,11 +247,11 @@ static void ippn10_setup_format_flags(enum surface_pixel_format input_format,\
*fmt = PIXEL_FORMAT_FIXED; *fmt = PIXEL_FORMAT_FIXED;
} }
static void ippn10_set_degamma_format_float( static void dpp1_set_degamma_format_float(
struct transform *xfm_base, struct dpp *dpp_base,
bool is_float) bool is_float)
{ {
struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
if (is_float) { if (is_float) {
REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3); REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 3);
...@@ -261,8 +262,8 @@ static void ippn10_set_degamma_format_float( ...@@ -261,8 +262,8 @@ static void ippn10_set_degamma_format_float(
} }
} }
void ippn10_cnv_setup ( void dpp1_cnv_setup (
struct transform *xfm_base, struct dpp *dpp_base,
enum surface_pixel_format input_format, enum surface_pixel_format input_format,
enum expansion_mode mode) enum expansion_mode mode)
{ {
...@@ -272,10 +273,10 @@ void ippn10_cnv_setup ( ...@@ -272,10 +273,10 @@ void ippn10_cnv_setup (
enum dc_color_space color_space; enum dc_color_space color_space;
enum dcn10_input_csc_select select; enum dcn10_input_csc_select select;
bool is_float; bool is_float;
struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base); struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
bool force_disable_cursor = false; bool force_disable_cursor = false;
ippn10_setup_format_flags(input_format, &fmt); dpp1_setup_format_flags(input_format, &fmt);
alpha_en = 1; alpha_en = 1;
pixel_format = 0; pixel_format = 0;
color_space = COLOR_SPACE_SRGB; color_space = COLOR_SPACE_SRGB;
...@@ -303,7 +304,7 @@ void ippn10_cnv_setup ( ...@@ -303,7 +304,7 @@ void ippn10_cnv_setup (
break; break;
} }
ippn10_set_degamma_format_float(xfm_base, is_float); dpp1_set_degamma_format_float(dpp_base, is_float);
switch (input_format) { switch (input_format) {
case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
...@@ -361,7 +362,7 @@ void ippn10_cnv_setup ( ...@@ -361,7 +362,7 @@ void ippn10_cnv_setup (
CNVC_SURFACE_PIXEL_FORMAT, pixel_format); CNVC_SURFACE_PIXEL_FORMAT, pixel_format);
REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en); REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en);
ippn10_program_input_csc(xfm_base, color_space, select); dpp1_program_input_csc(dpp_base, color_space, select);
if (force_disable_cursor) { if (force_disable_cursor) {
REG_UPDATE(CURSOR_CONTROL, REG_UPDATE(CURSOR_CONTROL,
...@@ -371,54 +372,110 @@ void ippn10_cnv_setup ( ...@@ -371,54 +372,110 @@ void ippn10_cnv_setup (
} }
} }
static const struct transform_funcs dcn10_dpp_funcs = { void dpp1_set_cursor_attributes(
.transform_reset = dpp_reset, struct dpp *dpp_base,
.transform_set_scaler = dcn10_dpp_dscl_set_scaler_manual_scale, const struct dc_cursor_attributes *attr)
.transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps, {
.transform_set_gamut_remap = dcn10_dpp_cm_set_gamut_remap, struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
.opp_set_csc_adjustment = dcn10_dpp_cm_set_output_csc_adjustment, enum dc_cursor_color_format color_format = attr->color_format;
.opp_set_csc_default = dcn10_dpp_cm_set_output_csc_default,
.opp_power_on_regamma_lut = dcn10_dpp_cm_power_on_regamma_lut, REG_UPDATE_2(CURSOR0_CONTROL,
.opp_program_regamma_lut = dcn10_dpp_cm_program_regamma_lut, CUR0_MODE, color_format,
.opp_configure_regamma_lut = dcn10_dpp_cm_configure_regamma_lut, CUR0_EXPANSION_MODE, 0);
.opp_program_regamma_lutb_settings = dcn10_dpp_cm_program_regamma_lutb_settings,
.opp_program_regamma_luta_settings = dcn10_dpp_cm_program_regamma_luta_settings, if (color_format == CURSOR_MODE_MONO) {
.opp_program_regamma_pwl = dcn10_dpp_cm_set_regamma_pwl, /* todo: clarify what to program these to */
.opp_set_regamma_mode = dcn10_dpp_cm_set_regamma_mode, REG_UPDATE(CURSOR0_COLOR0,
.ipp_set_degamma = ippn10_set_degamma, CUR0_COLOR0, 0x00000000);
.ipp_program_input_lut = ippn10_program_input_lut, REG_UPDATE(CURSOR0_COLOR1,
.ipp_program_degamma_pwl = ippn10_set_degamma_pwl, CUR0_COLOR1, 0xFFFFFFFF);
.ipp_setup = ippn10_cnv_setup, }
.ipp_full_bypass = ippn10_full_bypass,
/* TODO: Fixed vs float */
REG_UPDATE_3(FORMAT_CONTROL,
CNVC_BYPASS, 0,
FORMAT_CONTROL__ALPHA_EN, 1,
FORMAT_EXPANSION_MODE, 0);
}
void dpp1_set_cursor_position(
struct dpp *dpp_base,
const struct dc_cursor_position *pos,
const struct dc_cursor_mi_param *param,
uint32_t width)
{
struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start;
uint32_t cur_en = pos->enable ? 1 : 0;
if (src_x_offset >= (int)param->viewport_width)
cur_en = 0; /* not visible beyond right edge*/
if (src_x_offset + (int)width < 0)
cur_en = 0; /* not visible beyond left edge*/
REG_UPDATE(CURSOR0_CONTROL,
CUR0_ENABLE, cur_en);
}
static const struct dpp_funcs dcn10_dpp_funcs = {
.dpp_reset = dpp_reset,
.dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale,
.dpp_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps,
.dpp_set_gamut_remap = dpp1_cm_set_gamut_remap,
.opp_set_csc_adjustment = dpp1_cm_set_output_csc_adjustment,
.opp_set_csc_default = dpp1_cm_set_output_csc_default,
.opp_power_on_regamma_lut = dpp1_cm_power_on_regamma_lut,
.opp_program_regamma_lut = dpp1_cm_program_regamma_lut,
.opp_configure_regamma_lut = dpp1_cm_configure_regamma_lut,
.opp_program_regamma_lutb_settings = dpp1_cm_program_regamma_lutb_settings,
.opp_program_regamma_luta_settings = dpp1_cm_program_regamma_luta_settings,
.opp_program_regamma_pwl = dpp1_cm_set_regamma_pwl,
.opp_set_regamma_mode = dpp1_cm_set_regamma_mode,
.ipp_set_degamma = dpp1_set_degamma,
.ipp_program_input_lut = dpp1_program_input_lut,
.ipp_program_degamma_pwl = dpp1_set_degamma_pwl,
.ipp_setup = dpp1_cnv_setup,
.ipp_full_bypass = dpp1_full_bypass,
.set_cursor_attributes = dpp1_set_cursor_attributes,
.set_cursor_position = dpp1_set_cursor_position,
}; };
static struct dpp_caps dcn10_dpp_cap = {
.dscl_data_proc_format = DSCL_DATA_PRCESSING_FIXED_FORMAT,
.dscl_calc_lb_num_partitions = dpp1_dscl_calc_lb_num_partitions,
};
/*****************************************/ /*****************************************/
/* Constructor, Destructor */ /* Constructor, Destructor */
/*****************************************/ /*****************************************/
void dcn10_dpp_construct( void dpp1_construct(
struct dcn10_dpp *xfm, struct dcn10_dpp *dpp,
struct dc_context *ctx, struct dc_context *ctx,
uint32_t inst, uint32_t inst,
const struct dcn_dpp_registers *tf_regs, const struct dcn_dpp_registers *tf_regs,
const struct dcn_dpp_shift *tf_shift, const struct dcn_dpp_shift *tf_shift,
const struct dcn_dpp_mask *tf_mask) const struct dcn_dpp_mask *tf_mask)
{ {
xfm->base.ctx = ctx; dpp->base.ctx = ctx;
xfm->base.inst = inst; dpp->base.inst = inst;
xfm->base.funcs = &dcn10_dpp_funcs; dpp->base.funcs = &dcn10_dpp_funcs;
dpp->base.caps = &dcn10_dpp_cap;
xfm->tf_regs = tf_regs; dpp->tf_regs = tf_regs;
xfm->tf_shift = tf_shift; dpp->tf_shift = tf_shift;
xfm->tf_mask = tf_mask; dpp->tf_mask = tf_mask;
xfm->lb_pixel_depth_supported = dpp->lb_pixel_depth_supported =
LB_PIXEL_DEPTH_18BPP | LB_PIXEL_DEPTH_18BPP |
LB_PIXEL_DEPTH_24BPP | LB_PIXEL_DEPTH_24BPP |
LB_PIXEL_DEPTH_30BPP; LB_PIXEL_DEPTH_30BPP;
xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY; dpp->lb_bits_per_entry = LB_BITS_PER_ENTRY;
xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/ dpp->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/
} }
...@@ -25,10 +25,10 @@ ...@@ -25,10 +25,10 @@
#ifndef __DAL_DPP_DCN10_H__ #ifndef __DAL_DPP_DCN10_H__
#define __DAL_DPP_DCN10_H__ #define __DAL_DPP_DCN10_H__
#include "transform.h" #include "dpp.h"
#define TO_DCN10_DPP(transform)\ #define TO_DCN10_DPP(dpp)\
container_of(transform, struct dcn10_dpp, base) container_of(dpp, struct dcn10_dpp, base)
/* TODO: Use correct number of taps. Using polaris values for now */ /* TODO: Use correct number of taps. Using polaris values for now */
#define LB_TOTAL_NUMBER_OF_ENTRIES 5124 #define LB_TOTAL_NUMBER_OF_ENTRIES 5124
...@@ -112,7 +112,9 @@ ...@@ -112,7 +112,9 @@
SRI(CM_DGAM_CONTROL, CM, id), \ SRI(CM_DGAM_CONTROL, CM, id), \
SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(FORMAT_CONTROL, CNVC_CFG, id), \
SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \
SRI(CURSOR0_CONTROL, CNVC_CUR, id) SRI(CURSOR0_CONTROL, CNVC_CUR, id), \
SRI(CURSOR0_COLOR0, CNVC_CUR, id), \
SRI(CURSOR0_COLOR1, CNVC_CUR, id)
...@@ -162,7 +164,8 @@ ...@@ -162,7 +164,8 @@
SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \ SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \
SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \ SRI(CM_IGAM_LUT_RW_INDEX, CM, id), \
SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \ SRI(CM_IGAM_LUT_SEQ_COLOR, CM, id), \
SRI(CURSOR_CONTROL, CURSOR, id) SRI(CURSOR_CONTROL, CURSOR, id), \
SRI(CM_CMOUT_CONTROL, CM, id)
#define TF_REG_LIST_SH_MASK_DCN(mask_sh)\ #define TF_REG_LIST_SH_MASK_DCN(mask_sh)\
...@@ -302,7 +305,9 @@ ...@@ -302,7 +305,9 @@
TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \ TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \
TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \
TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \ TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \
TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh) TF_SF(CNVC_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \
TF_SF(CNVC_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \
TF_SF(CNVC_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh)
#define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\ #define TF_REG_LIST_SH_MASK_DCN10(mask_sh)\
TF_REG_LIST_SH_MASK_DCN(mask_sh),\ TF_REG_LIST_SH_MASK_DCN(mask_sh),\
...@@ -397,6 +402,7 @@ ...@@ -397,6 +402,7 @@
TF_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \ TF_SF(CM0_CM_CONTROL, CM_BYPASS_EN, mask_sh), \
TF_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \ TF_SF(CM0_CM_IGAM_LUT_SEQ_COLOR, CM_IGAM_LUT_SEQ_COLOR, mask_sh), \
TF_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh), \ TF_SF(CNVC_CFG0_FORMAT_CONTROL, OUTPUT_FP, mask_sh), \
TF_SF(CM0_CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, mask_sh), \
TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \
TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \
TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \ TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \
...@@ -545,6 +551,7 @@ ...@@ -545,6 +551,7 @@
type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \ type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \
type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \ type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \
type CM_RGAM_LUT_MODE; \ type CM_RGAM_LUT_MODE; \
type CM_CMOUT_ROUND_TRUNC_MODE; \
type OBUF_BYPASS; \ type OBUF_BYPASS; \
type OBUF_H_2X_UPSCALE_EN; \ type OBUF_H_2X_UPSCALE_EN; \
type CM_BLNDGAM_LUT_MODE; \ type CM_BLNDGAM_LUT_MODE; \
...@@ -989,7 +996,9 @@ ...@@ -989,7 +996,9 @@
type CUR0_EXPANSION_MODE; \ type CUR0_EXPANSION_MODE; \
type CUR0_ENABLE; \ type CUR0_ENABLE; \
type CM_BYPASS; \ type CM_BYPASS; \
type FORMAT_CONTROL__ALPHA_EN type FORMAT_CONTROL__ALPHA_EN; \
type CUR0_COLOR0; \
type CUR0_COLOR1
...@@ -1075,6 +1084,7 @@ struct dcn_dpp_registers { ...@@ -1075,6 +1084,7 @@ struct dcn_dpp_registers {
uint32_t CM_RGAM_RAMA_REGION_0_1; uint32_t CM_RGAM_RAMA_REGION_0_1;
uint32_t CM_RGAM_RAMA_REGION_32_33; uint32_t CM_RGAM_RAMA_REGION_32_33;
uint32_t CM_RGAM_CONTROL; uint32_t CM_RGAM_CONTROL;
uint32_t CM_CMOUT_CONTROL;
uint32_t OBUF_CONTROL; uint32_t OBUF_CONTROL;
uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK; uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK;
uint32_t CM_BLNDGAM_CONTROL; uint32_t CM_BLNDGAM_CONTROL;
...@@ -1237,10 +1247,12 @@ struct dcn_dpp_registers { ...@@ -1237,10 +1247,12 @@ struct dcn_dpp_registers {
uint32_t CNVC_SURFACE_PIXEL_FORMAT; uint32_t CNVC_SURFACE_PIXEL_FORMAT;
uint32_t CURSOR_CONTROL; uint32_t CURSOR_CONTROL;
uint32_t CURSOR0_CONTROL; uint32_t CURSOR0_CONTROL;
uint32_t CURSOR0_COLOR0;
uint32_t CURSOR0_COLOR1;
}; };
struct dcn10_dpp { struct dcn10_dpp {
struct transform base; struct dpp base;
const struct dcn_dpp_registers *tf_regs; const struct dcn_dpp_registers *tf_regs;
const struct dcn_dpp_shift *tf_shift; const struct dcn_dpp_shift *tf_shift;
...@@ -1256,107 +1268,116 @@ struct dcn10_dpp { ...@@ -1256,107 +1268,116 @@ struct dcn10_dpp {
bool is_write_to_ram_a_safe; bool is_write_to_ram_a_safe;
}; };
enum dcn10_input_csc_select { enum dcn10_input_csc_select {
INPUT_CSC_SELECT_BYPASS = 0, INPUT_CSC_SELECT_BYPASS = 0,
INPUT_CSC_SELECT_ICSC, INPUT_CSC_SELECT_ICSC,
INPUT_CSC_SELECT_COMA INPUT_CSC_SELECT_COMA
}; };
void ippn10_degamma_ram_select( bool dpp1_dscl_is_lb_conf_valid(
struct transform *xfm_base, int ceil_vratio,
int num_partitions,
int vtaps);
void dpp1_dscl_calc_lb_num_partitions(
const struct scaler_data *scl_data,
enum lb_memory_config lb_config,
int *num_part_y,
int *num_part_c);
void dpp1_degamma_ram_select(
struct dpp *dpp_base,
bool use_ram_a); bool use_ram_a);
void ippn10_program_degamma_luta_settings( void dpp1_program_degamma_luta_settings(
struct transform *xfm_base, struct dpp *dpp_base,
const struct pwl_params *params); const struct pwl_params *params);
void ippn10_program_degamma_lutb_settings( void dpp1_program_degamma_lutb_settings(
struct transform *xfm_base, struct dpp *dpp_base,
const struct pwl_params *params); const struct pwl_params *params);
void ippn10_program_degamma_lut( void dpp1_program_degamma_lut(
struct transform *xfm_base, struct dpp *dpp_base,
const struct pwl_result_data *rgb, const struct pwl_result_data *rgb,
uint32_t num, uint32_t num,
bool is_ram_a); bool is_ram_a);
void ippn10_power_on_degamma_lut( void dpp1_power_on_degamma_lut(
struct transform *xfm_base, struct dpp *dpp_base,
bool power_on); bool power_on);
void ippn10_program_input_csc( void dpp1_program_input_csc(
struct transform *xfm_base, struct dpp *dpp_base,
enum dc_color_space color_space, enum dc_color_space color_space,
enum dcn10_input_csc_select select); enum dcn10_input_csc_select select);
void ippn10_program_input_lut( void dpp1_program_input_lut(
struct transform *xfm_base, struct dpp *dpp_base,
const struct dc_gamma *gamma); const struct dc_gamma *gamma);
void ippn10_full_bypass(struct transform *xfm_base); void dpp1_full_bypass(struct dpp *dpp_base);
void ippn10_set_degamma( void dpp1_set_degamma(
struct transform *xfm_base, struct dpp *dpp_base,
enum ipp_degamma_mode mode); enum ipp_degamma_mode mode);
void ippn10_set_degamma_pwl(struct transform *xfm_base, void dpp1_set_degamma_pwl(struct dpp *dpp_base,
const struct pwl_params *params); const struct pwl_params *params);
bool dpp_get_optimal_number_of_taps( bool dpp_get_optimal_number_of_taps(
struct transform *xfm, struct dpp *dpp,
struct scaler_data *scl_data, struct scaler_data *scl_data,
const struct scaling_taps *in_taps); const struct scaling_taps *in_taps);
void dpp_reset(struct transform *xfm_base); void dpp_reset(struct dpp *dpp_base);
void dcn10_dpp_cm_program_regamma_lut( void dpp1_cm_program_regamma_lut(
struct transform *xfm_base, struct dpp *dpp_base,
const struct pwl_result_data *rgb, const struct pwl_result_data *rgb,
uint32_t num); uint32_t num);
void dcn10_dpp_cm_power_on_regamma_lut( void dpp1_cm_power_on_regamma_lut(
struct transform *xfm_base, struct dpp *dpp_base,
bool power_on); bool power_on);
void dcn10_dpp_cm_configure_regamma_lut( void dpp1_cm_configure_regamma_lut(
struct transform *xfm_base, struct dpp *dpp_base,
bool is_ram_a); bool is_ram_a);
/*program re gamma RAM A*/ /*program re gamma RAM A*/
void dcn10_dpp_cm_program_regamma_luta_settings( void dpp1_cm_program_regamma_luta_settings(
struct transform *xfm_base, struct dpp *dpp_base,
const struct pwl_params *params); const struct pwl_params *params);
/*program re gamma RAM B*/ /*program re gamma RAM B*/
void dcn10_dpp_cm_program_regamma_lutb_settings( void dpp1_cm_program_regamma_lutb_settings(
struct transform *xfm_base, struct dpp *dpp_base,
const struct pwl_params *params); const struct pwl_params *params);
void dcn10_dpp_cm_set_output_csc_adjustment( void dpp1_cm_set_output_csc_adjustment(
struct transform *xfm_base, struct dpp *dpp_base,
const struct out_csc_color_matrix *tbl_entry); const struct out_csc_color_matrix *tbl_entry);
void dcn10_dpp_cm_set_output_csc_default( void dpp1_cm_set_output_csc_default(
struct transform *xfm_base, struct dpp *dpp_base,
const struct default_adjustment *default_adjust); const struct default_adjustment *default_adjust);
void dcn10_dpp_cm_set_gamut_remap( void dpp1_cm_set_gamut_remap(
struct transform *xfm, struct dpp *dpp,
const struct xfm_grph_csc_adjustment *adjust); const struct dpp_grph_csc_adjustment *adjust);
void dcn10_dpp_dscl_set_scaler_manual_scale( void dpp1_dscl_set_scaler_manual_scale(
struct transform *xfm_base, struct dpp *dpp_base,
const struct scaler_data *scl_data); const struct scaler_data *scl_data);
void ippn10_cnv_setup ( void dpp1_cnv_setup (
struct transform *xfm_base, struct dpp *dpp_base,
enum surface_pixel_format input_format, enum surface_pixel_format input_format,
enum expansion_mode mode); enum expansion_mode mode);
void ippn10_full_bypass(struct transform *xfm_base); void dpp1_full_bypass(struct dpp *dpp_base);
void dcn10_dpp_construct(struct dcn10_dpp *xfm110, void dpp1_construct(struct dcn10_dpp *dpp1,
struct dc_context *ctx, struct dc_context *ctx,
uint32_t inst, uint32_t inst,
const struct dcn_dpp_registers *tf_regs, const struct dcn_dpp_registers *tf_regs,
......
...@@ -37,188 +37,6 @@ ...@@ -37,188 +37,6 @@
#define CTX \ #define CTX \
ippn10->base.ctx ippn10->base.ctx
static bool ippn10_cursor_program_control(
struct dcn10_ipp *ippn10,
bool pixel_data_invert,
enum dc_cursor_color_format color_format)
{
if (REG(CURSOR_SETTINS))
REG_SET_2(CURSOR_SETTINS, 0,
/* no shift of the cursor HDL schedule */
CURSOR0_DST_Y_OFFSET, 0,
/* used to shift the cursor chunk request deadline */
CURSOR0_CHUNK_HDL_ADJUST, 3);
else
REG_SET_2(CURSOR_SETTINGS, 0,
/* no shift of the cursor HDL schedule */
CURSOR0_DST_Y_OFFSET, 0,
/* used to shift the cursor chunk request deadline */
CURSOR0_CHUNK_HDL_ADJUST, 3);
REG_UPDATE_2(CURSOR0_CONTROL,
CUR0_MODE, color_format,
CUR0_EXPANSION_MODE, 0);
if (color_format == CURSOR_MODE_MONO) {
/* todo: clarify what to program these to */
REG_UPDATE(CURSOR0_COLOR0,
CUR0_COLOR0, 0x00000000);
REG_UPDATE(CURSOR0_COLOR1,
CUR0_COLOR1, 0xFFFFFFFF);
}
/* TODO: Fixed vs float */
REG_UPDATE_3(FORMAT_CONTROL,
CNVC_BYPASS, 0,
ALPHA_EN, 1,
FORMAT_EXPANSION_MODE, 0);
return true;
}
enum cursor_pitch {
CURSOR_PITCH_64_PIXELS = 0,
CURSOR_PITCH_128_PIXELS,
CURSOR_PITCH_256_PIXELS
};
enum cursor_lines_per_chunk {
CURSOR_LINE_PER_CHUNK_2 = 1,
CURSOR_LINE_PER_CHUNK_4,
CURSOR_LINE_PER_CHUNK_8,
CURSOR_LINE_PER_CHUNK_16
};
static enum cursor_pitch ippn10_get_cursor_pitch(
unsigned int pitch)
{
enum cursor_pitch hw_pitch;
switch (pitch) {
case 64:
hw_pitch = CURSOR_PITCH_64_PIXELS;
break;
case 128:
hw_pitch = CURSOR_PITCH_128_PIXELS;
break;
case 256:
hw_pitch = CURSOR_PITCH_256_PIXELS;
break;
default:
DC_ERR("Invalid cursor pitch of %d. "
"Only 64/128/256 is supported on DCN.\n", pitch);
hw_pitch = CURSOR_PITCH_64_PIXELS;
break;
}
return hw_pitch;
}
static enum cursor_lines_per_chunk ippn10_get_lines_per_chunk(
unsigned int cur_width,
enum dc_cursor_color_format format)
{
enum cursor_lines_per_chunk line_per_chunk;
if (format == CURSOR_MODE_MONO)
/* impl B. expansion in CUR Buffer reader */
line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
else if (cur_width <= 32)
line_per_chunk = CURSOR_LINE_PER_CHUNK_16;
else if (cur_width <= 64)
line_per_chunk = CURSOR_LINE_PER_CHUNK_8;
else if (cur_width <= 128)
line_per_chunk = CURSOR_LINE_PER_CHUNK_4;
else
line_per_chunk = CURSOR_LINE_PER_CHUNK_2;
return line_per_chunk;
}
static void ippn10_cursor_set_attributes(
struct input_pixel_processor *ipp,
const struct dc_cursor_attributes *attr)
{
struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
enum cursor_pitch hw_pitch = ippn10_get_cursor_pitch(attr->pitch);
enum cursor_lines_per_chunk lpc = ippn10_get_lines_per_chunk(
attr->width, attr->color_format);
ippn10->curs_attr = *attr;
REG_UPDATE(CURSOR_SURFACE_ADDRESS_HIGH,
CURSOR_SURFACE_ADDRESS_HIGH, attr->address.high_part);
REG_UPDATE(CURSOR_SURFACE_ADDRESS,
CURSOR_SURFACE_ADDRESS, attr->address.low_part);
REG_UPDATE_2(CURSOR_SIZE,
CURSOR_WIDTH, attr->width,
CURSOR_HEIGHT, attr->height);
REG_UPDATE_3(CURSOR_CONTROL,
CURSOR_MODE, attr->color_format,
CURSOR_PITCH, hw_pitch,
CURSOR_LINES_PER_CHUNK, lpc);
ippn10_cursor_program_control(ippn10,
attr->attribute_flags.bits.INVERT_PIXEL_DATA,
attr->color_format);
}
static void ippn10_cursor_set_position(
struct input_pixel_processor *ipp,
const struct dc_cursor_position *pos,
const struct dc_cursor_mi_param *param)
{
struct dcn10_ipp *ippn10 = TO_DCN10_IPP(ipp);
int src_x_offset = pos->x - pos->x_hotspot - param->viewport_x_start;
uint32_t cur_en = pos->enable ? 1 : 0;
uint32_t dst_x_offset = (src_x_offset >= 0) ? src_x_offset : 0;
/*
* Guard aganst cursor_set_position() from being called with invalid
* attributes
*
* TODO: Look at combining cursor_set_position() and
* cursor_set_attributes() into cursor_update()
*/
if (ippn10->curs_attr.address.quad_part == 0)
return;
dst_x_offset *= param->ref_clk_khz;
dst_x_offset /= param->pixel_clk_khz;
ASSERT(param->h_scale_ratio.value);
if (param->h_scale_ratio.value)
dst_x_offset = dal_fixed31_32_floor(dal_fixed31_32_div(
dal_fixed31_32_from_int(dst_x_offset),
param->h_scale_ratio));
if (src_x_offset >= (int)param->viewport_width)
cur_en = 0; /* not visible beyond right edge*/
if (src_x_offset + (int)ippn10->curs_attr.width < 0)
cur_en = 0; /* not visible beyond left edge*/
if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
ippn10_cursor_set_attributes(ipp, &ippn10->curs_attr);
REG_UPDATE(CURSOR_CONTROL,
CURSOR_ENABLE, cur_en);
REG_UPDATE(CURSOR0_CONTROL,
CUR0_ENABLE, cur_en);
REG_SET_2(CURSOR_POSITION, 0,
CURSOR_X_POSITION, pos->x,
CURSOR_Y_POSITION, pos->y);
REG_SET_2(CURSOR_HOT_SPOT, 0,
CURSOR_HOT_SPOT_X, pos->x_hotspot,
CURSOR_HOT_SPOT_Y, pos->y_hotspot);
REG_SET(CURSOR_DST_OFFSET, 0,
CURSOR_DST_X_OFFSET, dst_x_offset);
/* TODO Handle surface pixel formats other than 4:4:4 */
}
/*****************************************/ /*****************************************/
/* Constructor, Destructor */ /* Constructor, Destructor */
/*****************************************/ /*****************************************/
...@@ -230,13 +48,6 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp) ...@@ -230,13 +48,6 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp)
} }
static const struct ipp_funcs dcn10_ipp_funcs = { static const struct ipp_funcs dcn10_ipp_funcs = {
.ipp_cursor_set_attributes = ippn10_cursor_set_attributes,
.ipp_cursor_set_position = ippn10_cursor_set_position,
.ipp_set_degamma = NULL,
.ipp_program_input_lut = NULL,
.ipp_full_bypass = NULL,
.ipp_setup = NULL,
.ipp_program_degamma_pwl = NULL,
.ipp_destroy = dcn10_ipp_destroy .ipp_destroy = dcn10_ipp_destroy
}; };
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册