DCON status update

Adam Jackson ajackson at redhat.com
Mon Jun 11 10:47:36 EDT 2007


Just wanted to let people know where I'm at with the DCON support for X.
It's a little ugly, so, those with weak stomachs should read with the
'd' key.

A brief overview.  The DCON controls are exposed in sysfs
under /sys/devices/platform/dcon.  The video driver checks if that path
exists, and uses the files therein to do handoff between DCON and GPU
ownership of the screen.  The X server sets a damage handler on the root
window pixmap, and uses that to initiate transition from the DCON back
to the GPU.  The damage handler also sets a soft timer to expire one
frame time in the future; however, this timer is continuously pushed
back as more updates come in to the screen, so as long as you keep
drawing to the screen, the GPU remains in control.  Once the timer
fires, the X server tells the kernel to switch to DCON control.
(There's a detail or two I'm omitting here, having to do with Xv and
with VT switch, but pretend I didn't say anything.)

This is about as optimal as we can get on the X side.  Note that since
the damage handler responds to damage on the root window only, X can
still be doing stuff while the DCON is in control - render to offscreen
pixmaps, send events and messages, etc.  The "one frame time" idle
estimate is a bit of a hack, but it seems reasonable so far, we don't
have any better way of guessing, and we have to make _some_ guess, since
the handoff between the two isn't automatic.

The kernel is what implements the actual handoff between GPU and DCON
and back.  GPU to DCON transition is simple enough: you wiggle a pin on
the DCON, which waits for the next full frame from the GPU, loads it
into its internal RAM, and then takes over the screen, after which we
power down the TFT interface on the GPU.  This is non-optimal, frame
load and display takeover should be separate operations, but they're not
and the silicon ain't about to change for Gen1.  Oh well.  Works, looks
very pretty.

Going back the other direction is proving to be challenging.  You need
to switch sources during the vertical retrace interval, to avoid
glitching.  But the pixel clocks for the DCON and GPU are not the same
and will skew. [1]  So you need to get the two clocks to align somehow,
at least to the point of both sources clocking out a vsync cycle at the
same time.

You can't know where you are on the DCON's scanout through the frame,
because while we do get an interrupt for any single scanline we want, we
can't tell which one we're on _now_.  You could take scanline interrupts
from the DCON continuously, and interpolate over time, but obviously
that's not acceptable for power reasons.  And I _think_ you can do
multiple scanline interrupts per frame, since that seems like the easy
and lazy way of building the hardware, but I'm not sure.

On LX and possibly also GX, we can also read which scanline we're on.
For LX, we can get interrupts on arbitrary GPU scanline as well.  But we
have no idea - besides "sometime in the next frame time" - what the
interval is between powering up the TFT pixel pump, and when it will hit
the next vsync.  Also, we can only change timings for the GPU at vsync.
And again, we could try to PLL the GPU and DCON clocks together by not
powering down the pixel pump on the GPU, taking vblank intervals on
both, and shifting them together, but that defeats the whole point of
having a DCON.

So the idea currently looks like: before sleeping the LX, set it to scan
out as tiny of frames as possible, so we'll get lots of fine-grained
chances to change timings.  When we wake up, set a series of scanline
interrupts on the DCON, and measure the timing between the two, so we
can figure out both where we are in the frame, and how much the DCON
clock is skewed from the GPU clock.  At the second measurement, compute
a new frame size to scan out that puts the vblank of the DCON and of the
GPU at the same time.  Set one more DCON scanline interrupt for just
before end-of-frame, since it takes time to post the DCONLOAD write
through GPIO, such that DCONLOAD is deasserted during the blank
interval.

And, hopefully, win.  It's 1+epsilon frames, but I think that's as good
as you can hope for anyway.

[1] - They could be tied together, now, maybe, since LX supports genlock
but GX didn't.  I don't know if we could change that at this point in
time, both due to time constraints and because I don't know if the DCON
can be made to clock constantly.  I think it's built so that when in GPU
mode it turns off internal clocking and uses the GPU clock, in which
case there's no chance of changing it.  But if we can change it, then
this whole discussion gets a lot simpler, you just set the scanline
interrupt for the right timing to deassert DCONLOAD during blank, and
you're done.

- ajax




More information about the Devel mailing list