Commit f5e94d10 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'drm-next-2020-04-08' of git://anongit.freedesktop.org/drm/drm

Pull drm fixes from Dave Airlie:
 "This is a set of fixes that have queued up, I think I might have
  another pull with some more before rc1 but I'd like to dequeue what I
  have now just in case Easter is more eggciting that expected.

  The main thing in here is a fix for a longstanding nouveau power
  management issues on certain laptops, it should help runtime
  suspend/resume for a lot of people.

  There is also a reverted patch for some drm_mm behaviour in atomic
  contexts.

  Summary:

  core:
   - revert drm_mm atomic patch
   - dt binding fixes

  fbcon:
   - null ptr error fix

  i915:
   - GVT fixes

  nouveau:
   - runpm fix
   - svm fixes

  amdgpu:
   - HDCP fixes
   - gfx10 fix
   - Misc display fixes
   - BACO fixes

  amdkfd:
   - Fix memory leak

  vboxvideo:
   - remove conflicting fbs

  vc4:
   - mode validation fix

  xen:
   - fix PTR_ERR usage"

* tag 'drm-next-2020-04-08' of git://anongit.freedesktop.org/drm/drm: (41 commits)
  drm/nouveau/kms/nv50-: wait for FIFO space on PIO channels
  drm/nouveau/nvif: protect waits against GPU falling off the bus
  drm/nouveau/nvif: access PTIMER through usermode class, if available
  drm/nouveau/gr/gp107,gp108: implement workaround for HW hanging during init
  drm/nouveau: workaround runpm fail by disabling PCI power management on certain intel bridges
  drm/nouveau/svm: remove useless SVM range check
  drm/nouveau/svm: check for SVM initialized before migrating
  drm/nouveau/svm: fix vma range check for migration
  drm/nouveau: remove checks for return value of debugfs functions
  drm/nouveau/ttm: evict other IO mappings when running out of BAR1 space
  drm/amdkfd: kfree the wrong pointer
  drm/amd/display: increase HDCP authentication delay
  drm/amd/display: Correctly cancel future watchdog and callback events
  drm/amd/display: Don't try hdcp1.4 when content_type is set to type1
  drm/amd/powerplay: move the ASIC specific nbio operation out of smu_v11_0.c
  drm/amd/powerplay: drop redundant BIF doorbell interrupt operations
  drm/amd/display: Fix dcn21 num_states
  drm/amd/display: Enable BT2020 in COLOR_ENCODING property
  drm/amd/display: LFC not working on 2.0x range monitors (v2)
  drm/amd/display: Support plane level CTM
  ...
parents 9ebe5422 12ab316c
......@@ -21,15 +21,6 @@ properties:
- {}
- const: panel-dpi
data-mapping:
enum:
- rgb24
- rgb565
- bgr666
description: |
Describes the media format, how the display panel is connected
to the display interface.
backlight: true
enable-gpios: true
height-mm: true
......@@ -52,7 +43,6 @@ examples:
compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
label = "osddisplay";
power-supply = <&vcc_supply>;
data-mapping = "rgb565";
backlight = <&backlight>;
port {
......
......@@ -65,7 +65,7 @@ properties:
ports:
type: object
description:
Ports as described in Documentation/devictree/bindings/graph.txt
Ports as described in Documentation/devicetree/bindings/graph.txt
properties:
"#address-cells":
const: 1
......@@ -121,7 +121,7 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/soc/ti,sci_pm_domain.h>
dss: dss@04a00000 {
dss: dss@4a00000 {
compatible = "ti,am65x-dss";
reg = <0x0 0x04a00000 0x0 0x1000>, /* common */
<0x0 0x04a02000 0x0 0x1000>, /* vidl1 */
......
......@@ -98,7 +98,7 @@ properties:
ports:
type: object
description:
Ports as described in Documentation/devictree/bindings/graph.txt
Ports as described in Documentation/devicetree/bindings/graph.txt
properties:
"#address-cells":
const: 1
......@@ -154,7 +154,7 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/soc/ti,sci_pm_domain.h>
dss: dss@04a00000 {
dss: dss@4a00000 {
compatible = "ti,j721e-dss";
reg = <0x00 0x04a00000 0x00 0x10000>, /* common_m */
<0x00 0x04a10000 0x00 0x10000>, /* common_s0*/
......
......@@ -56,7 +56,7 @@ properties:
port:
type: object
description:
Port as described in Documentation/devictree/bindings/graph.txt.
Port as described in Documentation/devicetree/bindings/graph.txt.
The DSS DPI output port node
max-memory-bandwidth:
......@@ -81,7 +81,7 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
dss: dss@02540000 {
dss: dss@2540000 {
compatible = "ti,k2g-dss";
reg = <0x02540000 0x400>,
<0x02550000 0x1000>,
......
......@@ -43,11 +43,12 @@ config DMABUF_MOVE_NOTIFY
bool "Move notify between drivers (EXPERIMENTAL)"
default n
help
Don''t pin buffers if the dynamic DMA-buf interface is available on both the
exporter as well as the importer. This fixes a security problem where
userspace is able to pin unrestricted amounts of memory through DMA-buf.
But marked experimental because we don''t jet have a consistent execution
context and memory management between drivers.
Don't pin buffers if the dynamic DMA-buf interface is available on
both the exporter as well as the importer. This fixes a security
problem where userspace is able to pin unrestricted amounts of memory
through DMA-buf.
This is marked experimental because we don't yet have a consistent
execution context and memory management between drivers.
config DMABUF_SELFTESTS
tristate "Selftests for the dma-buf interfaces"
......
......@@ -1113,7 +1113,7 @@ static int gfx_v10_0_mec_init(struct amdgpu_device *adev)
return r;
}
memset(hpd, 0, adev->gfx.mec.hpd_eop_obj->tbo.mem.size);
memset(hpd, 0, mec_hpd_size);
amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj);
amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj);
......
......@@ -1946,7 +1946,7 @@ static int gfx_v9_0_mec_init(struct amdgpu_device *adev)
return r;
}
memset(hpd, 0, adev->gfx.mec.hpd_eop_obj->tbo.mem.size);
memset(hpd, 0, mec_hpd_size);
amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj);
amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj);
......
......@@ -1112,9 +1112,9 @@ int kfd_gtt_sa_allocate(struct kfd_dev *kfd, unsigned int size,
return 0;
kfd_gtt_no_free_chunk:
pr_debug("Allocation failed with mem_obj = %p\n", mem_obj);
pr_debug("Allocation failed with mem_obj = %p\n", *mem_obj);
mutex_unlock(&kfd->gtt_sa_lock);
kfree(mem_obj);
kfree(*mem_obj);
return -ENOMEM;
}
......
......@@ -3639,6 +3639,9 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
case DRM_FORMAT_NV12:
plane_info->format = SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb;
break;
case DRM_FORMAT_P010:
plane_info->format = SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb;
break;
default:
DRM_ERROR(
"Unsupported screen format %s\n",
......@@ -5535,6 +5538,8 @@ static int get_plane_formats(const struct drm_plane *plane,
if (plane_cap && plane_cap->pixel_format_support.nv12)
formats[num_formats++] = DRM_FORMAT_NV12;
if (plane_cap && plane_cap->pixel_format_support.p010)
formats[num_formats++] = DRM_FORMAT_P010;
break;
case DRM_PLANE_TYPE_OVERLAY:
......@@ -5587,12 +5592,15 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
}
if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
plane_cap && plane_cap->pixel_format_support.nv12) {
plane_cap &&
(plane_cap->pixel_format_support.nv12 ||
plane_cap->pixel_format_support.p010)) {
/* This only affects YUV formats. */
drm_plane_create_color_properties(
plane,
BIT(DRM_COLOR_YCBCR_BT601) |
BIT(DRM_COLOR_YCBCR_BT709),
BIT(DRM_COLOR_YCBCR_BT709) |
BIT(DRM_COLOR_YCBCR_BT2020),
BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
BIT(DRM_COLOR_YCBCR_FULL_RANGE),
DRM_COLOR_YCBCR_BT709, DRM_COLOR_YCBCR_LIMITED_RANGE);
......
......@@ -192,10 +192,13 @@ void hdcp_update_display(struct hdcp_workqueue *hdcp_work,
&hdcp_work->srm_version);
display->adjust.disable = 0;
if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0)
if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) {
hdcp_w->link.adjust.hdcp1.disable = 0;
hdcp_w->link.adjust.hdcp2.force_type = MOD_HDCP_FORCE_TYPE_0;
else if (content_type == DRM_MODE_HDCP_CONTENT_TYPE1)
} else if (content_type == DRM_MODE_HDCP_CONTENT_TYPE1) {
hdcp_w->link.adjust.hdcp1.disable = 1;
hdcp_w->link.adjust.hdcp2.force_type = MOD_HDCP_FORCE_TYPE_1;
}
schedule_delayed_work(&hdcp_w->property_validate_dwork,
msecs_to_jiffies(DRM_HDCP_CHECK_PERIOD_MS));
......@@ -263,7 +266,7 @@ static void event_callback(struct work_struct *work)
mutex_lock(&hdcp_work->mutex);
cancel_delayed_work(&hdcp_work->watchdog_timer_dwork);
cancel_delayed_work(&hdcp_work->callback_dwork);
mod_hdcp_process_event(&hdcp_work->hdcp, MOD_HDCP_EVENT_CALLBACK,
&hdcp_work->output);
......@@ -344,6 +347,8 @@ static void event_watchdog_timer(struct work_struct *work)
mutex_lock(&hdcp_work->mutex);
cancel_delayed_work(&hdcp_work->watchdog_timer_dwork);
mod_hdcp_process_event(&hdcp_work->hdcp,
MOD_HDCP_EVENT_WATCHDOG_TIMEOUT,
&hdcp_work->output);
......@@ -414,7 +419,8 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
link->dp.rev = aconnector->dc_link->dpcd_caps.dpcd_rev.raw;
link->dp.mst_supported = config->mst_supported;
display->adjust.disable = 1;
link->adjust.auth_delay = 2;
link->adjust.auth_delay = 3;
link->adjust.hdcp1.disable = 0;
hdcp_update_display(hdcp_work, link_index, aconnector, DRM_MODE_HDCP_CONTENT_TYPE0, false);
}
......
......@@ -1360,6 +1360,26 @@ bool dc_commit_state(struct dc *dc, struct dc_state *context)
return (result == DC_OK);
}
static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
{
int i;
struct pipe_ctx *pipe;
for (i = 0; i < MAX_PIPES; i++) {
pipe = &context->res_ctx.pipe_ctx[i];
if (!pipe->plane_state)
continue;
/* Must set to false to start with, due to OR in update function */
pipe->plane_state->status.is_flip_pending = false;
dc->hwss.update_pending_status(pipe);
if (pipe->plane_state->status.is_flip_pending)
return true;
}
return false;
}
bool dc_post_update_surfaces_to_stream(struct dc *dc)
{
int i;
......@@ -1370,6 +1390,9 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
post_surface_trace(dc);
if (is_flip_pending_in_pipes(dc, context))
return true;
for (i = 0; i < dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].stream == NULL ||
context->res_ctx.pipe_ctx[i].plane_state == NULL) {
......@@ -1703,6 +1726,9 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
if (u->coeff_reduction_factor)
update_flags->bits.coeff_reduction_change = 1;
if (u->gamut_remap_matrix)
update_flags->bits.gamut_remap_change = 1;
if (u->gamma) {
enum surface_pixel_format format = SURFACE_PIXEL_FORMAT_GRPH_BEGIN;
......@@ -1728,7 +1754,8 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
if (update_flags->bits.input_csc_change
|| update_flags->bits.coeff_reduction_change
|| update_flags->bits.gamma_change) {
|| update_flags->bits.gamma_change
|| update_flags->bits.gamut_remap_change) {
type = UPDATE_TYPE_FULL;
elevate_update_type(&overall_type, type);
}
......@@ -1973,6 +2000,10 @@ static void copy_surface_update_to_plane(
if (srf_update->coeff_reduction_factor)
surface->coeff_reduction_factor =
*srf_update->coeff_reduction_factor;
if (srf_update->gamut_remap_matrix)
surface->gamut_remap_matrix =
*srf_update->gamut_remap_matrix;
}
static void copy_stream_update_to_stream(struct dc *dc,
......
......@@ -1077,6 +1077,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
* on certain displays, such as the Sharp 4k
*/
pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left;
pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top;
......
......@@ -726,6 +726,7 @@ union surface_update_flags {
uint32_t output_tf_change:1;
uint32_t pixel_format_change:1;
uint32_t plane_size_change:1;
uint32_t gamut_remap_change:1;
/* Full updates */
uint32_t new_plane:1;
......@@ -760,6 +761,7 @@ struct dc_plane_state {
struct dc_csc_transform input_csc_color_matrix;
struct fixed31_32 coeff_reduction_factor;
struct fixed31_32 hdr_mult;
struct colorspace_transform gamut_remap_matrix;
// TODO: No longer used, remove
struct dc_hdr_static_metadata hdr_static_ctx;
......@@ -839,6 +841,7 @@ struct dc_surface_update {
const struct dc_transfer_func *func_shaper;
const struct dc_3dlut *lut3d_func;
const struct dc_transfer_func *blend_tf;
const struct colorspace_transform *gamut_remap_matrix;
};
/*
......
......@@ -2004,6 +2004,12 @@ void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx)
for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
adjust.temperature_matrix[i] =
pipe_ctx->stream->gamut_remap_matrix.matrix[i];
} else if (pipe_ctx->plane_state &&
pipe_ctx->plane_state->gamut_remap_matrix.enable_remap == true) {
adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
adjust.temperature_matrix[i] =
pipe_ctx->plane_state->gamut_remap_matrix.matrix[i];
}
pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust);
......
......@@ -342,6 +342,23 @@ void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enab
OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable);
}
/**
* optc1_set_timing_double_buffer() - DRR double buffering control
*
* Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN,
* VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers.
*
* Options: any time, start of frame, dp start of frame (range timing)
*/
void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable)
{
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t mode = enable ? 2 : 0;
REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL,
OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mode);
}
/**
* unblank_crtc
* Call ASIC Control Object to UnBlank CRTC.
......@@ -1353,6 +1370,7 @@ void optc1_clear_optc_underflow(struct timing_generator *optc)
void optc1_tg_init(struct timing_generator *optc)
{
optc1_set_blank_data_double_buffer(optc, true);
optc1_set_timing_double_buffer(optc, true);
optc1_clear_optc_underflow(optc);
}
......
......@@ -185,6 +185,7 @@ struct dcn_optc_registers {
SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\
SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\
SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\
SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\
SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\
SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\
SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\
......@@ -643,6 +644,8 @@ bool optc1_is_optc_underflow_occurred(struct timing_generator *optc);
void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable);
void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable);
bool optc1_get_otg_active_size(struct timing_generator *optc,
uint32_t *otg_active_width,
uint32_t *otg_active_height);
......
......@@ -552,7 +552,8 @@ static const struct dc_plane_cap plane_cap = {
.pixel_format_support = {
.argb8888 = true,
.nv12 = true,
.fp16 = true
.fp16 = true,
.p010 = true
},
.max_upscale_factor = {
......
......@@ -1012,7 +1012,8 @@ static const struct dc_plane_cap plane_cap = {
.pixel_format_support = {
.argb8888 = true,
.nv12 = true,
.fp16 = true
.fp16 = true,
.p010 = true
},
.max_upscale_factor = {
......@@ -3342,7 +3343,7 @@ void dcn20_cap_soc_clocks(
void dcn20_update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb,
struct pp_smu_nv_clock_table *max_clocks, unsigned int *uclk_states, unsigned int num_states)
{
struct _vcs_dpi_voltage_scaling_st calculated_states[MAX_CLOCK_LIMIT_STATES];
struct _vcs_dpi_voltage_scaling_st calculated_states[DC__VOLTAGE_STATES];
int i;
int num_calculated_states = 0;
int min_dcfclk = 0;
......
......@@ -300,7 +300,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
.xfc_bus_transport_time_us = 4,
.xfc_xbuf_latency_tolerance_us = 4,
.use_urgent_burst_bw = 1,
.num_states = 9
.num_states = 8
};
#ifndef MAX
......@@ -838,7 +838,8 @@ static const struct dc_plane_cap plane_cap = {
.pixel_format_support = {
.argb8888 = true,
.nv12 = true,
.fp16 = true
.fp16 = true,
.p010 = true
},
.max_upscale_factor = {
......@@ -1376,21 +1377,8 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
unsigned int i, j, k;
int closest_clk_lvl;
// diags does not retrieve proper values from SMU
// cap states to 5 and make state 5 the max state
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) || IS_DIAG_DC(dc->ctx->dce_environment)) {
dcn2_1_soc.num_states = 5;
dcn2_1_soc.clock_limits[5].state = 5;
dcn2_1_soc.clock_limits[5].dcfclk_mhz = 810.0;
dcn2_1_soc.clock_limits[5].fabricclk_mhz = 1600.0;
dcn2_1_soc.clock_limits[5].dispclk_mhz = 1395.0;
dcn2_1_soc.clock_limits[5].dppclk_mhz = 1285.0;
dcn2_1_soc.clock_limits[5].phyclk_mhz = 1325.0;
dcn2_1_soc.clock_limits[5].socclk_mhz = 953.0;
dcn2_1_soc.clock_limits[5].dscclk_mhz = 489.0;
dcn2_1_soc.clock_limits[5].dram_speed_mts = 4266.0;
} else {
// Default clock levels are used for diags, which may lead to overclocking.
if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) && !IS_DIAG_DC(dc->ctx->dce_environment)) {
dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
dcn2_1_ip.max_num_dpp = pool->base.pipe_count;
dcn2_1_soc.num_chans = bw_params->num_channels;
......@@ -1403,16 +1391,16 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
dcn2_1_soc.clock_limits[0].dram_speed_mts = clk_table->entries[0].memclk_mhz * 2;
/*
* Other levels: find cloest DCN clocks that fit the given clock limit using dcfclk
* as indicater
* Other levels: find closest DCN clocks that fit the given clock limit using dcfclk
* as indicator
*/
closest_clk_lvl = -1;
/* index currently being filled */
k = 1;
for (i = 1; i < clk_table->num_entries; i++) {
/* loop backwards, skip duplicate state, +1 because SMU has precision issue */
for (j = dcn2_1_soc.num_states - 2; j >= k; j--) {
/* loop backwards, skip duplicate state*/
for (j = dcn2_1_soc.num_states - 1; j >= k; j--) {
if ((unsigned int) dcn2_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) {
closest_clk_lvl = j;
break;
......@@ -1437,13 +1425,13 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
k++;
}
}
/* duplicate last level */
dcn2_1_soc.clock_limits[k] = dcn2_1_soc.clock_limits[k - 1];
dcn2_1_soc.clock_limits[k].state = k;
dcn2_1_soc.num_states = k + 1;
dcn2_1_soc.num_states = k;
}
/* duplicate last level */
dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1];
dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states;
dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21);
}
......
......@@ -29,7 +29,7 @@
#define DC__PRESENT 1
#define DC__PRESENT__1 1
#define DC__NUM_DPP 4
#define DC__VOLTAGE_STATES 7
#define DC__VOLTAGE_STATES 9
#define DC__NUM_DPP__4 1
#define DC__NUM_DPP__0_PRESENT 1
#define DC__NUM_DPP__1_PRESENT 1
......
......@@ -22,11 +22,12 @@
* Authors: AMD
*
*/
#include "dc_features.h"
#ifndef __DISPLAY_MODE_STRUCTS_H__
#define __DISPLAY_MODE_STRUCTS_H__
#define MAX_CLOCK_LIMIT_STATES 9
typedef struct _vcs_dpi_voltage_scaling_st voltage_scaling_st;
typedef struct _vcs_dpi_soc_bounding_box_st soc_bounding_box_st;
typedef struct _vcs_dpi_ip_params_st ip_params_st;
......@@ -68,7 +69,7 @@ struct _vcs_dpi_voltage_scaling_st {
};
struct _vcs_dpi_soc_bounding_box_st {
struct _vcs_dpi_voltage_scaling_st clock_limits[MAX_CLOCK_LIMIT_STATES];
struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES];
unsigned int num_states;
double sr_exit_time_us;
double sr_enter_plus_exit_time_us;
......
......@@ -734,6 +734,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
{
struct core_freesync *core_freesync = NULL;
unsigned long long nominal_field_rate_in_uhz = 0;
unsigned long long rounded_nominal_in_uhz = 0;
unsigned int refresh_range = 0;
unsigned long long min_refresh_in_uhz = 0;
unsigned long long max_refresh_in_uhz = 0;
......@@ -750,17 +751,20 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
min_refresh_in_uhz = in_config->min_refresh_in_uhz;
max_refresh_in_uhz = in_config->max_refresh_in_uhz;
// Don't allow min > max
if (min_refresh_in_uhz > max_refresh_in_uhz)
min_refresh_in_uhz = max_refresh_in_uhz;
// Full range may be larger than current video timing, so cap at nominal
if (max_refresh_in_uhz > nominal_field_rate_in_uhz)
max_refresh_in_uhz = nominal_field_rate_in_uhz;
// Full range may be larger than current video timing, so cap at nominal
if (min_refresh_in_uhz > nominal_field_rate_in_uhz)
min_refresh_in_uhz = nominal_field_rate_in_uhz;
if (min_refresh_in_uhz > max_refresh_in_uhz)
min_refresh_in_uhz = max_refresh_in_uhz;
// If a monitor reports exactly max refresh of 2x of min, enforce it on nominal
rounded_nominal_in_uhz =
div_u64(nominal_field_rate_in_uhz + 50000, 100000) * 100000;
if (in_config->max_refresh_in_uhz == (2 * in_config->min_refresh_in_uhz) &&
in_config->max_refresh_in_uhz == rounded_nominal_in_uhz)
min_refresh_in_uhz = div_u64(nominal_field_rate_in_uhz, 2);
if (!vrr_settings_require_update(core_freesync,
in_config, (unsigned int)min_refresh_in_uhz, (unsigned int)max_refresh_in_uhz,
......@@ -792,11 +796,6 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
refresh_range = in_out_vrr->max_refresh_in_uhz -
in_out_vrr->min_refresh_in_uhz;
in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
2 * in_out_vrr->min_duration_in_us;
if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
in_out_vrr->supported = true;
}
......@@ -804,9 +803,14 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
in_out_vrr->btr.btr_enabled = in_config->btr;
if (in_out_vrr->max_refresh_in_uhz <
2 * in_out_vrr->min_refresh_in_uhz)
if (in_out_vrr->max_refresh_in_uhz < (2 * in_out_vrr->min_refresh_in_uhz))
in_out_vrr->btr.btr_enabled = false;
else {
in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
2 * in_out_vrr->min_duration_in_us;
if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
}
in_out_vrr->btr.btr_active = false;
in_out_vrr->btr.inserted_duration_in_us = 0;
......@@ -1008,8 +1012,8 @@ unsigned long long mod_freesync_calc_nominal_field_rate(
unsigned int total = stream->timing.h_total * stream->timing.v_total;
/* Calculate nominal field rate for stream, rounded up to nearest integer */
nominal_field_rate_in_uhz = stream->timing.pix_clk_100hz / 10;
nominal_field_rate_in_uhz *= 1000ULL * 1000ULL * 1000ULL;
nominal_field_rate_in_uhz = stream->timing.pix_clk_100hz;
nominal_field_rate_in_uhz *= 100000000ULL;
nominal_field_rate_in_uhz = div_u64(nominal_field_rate_in_uhz, total);
......
......@@ -328,8 +328,7 @@ enum mod_hdcp_status mod_hdcp_add_display(struct mod_hdcp *hdcp,
/* add display to connection */
hdcp->connection.link = *link;
*display_container = *display;
status = mod_hdcp_add_display_to_topology(hdcp, display_container);
status = mod_hdcp_add_display_to_topology(hdcp, display->index);
if (status != MOD_HDCP_STATUS_SUCCESS)
goto out;
......@@ -375,7 +374,7 @@ enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp,
status = mod_hdcp_remove_display_from_topology(hdcp, index);
if (status != MOD_HDCP_STATUS_SUCCESS)
goto out;
memset(display, 0, sizeof(struct mod_hdcp_display));
display->state = MOD_HDCP_DISPLAY_INACTIVE;