mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-27 03:49:57 -04:00
drm/dp_mst: Store the MST PBN divider value in fixed point format
On UHBR links the PBN divider is a fractional number, accordingly store it in fixed point format. For now drm_dp_get_vc_payload_bw() always returns a whole number and all callers will use only the integer part of it which should preserve the current behavior. The next patch will fix drm_dp_get_vc_payload_bw() for UHBR rates returning a fractional number for those (also accounting for the channel coding efficiency correctly). Cc: Lyude Paul <lyude@redhat.com> Cc: Harry Wentland <harry.wentland@amd.com> Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Wayne Lin <wayne.lin@amd.com> Cc: amd-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> [Rebased changes in dm_helpers_construct_old_payload() on drm-intel-next] Signed-off-by: Imre Deak <imre.deak@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20231116131841.1588781-2-imre.deak@intel.com
This commit is contained in:
@@ -85,6 +85,7 @@
|
|||||||
#include <drm/drm_atomic_uapi.h>
|
#include <drm/drm_atomic_uapi.h>
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_blend.h>
|
#include <drm/drm_blend.h>
|
||||||
|
#include <drm/drm_fixed.h>
|
||||||
#include <drm/drm_fourcc.h>
|
#include <drm/drm_fourcc.h>
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
#include <drm/drm_vblank.h>
|
#include <drm/drm_vblank.h>
|
||||||
@@ -6863,8 +6864,8 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
|
|||||||
if (IS_ERR(mst_state))
|
if (IS_ERR(mst_state))
|
||||||
return PTR_ERR(mst_state);
|
return PTR_ERR(mst_state);
|
||||||
|
|
||||||
if (!mst_state->pbn_div)
|
if (!mst_state->pbn_div.full)
|
||||||
mst_state->pbn_div = dm_mst_get_pbn_divider(aconnector->mst_root->dc_link);
|
mst_state->pbn_div.full = dfixed_const(dm_mst_get_pbn_divider(aconnector->mst_root->dc_link));
|
||||||
|
|
||||||
if (!state->duplicated) {
|
if (!state->duplicated) {
|
||||||
int max_bpc = conn_state->max_requested_bpc;
|
int max_bpc = conn_state->max_requested_bpc;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
#include <drm/amdgpu_drm.h>
|
#include <drm/amdgpu_drm.h>
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
|
#include <drm/drm_fixed.h>
|
||||||
|
|
||||||
#include "dm_services.h"
|
#include "dm_services.h"
|
||||||
#include "amdgpu.h"
|
#include "amdgpu.h"
|
||||||
@@ -205,13 +206,14 @@ void dm_helpers_dp_update_branch_info(
|
|||||||
|
|
||||||
static void dm_helpers_construct_old_payload(
|
static void dm_helpers_construct_old_payload(
|
||||||
struct dc_link *link,
|
struct dc_link *link,
|
||||||
int pbn_per_slot,
|
fixed20_12 pbn_per_slot_fp,
|
||||||
struct drm_dp_mst_atomic_payload *new_payload,
|
struct drm_dp_mst_atomic_payload *new_payload,
|
||||||
struct drm_dp_mst_atomic_payload *old_payload)
|
struct drm_dp_mst_atomic_payload *old_payload)
|
||||||
{
|
{
|
||||||
struct link_mst_stream_allocation_table current_link_table =
|
struct link_mst_stream_allocation_table current_link_table =
|
||||||
link->mst_stream_alloc_table;
|
link->mst_stream_alloc_table;
|
||||||
struct link_mst_stream_allocation *dc_alloc;
|
struct link_mst_stream_allocation *dc_alloc;
|
||||||
|
int pbn_per_slot = dfixed_trunc(pbn_per_slot_fp);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
*old_payload = *new_payload;
|
*old_payload = *new_payload;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <drm/display/drm_dp_mst_helper.h>
|
#include <drm/display/drm_dp_mst_helper.h>
|
||||||
#include <drm/drm_atomic.h>
|
#include <drm/drm_atomic.h>
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
|
#include <drm/drm_fixed.h>
|
||||||
#include "dm_services.h"
|
#include "dm_services.h"
|
||||||
#include "amdgpu.h"
|
#include "amdgpu.h"
|
||||||
#include "amdgpu_dm.h"
|
#include "amdgpu_dm.h"
|
||||||
@@ -935,10 +936,10 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
|
|||||||
link_timeslots_used = 0;
|
link_timeslots_used = 0;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, mst_state->pbn_div);
|
link_timeslots_used += DIV_ROUND_UP(vars[i + k].pbn, dfixed_trunc(mst_state->pbn_div));
|
||||||
|
|
||||||
fair_pbn_alloc =
|
fair_pbn_alloc =
|
||||||
(63 - link_timeslots_used) / remaining_to_increase * mst_state->pbn_div;
|
(63 - link_timeslots_used) / remaining_to_increase * dfixed_trunc(mst_state->pbn_div);
|
||||||
|
|
||||||
if (initial_slack[next_index] > fair_pbn_alloc) {
|
if (initial_slack[next_index] > fair_pbn_alloc) {
|
||||||
vars[next_index].pbn += fair_pbn_alloc;
|
vars[next_index].pbn += fair_pbn_alloc;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_drv.h>
|
#include <drm/drm_drv.h>
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
|
#include <drm/drm_fixed.h>
|
||||||
#include <drm/drm_print.h>
|
#include <drm/drm_print.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
|
|
||||||
@@ -3578,16 +3579,22 @@ static int drm_dp_send_up_ack_reply(struct drm_dp_mst_topology_mgr *mgr,
|
|||||||
* value is in units of PBNs/(timeslots/1 MTP). This value can be used to
|
* value is in units of PBNs/(timeslots/1 MTP). This value can be used to
|
||||||
* convert the number of PBNs required for a given stream to the number of
|
* convert the number of PBNs required for a given stream to the number of
|
||||||
* timeslots this stream requires in each MTP.
|
* timeslots this stream requires in each MTP.
|
||||||
|
*
|
||||||
|
* Returns the BW / timeslot value in 20.12 fixed point format.
|
||||||
*/
|
*/
|
||||||
int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,
|
fixed20_12 drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,
|
||||||
int link_rate, int link_lane_count)
|
int link_rate, int link_lane_count)
|
||||||
{
|
{
|
||||||
|
fixed20_12 ret;
|
||||||
|
|
||||||
if (link_rate == 0 || link_lane_count == 0)
|
if (link_rate == 0 || link_lane_count == 0)
|
||||||
drm_dbg_kms(mgr->dev, "invalid link rate/lane count: (%d / %d)\n",
|
drm_dbg_kms(mgr->dev, "invalid link rate/lane count: (%d / %d)\n",
|
||||||
link_rate, link_lane_count);
|
link_rate, link_lane_count);
|
||||||
|
|
||||||
/* See DP v2.0 2.6.4.2, VCPayload_Bandwidth_for_OneTimeSlotPer_MTP_Allocation */
|
/* See DP v2.0 2.6.4.2, VCPayload_Bandwidth_for_OneTimeSlotPer_MTP_Allocation */
|
||||||
return link_rate * link_lane_count / 54000;
|
ret.full = dfixed_const(link_rate * link_lane_count / 54000);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_dp_get_vc_payload_bw);
|
EXPORT_SYMBOL(drm_dp_get_vc_payload_bw);
|
||||||
|
|
||||||
@@ -4335,7 +4342,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req_slots = DIV_ROUND_UP(pbn, topology_state->pbn_div);
|
req_slots = DIV_ROUND_UP(pbn, dfixed_trunc(topology_state->pbn_div));
|
||||||
|
|
||||||
drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] TU %d -> %d\n",
|
drm_dbg_atomic(mgr->dev, "[CONNECTOR:%d:%s] [MST PORT:%p] TU %d -> %d\n",
|
||||||
port->connector->base.id, port->connector->name,
|
port->connector->base.id, port->connector->name,
|
||||||
@@ -4872,7 +4879,8 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
|
|||||||
state = to_drm_dp_mst_topology_state(mgr->base.state);
|
state = to_drm_dp_mst_topology_state(mgr->base.state);
|
||||||
seq_printf(m, "\n*** Atomic state info ***\n");
|
seq_printf(m, "\n*** Atomic state info ***\n");
|
||||||
seq_printf(m, "payload_mask: %x, max_payloads: %d, start_slot: %u, pbn_div: %d\n",
|
seq_printf(m, "payload_mask: %x, max_payloads: %d, start_slot: %u, pbn_div: %d\n",
|
||||||
state->payload_mask, mgr->max_payloads, state->start_slot, state->pbn_div);
|
state->payload_mask, mgr->max_payloads, state->start_slot,
|
||||||
|
dfixed_trunc(state->pbn_div));
|
||||||
|
|
||||||
seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc | status | sink name |\n");
|
seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc | status | sink name |\n");
|
||||||
for (i = 0; i < mgr->max_payloads; i++) {
|
for (i = 0; i < mgr->max_payloads; i++) {
|
||||||
@@ -5330,10 +5338,10 @@ drm_dp_mst_atomic_check_payload_alloc_limits(struct drm_dp_mst_topology_mgr *mgr
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!payload_count)
|
if (!payload_count)
|
||||||
mst_state->pbn_div = 0;
|
mst_state->pbn_div.full = dfixed_const(0);
|
||||||
|
|
||||||
drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p TU pbn_div=%d avail=%d used=%d\n",
|
drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p TU pbn_div=%d avail=%d used=%d\n",
|
||||||
mgr, mst_state, mst_state->pbn_div, avail_slots,
|
mgr, mst_state, dfixed_trunc(mst_state->pbn_div), avail_slots,
|
||||||
mst_state->total_avail_slots - avail_slots);
|
mst_state->total_avail_slots - avail_slots);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <drm/drm_atomic.h>
|
#include <drm/drm_atomic.h>
|
||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
|
#include <drm/drm_fixed.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
|
|
||||||
#include "i915_drv.h"
|
#include "i915_drv.h"
|
||||||
@@ -202,7 +203,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
|
|||||||
*/
|
*/
|
||||||
drm_WARN_ON(&i915->drm, remote_m_n.tu < crtc_state->dp_m_n.tu);
|
drm_WARN_ON(&i915->drm, remote_m_n.tu < crtc_state->dp_m_n.tu);
|
||||||
crtc_state->dp_m_n.tu = remote_m_n.tu;
|
crtc_state->dp_m_n.tu = remote_m_n.tu;
|
||||||
crtc_state->pbn = remote_m_n.tu * mst_state->pbn_div;
|
crtc_state->pbn = remote_m_n.tu * dfixed_trunc(mst_state->pbn_div);
|
||||||
|
|
||||||
slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
|
slots = drm_dp_atomic_find_time_slots(state, &intel_dp->mst_mgr,
|
||||||
connector->port,
|
connector->port,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include <drm/drm_atomic_helper.h>
|
#include <drm/drm_atomic_helper.h>
|
||||||
#include <drm/drm_edid.h>
|
#include <drm/drm_edid.h>
|
||||||
#include <drm/drm_fb_helper.h>
|
#include <drm/drm_fb_helper.h>
|
||||||
|
#include <drm/drm_fixed.h>
|
||||||
#include <drm/drm_probe_helper.h>
|
#include <drm/drm_probe_helper.h>
|
||||||
#include <drm/drm_vblank.h>
|
#include <drm/drm_vblank.h>
|
||||||
|
|
||||||
@@ -945,7 +946,8 @@ nv50_msto_prepare(struct drm_atomic_state *state,
|
|||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index,
|
nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index,
|
||||||
payload->vc_start_slot, payload->time_slots,
|
payload->vc_start_slot, payload->time_slots,
|
||||||
payload->pbn, payload->time_slots * mst_state->pbn_div);
|
payload->pbn,
|
||||||
|
payload->time_slots * dfixed_trunc(mst_state->pbn_div));
|
||||||
} else {
|
} else {
|
||||||
nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
|
nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -989,7 +991,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
|
|||||||
if (IS_ERR(mst_state))
|
if (IS_ERR(mst_state))
|
||||||
return PTR_ERR(mst_state);
|
return PTR_ERR(mst_state);
|
||||||
|
|
||||||
if (!mst_state->pbn_div) {
|
if (!mst_state->pbn_div.full) {
|
||||||
struct nouveau_encoder *outp = mstc->mstm->outp;
|
struct nouveau_encoder *outp = mstc->mstm->outp;
|
||||||
|
|
||||||
mst_state->pbn_div = drm_dp_get_vc_payload_bw(&mstm->mgr,
|
mst_state->pbn_div = drm_dp_get_vc_payload_bw(&mstm->mgr,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <drm/display/drm_dp_helper.h>
|
#include <drm/display/drm_dp_helper.h>
|
||||||
#include <drm/drm_atomic.h>
|
#include <drm/drm_atomic.h>
|
||||||
|
#include <drm/drm_fixed.h>
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
|
#if IS_ENABLED(CONFIG_DRM_DEBUG_DP_MST_TOPOLOGY_REFS)
|
||||||
#include <linux/stackdepot.h>
|
#include <linux/stackdepot.h>
|
||||||
@@ -617,7 +618,7 @@ struct drm_dp_mst_topology_state {
|
|||||||
* @pbn_div: The current PBN divisor for this topology. The driver is expected to fill this
|
* @pbn_div: The current PBN divisor for this topology. The driver is expected to fill this
|
||||||
* out itself.
|
* out itself.
|
||||||
*/
|
*/
|
||||||
int pbn_div;
|
fixed20_12 pbn_div;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define to_dp_mst_topology_mgr(x) container_of(x, struct drm_dp_mst_topology_mgr, base)
|
#define to_dp_mst_topology_mgr(x) container_of(x, struct drm_dp_mst_topology_mgr, base)
|
||||||
@@ -839,8 +840,8 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector,
|
|||||||
struct drm_dp_mst_topology_mgr *mgr,
|
struct drm_dp_mst_topology_mgr *mgr,
|
||||||
struct drm_dp_mst_port *port);
|
struct drm_dp_mst_port *port);
|
||||||
|
|
||||||
int drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,
|
fixed20_12 drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr,
|
||||||
int link_rate, int link_lane_count);
|
int link_rate, int link_lane_count);
|
||||||
|
|
||||||
int drm_dp_calc_pbn_mode(int clock, int bpp);
|
int drm_dp_calc_pbn_mode(int clock, int bpp);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user