|
@@ -208,9 +208,10 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
|
|
{
|
|
{
|
|
struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
|
|
struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
|
|
unsigned int num_planes = 0;
|
|
unsigned int num_planes = 0;
|
|
|
|
+ unsigned int dptsr_planes;
|
|
|
|
+ unsigned int hwplanes = 0;
|
|
unsigned int prio = 0;
|
|
unsigned int prio = 0;
|
|
unsigned int i;
|
|
unsigned int i;
|
|
- u32 dptsr = 0;
|
|
|
|
u32 dspr = 0;
|
|
u32 dspr = 0;
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) {
|
|
for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) {
|
|
@@ -238,37 +239,44 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
|
|
|
|
|
|
prio -= 4;
|
|
prio -= 4;
|
|
dspr |= (index + 1) << prio;
|
|
dspr |= (index + 1) << prio;
|
|
- dptsr |= DPTSR_PnDK(index) | DPTSR_PnTS(index);
|
|
|
|
|
|
+ hwplanes |= 1 << index;
|
|
|
|
|
|
if (plane_format(plane)->planes == 2) {
|
|
if (plane_format(plane)->planes == 2) {
|
|
index = (index + 1) % 8;
|
|
index = (index + 1) % 8;
|
|
|
|
|
|
prio -= 4;
|
|
prio -= 4;
|
|
dspr |= (index + 1) << prio;
|
|
dspr |= (index + 1) << prio;
|
|
- dptsr |= DPTSR_PnDK(index) | DPTSR_PnTS(index);
|
|
|
|
|
|
+ hwplanes |= 1 << index;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /* Select display timing and dot clock generator 2 for planes associated
|
|
|
|
- * with superposition controller 2.
|
|
|
|
|
|
+ /* Update the planes to display timing and dot clock generator
|
|
|
|
+ * associations.
|
|
|
|
+ *
|
|
|
|
+ * Updating the DPTSR register requires restarting the CRTC group,
|
|
|
|
+ * resulting in visible flicker. To mitigate the issue only update the
|
|
|
|
+ * association if needed by enabled planes. Planes being disabled will
|
|
|
|
+ * keep their current association.
|
|
|
|
+ *
|
|
|
|
+ * To mitigate the issue further we could pre-associate planes with
|
|
|
|
+ * CRTCs, either with a fixed 4/4 split, or through a module parameter.
|
|
*/
|
|
*/
|
|
- if (rcrtc->index % 2) {
|
|
|
|
- /* The DPTSR register is updated when the display controller is
|
|
|
|
- * stopped. We thus need to restart the DU. Once again, sorry
|
|
|
|
- * for the flicker. One way to mitigate the issue would be to
|
|
|
|
- * pre-associate planes with CRTCs (either with a fixed 4/4
|
|
|
|
- * split, or through a module parameter). Flicker would then
|
|
|
|
- * occur only if we need to break the pre-association.
|
|
|
|
- */
|
|
|
|
- mutex_lock(&rcrtc->group->lock);
|
|
|
|
- if (rcar_du_group_read(rcrtc->group, DPTSR) != dptsr) {
|
|
|
|
- rcar_du_group_write(rcrtc->group, DPTSR, dptsr);
|
|
|
|
- if (rcrtc->group->used_crtcs)
|
|
|
|
- rcar_du_group_restart(rcrtc->group);
|
|
|
|
- }
|
|
|
|
- mutex_unlock(&rcrtc->group->lock);
|
|
|
|
|
|
+ mutex_lock(&rcrtc->group->lock);
|
|
|
|
+
|
|
|
|
+ dptsr_planes = rcrtc->index % 2 ? rcrtc->group->dptsr_planes | hwplanes
|
|
|
|
+ : rcrtc->group->dptsr_planes & ~hwplanes;
|
|
|
|
+
|
|
|
|
+ if (dptsr_planes != rcrtc->group->dptsr_planes) {
|
|
|
|
+ rcar_du_group_write(rcrtc->group, DPTSR,
|
|
|
|
+ (dptsr_planes << 16) | dptsr_planes);
|
|
|
|
+ rcrtc->group->dptsr_planes = dptsr_planes;
|
|
|
|
+
|
|
|
|
+ if (rcrtc->group->used_crtcs)
|
|
|
|
+ rcar_du_group_restart(rcrtc->group);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ mutex_unlock(&rcrtc->group->lock);
|
|
|
|
+
|
|
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
|
|
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
|
|
dspr);
|
|
dspr);
|
|
}
|
|
}
|