drm/i915: Write AVI infoframes for MCA LSPCON
LSPCON is a DP branch device, so LSPCON vendors define specific methods to pass AVI infoframes to the the chip. This patch adds: - a generic wrapper function for writing AVI infoframes for all LSPCON devices. - a vendor specific function to wrire AVI infoframes into MCA LSPCON devices. V2: Rebase V3: Added r-b from Maarten V4: Rebase V5: Rebase V6: Rebase V7: Fixed checkpatch warnings for alignment V8: Rebase V9: Added the retry logic, with 50ms incremental delays while writing AVI IF V10: Changed the return value check V11: Fixed checkpatch warning V12: Rebase Cc: Imre Deak <imre.deak@intel.com> Cc: Ville Syrjälä <ville.syrjala@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-6-git-send-email-shashank.sharma@intel.com
This commit is contained in:
parent
06c812d7c5
commit
7cbf19fd54
|
@ -2215,6 +2215,10 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state);
|
|||
bool lspcon_init(struct intel_digital_port *intel_dig_port);
|
||||
void lspcon_resume(struct intel_lspcon *lspcon);
|
||||
void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
|
||||
void lspcon_write_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
unsigned int type,
|
||||
const void *buf, ssize_t len);
|
||||
void lspcon_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
|
|
|
@ -2322,6 +2322,8 @@ void intel_infoframe_init(struct intel_digital_port *intel_dig_port)
|
|||
intel_dig_port->infoframe_enabled = g4x_infoframe_enabled;
|
||||
} else if (HAS_DDI(dev_priv)) {
|
||||
if (intel_dig_port->lspcon.active) {
|
||||
intel_dig_port->write_infoframe =
|
||||
lspcon_write_infoframe;
|
||||
intel_dig_port->set_infoframes = lspcon_set_infoframes;
|
||||
intel_dig_port->infoframe_enabled =
|
||||
lspcon_infoframe_enabled;
|
||||
|
|
|
@ -31,6 +31,12 @@
|
|||
#define LSPCON_VENDOR_PARADE_OUI 0x001CF8
|
||||
#define LSPCON_VENDOR_MCA_OUI 0x0060AD
|
||||
|
||||
/* AUX addresses to write MCA AVI IF */
|
||||
#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
|
||||
#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
|
||||
#define LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
|
||||
#define LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
|
||||
|
||||
static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
|
||||
{
|
||||
struct intel_digital_port *dig_port =
|
||||
|
@ -234,6 +240,88 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
|
|||
DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n");
|
||||
}
|
||||
|
||||
static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux,
|
||||
const uint8_t *buffer, ssize_t len)
|
||||
{
|
||||
int ret;
|
||||
uint32_t val = 0;
|
||||
uint32_t retry;
|
||||
uint16_t reg;
|
||||
const uint8_t *data = buffer;
|
||||
|
||||
reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
|
||||
while (val < len) {
|
||||
/* DPCD write for AVI IF can fail on a slow FW day, so retry */
|
||||
for (retry = 0; retry < 5; retry++) {
|
||||
ret = drm_dp_dpcd_write(aux, reg, (void *)data, 1);
|
||||
if (ret == 1) {
|
||||
break;
|
||||
} else if (retry < 4) {
|
||||
mdelay(50);
|
||||
continue;
|
||||
} else {
|
||||
DRM_ERROR("DPCD write failed at:0x%x\n", reg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
val++; reg++; data++;
|
||||
}
|
||||
|
||||
val = 0;
|
||||
reg = LSPCON_MCA_AVI_IF_CTRL;
|
||||
ret = drm_dp_dpcd_read(aux, reg, &val, 1);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
|
||||
val &= ~LSPCON_MCA_AVI_IF_HANDLED;
|
||||
val |= LSPCON_MCA_AVI_IF_KICKOFF;
|
||||
|
||||
ret = drm_dp_dpcd_write(aux, reg, &val, 1);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
|
||||
return false;
|
||||
}
|
||||
|
||||
val = 0;
|
||||
ret = drm_dp_dpcd_read(aux, reg, &val, 1);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (val == LSPCON_MCA_AVI_IF_HANDLED)
|
||||
DRM_DEBUG_KMS("AVI IF handled by FW\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void lspcon_write_infoframe(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
unsigned int type,
|
||||
const void *frame, ssize_t len)
|
||||
{
|
||||
bool ret = true;
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
|
||||
struct intel_lspcon *lspcon = enc_to_intel_lspcon(&encoder->base);
|
||||
|
||||
/* LSPCON only needs AVI IF */
|
||||
if (type != HDMI_INFOFRAME_TYPE_AVI)
|
||||
return;
|
||||
|
||||
if (lspcon->vendor == LSPCON_VENDOR_MCA)
|
||||
ret = _lspcon_write_avi_infoframe_mca(&intel_dp->aux,
|
||||
frame, len);
|
||||
if (!ret) {
|
||||
DRM_ERROR("Failed to write AVI infoframes\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
|
||||
}
|
||||
|
||||
void lspcon_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
|
|
Loading…
Reference in New Issue