drm/i915: Add AVI infoframe support for LSPCON
In order to pass AVI infoframes to LSPCON devices, a source has to write them in a vendor recommended method and location. This patch series: - adds generic LSPCON infoframe setup functions. - registers these functions into existing AVI infoframe framework. - triggers these functions from modeset sequence. Next patches in the series will add vendor specific code. V2: Added new parameter to align with new definition of drm_hdmi_avi_infoframe_quant_range V3: Added r-b from Maarten (for V2) Added new parameter output_format in struct lspcon to accommodate Ville's review comments on last patch of the series V4: Addressed Ville's review comment - Do not add output_format in LSPCON state, as its non-atomic. Add this into CRTC state (added in a later patch). V5: Rebase V6: Rebase V7: Rebase V8: Rebase V9: Rebase V10: Rebase V11: Accommodated rebasing changes in intel_git_port fptrs (set_infoframes and infoframe_enabled) Cc: Ville Syrjala <ville.syrjala@linux.intel.com> Cc: Imre Deak <imre.deak@linux.intel.com> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/1539325394-20788-5-git-send-email-shashank.sharma@intel.com
This commit is contained in:
parent
96e35598ce
commit
06c812d7c5
|
@ -2978,10 +2978,22 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder,
|
||||||
|
|
||||||
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
|
||||||
|
|
||||||
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
|
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
|
||||||
intel_ddi_pre_enable_hdmi(encoder, crtc_state, conn_state);
|
intel_ddi_pre_enable_hdmi(encoder, crtc_state, conn_state);
|
||||||
else
|
} else {
|
||||||
|
struct intel_lspcon *lspcon =
|
||||||
|
enc_to_intel_lspcon(&encoder->base);
|
||||||
|
|
||||||
intel_ddi_pre_enable_dp(encoder, crtc_state, conn_state);
|
intel_ddi_pre_enable_dp(encoder, crtc_state, conn_state);
|
||||||
|
if (lspcon->active) {
|
||||||
|
struct intel_digital_port *dig_port =
|
||||||
|
enc_to_dig_port(&encoder->base);
|
||||||
|
|
||||||
|
dig_port->set_infoframes(encoder,
|
||||||
|
crtc_state->has_infoframe,
|
||||||
|
crtc_state, conn_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_disable_ddi_buf(struct intel_encoder *encoder)
|
static void intel_disable_ddi_buf(struct intel_encoder *encoder)
|
||||||
|
@ -3845,8 +3857,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
|
||||||
MISSING_CASE(port);
|
MISSING_CASE(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
intel_infoframe_init(intel_dig_port);
|
|
||||||
|
|
||||||
if (init_dp) {
|
if (init_dp) {
|
||||||
if (!intel_ddi_init_dp_connector(intel_dig_port))
|
if (!intel_ddi_init_dp_connector(intel_dig_port))
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -3875,6 +3885,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
|
||||||
port_name(port));
|
port_name(port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intel_infoframe_init(intel_dig_port);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
|
|
@ -1318,6 +1318,12 @@ static inline bool intel_encoder_is_dp(struct intel_encoder *encoder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct intel_lspcon *
|
||||||
|
enc_to_intel_lspcon(struct drm_encoder *encoder)
|
||||||
|
{
|
||||||
|
return &enc_to_dig_port(encoder)->lspcon;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct intel_digital_port *
|
static inline struct intel_digital_port *
|
||||||
dp_to_dig_port(struct intel_dp *intel_dp)
|
dp_to_dig_port(struct intel_dp *intel_dp)
|
||||||
{
|
{
|
||||||
|
@ -1879,7 +1885,6 @@ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder,
|
||||||
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
|
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
|
||||||
void intel_infoframe_init(struct intel_digital_port *intel_dig_port);
|
void intel_infoframe_init(struct intel_digital_port *intel_dig_port);
|
||||||
|
|
||||||
|
|
||||||
/* intel_lvds.c */
|
/* intel_lvds.c */
|
||||||
bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv,
|
bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv,
|
||||||
i915_reg_t lvds_reg, enum pipe *pipe);
|
i915_reg_t lvds_reg, enum pipe *pipe);
|
||||||
|
@ -2210,6 +2215,12 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state);
|
||||||
bool lspcon_init(struct intel_digital_port *intel_dig_port);
|
bool lspcon_init(struct intel_digital_port *intel_dig_port);
|
||||||
void lspcon_resume(struct intel_lspcon *lspcon);
|
void lspcon_resume(struct intel_lspcon *lspcon);
|
||||||
void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
|
void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
|
||||||
|
void lspcon_set_infoframes(struct intel_encoder *encoder,
|
||||||
|
bool enable,
|
||||||
|
const struct intel_crtc_state *crtc_state,
|
||||||
|
const struct drm_connector_state *conn_state);
|
||||||
|
bool lspcon_infoframe_enabled(struct intel_encoder *encoder,
|
||||||
|
const struct intel_crtc_state *pipe_config);
|
||||||
|
|
||||||
/* intel_pipe_crc.c */
|
/* intel_pipe_crc.c */
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
|
@ -2321,9 +2321,16 @@ void intel_infoframe_init(struct intel_digital_port *intel_dig_port)
|
||||||
intel_dig_port->set_infoframes = g4x_set_infoframes;
|
intel_dig_port->set_infoframes = g4x_set_infoframes;
|
||||||
intel_dig_port->infoframe_enabled = g4x_infoframe_enabled;
|
intel_dig_port->infoframe_enabled = g4x_infoframe_enabled;
|
||||||
} else if (HAS_DDI(dev_priv)) {
|
} else if (HAS_DDI(dev_priv)) {
|
||||||
intel_dig_port->write_infoframe = hsw_write_infoframe;
|
if (intel_dig_port->lspcon.active) {
|
||||||
|
intel_dig_port->set_infoframes = lspcon_set_infoframes;
|
||||||
|
intel_dig_port->infoframe_enabled =
|
||||||
|
lspcon_infoframe_enabled;
|
||||||
|
} else {
|
||||||
intel_dig_port->set_infoframes = hsw_set_infoframes;
|
intel_dig_port->set_infoframes = hsw_set_infoframes;
|
||||||
intel_dig_port->infoframe_enabled = hsw_infoframe_enabled;
|
intel_dig_port->infoframe_enabled =
|
||||||
|
hsw_infoframe_enabled;
|
||||||
|
intel_dig_port->write_infoframe = hsw_write_infoframe;
|
||||||
|
}
|
||||||
} else if (HAS_PCH_IBX(dev_priv)) {
|
} else if (HAS_PCH_IBX(dev_priv)) {
|
||||||
intel_dig_port->write_infoframe = ibx_write_infoframe;
|
intel_dig_port->write_infoframe = ibx_write_infoframe;
|
||||||
intel_dig_port->set_infoframes = ibx_set_infoframes;
|
intel_dig_port->set_infoframes = ibx_set_infoframes;
|
||||||
|
|
|
@ -234,6 +234,55 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
|
||||||
DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n");
|
DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lspcon_set_infoframes(struct intel_encoder *encoder,
|
||||||
|
bool enable,
|
||||||
|
const struct intel_crtc_state *crtc_state,
|
||||||
|
const struct drm_connector_state *conn_state)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
union hdmi_infoframe frame;
|
||||||
|
uint8_t buf[VIDEO_DIP_DATA_SIZE];
|
||||||
|
struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
|
||||||
|
struct intel_lspcon *lspcon = &dig_port->lspcon;
|
||||||
|
struct intel_dp *intel_dp = &dig_port->dp;
|
||||||
|
struct drm_connector *connector = &intel_dp->attached_connector->base;
|
||||||
|
const struct drm_display_mode *mode = &crtc_state->base.adjusted_mode;
|
||||||
|
bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
|
||||||
|
|
||||||
|
if (!lspcon->active) {
|
||||||
|
DRM_ERROR("Writing infoframes while LSPCON disabled ?\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
|
||||||
|
mode, is_hdmi2_sink);
|
||||||
|
if (ret < 0) {
|
||||||
|
DRM_ERROR("couldn't fill AVI infoframe\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_hdmi_avi_infoframe_quant_range(&frame.avi, mode,
|
||||||
|
crtc_state->limited_color_range ?
|
||||||
|
HDMI_QUANTIZATION_RANGE_LIMITED :
|
||||||
|
HDMI_QUANTIZATION_RANGE_FULL,
|
||||||
|
false, is_hdmi2_sink);
|
||||||
|
|
||||||
|
ret = hdmi_infoframe_pack(&frame, buf, sizeof(buf));
|
||||||
|
if (ret < 0) {
|
||||||
|
DRM_ERROR("Failed to pack AVI IF\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dig_port->write_infoframe(encoder, crtc_state, HDMI_INFOFRAME_TYPE_AVI,
|
||||||
|
buf, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lspcon_infoframe_enabled(struct intel_encoder *encoder,
|
||||||
|
const struct intel_crtc_state *pipe_config)
|
||||||
|
{
|
||||||
|
return enc_to_intel_lspcon(&encoder->base)->active;
|
||||||
|
}
|
||||||
|
|
||||||
void lspcon_resume(struct intel_lspcon *lspcon)
|
void lspcon_resume(struct intel_lspcon *lspcon)
|
||||||
{
|
{
|
||||||
enum drm_lspcon_mode expected_mode;
|
enum drm_lspcon_mode expected_mode;
|
||||||
|
|
Loading…
Reference in New Issue