|
@@ -3674,15 +3674,24 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
|
|
|
drm_mode_connector_attach_encoder(connector, encoder);
|
|
|
|
|
|
if (dcbe->type == DCB_OUTPUT_DP) {
|
|
|
+ struct nv50_disp *disp = nv50_disp(encoder->dev);
|
|
|
struct nvkm_i2c_aux *aux =
|
|
|
nvkm_i2c_aux_find(i2c, dcbe->i2c_index);
|
|
|
if (aux) {
|
|
|
- nv_encoder->i2c = &nv_connector->aux.ddc;
|
|
|
+ if (disp->disp->oclass < GF110_DISP) {
|
|
|
+ /* HW has no support for address-only
|
|
|
+ * transactions, so we're required to
|
|
|
+ * use custom I2C-over-AUX code.
|
|
|
+ */
|
|
|
+ nv_encoder->i2c = &aux->i2c;
|
|
|
+ } else {
|
|
|
+ nv_encoder->i2c = &nv_connector->aux.ddc;
|
|
|
+ }
|
|
|
nv_encoder->aux = aux;
|
|
|
}
|
|
|
|
|
|
/*TODO: Use DP Info Table to check for support. */
|
|
|
- if (nv50_disp(encoder->dev)->disp->oclass >= GF110_DISP) {
|
|
|
+ if (disp->disp->oclass >= GF110_DISP) {
|
|
|
ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16,
|
|
|
nv_connector->base.base.id,
|
|
|
&nv_encoder->dp.mstm);
|
|
@@ -3931,6 +3940,8 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
|
|
|
|
|
NV_ATOMIC(drm, "%s: clr %04x (set %04x)\n", crtc->name,
|
|
|
asyh->clr.mask, asyh->set.mask);
|
|
|
+ if (crtc_state->active && !asyh->state.active)
|
|
|
+ drm_crtc_vblank_off(crtc);
|
|
|
|
|
|
if (asyh->clr.mask) {
|
|
|
nv50_head_flush_clr(head, asyh, atom->flush_disable);
|
|
@@ -4016,11 +4027,13 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
|
|
nv50_head_flush_set(head, asyh);
|
|
|
interlock_core = 1;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
|
|
- if (crtc->state->event)
|
|
|
- drm_crtc_vblank_get(crtc);
|
|
|
+ if (asyh->state.active) {
|
|
|
+ if (!crtc_state->active)
|
|
|
+ drm_crtc_vblank_on(crtc);
|
|
|
+ if (asyh->state.event)
|
|
|
+ drm_crtc_vblank_get(crtc);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* Update plane(s). */
|
|
@@ -4067,12 +4080,14 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
|
|
if (crtc->state->event) {
|
|
|
unsigned long flags;
|
|
|
/* Get correct count/ts if racing with vblank irq */
|
|
|
- drm_accurate_vblank_count(crtc);
|
|
|
+ if (crtc->state->active)
|
|
|
+ drm_accurate_vblank_count(crtc);
|
|
|
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
|
|
drm_crtc_send_vblank_event(crtc, crtc->state->event);
|
|
|
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
|
|
crtc->state->event = NULL;
|
|
|
- drm_crtc_vblank_put(crtc);
|
|
|
+ if (crtc->state->active)
|
|
|
+ drm_crtc_vblank_put(crtc);
|
|
|
}
|
|
|
}
|
|
|
|