drm fixes for 5.7-rc1

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
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJejR7RAAoJEAx081l5xIa+heoP/jBjHdwaZsLOkZFqFr8613mR
 juL53xEn7RK7lnVSWBRqAdJznRyJqAyCtDrxW5Au3t0x6zetOv3AhS8fQBtqv/Ze
 ghSdLZdjuTd4Lm2qyS2aWU3DBNnBlYcGcTD6bxwJn3EXSSR1z8YabT2osOOhj7cz
 HwZjhW/XmIOpuhCKDEyyzeTCSLRISBdzgipIbuUXHeqUGB2jt/vpHTiqm+FgTFo5
 hrHfM2EPpUK7LDq+REfXFeIwaQvtRDB1AJ3p8JM9iLt2GvTfavjGIDKDG9XReQhC
 l8WeaMQD69ZbujmBX+XRuP7qj+vfnVYcV/RuMm8Yr09W2Ac8RZOQknvp9PlVmqVl
 xYAvSu1DSD/88/5fvaDxYR2pyCE2ui+3hbFd9WHGFEX8h/cIhGJZ+cZqDO4K0nmY
 vw5JmtSr0Eiwrv2dFn/CFYCxxGz0BdGxVOskbUCwZUPHaTLTAbpfFIaKEABW/sbR
 k5P+cQFjxUJMbCMQeZKSa7L2GZAjf/K/SKyRNMeBuCsfn8KpEUo1W4hhGijtxL//
 akwBFwVeZ0bLTELwB6mFdYGQ987vIcfYjJV0ochPlJCPWJ1OGx6jh1+gYR81W7Np
 5mVFApS2FybmBaTQYWH0E+AhJxyxEHE6spgaGCgCHTlknANmCu3lF90NFVPAK7JB
 Vvlj3gJnOzoguejWzomE
 =HNn4
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2020-04-07 20:24:34 -07:00
commit f5e94d10e4
65 changed files with 538 additions and 227 deletions

View File

@ -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 {

View File

@ -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 */

View File

@ -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*/

View File

@ -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>,

View File

@ -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"

View File

@ -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);

View File

@ -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);

View File

@ -1112,9 +1112,9 @@ kfd_gtt_out:
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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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,

View File

@ -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;

View File

@ -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;
};
/*

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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 = {

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;
/* request authentication when connection is not reset */
if (current_state(hdcp) != HDCP_UNINITIALIZED)

View File

@ -328,7 +328,7 @@ void mod_hdcp_dump_binary_message(uint8_t *msg, uint32_t msg_size,
/* psp functions */
enum mod_hdcp_status mod_hdcp_add_display_to_topology(
struct mod_hdcp *hdcp, struct mod_hdcp_display *display);
struct mod_hdcp *hdcp, uint8_t index);
enum mod_hdcp_status mod_hdcp_remove_display_from_topology(
struct mod_hdcp *hdcp, uint8_t index);
enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp);
@ -503,6 +503,11 @@ static inline uint8_t is_display_active(struct mod_hdcp_display *display)
return display->state >= MOD_HDCP_DISPLAY_ACTIVE;
}
static inline uint8_t is_display_added(struct mod_hdcp_display *display)
{
return display->state >= MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED;
}
static inline uint8_t is_display_encryption_enabled(struct mod_hdcp_display *display)
{
return display->state >= MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED;
@ -510,23 +515,34 @@ static inline uint8_t is_display_encryption_enabled(struct mod_hdcp_display *dis
static inline uint8_t get_active_display_count(struct mod_hdcp *hdcp)
{
uint8_t active_count = 0;
uint8_t added_count = 0;
uint8_t i;
for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++)
if (is_display_active(&hdcp->displays[i]))
active_count++;
return active_count;
added_count++;
return added_count;
}
static inline struct mod_hdcp_display *get_first_active_display(
static inline uint8_t get_added_display_count(struct mod_hdcp *hdcp)
{
uint8_t added_count = 0;
uint8_t i;
for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++)
if (is_display_added(&hdcp->displays[i]))
added_count++;
return added_count;
}
static inline struct mod_hdcp_display *get_first_added_display(
struct mod_hdcp *hdcp)
{
uint8_t i;
struct mod_hdcp_display *display = NULL;
for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++)
if (is_display_active(&hdcp->displays[i])) {
if (is_display_added(&hdcp->displays[i])) {
display = &hdcp->displays[i];
break;
}

View File

@ -129,7 +129,7 @@ static inline uint8_t get_device_count(struct mod_hdcp *hdcp)
static inline enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp)
{
/* device count must be greater than or equal to tracked hdcp displays */
return (get_device_count(hdcp) < get_active_display_count(hdcp)) ?
return (get_device_count(hdcp) < get_added_display_count(hdcp)) ?
MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE :
MOD_HDCP_STATUS_SUCCESS;
}

View File

@ -208,7 +208,7 @@ static inline uint8_t get_device_count(struct mod_hdcp *hdcp)
static enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp)
{
/* device count must be greater than or equal to tracked hdcp displays */
return (get_device_count(hdcp) < get_active_display_count(hdcp)) ?
return (get_device_count(hdcp) < get_added_display_count(hdcp)) ?
MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE :
MOD_HDCP_STATUS_SUCCESS;
}

View File

@ -54,7 +54,7 @@ enum mod_hdcp_status mod_hdcp_remove_display_from_topology(
dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf;
if (!display || !is_display_active(display))
if (!display || !is_display_added(display))
return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory));
@ -73,21 +73,25 @@ enum mod_hdcp_status mod_hdcp_remove_display_from_topology(
HDCP_TOP_REMOVE_DISPLAY_TRACE(hdcp, display->index);
return MOD_HDCP_STATUS_SUCCESS;
}
enum mod_hdcp_status mod_hdcp_add_display_to_topology(
struct mod_hdcp *hdcp, struct mod_hdcp_display *display)
}
enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp,
uint8_t index)
{
struct psp_context *psp = hdcp->config.psp.handle;
struct ta_dtm_shared_memory *dtm_cmd;
struct mod_hdcp_display *display =
get_active_display_at_index(hdcp, index);
struct mod_hdcp_link *link = &hdcp->connection.link;
if (!psp->dtm_context.dtm_initialized) {
DRM_ERROR("Failed to add display topology, DTM TA is not initialized.");
display->state = MOD_HDCP_DISPLAY_INACTIVE;
return MOD_HDCP_STATUS_FAILURE;
}
if (!display || is_display_added(display))
return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE;
dtm_cmd = (struct ta_dtm_shared_memory *)psp->dtm_context.dtm_shared_buf;
memset(dtm_cmd, 0, sizeof(struct ta_dtm_shared_memory));
@ -109,11 +113,10 @@ enum mod_hdcp_status mod_hdcp_add_display_to_topology(
psp_dtm_invoke(psp, dtm_cmd->cmd_id);
if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS) {
display->state = MOD_HDCP_DISPLAY_INACTIVE;
if (dtm_cmd->dtm_status != TA_DTM_STATUS__SUCCESS)
return MOD_HDCP_STATUS_UPDATE_TOPOLOGY_FAILURE;
}
display->state = MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED;
HDCP_TOP_ADD_DISPLAY_TRACE(hdcp, display->index);
return MOD_HDCP_STATUS_SUCCESS;
@ -123,7 +126,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp)
{
struct psp_context *psp = hdcp->config.psp.handle;
struct mod_hdcp_display *display = get_first_active_display(hdcp);
struct mod_hdcp_display *display = get_first_added_display(hdcp);
struct ta_hdcp_shared_memory *hdcp_cmd;
if (!psp->hdcp_context.hdcp_initialized) {
@ -176,7 +179,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_destroy_session(struct mod_hdcp *hdcp)
if (is_display_encryption_enabled(
&hdcp->displays[i])) {
hdcp->displays[i].state =
MOD_HDCP_DISPLAY_ACTIVE;
MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED;
HDCP_HDCP1_DISABLED_TRACE(hdcp,
hdcp->displays[i].index);
}
@ -228,7 +231,7 @@ enum mod_hdcp_status mod_hdcp_hdcp1_enable_encryption(struct mod_hdcp *hdcp)
{
struct psp_context *psp = hdcp->config.psp.handle;
struct ta_hdcp_shared_memory *hdcp_cmd;
struct mod_hdcp_display *display = get_first_active_display(hdcp);
struct mod_hdcp_display *display = get_first_added_display(hdcp);
hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
@ -298,7 +301,8 @@ enum mod_hdcp_status mod_hdcp_hdcp1_enable_dp_stream_encryption(struct mod_hdcp
for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
if (hdcp->displays[i].adjust.disable)
if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED ||
hdcp->displays[i].adjust.disable)
continue;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
@ -360,7 +364,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_create_session(struct mod_hdcp *hdcp)
{
struct psp_context *psp = hdcp->config.psp.handle;
struct ta_hdcp_shared_memory *hdcp_cmd;
struct mod_hdcp_display *display = get_first_active_display(hdcp);
struct mod_hdcp_display *display = get_first_added_display(hdcp);
if (!psp->hdcp_context.hdcp_initialized) {
DRM_ERROR("Failed to create hdcp session, HDCP TA is not initialized");
@ -419,7 +423,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_destroy_session(struct mod_hdcp *hdcp)
if (is_display_encryption_enabled(
&hdcp->displays[i])) {
hdcp->displays[i].state =
MOD_HDCP_DISPLAY_ACTIVE;
MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED;
HDCP_HDCP2_DISABLED_TRACE(hdcp,
hdcp->displays[i].index);
}
@ -658,7 +662,7 @@ enum mod_hdcp_status mod_hdcp_hdcp2_enable_encryption(struct mod_hdcp *hdcp)
{
struct psp_context *psp = hdcp->config.psp.handle;
struct ta_hdcp_shared_memory *hdcp_cmd;
struct mod_hdcp_display *display = get_first_active_display(hdcp);
struct mod_hdcp_display *display = get_first_added_display(hdcp);
hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.hdcp_shared_buf;
memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
@ -743,7 +747,8 @@ enum mod_hdcp_status mod_hdcp_hdcp2_enable_dp_stream_encryption(struct mod_hdcp
for (i = 0; i < MAX_NUM_OF_DISPLAYS; i++) {
if (hdcp->displays[i].adjust.disable)
if (hdcp->displays[i].state != MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED ||
hdcp->displays[i].adjust.disable)
continue;
hdcp_cmd->in_msg.hdcp2_enable_dp_stream_encryption.display_handle = hdcp->displays[i].index;
hdcp_cmd->in_msg.hdcp2_enable_dp_stream_encryption.session_handle = hdcp->auth.id;

View File

@ -117,6 +117,7 @@ enum mod_hdcp_operation_mode {
enum mod_hdcp_display_state {
MOD_HDCP_DISPLAY_INACTIVE = 0,
MOD_HDCP_DISPLAY_ACTIVE,
MOD_HDCP_DISPLAY_ACTIVE_AND_ADDED,
MOD_HDCP_DISPLAY_ENCRYPTION_ENABLED
};

View File

@ -35,6 +35,7 @@
#include "arcturus_ppt.h"
#include "smu_v11_0_pptable.h"
#include "arcturus_ppsmc.h"
#include "nbio/nbio_7_4_offset.h"
#include "nbio/nbio_7_4_sh_mask.h"
#include "amdgpu_xgmi.h"
#include <linux/i2c.h>
@ -2210,6 +2211,18 @@ static void arcturus_i2c_eeprom_control_fini(struct i2c_adapter *control)
i2c_del_adapter(control);
}
static bool arcturus_is_baco_supported(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
uint32_t val;
if (!smu_v11_0_baco_is_support(smu))
return false;
val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false;
}
static uint32_t arcturus_get_pptable_power_limit(struct smu_context *smu)
{
PPTable_t *pptable = smu->smu_table.driver_pptable;
@ -2321,7 +2334,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
.register_irq_handler = smu_v11_0_register_irq_handler,
.set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
.get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
.baco_is_support= smu_v11_0_baco_is_support,
.baco_is_support= arcturus_is_baco_supported,
.baco_get_state = smu_v11_0_baco_get_state,
.baco_set_state = smu_v11_0_baco_set_state,
.baco_enter = smu_v11_0_baco_enter,

View File

@ -28,13 +28,15 @@
#include "smu_internal.h"
#include "atomfirmware.h"
#include "amdgpu_atomfirmware.h"
#include "soc15_common.h"
#include "smu_v11_0.h"
#include "smu11_driver_if_navi10.h"
#include "atom.h"
#include "navi10_ppt.h"
#include "smu_v11_0_pptable.h"
#include "smu_v11_0_ppsmc.h"
#include "nbio/nbio_7_4_sh_mask.h"
#include "nbio/nbio_2_3_offset.h"
#include "nbio/nbio_2_3_sh_mask.h"
#include "asic_reg/mp/mp_11_0_sh_mask.h"
@ -1985,6 +1987,18 @@ static int navi10_setup_od_limits(struct smu_context *smu) {
return 0;
}
static bool navi10_is_baco_supported(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
uint32_t val;
if (!smu_v11_0_baco_is_support(smu))
return false;
val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false;
}
static int navi10_set_default_od_settings(struct smu_context *smu, bool initialize) {
OverDriveTable_t *od_table, *boot_od_table;
int ret = 0;
@ -2361,7 +2375,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.register_irq_handler = smu_v11_0_register_irq_handler,
.set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
.get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
.baco_is_support= smu_v11_0_baco_is_support,
.baco_is_support= navi10_is_baco_supported,
.baco_get_state = smu_v11_0_baco_get_state,
.baco_set_state = smu_v11_0_baco_set_state,
.baco_enter = smu_v11_0_baco_enter,

View File

@ -42,8 +42,6 @@
#include "asic_reg/thm/thm_11_0_2_sh_mask.h"
#include "asic_reg/mp/mp_11_0_offset.h"
#include "asic_reg/mp/mp_11_0_sh_mask.h"
#include "asic_reg/nbio/nbio_7_4_offset.h"
#include "asic_reg/nbio/nbio_7_4_sh_mask.h"
#include "asic_reg/smuio/smuio_11_0_0_offset.h"
#include "asic_reg/smuio/smuio_11_0_0_sh_mask.h"
@ -1662,9 +1660,7 @@ static int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, enum smu_v
bool smu_v11_0_baco_is_support(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
struct smu_baco_context *smu_baco = &smu->smu_baco;
uint32_t val;
bool baco_support;
mutex_lock(&smu_baco->mutex);
@ -1679,11 +1675,7 @@ bool smu_v11_0_baco_is_support(struct smu_context *smu)
!smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT))
return false;
val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
if (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK)
return true;
return false;
return true;
}
enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu)
@ -1700,11 +1692,9 @@ enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu)
int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
{
struct smu_baco_context *smu_baco = &smu->smu_baco;
struct amdgpu_device *adev = smu->adev;
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
uint32_t bif_doorbell_intr_cntl;
uint32_t data;
int ret = 0;
@ -1713,14 +1703,7 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
mutex_lock(&smu_baco->mutex);
bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL);
if (state == SMU_BACO_STATE_ENTER) {
bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl,
BIF_DOORBELL_INT_CNTL,
DOORBELL_INTERRUPT_DISABLE, 1);
WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl);
if (!ras || !ras->supported) {
data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
data |= 0x80000000;
@ -1735,11 +1718,6 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
if (ret)
goto out;
bif_doorbell_intr_cntl = REG_SET_FIELD(bif_doorbell_intr_cntl,
BIF_DOORBELL_INT_CNTL,
DOORBELL_INTERRUPT_DISABLE, 0);
WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl);
/* clear vbios scratch 6 and 7 for coming asic reinit */
WREG32(adev->bios_scratch_reg_offset + 6, 0);
WREG32(adev->bios_scratch_reg_offset + 7, 0);

View File

@ -35,6 +35,7 @@
#include "vega20_ppt.h"
#include "vega20_pptable.h"
#include "vega20_ppsmc.h"
#include "nbio/nbio_7_4_offset.h"
#include "nbio/nbio_7_4_sh_mask.h"
#include "asic_reg/thm/thm_11_0_2_offset.h"
#include "asic_reg/thm/thm_11_0_2_sh_mask.h"
@ -3174,6 +3175,17 @@ static int vega20_update_pcie_parameters(struct smu_context *smu,
return ret;
}
static bool vega20_is_baco_supported(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
uint32_t val;
if (!smu_v11_0_baco_is_support(smu))
return false;
val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false;
}
static const struct pptable_funcs vega20_ppt_funcs = {
.tables_init = vega20_tables_init,
@ -3262,7 +3274,7 @@ static const struct pptable_funcs vega20_ppt_funcs = {
.register_irq_handler = smu_v11_0_register_irq_handler,
.set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme,
.get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc,
.baco_is_support= smu_v11_0_baco_is_support,
.baco_is_support= vega20_is_baco_supported,
.baco_get_state = smu_v11_0_baco_get_state,
.baco_set_state = smu_v11_0_baco_set_state,
.baco_enter = smu_v11_0_baco_enter,

View File

@ -45,7 +45,6 @@
#include <linux/export.h>
#include <linux/interval_tree_generic.h>
#include <linux/seq_file.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/stacktrace.h>
@ -367,11 +366,6 @@ next_hole(struct drm_mm *mm,
struct drm_mm_node *node,
enum drm_mm_insert_mode mode)
{
/* Searching is slow; check if we ran out of time/patience */
cond_resched();
if (fatal_signal_pending(current))
return NULL;
switch (mode) {
default:
case DRM_MM_INSERT_BEST:
@ -563,7 +557,7 @@ int drm_mm_insert_node_in_range(struct drm_mm * const mm,
return 0;
}
return signal_pending(current) ? -ERESTARTSYS : -ENOSPC;
return -ENOSPC;
}
EXPORT_SYMBOL(drm_mm_insert_node_in_range);

View File

@ -164,6 +164,7 @@ struct decode_info {
#define OP_STATE_BASE_ADDRESS OP_3D_MEDIA(0x0, 0x1, 0x01)
#define OP_STATE_SIP OP_3D_MEDIA(0x0, 0x1, 0x02)
#define OP_3D_MEDIA_0_1_4 OP_3D_MEDIA(0x0, 0x1, 0x04)
#define OP_SWTESS_BASE_ADDRESS OP_3D_MEDIA(0x0, 0x1, 0x03)
#define OP_3DSTATE_VF_STATISTICS_GM45 OP_3D_MEDIA(0x1, 0x0, 0x0B)
@ -967,18 +968,6 @@ static int cmd_handler_lri(struct parser_exec_state *s)
{
int i, ret = 0;
int cmd_len = cmd_length(s);
u32 valid_len = CMD_LEN(1);
/*
* Official intel docs are somewhat sloppy , check the definition of
* MI_LOAD_REGISTER_IMM.
*/
#define MAX_VALID_LEN 127
if ((cmd_len < valid_len) || (cmd_len > MAX_VALID_LEN)) {
gvt_err("len is not valid: len=%u valid_len=%u\n",
cmd_len, valid_len);
return -EFAULT;
}
for (i = 1; i < cmd_len; i += 2) {
if (IS_BROADWELL(s->engine->i915) && s->engine->id != RCS0) {
@ -2485,6 +2474,9 @@ static const struct cmd_info cmd_info[] = {
{"OP_3D_MEDIA_0_1_4", OP_3D_MEDIA_0_1_4, F_LEN_VAR, R_RCS, D_ALL,
ADDR_FIX_1(1), 8, NULL},
{"OP_SWTESS_BASE_ADDRESS", OP_SWTESS_BASE_ADDRESS,
F_LEN_VAR, R_RCS, D_ALL, ADDR_FIX_2(1, 2), 3, NULL},
{"3DSTATE_VS", OP_3DSTATE_VS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
{"3DSTATE_SF", OP_3DSTATE_SF, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},

View File

@ -221,7 +221,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
TRANS_DDI_PORT_MASK);
vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DVI |
(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
(PORT_B << TRANS_DDI_PORT_SHIFT) |
TRANS_DDI_FUNC_ENABLE);
if (IS_BROADWELL(dev_priv)) {
@ -241,7 +241,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
TRANS_DDI_PORT_MASK);
vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DVI |
(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
(PORT_C << TRANS_DDI_PORT_SHIFT) |
TRANS_DDI_FUNC_ENABLE);
if (IS_BROADWELL(dev_priv)) {
@ -261,7 +261,7 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
TRANS_DDI_PORT_MASK);
vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DVI |
(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
(PORT_D << TRANS_DDI_PORT_SHIFT) |
TRANS_DDI_FUNC_ENABLE);
if (IS_BROADWELL(dev_priv)) {

View File

@ -462,11 +462,14 @@ static int pipeconf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
return 0;
}
/* ascendingly sorted */
/* sorted in ascending order */
static i915_reg_t force_nonpriv_white_list[] = {
_MMIO(0xd80),
GEN9_CS_DEBUG_MODE1, //_MMIO(0x20ec)
GEN9_CTX_PREEMPT_REG,//_MMIO(0x2248)
PS_INVOCATION_COUNT,//_MMIO(0x2348)
CL_PRIMITIVES_COUNT, //_MMIO(0x2340)
PS_INVOCATION_COUNT, //_MMIO(0x2348)
PS_DEPTH_COUNT, //_MMIO(0x2350)
GEN8_CS_CHICKEN1,//_MMIO(0x2580)
_MMIO(0x2690),
_MMIO(0x2694),
@ -491,6 +494,7 @@ static i915_reg_t force_nonpriv_white_list[] = {
_MMIO(0xe18c),
_MMIO(0xe48c),
_MMIO(0xe5f4),
_MMIO(0x64844),
};
/* a simple bsearch */

View File

@ -296,8 +296,8 @@ shadow_context_descriptor_update(struct intel_context *ce,
* Update bits 0-11 of the context descriptor which includes flags
* like GEN8_CTX_* cached in desc_template
*/
desc &= ~(0x3 << GEN8_CTX_ADDRESSING_MODE_SHIFT);
desc |= workload->ctx_desc.addressing_mode <<
desc &= ~(0x3ull << GEN8_CTX_ADDRESSING_MODE_SHIFT);
desc |= (u64)workload->ctx_desc.addressing_mode <<
GEN8_CTX_ADDRESSING_MODE_SHIFT;
ce->lrc_desc = desc;

View File

@ -35,7 +35,8 @@
#include <subdev/bios/gpio.h>
#include <subdev/gpio.h>
#include <subdev/timer.h>
#include <nvif/timer.h>
int nv04_dac_output_offset(struct drm_encoder *encoder)
{

View File

@ -26,6 +26,7 @@
#include "hw.h"
#include <subdev/bios/pll.h>
#include <nvif/timer.h>
#define CHIPSET_NFORCE 0x01a0
#define CHIPSET_NFORCE2 0x01f0

View File

@ -23,6 +23,7 @@
#include <nvif/cl507c.h>
#include <nvif/event.h>
#include <nvif/timer.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fourcc.h>

View File

@ -23,6 +23,7 @@
#include "head.h"
#include <nvif/cl507d.h>
#include <nvif/timer.h>
#include "nouveau_bo.h"

View File

@ -24,6 +24,8 @@
#include <nouveau_bo.h>
#include <nvif/timer.h>
void
corec37d_wndw_owner(struct nv50_core *core)
{

View File

@ -24,21 +24,36 @@
#include "head.h"
#include <nvif/cl507a.h>
#include <nvif/timer.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
bool
curs507a_space(struct nv50_wndw *wndw)
{
nvif_msec(&nouveau_drm(wndw->plane.dev)->client.device, 2,
if (nvif_rd32(&wndw->wimm.base.user, 0x0008) >= 4)
return true;
);
WARN_ON(1);
return false;
}
static void
curs507a_update(struct nv50_wndw *wndw, u32 *interlock)
{
nvif_wr32(&wndw->wimm.base.user, 0x0080, 0x00000000);
if (curs507a_space(wndw))
nvif_wr32(&wndw->wimm.base.user, 0x0080, 0x00000000);
}
static void
curs507a_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
nvif_wr32(&wndw->wimm.base.user, 0x0084, asyw->point.y << 16 |
asyw->point.x);
if (curs507a_space(wndw)) {
nvif_wr32(&wndw->wimm.base.user, 0x0084, asyw->point.y << 16 |
asyw->point.x);
}
}
const struct nv50_wimm_func

View File

@ -25,14 +25,17 @@
static void
cursc37a_update(struct nv50_wndw *wndw, u32 *interlock)
{
nvif_wr32(&wndw->wimm.base.user, 0x0200, 0x00000001);
if (curs507a_space(wndw))
nvif_wr32(&wndw->wimm.base.user, 0x0200, 0x00000001);
}
static void
cursc37a_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{
nvif_wr32(&wndw->wimm.base.user, 0x0208, asyw->point.y << 16 |
asyw->point.x);
if (curs507a_space(wndw)) {
nvif_wr32(&wndw->wimm.base.user, 0x0208, asyw->point.y << 16 |
asyw->point.x);
}
}
static const struct nv50_wimm_func

View File

@ -45,6 +45,7 @@
#include <nvif/cl5070.h>
#include <nvif/cl507d.h>
#include <nvif/event.h>
#include <nvif/timer.h>
#include "nouveau_drv.h"
#include "nouveau_dma.h"

View File

@ -24,6 +24,8 @@
#include <nouveau_bo.h>
#include <nvif/timer.h>
static void
ovly827e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
{

View File

@ -97,6 +97,7 @@ struct nv50_wimm_func {
};
extern const struct nv50_wimm_func curs507a;
bool curs507a_space(struct nv50_wndw *);
int wndwc37e_new(struct nouveau_drm *, enum drm_plane_type, int, s32,
struct nv50_wndw **);

View File

@ -23,27 +23,6 @@ int nvif_device_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32,
void nvif_device_fini(struct nvif_device *);
u64 nvif_device_time(struct nvif_device *);
/* Delay based on GPU time (ie. PTIMER).
*
* Will return -ETIMEDOUT unless the loop was terminated with 'break',
* where it will return the number of nanoseconds taken instead.
*/
#define nvif_nsec(d,n,cond...) ({ \
struct nvif_device *_device = (d); \
u64 _nsecs = (n), _time0 = nvif_device_time(_device); \
s64 _taken = 0; \
\
do { \
cond \
} while (_taken = nvif_device_time(_device) - _time0, _taken < _nsecs);\
\
if (_taken >= _nsecs) \
_taken = -ETIMEDOUT; \
_taken; \
})
#define nvif_usec(d,u,cond...) nvif_nsec((d), (u) * 1000, ##cond)
#define nvif_msec(d,m,cond...) nvif_usec((d), (m) * 1000, ##cond)
/*XXX*/
#include <subdev/bios.h>
#include <subdev/fb.h>

View File

@ -0,0 +1,35 @@
#ifndef __NVIF_TIMER_H__
#define __NVIF_TIMER_H__
#include <nvif/os.h>
struct nvif_timer_wait {
struct nvif_device *device;
u64 limit;
u64 time0;
u64 time1;
int reads;
};
void nvif_timer_wait_init(struct nvif_device *, u64 nsec,
struct nvif_timer_wait *);
s64 nvif_timer_wait_test(struct nvif_timer_wait *);
/* Delay based on GPU time (ie. PTIMER).
*
* Will return -ETIMEDOUT unless the loop was terminated with 'break',
* where it will return the number of nanoseconds taken instead.
*/
#define nvif_nsec(d,n,cond...) ({ \
struct nvif_timer_wait _wait; \
s64 _taken = 0; \
\
nvif_timer_wait_init((d), (n), &_wait); \
do { \
cond \
} while ((_taken = nvif_timer_wait_test(&_wait)) >= 0); \
\
_taken; \
})
#define nvif_usec(d,u,cond...) nvif_nsec((d), (u) * 1000, ##cond)
#define nvif_msec(d,m,cond...) nvif_usec((d), (m) * 1000, ##cond)
#endif

View File

@ -10,6 +10,7 @@ struct nvif_user {
struct nvif_user_func {
void (*doorbell)(struct nvif_user *, u32 token);
u64 (*time)(struct nvif_user *);
};
int nvif_user_init(struct nvif_device *);

View File

@ -1494,8 +1494,13 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
ret = nvif_object_map_handle(&mem->mem.object,
&args, argc,
&handle, &length);
if (ret != 1)
return ret ? ret : -EINVAL;
if (ret != 1) {
if (WARN_ON(ret == 0))
return -EINVAL;
if (ret == -ENOSPC)
return -EAGAIN;
return ret;
}
reg->bus.base = 0;
reg->bus.offset = handle;

View File

@ -222,22 +222,18 @@ nouveau_drm_debugfs_init(struct drm_minor *minor)
{
struct nouveau_drm *drm = nouveau_drm(minor->dev);
struct dentry *dentry;
int i, ret;
int i;
for (i = 0; i < ARRAY_SIZE(nouveau_debugfs_files); i++) {
dentry = debugfs_create_file(nouveau_debugfs_files[i].name,
S_IRUGO | S_IWUSR,
minor->debugfs_root, minor->dev,
nouveau_debugfs_files[i].fops);
if (!dentry)
return -ENOMEM;
debugfs_create_file(nouveau_debugfs_files[i].name,
S_IRUGO | S_IWUSR,
minor->debugfs_root, minor->dev,
nouveau_debugfs_files[i].fops);
}
ret = drm_debugfs_create_files(nouveau_debugfs_list,
NOUVEAU_DEBUGFS_ENTRIES,
minor->debugfs_root, minor);
if (ret)
return ret;
drm_debugfs_create_files(nouveau_debugfs_list,
NOUVEAU_DEBUGFS_ENTRIES,
minor->debugfs_root, minor);
/* Set the size of the vbios since we know it, and it's confusing to
* userspace if it wants to seek() but the file has a length of 0

View File

@ -618,6 +618,64 @@ nouveau_drm_device_fini(struct drm_device *dev)
kfree(drm);
}
/*
* On some Intel PCIe bridge controllers doing a
* D0 -> D3hot -> D3cold -> D0 sequence causes Nvidia GPUs to not reappear.
* Skipping the intermediate D3hot step seems to make it work again. This is
* probably caused by not meeting the expectation the involved AML code has
* when the GPU is put into D3hot state before invoking it.
*
* This leads to various manifestations of this issue:
* - AML code execution to power on the GPU hits an infinite loop (as the
* code waits on device memory to change).
* - kernel crashes, as all PCI reads return -1, which most code isn't able
* to handle well enough.
*
* In all cases dmesg will contain at least one line like this:
* 'nouveau 0000:01:00.0: Refused to change power state, currently in D3'
* followed by a lot of nouveau timeouts.
*
* In the \_SB.PCI0.PEG0.PG00._OFF code deeper down writes bit 0x80 to the not
* documented PCI config space register 0x248 of the Intel PCIe bridge
* controller (0x1901) in order to change the state of the PCIe link between
* the PCIe port and the GPU. There are alternative code paths using other
* registers, which seem to work fine (executed pre Windows 8):
* - 0xbc bit 0x20 (publicly available documentation claims 'reserved')
* - 0xb0 bit 0x10 (link disable)
* Changing the conditions inside the firmware by poking into the relevant
* addresses does resolve the issue, but it seemed to be ACPI private memory
* and not any device accessible memory at all, so there is no portable way of
* changing the conditions.
* On a XPS 9560 that means bits [0,3] on \CPEX need to be cleared.
*
* The only systems where this behavior can be seen are hybrid graphics laptops
* with a secondary Nvidia Maxwell, Pascal or Turing GPU. It's unclear whether
* this issue only occurs in combination with listed Intel PCIe bridge
* controllers and the mentioned GPUs or other devices as well.
*
* documentation on the PCIe bridge controller can be found in the
* "7th Generation Intel® Processor Families for H Platforms Datasheet Volume 2"
* Section "12 PCI Express* Controller (x16) Registers"
*/
static void quirk_broken_nv_runpm(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct pci_dev *bridge = pci_upstream_bridge(pdev);
if (!bridge || bridge->vendor != PCI_VENDOR_ID_INTEL)
return;
switch (bridge->device) {
case 0x1901:
drm->old_pm_cap = pdev->pm_cap;
pdev->pm_cap = 0;
NV_INFO(drm, "Disabling PCI power management to avoid bug\n");
break;
}
}
static int nouveau_drm_probe(struct pci_dev *pdev,
const struct pci_device_id *pent)
{
@ -699,6 +757,7 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
if (ret)
goto fail_drm_dev_init;
quirk_broken_nv_runpm(pdev);
return 0;
fail_drm_dev_init:
@ -734,7 +793,11 @@ static void
nouveau_drm_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct nouveau_drm *drm = nouveau_drm(dev);
/* revert our workaround */
if (drm->old_pm_cap)
pdev->pm_cap = drm->old_pm_cap;
nouveau_drm_device_remove(dev);
pci_disable_device(pdev);
}

View File

@ -140,6 +140,8 @@ struct nouveau_drm {
struct list_head clients;
u8 old_pm_cap;
struct {
struct agp_bridge_data *bridge;
u32 base;

View File

@ -171,6 +171,11 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
mm = get_task_mm(current);
down_read(&mm->mmap_sem);
if (!cli->svm.svmm) {
up_read(&mm->mmap_sem);
return -EINVAL;
}
for (addr = args->va_start, end = args->va_start + size; addr < end;) {
struct vm_area_struct *vma;
unsigned long next;
@ -179,6 +184,7 @@ nouveau_svmm_bind(struct drm_device *dev, void *data,
if (!vma)
break;
addr = max(addr, vma->vm_start);
next = min(vma->vm_end, end);
/* This is a best effort so we ignore errors */
nouveau_dmem_migrate_vma(cli->drm, vma, addr, next);
@ -656,9 +662,6 @@ nouveau_svm_fault(struct nvif_notify *notify)
limit = start + (ARRAY_SIZE(args.phys) << PAGE_SHIFT);
if (start < svmm->unmanaged.limit)
limit = min_t(u64, limit, svmm->unmanaged.start);
else
if (limit > svmm->unmanaged.start)
start = max_t(u64, start, svmm->unmanaged.limit);
SVMM_DBG(svmm, "wndw %016llx-%016llx", start, limit);
mm = svmm->notifier.mm;

View File

@ -8,6 +8,7 @@ nvif-y += nvif/fifo.o
nvif-y += nvif/mem.o
nvif-y += nvif/mmu.o
nvif-y += nvif/notify.o
nvif-y += nvif/timer.o
nvif-y += nvif/vmm.o
# Usermode classes

View File

@ -27,11 +27,15 @@
u64
nvif_device_time(struct nvif_device *device)
{
struct nv_device_time_v0 args = {};
int ret = nvif_object_mthd(&device->object, NV_DEVICE_V0_TIME,
&args, sizeof(args));
WARN_ON_ONCE(ret != 0);
return args.time;
if (!device->user.func) {
struct nv_device_time_v0 args = {};
int ret = nvif_object_mthd(&device->object, NV_DEVICE_V0_TIME,
&args, sizeof(args));
WARN_ON_ONCE(ret != 0);
return args.time;
}
return device->user.func->time(&device->user);
}
void

View File

@ -0,0 +1,56 @@
/*
* Copyright 2020 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <nvif/timer.h>
#include <nvif/device.h>
s64
nvif_timer_wait_test(struct nvif_timer_wait *wait)
{
u64 time = nvif_device_time(wait->device);
if (wait->reads == 0) {
wait->time0 = time;
wait->time1 = time;
}
if (wait->time1 == time) {
if (WARN_ON(wait->reads++ == 16))
return -ETIMEDOUT;
} else {
wait->time1 = time;
wait->reads = 1;
}
if (wait->time1 - wait->time0 > wait->limit)
return -ETIMEDOUT;
return wait->time1 - wait->time0;
}
void
nvif_timer_wait_init(struct nvif_device *device, u64 nsec,
struct nvif_timer_wait *wait)
{
wait->device = device;
wait->limit = nsec;
wait->reads = 0;
}

View File

@ -21,6 +21,19 @@
*/
#include <nvif/user.h>
static u64
nvif_userc361_time(struct nvif_user *user)
{
u32 hi, lo;
do {
hi = nvif_rd32(&user->object, 0x084);
lo = nvif_rd32(&user->object, 0x080);
} while (hi != nvif_rd32(&user->object, 0x084));
return ((u64)hi << 32 | lo);
}
static void
nvif_userc361_doorbell(struct nvif_user *user, u32 token)
{
@ -30,4 +43,5 @@ nvif_userc361_doorbell(struct nvif_user *user, u32 token)
const struct nvif_user_func
nvif_userc361 = {
.doorbell = nvif_userc361_doorbell,
.time = nvif_userc361_time,
};

View File

@ -1981,8 +1981,34 @@ gf100_gr_init_(struct nvkm_gr *base)
{
struct gf100_gr *gr = gf100_gr(base);
struct nvkm_subdev *subdev = &base->engine.subdev;
struct nvkm_device *device = subdev->device;
bool reset = device->chipset == 0x137 || device->chipset == 0x138;
u32 ret;
/* On certain GP107/GP108 boards, we trigger a weird issue where
* GR will stop responding to PRI accesses after we've asked the
* SEC2 RTOS to boot the GR falcons. This happens with far more
* frequency when cold-booting a board (ie. returning from D3).
*
* The root cause for this is not known and has proven difficult
* to isolate, with many avenues being dead-ends.
*
* A workaround was discovered by Karol, whereby putting GR into
* reset for an extended period right before initialisation
* prevents the problem from occuring.
*
* XXX: As RM does not require any such workaround, this is more
* of a hack than a true fix.
*/
reset = nvkm_boolopt(device->cfgopt, "NvGrResetWar", reset);
if (reset) {
nvkm_mask(device, 0x000200, 0x00001000, 0x00000000);
nvkm_rd32(device, 0x000200);
msleep(50);
nvkm_mask(device, 0x000200, 0x00001000, 0x00001000);
nvkm_rd32(device, 0x000200);
}
nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false);
ret = nvkm_falcon_get(&gr->fecs.falcon, subdev);

View File

@ -361,7 +361,6 @@ static int panel_dpi_probe(struct device *dev,
struct panel_desc *desc;
unsigned int bus_flags;
struct videomode vm;
const char *mapping;
int ret;
np = dev->of_node;
@ -386,16 +385,6 @@ static int panel_dpi_probe(struct device *dev,
of_property_read_u32(np, "width-mm", &desc->size.width);
of_property_read_u32(np, "height-mm", &desc->size.height);
of_property_read_string(np, "data-mapping", &mapping);
if (!strcmp(mapping, "rgb24"))
desc->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
else if (!strcmp(mapping, "rgb565"))
desc->bus_format = MEDIA_BUS_FMT_RGB565_1X16;
else if (!strcmp(mapping, "bgr666"))
desc->bus_format = MEDIA_BUS_FMT_RGB666_1X18;
else if (!strcmp(mapping, "lvds666"))
desc->bus_format = MEDIA_BUS_FMT_RGB666_1X24_CPADHI;
/* Extract bus_flags from display_timing */
bus_flags = 0;
vm.flags = timing->flags;

View File

@ -41,6 +41,10 @@ static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!vbox_check_supported(VBE_DISPI_ID_HGSMI))
return -ENODEV;
ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "vboxvideodrmfb");
if (ret)
return ret;
vbox = kzalloc(sizeof(*vbox), GFP_KERNEL);
if (!vbox)
return -ENOMEM;

View File

@ -681,11 +681,23 @@ static enum drm_mode_status
vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
const struct drm_display_mode *mode)
{
/* HSM clock must be 108% of the pixel clock. Additionally,
* the AXI clock needs to be at least 25% of pixel clock, but
* HSM ends up being the limiting factor.
/*
* As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
* be faster than pixel clock, infinitesimally faster, tested in
* simulation. Otherwise, exact value is unimportant for HDMI
* operation." This conflicts with bcm2835's vc4 documentation, which
* states HSM's clock has to be at least 108% of the pixel clock.
*
* Real life tests reveal that vc4's firmware statement holds up, and
* users are able to use pixel clocks closer to HSM's, namely for
* 1920x1200@60Hz. So it was decided to have leave a 1% margin between
* both clocks. Which, for RPi0-3 implies a maximum pixel clock of
* 162MHz.
*
* Additionally, the AXI clock needs to be at least 25% of
* pixel clock, but HSM ends up being the limiting factor.
*/
if (mode->clock > HSM_CLOCK_FREQ / (1000 * 108 / 100))
if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
return MODE_CLOCK_HIGH;
return MODE_OK;

View File

@ -401,7 +401,7 @@ static int xen_drm_drv_dumb_create(struct drm_file *filp,
obj = xen_drm_front_gem_create(dev, args->size);
if (IS_ERR_OR_NULL(obj)) {
ret = PTR_ERR(obj);
ret = PTR_ERR_OR_ZERO(obj);
goto fail;
}

View File

@ -1282,6 +1282,9 @@ finished:
if (!con_is_bound(&fb_con))
fbcon_exit();
if (vc->vc_num == logo_shown)
logo_shown = FBCON_LOGO_CANSHOW;
return;
}