Commit 32bbc3d4 authored by Madhav Chauhan's avatar Madhav Chauhan Committed by Jani Nikula

drm/i915/icl: Wait for header/payload credits release

Driver needs payload/header credits for sending any command
and data over DSI link. These credits are released once command
or data sent to link. This patch adds functions to wait for releasing
of payload and header credits.

As per BSPEC, driver needs to ensure that all of commands/data
has been dispatched to panel before the transcoder is enabled.
This patch implement those steps i.e. sending NOP DCS command,
wait for header/payload credit to be released etc.

v2 by Jani:
 - squash the credit wait helpers patch with the first user
 - pass dev_priv to the credit wait helpers
 - bikeshed credit helper names
 - wait for *at least* the current maximum number of credits
 - indentation fix
 - add helpers for credits available
Signed-off-by: default avatarMadhav Chauhan <madhav.chauhan@intel.com>
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/84bc509beabf2a2d1324a9f2a67ab4ebe05b10a6.1540900289.git.jani.nikula@intel.com
parent 77c8fdae
...@@ -28,6 +28,36 @@ ...@@ -28,6 +28,36 @@
#include <drm/drm_mipi_dsi.h> #include <drm/drm_mipi_dsi.h>
#include "intel_dsi.h" #include "intel_dsi.h"
static inline int header_credits_available(struct drm_i915_private *dev_priv,
enum transcoder dsi_trans)
{
return (I915_READ(DSI_CMD_TXCTL(dsi_trans)) & FREE_HEADER_CREDIT_MASK)
>> FREE_HEADER_CREDIT_SHIFT;
}
static inline int payload_credits_available(struct drm_i915_private *dev_priv,
enum transcoder dsi_trans)
{
return (I915_READ(DSI_CMD_TXCTL(dsi_trans)) & FREE_PLOAD_CREDIT_MASK)
>> FREE_PLOAD_CREDIT_SHIFT;
}
static void wait_for_header_credits(struct drm_i915_private *dev_priv,
enum transcoder dsi_trans)
{
if (wait_for_us(header_credits_available(dev_priv, dsi_trans) >=
MAX_HEADER_CREDIT, 100))
DRM_ERROR("DSI header credits not released\n");
}
static void wait_for_payload_credits(struct drm_i915_private *dev_priv,
enum transcoder dsi_trans)
{
if (wait_for_us(payload_credits_available(dev_priv, dsi_trans) >=
MAX_PLOAD_CREDIT, 100))
DRM_ERROR("DSI payload credits not released\n");
}
static enum transcoder dsi_port_to_transcoder(enum port port) static enum transcoder dsi_port_to_transcoder(enum port port)
{ {
if (port == PORT_A) if (port == PORT_A)
...@@ -36,6 +66,47 @@ static enum transcoder dsi_port_to_transcoder(enum port port) ...@@ -36,6 +66,47 @@ static enum transcoder dsi_port_to_transcoder(enum port port)
return TRANSCODER_DSI_1; return TRANSCODER_DSI_1;
} }
static void wait_for_cmds_dispatched_to_panel(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
struct mipi_dsi_device *dsi;
enum port port;
enum transcoder dsi_trans;
int ret;
/* wait for header/payload credits to be released */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
wait_for_header_credits(dev_priv, dsi_trans);
wait_for_payload_credits(dev_priv, dsi_trans);
}
/* send nop DCS command */
for_each_dsi_port(port, intel_dsi->ports) {
dsi = intel_dsi->dsi_hosts[port]->device;
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
dsi->channel = 0;
ret = mipi_dsi_dcs_nop(dsi);
if (ret < 0)
DRM_ERROR("error sending DCS NOP command\n");
}
/* wait for header credits to be released */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
wait_for_header_credits(dev_priv, dsi_trans);
}
/* wait for LP TX in progress bit to be cleared */
for_each_dsi_port(port, intel_dsi->ports) {
dsi_trans = dsi_port_to_transcoder(port);
if (wait_for_us(!(I915_READ(DSI_LP_MSG(dsi_trans)) &
LPTX_IN_PROGRESS), 20))
DRM_ERROR("LPTX bit not cleared\n");
}
}
static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder) static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
{ {
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
...@@ -671,6 +742,9 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) ...@@ -671,6 +742,9 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder)
intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET);
intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP);
intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON);
/* ensure all panel commands dispatched before enabling transcoder */
wait_for_cmds_dispatched_to_panel(encoder);
} }
static void __attribute__((unused)) static void __attribute__((unused))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment