Bug 71769

Summary: Monitor not recognizing RGB limited/full color range
Product: DRI Reporter: Lauri Mylläri <lauri.myllari>
Component: DRM/IntelAssignee: Ville Syrjala <ville.syrjala>
Status: CLOSED FIXED QA Contact: Intel GFX Bugs mailing list <intel-gfx-bugs>
Severity: normal    
Priority: medium CC: intel-gfx-bugs, tuksgig
Version: unspecified   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Attachments:
Description Flags
dmesg output with drm.debug=0xe
none
dmesg output from switching range with xrandr
none
EDID data from /sys/class/drm/card0-HDMI-A-1/edid
none
Fix for limited range output on HSW+ none

Description Lauri Mylläri 2013-11-19 05:17:36 UTC
Created attachment 89442 [details]
dmesg output with drm.debug=0xe

I am outputting from a D54250WYK NUC to Pioneer KRP-500m (via Yamaha RX-A1000) and seeing grey blacks with the default limited RGB range. When I switch to full range using xrandr, picture is fine.

I assume my monitor supports switching RGB range automatically as my bluray player is able to signal it. The player (Oppo BDP-93) allows selecting between "RGB Video Level", "RGB PC Level", "YCbCr 4:4:4" and "YCbCr 4:2:2". These all seem to function as expected (tested with manual input settings on the monitor). Switching between "RGB Video Level" and "RGB PC Level" doesn't affect visible black levels when monitor is set to automatic input format, but using manual input level setting on the monitor confirms that the RGB range changes between them.

I am attaching dmesg output with drm.debug=0xe, dmesg output from 'xrandr --output HDMI1 --set "Broadcast RGB" "Limited 16:235"' and EDID read from /sys/class/drm/card0-HDMI-A-1/edid. The kernel is drm-intel-next from Ubuntu mainline archive, git commit 7f16e5c1416070dc590dd333a2d677700046a4ab (I see same behavior with standard Ubuntu 13.10 and OpenELEC 3.2.3 kernels).

I tried checking the register values for AVI infoframe and got the following:

$ sudo intel_reg_read -c 4 0x60220
0x60220 : 0xD0282
0x60224 : 0x808103F
0x60228 : 0x10
0x6022C : 0x0
$ DISPLAY=:0 xrandr --output HDMI1 --set "Broadcast RGB" "Limited 16:235"
lauri@lauri-nuc:~$ sudo intel_reg_read -c 4 0x60220
0x60220 : 0xD0282
0x60224 : 0x4081043
0x60228 : 0x10
0x6022C : 0x0

I decoded these using http://www.edidreader.com/infoframes/avi/ and they look fine to me. Below the blocks in a suitable format for convenience.

0x82 0x02 0x0D 0x3F
0x10 0x08 0x08 0x10
0x00 0x00 0x00 0x00
0x00 0x00 0x00

0x82 0x02 0x0D 0x43
0x10 0x08 0x04 0x10
0x00 0x00 0x00 0x00
0x00 0x00 0x00
Comment 1 Lauri Mylläri 2013-11-19 05:19:57 UTC
Created attachment 89443 [details]
dmesg output from switching range with xrandr
Comment 2 Lauri Mylläri 2013-11-19 05:20:50 UTC
Created attachment 89444 [details]
EDID data from /sys/class/drm/card0-HDMI-A-1/edid
Comment 3 Daniel Vetter 2013-11-19 19:00:07 UTC
We need someone with an analyzer sniffing out the infoframes your pioner box sends around ;-)

tbh I don't really know what to do here, assigning to Ville for luck.
Comment 4 Lauri Mylläri 2013-11-19 19:26:39 UTC
Has the AVI infoframe sending been verified to work?

I am thinking of changing the AVI infoframe to indicate YCbCr 4:4:4 instead of RGB to see if my monitor reacts to that (by messed up colors since the signal content would still be RGB) to confirm the infoframes are being transmitted. Would that be possible by changing the register contents using intel-gpu-tools, or should I just modify the kernel?
Comment 5 Ville Syrjala 2013-11-19 20:09:49 UTC
(In reply to comment #4)
> Has the AVI infoframe sending been verified to work?

I seem to recall some patches that supposedly fixed some HDMI conformance
issues with infoframes. But that was before we switched over to the generic infoframe helpers. I don't recall if there was any mention of which hardware was used for the tests.

> 
> I am thinking of changing the AVI infoframe to indicate YCbCr 4:4:4 instead
> of RGB to see if my monitor reacts to that (by messed up colors since the
> signal content would still be RGB) to confirm the infoframes are being
> transmitted. Would that be possible by changing the register contents using
> intel-gpu-tools, or should I just modify the kernel?

I think it should be doable w/ igt. You just need to follow the infoframe programming sequence.
 - disable AVI infoframe
 - write the new infoframe data w/ updated checksum naturally, and remember the magic ECC hole at byte 3.
 - re-enable AVI infoframe

Our spec say we should wait for some vsyncs/hsyncs before disabling the infoframe, but that makes no sense to me since the hardware might start transmitting the infoframe again before we disable it. So I think the specs are just a bit nuts, and we should in fact wait for at least one frame _after_ disabling the infoframe in question so that we don't corrupt any currently transmitting infoframes.

Since this is HDMI, and getting incorrect colors is OK, I don't think there are any other register that need frobbing actually.
Comment 6 Daniel Vetter 2013-11-19 20:19:59 UTC
We have a helper to do this in i-g-t called intel_infoframes. It should dtrt, so you can use it to send different infoframes around. At least Paulo used it do debug our infoframe update code.
Comment 7 Lauri Mylläri 2013-11-20 16:23:30 UTC
intel_infoframes didn't detect any HDMIs and looking at the source I think it needs to be updated for Haswell.

I used the following to successfully change the infoframe to claim YCbCr 4:4:4

sudo intel_reg_write 0x60200 0x0001     ; \
sudo intel_reg_write 0x60220 0x000d0282 ; \
sudo intel_reg_write 0x60224 0x0808400f ; \
sudo intel_reg_write 0x60228 0x00000010 ; \
sudo intel_reg_write 0x6022C 0x00000000 ; \
sudo intel_reg_write 0x60200 0x1001

This changed the colors on screen, so the infoframes are clearly sent and understood by the monitor.

I wish I had an HDMI analyzer to see what the Oppo sends.
Comment 8 Lauri Mylläri 2013-11-22 03:39:48 UTC
I am able to switch my monitor to limited range, if I use xrandr to set full range output first:

$ DISPLAY=:0 xrandr --output HDMI1 --set "Broadcast RGB" "Full"
$ sudo intel_reg_write 0x60200 0x1
$ sudo intel_reg_write 0x60220 0xd0282
$ sudo intel_reg_write 0x60224 0x4081043
$ sudo intel_reg_write 0x60228 0x10
$ sudo intel_reg_write 0x6022c 0x0
$ sudo intel_reg_write 0x60230 0x0
$ sudo intel_reg_write 0x60200 0x1001

But for some reason when I try this after setting limited range output with DISPLAY=:0 xrandr --output HDMI1 --set "Broadcast RGB" "Limited 16:235", nothing seems to happen. If I try my earlier YCbCr 4:4:4 infoframe, it still gets sent and colors change.

I constructed another infoframe to claim full range output:

DISPLAY=:0 xrandr --output HDMI1 --set "Broadcast RGB" "Limited 16:235"
sudo intel_reg_write 0x60200 0x1
sudo intel_reg_write 0x60220 0xd0282
sudo intel_reg_write 0x60224 0x808103f
sudo intel_reg_write 0x60228 0x10
sudo intel_reg_write 0x6022c 0x0
sudo intel_reg_write 0x60230 0x0
sudo intel_reg_write 0x60200 0x1001

And now my monitor switches to full range and the grey blacks turn even lighter.


If I'm reading this right, the infoframes are working properly, but colors are scaled too much with xrandr --output HDMI1 --set "Broadcast RGB" "Limited 16:235"
Comment 9 Ville Syrjala 2013-11-22 17:36:23 UTC
(In reply to comment #8)
> If I'm reading this right, the infoframes are working properly, but colors
> are scaled too much with xrandr --output HDMI1 --set "Broadcast RGB"
> "Limited 16:235"

Hmm. I tried to compare my IVB vs. HSW a bit, and it does look like HSW blacks are more grayish in limited range mode. But I double checked the code and we're computing the coefficients correctly as far as the spec is concerned. I need to
ask our display hardware guy whether the spec is wrong, or if I just misunderstood it.

I experimented a bit and simply halving the pipe CSC post coeffs seems to make the output look better.

Something like this (for pipe A, add 0x100 to register offsets for pipe B, 0x200 for pipe C)
intel_reg_write 0x49040 0x101
intel_reg_write 0x49048 0x101
intel_reg_write 0x49044 0x101
intel_reg_write 0x49028 0x0
Comment 10 Lauri Mylläri 2013-11-23 04:44:53 UTC
Thanks, that seems a lot better.

I don't know if it's 100% accurate, I can see banding on a greyscale ramp. Do you think it's possible to map back to the original luma values after conversion to full range?

Other than that it looks good.
Comment 11 Daniel Vetter 2013-11-25 09:41:10 UTC
Ville confirmed with hw architects that our current hsw code is broken, assigning to him for the fix.
Comment 12 Daniel Vetter 2013-11-25 09:42:22 UTC
(In reply to comment #10)
> Thanks, that seems a lot better.
> 
> I don't know if it's 100% accurate, I can see banding on a greyscale ramp.
> Do you think it's possible to map back to the original luma values after
> conversion to full range?

The compression/expansion will leave some banding artifacts behind, that's somewhat inevitable. Afaik our hw doesn't have support to dither the colors a bit when compressing, so we can't fix this.
Comment 13 Ville Syrjala 2013-11-25 14:30:32 UTC
Created attachment 89751 [details] [review]
Fix for limited range output on HSW+

This should fix the problem.
Comment 14 Ville Syrjala 2013-11-28 20:04:24 UTC
Lauri, did you try the patch? And it so does it appear to work? It should, but there's always the possibility that I fumbled something. So a confirmation would be nice :)
Comment 15 Lauri Mylläri 2013-11-28 20:05:51 UTC
I can confirm it's working. It's already been pulled into OpenELEC and other users are reporting success too.
Comment 16 Daniel Vetter 2013-11-28 22:09:55 UTC
commit 32cf0cb0294814cb1ee5d8727e9aac0e9aa80d2e
Author: Ville Syrjälä <ville.syrjala@linux.intel.com>
Date:   Thu Nov 28 22:10:38 2013 +0200

    drm/i915: Fix pipe CSC post offset calculation

merged to -fixes with cc: stable, so should trickle down to released kernels.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.