Commit af911133 authored by Dave Airlie's avatar 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.
  ...
parents bd21a37d 9b38bd1b
......@@ -17,6 +17,16 @@ config DRM_AMD_DC_PRE_VEGA
by default. This includes Polaris, Carrizo, Tonga, Bonaire,
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
bool "DCN 1.0 Raven family"
depends on DRM_AMD_DC && X86
......
......@@ -208,24 +208,21 @@ static void remove_timer_handler(struct amdgpu_device *adev,
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
}
if (handler_in == NULL) {
/* Remove ALL handlers. */
/* Remove ALL handlers. */
if (handler_in == NULL)
continue;
}
if (handler_in == handler_temp) {
/* Remove a SPECIFIC handler.
* Found our handler - we can stop here. */
/* Remove a SPECIFIC handler.
* Found our handler - we can stop here. */
if (handler_in == handler_temp)
break;
}
}
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",
handler_in);
}
}
static bool
......@@ -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
* 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_h = &adev->dm.irq_handler_list_high_tab[src];
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)
DRM_DEBUG_KMS("DM_IRQ: early resume\n");
/* 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_h = &adev->dm.irq_handler_list_high_tab[src];
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)
* Renable HW interrupt for HPD and only since FLIP and VBLANK
* 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_h = &adev->dm.irq_handler_list_high_tab[src];
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 = {
.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)
{
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
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;
}
......@@ -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_dm_connector *aconnector;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_connector_list_iter_begin(dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
aconnector = to_amdgpu_dm_connector(connector);
if (aconnector->mst_port == master
&& !aconnector->port) {
......@@ -253,11 +300,11 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
aconnector->port = port;
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;
}
}
drm_modeset_unlock(&dev->mode_config.connection_mutex);
drm_connector_list_iter_end(&conn_iter);
aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
if (!aconnector)
......@@ -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 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(
&aconnector->base,
aconnector->edid);
}
}
drm_modeset_unlock_all(dev);
schedule_work(&adev->dm.mst_hotplug_work);
drm_kms_helper_hotplug_event(dev);
}
static void dm_dp_mst_register_connector(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
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);
}
else
DRM_ERROR("adev->mode_info.rfbdev is NULL\n");
drm_modeset_unlock_all(dev);
drm_connector_register(connector);
}
......
......@@ -35,6 +35,12 @@
#include "amdgpu_dm_irq.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,
const struct dc_sink *sink,
const char *module_name,
......
......@@ -80,8 +80,6 @@ static bool construct(struct dc_context *ctx, struct dal_logger *logger,
logger->buffer_read_offset = 0;
logger->buffer_write_offset = 0;
logger->write_wrap_count = 0;
logger->read_wrap_count = 0;
logger->open_count = 0;
logger->flags.bits.ENABLE_CONSOLE = 1;
......@@ -162,23 +160,24 @@ static void log_to_debug_console(struct log_entry *entry)
}
/* 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[i];
char *string_start = &logger->log_buffer[logger->buffer_read_offset];
dm_output_to_console(
"---------------- FLUSHING LOG BUFFER ----------------\n");
while (i < logger->buffer_write_offset) {
if (should_warn)
dm_output_to_console(
"---------------- 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);
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(
"-------------- END FLUSHING LOG BUFFER --------------\n\n");
if (should_warn)
dm_output_to_console(
"-------------- END FLUSHING LOG BUFFER --------------\n\n");
}
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) {
int total_free_space = 0;
int space_before_wrap = 0;
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 {
int buffer_space = logger->log_buffer_size -
logger->buffer_write_offset;
if (logger->buffer_write_offset == logger->buffer_read_offset) {
/* Buffer is empty, start writing at beginning */
total_free_space = logger->log_buffer_size;
space_before_wrap = logger->log_buffer_size;
buffer_space = logger->log_buffer_size;
logger->buffer_write_offset = 0;
logger->buffer_read_offset = 0;
}
if (space_before_wrap > size) {
if (buffer_space > size) {
/* No wrap around, copy 'size' bytes
* from 'entry->buf' to 'log_buffer'
*/
......@@ -232,28 +213,12 @@ static void log_to_internal_buffer(struct log_entry *entry)
entry->buf, 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 {
/* Not enough room remaining, we should flush
* existing logs */
/* Flush existing unread logs to console */
flush_to_debug_console(logger);
dm_logger_flush_buffer(logger, true);
/* Start writing to beginning of buffer */
memmove(logger->log_buffer, entry->buf, size);
......@@ -325,9 +290,10 @@ void dm_logger_write(
log_heading(&entry);
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-- */
/* print to kernel console */
......
......@@ -26,42 +26,5 @@
#ifndef __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__ */
......@@ -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.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 =
lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2;
!!(lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2);
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 =
lvds->lcd_timing.miscinfo & ATOM_INTERLACE;
!!(lvds->lcd_timing.miscinfo & ATOM_INTERLACE);
/* not provided by VBIOS*/
info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;
......@@ -1056,7 +1056,7 @@ static enum bp_result get_embedded_panel_info_v2_1(
info->ss_id = 0;
info->realtek_eDPToLVDS =
(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID ? 1:0);
!!(lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID);
return BP_RESULT_OK;
}
......
......@@ -5,7 +5,7 @@
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_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
......
......@@ -25,6 +25,41 @@
#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)
{
if (significance == 0)
......@@ -40,6 +75,16 @@ float dcn_bw_ceil2(const float arg, const float 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 temp;
......
......@@ -26,38 +26,14 @@
#ifndef _DCN_CALC_MATH_H_
#define _DCN_CALC_MATH_H_
static inline float dcn_bw_mod(const float arg1, const float arg2)
{
return arg1 - arg1 * ((int) (arg1 / 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_mod(const float arg1, const float arg2);
float dcn_bw_min2(const float arg1, const float arg2);
unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2);
float dcn_bw_max2(const float arg1, const float arg2);
float dcn_bw_floor2(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_log(float a, float b);
......
This diff is collapsed.
......@@ -45,6 +45,7 @@
#include "dce/dce_11_0_enum.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(...) \
dm_logger_write(dc_ctx->logger, LOG_HW_HOTPLUG, \
__VA_ARGS__)
......@@ -78,14 +79,15 @@ static void destruct(struct dc_link *link)
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;
struct dc_bios *dcb = link->ctx->dc_bios;
struct graphics_object_hpd_info hpd_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;
bp_result = dcb->funcs->get_gpio_pin_info(dcb,
......@@ -97,7 +99,7 @@ static struct gpio *get_hpd_gpio(const struct dc_link *link)
}
return dal_gpio_service_create_irq(
link->ctx->gpio_service,
gpio_service,
pin_info.offset,
pin_info.mask);
}
......@@ -153,7 +155,7 @@ static bool program_hpd_filter(
}
/* 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)
return result;
......@@ -186,7 +188,7 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type)
struct gpio *hpd_pin;
/* 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)
goto hpd_gpio_failure;
......@@ -496,6 +498,7 @@ static void detect_dp(
}
if (is_mst_supported(link)) {
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
link->type = dc_connection_mst_branch;
/*
* This call will initiate MST topology discovery. Which
......@@ -524,12 +527,11 @@ static void detect_dp(
if (reason == DETECT_REASON_BOOT)
boot = true;
if (dm_helpers_dp_mst_start_top_mgr(
if (!dm_helpers_dp_mst_start_top_mgr(
link->ctx,
link, boot)) {
link->type = dc_connection_mst_branch;
} else {
/* MST not supported */
link->type = dc_connection_single;
sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
}
}
......@@ -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)
link->dpcd_sink_count = link->dpcd_caps.sink_count.
bits.SINK_COUNT;
else
link->dpcd_sink_count = 1;
else
link->dpcd_sink_count = 1;
dal_ddc_service_set_transaction_type(
link->ddc,
......@@ -746,6 +748,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
if (link->type == dc_connection_mst_branch) {
LINK_INFO("link=%d, mst branch is now Disconnected\n",
link->link_index);
dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
link->mst_stream_alloc_table.stream_count = 0;
......@@ -770,7 +773,7 @@ static enum hpd_source_id get_hpd_line(
struct gpio *hpd;
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) {
switch (dal_irq_get_source(hpd)) {
......@@ -940,7 +943,7 @@ static bool construct(
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)
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,
sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings));
result = true;
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:
break;
}
......@@ -1680,7 +1694,9 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
is_over_340mhz = true;
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 */
eng_id = pipe_ctx->stream_res.stream_enc->id;
......@@ -1691,7 +1707,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
write_i2c_default_retimer_setting(pipe_ctx,
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 */
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)
else
dp_disable_link_phy_mst(link, signal);
} 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(
......@@ -2319,16 +2335,20 @@ void core_link_enable_stream(
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
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;
if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
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);
}
......
......@@ -1700,6 +1700,12 @@ static void dp_test_send_link_training(struct dc_link *link)
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)
{
union phy_test_pattern dpcd_test_pattern;
......@@ -1758,10 +1764,16 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link)
test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
break;
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;
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;
case PHY_TEST_PATTERN_CP2520_3:
test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
......
......@@ -89,12 +89,12 @@ void dp_enable_link_phy(
if (dc_is_dp_sst_signal(signal)) {
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,
link_settings,
clock_source);
link_enc->funcs->backlight_control(link_enc, true);
link->dc->hwss.edp_backlight_control(link, true);
} else
link_enc->funcs->enable_dp_output(
link_enc,
......@@ -138,12 +138,12 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
dp_receiver_power_ctrl(link, false);
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);
link->link_enc->funcs->disable_output(link->link_enc, signal);
link->link_enc->funcs->power_control(link->link_enc, false);
link->link_enc->funcs->disable_output(link->link_enc, signal, link);
link->dc->hwss.edp_power_control(link->link_enc, false);
} 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.*/
memset(&link->cur_link_settings, 0,
......@@ -282,11 +282,12 @@ void dp_retrain_link_dp_test(struct dc_link *link,
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,
SIGNAL_TYPE_DISPLAY_PORT);
SIGNAL_TYPE_DISPLAY_PORT,
link);
/* Clear current link setting. */
memset(&link->cur_link_settings, 0,
......
......@@ -31,6 +31,7 @@
#include "opp.h"
#include "timing_generator.h"
#include "transform.h"
#include "dpp.h"
#include "core_types.h"
#include "set_mode_types.h"
#include "virtual/virtual_stream_encoder.h"
......@@ -242,7 +243,10 @@ bool resource_construct(
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++) {
pool->stream_enc[pool->stream_enc_count] =
virtual_stream_encoder_create(
......@@ -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.h_active = timing->h_addressable;
pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable;
pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left;
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 */
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.xfm != NULL)
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) {
/* Try 24 bpp linebuffer */
......@@ -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(
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)
......@@ -1021,9 +1036,9 @@ static int acquire_first_split_pipe(
memset(pipe_ctx, 0, sizeof(*pipe_ctx));
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.xfm = pool->transforms[i];
pipe_ctx->plane_res.dpp = pool->dpps[i];
pipe_ctx->stream_res.opp = pool->opps[i];
pipe_ctx->pipe_idx = i;
......@@ -1070,9 +1085,6 @@ bool dc_add_plane_to_context(
return false;
}
/* retain new surfaces */
dc_plane_state_retain(plane_state);
free_pipe = acquire_free_pipe_for_stream(context, pool, stream);
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
......@@ -1082,11 +1094,11 @@ bool dc_add_plane_to_context(
free_pipe = &context->res_ctx.pipe_ctx[pipe_idx];
}
#endif
if (!free_pipe) {
stream_status->plane_states[i] = NULL;
if (!free_pipe)
return false;
}
/* retain new surfaces */
dc_plane_state_retain(plane_state);
free_pipe->plane_state = plane_state;
if (head_pipe != free_pipe) {
......@@ -1178,8 +1190,8 @@ bool dc_remove_plane_from_context(
stream_status->plane_count--;
/* Trim back arrays */
for (i = 0; i < stream_status->plane_count; i++)
/* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */
for (; i < stream_status->plane_count; i++)
stream_status->plane_states[i] = stream_status->plane_states[i + 1];
stream_status->plane_states[stream_status->plane_count] = NULL;
......@@ -1312,6 +1324,28 @@ bool dc_is_stream_unchanged(
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 */
#define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000
......@@ -1330,7 +1364,7 @@ static void update_stream_engine_usage(
}
/* TODO: release audio object */
static void update_audio_usage(
void update_audio_usage(
struct resource_context *res_ctx,
const struct resource_pool *pool,
struct audio *audio,
......@@ -1356,8 +1390,10 @@ static int acquire_first_free_pipe(
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.xfm = pool->transforms[i];
pipe_ctx->plane_res.dpp = pool->dpps[i];
pipe_ctx->stream_res.opp = pool->opps[i];
pipe_ctx->pipe_idx = i;
......@@ -1414,12 +1450,17 @@ static struct audio *find_first_free_audio(
const struct resource_pool *pool)
{
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++) {
if (res_ctx->is_audio_acquired[i] == false) {
return pool->audios[i];
}
}
return 0;
}
......@@ -1438,7 +1479,7 @@ bool resource_is_stream_unchanged(
return false;
}
bool dc_add_stream_to_ctx(
enum dc_status dc_add_stream_to_ctx(
struct dc *dc,
struct dc_state *new_ctx,
struct dc_stream_state *stream)
......@@ -1459,10 +1500,10 @@ bool dc_add_stream_to_ctx(
if (res != DC_OK)
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_state *new_ctx,
struct dc_stream_state *stream)
......@@ -1632,10 +1673,11 @@ enum dc_status resource_map_pool_resources(
/* acquire new resources */
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)
acquire_first_split_pipe(&context->res_ctx, pool, stream);
pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
#endif
if (pipe_idx < 0)
return DC_NO_CONTROLLER_RESOURCE;
......@@ -1716,17 +1758,18 @@ void dc_resource_state_construct(
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_state *new_ctx)
{
enum dc_status result = DC_ERROR_UNEXPECTED;
int i, j;
if (dc->res_pool->funcs->validate_global &&
dc->res_pool->funcs->validate_global(
dc, new_ctx) != DC_OK)
return false;
if (dc->res_pool->funcs->validate_global) {
result = dc->res_pool->funcs->validate_global(dc, new_ctx);
if (result != DC_OK)
return result;
}
for (i = 0; new_ctx && i < new_ctx->stream_count; 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,
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_link *link = stream->sink->link;
......@@ -2737,16 +2780,16 @@ bool dc_validate_stream(struct dc *dc, struct dc_stream_state *stream)
link,
&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 */
if (core_dc->res_pool->funcs->validate_plane)
return core_dc->res_pool->funcs->validate_plane(plane_state) == DC_OK;
if (dc->res_pool->funcs->validate_plane)
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(
* Update the cursor attributes and set cursor surface address
*/
bool dc_stream_set_cursor_attributes(
const struct dc_stream_state *stream,
struct dc_stream_state *stream,
const struct dc_cursor_attributes *attributes)
{
int i;
......@@ -189,21 +189,51 @@ bool dc_stream_set_cursor_attributes(
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;
res_ctx = &core_dc->current_state->res_ctx;
for (i = 0; i < MAX_PIPES; 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;
if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
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;
}
......@@ -231,6 +261,10 @@ bool dc_stream_set_cursor_position(
for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
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_mi_param param = {
.pixel_clk_khz = stream->timing.pix_clk_khz,
......@@ -241,7 +275,9 @@ bool dc_stream_set_cursor_position(
};
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;
if (pipe_ctx->plane_state->address.type
......@@ -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)
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;
......
......@@ -30,6 +30,7 @@
/* DC core (private) */
#include "core_types.h"
#include "transform.h"
#include "dpp.h"
/*******************************************************************************
* Private functions
......
......@@ -38,7 +38,7 @@
#include "inc/compressor.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_STREAMS 6
......@@ -56,11 +56,12 @@ struct dc_caps {
uint32_t max_planes;
uint32_t max_downscale_ratio;
uint32_t i2c_speed_in_khz;
unsigned int max_cursor_size;
unsigned int max_video_width;
bool dcc_const_color;
bool dynamic_audio;
};
struct dc_dcc_surface_param {
struct dc_size surface_size;
enum surface_pixel_format format;
......@@ -132,6 +133,10 @@ struct dc_stream_state_funcs {
void (*set_dither_option)(struct dc_stream_state *stream,
enum dc_dither_option option);
void (*set_dpms)(struct dc *dc,
struct dc_stream_state *stream,
bool dpms_off);
};
struct link_training_settings;
......@@ -162,6 +167,23 @@ struct dc_config {
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 {
bool surface_visual_confirm;
bool sanity_checks;
......@@ -170,14 +192,21 @@ struct dc_debug {
bool timing_trace;
bool clock_trace;
bool validation_trace;
/* stutter efficiency related */
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_dpp_power_gate;
bool disable_hubp_power_gate;
bool disable_pplib_wm_range;
bool use_dml_wm;
bool disable_pipe_split;
enum wm_report_mode pplib_wm_report_mode;
unsigned int min_disp_clk_khz;
int sr_exit_time_dpm0_ns;
int sr_enter_plus_exit_time_dpm0_ns;
int sr_exit_time_ns;
......@@ -191,6 +220,11 @@ struct dc_debug {
bool disable_dmcu;
bool disable_psr;
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 resource_pool;
......@@ -233,7 +267,7 @@ struct dc {
struct dm_pp_display_configuration prev_display_config;
/* FBC compressor */
#ifdef ENABLE_FBC
#if defined(CONFIG_DRM_AMD_DC_FBC)
struct compressor *fbc_compressor;
#endif
};
......@@ -268,7 +302,7 @@ struct dc_init_data {
struct dc_config flags;
uint32_t log_mask;
#ifdef ENABLE_FBC
#if defined(CONFIG_DRM_AMD_DC_FBC)
uint64_t fbc_gpu_addr;
#endif
};
......@@ -285,6 +319,38 @@ enum {
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 {
/* display chromaticities and white point in units of 0.00001 */
unsigned int chromaticity_green_x;
......@@ -365,6 +431,12 @@ struct dc_plane_state {
struct dc_gamma *gamma_correction;
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 surface_pixel_format format;
enum dc_rotation_angle rotation;
......@@ -449,23 +521,6 @@ struct dc_flip_addrs {
/* 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(
struct dc *dc);
......@@ -554,9 +609,12 @@ struct dc_stream_state {
int phy_pix_clk;
enum signal_type signal;
bool dpms_off;
struct dc_stream_status status;
struct dc_cursor_attributes cursor_attributes;
/* from stream struct */
struct kref refcount;
};
......@@ -569,11 +627,10 @@ struct dc_stream_update {
bool dc_is_stream_unchanged(
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
* 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.
......@@ -582,14 +639,22 @@ bool dc_is_stream_unchanged(
* 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.
*
*/
void dc_update_planes_and_stream(struct dc *dc,
struct dc_surface_update *surface_updates, int surface_count,
bool dc_commit_planes_to_stream(
struct dc *dc,
struct dc_plane_state **plane_states,
uint8_t new_plane_count,
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.
*/
......@@ -616,12 +681,12 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
uint32_t *h_position,
uint32_t *v_position);
bool dc_add_stream_to_ctx(
enum dc_status dc_add_stream_to_ctx(
struct dc *dc,
struct dc_state *new_ctx,
struct dc_stream_state *stream);
bool dc_remove_stream_from_ctx(
enum dc_status dc_remove_stream_from_ctx(
struct dc *dc,
struct dc_state *new_ctx,
struct dc_stream_state *stream);
......@@ -660,11 +725,11 @@ struct dc_validation_set {
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_state *new_ctx);
......@@ -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 */
bool dc_stream_set_cursor_attributes(
const struct dc_stream_state *stream,
struct dc_stream_state *stream,
const struct dc_cursor_attributes *attributes);
bool dc_stream_set_cursor_position(
......
......@@ -204,6 +204,8 @@ enum surface_pixel_format {
/*grow 444 video here if necessary */
};
/* Pixel format */
enum pixel_format {
/*graph*/
......
......@@ -92,7 +92,7 @@ struct dc_context {
bool created_bios;
struct gpio_service *gpio_service;
struct i2caux *i2caux;
#ifdef ENABLE_FBC
#if defined(CONFIG_DRM_AMD_DC_FBC)
uint64_t fbc_gpu_addr;
#endif
};
......@@ -151,6 +151,7 @@ enum dc_edid_status {
EDID_BAD_INPUT,
EDID_NO_RESPONSE,
EDID_BAD_CHECKSUM,
EDID_THE_SAME,
};
/* audio capability from EDID*/
......
......@@ -37,6 +37,7 @@
#define CTX \
ipp_dce->base.ctx
static void dce_ipp_cursor_set_position(
struct input_pixel_processor *ipp,
const struct dc_cursor_position *position,
......@@ -133,6 +134,7 @@ static void dce_ipp_cursor_set_attributes(
REG_UPDATE(CUR_UPDATE, CURSOR_UPDATE_LOCK, false);
}
static void dce_ipp_program_prescale(
struct input_pixel_processor *ipp,
struct ipp_prescale_params *params)
......
......@@ -82,13 +82,6 @@
#define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20
#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 */
#define TMDS_MIN_PIXEL_CLOCK 25000
/* 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 = {
.psr_program_dp_dphy_fast_training =
dce110_psr_program_dp_dphy_fast_training,
.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,
.enable_hpd = dce110_link_encoder_enable_hpd,
.disable_hpd = dce110_link_encoder_disable_hpd,
......@@ -493,165 +484,6 @@ static void configure_encoder(
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(
struct dce110_link_encoder *enc110)
{
......@@ -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,
bool exit_link_training_required)
{
......@@ -718,69 +540,6 @@ void dce110_psr_program_secondary_packet(struct link_encoder *enc,
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)
{
uint32_t value;
......@@ -998,11 +757,6 @@ void dce110_link_encoder_construct(
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 */
if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info(
enc110->base.ctx->dc_bios, enc110->base.id,
......@@ -1092,7 +846,7 @@ void dce110_link_encoder_hw_init(
ASSERT(result == BP_RESULT_OK);
} 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);
......@@ -1279,7 +1033,8 @@ void dce110_link_encoder_enable_dp_mst_output(
*/
void dce110_link_encoder_disable_output(
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 dc_context *ctx = enc110->base.ctx;
......@@ -1291,7 +1046,7 @@ void dce110_link_encoder_disable_output(
return;
}
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.
* Disabling PHY without powering down RX may cause
* symbol lock loss, on which we will get DP Sink interrupt. */
......
......@@ -44,8 +44,6 @@
SRI(DC_HPD_CONTROL, HPD, id)
#define LE_COMMON_REG_LIST_BASE(id) \
SR(LVTMA_PWRSEQ_CNTL), \
SR(LVTMA_PWRSEQ_STATE), \
SR(DMCU_RAM_ACCESS_CTRL), \
SR(DMCU_IRAM_RD_CTRL), \
SR(DMCU_IRAM_RD_DATA), \
......@@ -104,8 +102,7 @@
LE_COMMON_REG_LIST_BASE(id), \
SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id), \
SR(DMU_MEM_PWR_CNTL)
SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id)
struct dce110_link_enc_aux_registers {
uint32_t AUX_CONTROL;
......@@ -117,10 +114,6 @@ struct dce110_link_enc_hpd_registers {
};
struct dce110_link_enc_registers {
/* Backlight registers */
uint32_t LVTMA_PWRSEQ_CNTL;
uint32_t LVTMA_PWRSEQ_STATE;
/* DMCU registers */
uint32_t MASTER_COMM_DATA_REG1;
uint32_t MASTER_COMM_DATA_REG2;
......@@ -236,7 +229,8 @@ void dce110_link_encoder_enable_dp_mst_output(
/* disable PHY output */
void dce110_link_encoder_disable_output(
struct link_encoder *link_enc,
enum signal_type signal);
enum signal_type signal,
struct dc_link *link);
/* set DP lane settings */
void dce110_link_encoder_dp_set_lane_settings(
......@@ -252,14 +246,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table(
struct link_encoder *enc,
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(
struct link_encoder *enc,
enum engine_id engine,
......
......@@ -361,7 +361,7 @@ static void program_grph_pixel_format(
enum surface_pixel_format format)
{
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;
if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888 ||
......@@ -685,9 +685,6 @@ void dce_mem_input_construct(
dce_mi->regs = regs;
dce_mi->shifts = mi_shift;
dce_mi->masks = mi_mask;
dce_mi->base.mpcc_id = 0xf;
dce_mi->base.opp_id = 0xf;
}
void dce112_mem_input_construct(
......
......@@ -743,7 +743,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool)
*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)
......
......@@ -16,7 +16,7 @@ struct resource_pool *dce100_create_resource_pool(
uint8_t num_virtual_links,
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(
struct dc *dc,
......
......@@ -514,7 +514,7 @@ void dce110_compressor_construct(struct dce110_compressor *compressor,
compressor->base.lpt_channels_num = 0;
compressor->base.attached_inst = 0;
compressor->base.is_enabled = false;
#ifdef ENABLE_FBC
#if defined(CONFIG_DRM_AMD_DC_FBC)
compressor->base.funcs = &dce110_compressor_funcs;
#endif
......
......@@ -47,7 +47,7 @@ void dce110_set_displaymarks(
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,
struct dc_link_settings *link_settings);
......@@ -68,5 +68,14 @@ void dce110_fill_display_configs(
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 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__ */
......@@ -52,7 +52,7 @@
#include "dce/dce_abm.h"
#include "dce/dce_dmcu.h"
#ifdef ENABLE_FBC
#if defined(CONFIG_DRM_AMD_DC_FBC)
#include "dce110/dce110_compressor.h"
#endif
......@@ -849,7 +849,7 @@ static bool dce110_validate_bandwidth(
static bool dce110_validate_surface_sets(
struct dc_state *context)
{
int i;
int i, j;
for (i = 0; i < context->stream_count; i++) {
if (context->stream_status[i].plane_count == 0)
......@@ -858,14 +858,27 @@ static bool dce110_validate_surface_sets(
if (context->stream_status[i].plane_count > 2)
return false;
if ((context->stream_status[i].plane_states[i]->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) &&
(context->stream_status[i].plane_states[i]->src_rect.width > 1920 ||
context->stream_status[i].plane_states[i]->src_rect.height > 1080))
return false;
for (j = 0; j < context->stream_status[i].plane_count; j++) {
struct dc_plane_state *plane =
context->stream_status[i].plane_states[j];
/* irrespective of plane format, stream should be RGB encoded */
if (context->streams[i]->timing.pixel_encoding != PIXEL_ENCODING_RGB)
return false;
/* underlay validation */
if (plane->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
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;
......@@ -1266,7 +1279,7 @@ static bool construct(
}
}
#ifdef ENABLE_FBC
#if defined(CONFIG_DRM_AMD_DC_FBC)
dc->fbc_compressor = dce110_compressor_create(ctx);
......
......@@ -3,8 +3,8 @@
DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \
dcn10_dpp.o dcn10_opp.o dcn10_timing_generator.o \
dcn10_mem_input.o dcn10_mpc.o \
dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_dpp_cm_helper.o
dcn10_hubp.o dcn10_mpc.o \
dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o
AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10))
......
......@@ -26,7 +26,7 @@
#include "reg_helper.h"
#include "dcn10_dpp.h"
#include "dcn10_dpp_cm_helper.h"
#include "dcn10_cm_common.h"
#define REG(reg) reg
......
......@@ -23,8 +23,8 @@
*
*/
#ifndef __DAL_DPP_DCN10_CM_HELPER_H__
#define __DAL_DPP_DCN10_CM_HELPER_H__
#ifndef __DAL_DCN10_CM_COMMON_H__
#define __DAL_DCN10_CM_COMMON_H__
#define TF_HELPER_REG_FIELD_LIST(type) \
type exp_region0_lut_offset; \
......
......@@ -25,10 +25,10 @@
#ifndef __DAL_DPP_DCN10_H__
#define __DAL_DPP_DCN10_H__
#include "transform.h"
#include "dpp.h"
#define TO_DCN10_DPP(transform)\
container_of(transform, struct dcn10_dpp, base)
#define TO_DCN10_DPP(dpp)\
container_of(dpp, struct dcn10_dpp, base)
/* TODO: Use correct number of taps. Using polaris values for now */
#define LB_TOTAL_NUMBER_OF_ENTRIES 5124
......@@ -112,7 +112,9 @@
SRI(CM_DGAM_CONTROL, CM, id), \
SRI(FORMAT_CONTROL, 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 @@
SRI(CM_IGAM_LUT_RW_CONTROL, CM, id), \
SRI(CM_IGAM_LUT_RW_INDEX, 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)\
......@@ -302,7 +305,9 @@
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_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)\
TF_REG_LIST_SH_MASK_DCN(mask_sh),\
......@@ -397,6 +402,7 @@
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(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_PITCH, mask_sh), \
TF_SF(CURSOR0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \
......@@ -545,6 +551,7 @@
type CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET; \
type CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS; \
type CM_RGAM_LUT_MODE; \
type CM_CMOUT_ROUND_TRUNC_MODE; \
type OBUF_BYPASS; \
type OBUF_H_2X_UPSCALE_EN; \
type CM_BLNDGAM_LUT_MODE; \
......@@ -989,7 +996,9 @@
type CUR0_EXPANSION_MODE; \
type CUR0_ENABLE; \
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 {
uint32_t CM_RGAM_RAMA_REGION_0_1;
uint32_t CM_RGAM_RAMA_REGION_32_33;
uint32_t CM_RGAM_CONTROL;
uint32_t CM_CMOUT_CONTROL;
uint32_t OBUF_CONTROL;
uint32_t CM_BLNDGAM_LUT_WRITE_EN_MASK;
uint32_t CM_BLNDGAM_CONTROL;
......@@ -1237,10 +1247,12 @@ struct dcn_dpp_registers {
uint32_t CNVC_SURFACE_PIXEL_FORMAT;
uint32_t CURSOR_CONTROL;
uint32_t CURSOR0_CONTROL;
uint32_t CURSOR0_COLOR0;
uint32_t CURSOR0_COLOR1;
};
struct dcn10_dpp {
struct transform base;
struct dpp base;
const struct dcn_dpp_registers *tf_regs;
const struct dcn_dpp_shift *tf_shift;
......@@ -1256,107 +1268,116 @@ struct dcn10_dpp {
bool is_write_to_ram_a_safe;
};
enum dcn10_input_csc_select {
INPUT_CSC_SELECT_BYPASS = 0,
INPUT_CSC_SELECT_ICSC,
INPUT_CSC_SELECT_COMA
};
void ippn10_degamma_ram_select(
struct transform *xfm_base,
bool dpp1_dscl_is_lb_conf_valid(
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);
void ippn10_program_degamma_luta_settings(
struct transform *xfm_base,
void dpp1_program_degamma_luta_settings(
struct dpp *dpp_base,
const struct pwl_params *params);
void ippn10_program_degamma_lutb_settings(
struct transform *xfm_base,
void dpp1_program_degamma_lutb_settings(
struct dpp *dpp_base,
const struct pwl_params *params);
void ippn10_program_degamma_lut(
struct transform *xfm_base,
void dpp1_program_degamma_lut(
struct dpp *dpp_base,
const struct pwl_result_data *rgb,
uint32_t num,
bool is_ram_a);
void ippn10_power_on_degamma_lut(
struct transform *xfm_base,
void dpp1_power_on_degamma_lut(
struct dpp *dpp_base,
bool power_on);
void ippn10_program_input_csc(
struct transform *xfm_base,
void dpp1_program_input_csc(
struct dpp *dpp_base,
enum dc_color_space color_space,
enum dcn10_input_csc_select select);
void ippn10_program_input_lut(
struct transform *xfm_base,
void dpp1_program_input_lut(
struct dpp *dpp_base,
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(
struct transform *xfm_base,
void dpp1_set_degamma(
struct dpp *dpp_base,
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);
bool dpp_get_optimal_number_of_taps(
struct transform *xfm,
struct dpp *dpp,
struct scaler_data *scl_data,
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(
struct transform *xfm_base,
void dpp1_cm_program_regamma_lut(
struct dpp *dpp_base,
const struct pwl_result_data *rgb,
uint32_t num);
void dcn10_dpp_cm_power_on_regamma_lut(
struct transform *xfm_base,
void dpp1_cm_power_on_regamma_lut(
struct dpp *dpp_base,
bool power_on);
void dcn10_dpp_cm_configure_regamma_lut(
struct transform *xfm_base,
void dpp1_cm_configure_regamma_lut(
struct dpp *dpp_base,
bool is_ram_a);
/*program re gamma RAM A*/
void dcn10_dpp_cm_program_regamma_luta_settings(
struct transform *xfm_base,
void dpp1_cm_program_regamma_luta_settings(
struct dpp *dpp_base,
const struct pwl_params *params);
/*program re gamma RAM B*/
void dcn10_dpp_cm_program_regamma_lutb_settings(
struct transform *xfm_base,
void dpp1_cm_program_regamma_lutb_settings(
struct dpp *dpp_base,
const struct pwl_params *params);
void dcn10_dpp_cm_set_output_csc_adjustment(
struct transform *xfm_base,
void dpp1_cm_set_output_csc_adjustment(
struct dpp *dpp_base,
const struct out_csc_color_matrix *tbl_entry);
void dcn10_dpp_cm_set_output_csc_default(
struct transform *xfm_base,
void dpp1_cm_set_output_csc_default(
struct dpp *dpp_base,
const struct default_adjustment *default_adjust);
void dcn10_dpp_cm_set_gamut_remap(
struct transform *xfm,
const struct xfm_grph_csc_adjustment *adjust);
void dpp1_cm_set_gamut_remap(
struct dpp *dpp,
const struct dpp_grph_csc_adjustment *adjust);
void dcn10_dpp_dscl_set_scaler_manual_scale(
struct transform *xfm_base,
void dpp1_dscl_set_scaler_manual_scale(
struct dpp *dpp_base,
const struct scaler_data *scl_data);
void ippn10_cnv_setup (
struct transform *xfm_base,
void dpp1_cnv_setup (
struct dpp *dpp_base,
enum surface_pixel_format input_format,
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,
uint32_t inst,
const struct dcn_dpp_registers *tf_regs,
......
......@@ -37,188 +37,6 @@
#define 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 */
/*****************************************/
......@@ -230,13 +48,6 @@ static void dcn10_ipp_destroy(struct input_pixel_processor **ipp)
}
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
};
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment