diff options
author | Ma Ling <ling.ma@intel.com> | 2009-04-13 14:23:06 +0800 |
---|---|---|
committer | Zhenyu Wang <zhenyu.z.wang@intel.com> | 2009-04-13 14:29:44 +0800 |
commit | 69388953ce889080d5f014123d89bf3eb45f3d8d (patch) | |
tree | 7cf2ce7daf8f3e46b53b08b39117cf44fae0cb25 | |
parent | 6d345c49f693cc5cffaa00b94559d2afcb3a0864 (diff) |
set broadcast RGB mode for HDMI and TMDS from SDVOX output
Almost all digital TVs accept broadcast RGB values from 16 to 235 for each channel,
otherwise for those uncompensated videos, when RGB values are set from 0 to 255,
they will shows black and whiter clamping, which seriously degrades picture quality.
The patch will enable the broadcast RGB mode for hdtv according to user's setting.
It fixed bug #14486
-rw-r--r-- | src/i810_reg.h | 1 | ||||
-rw-r--r-- | src/i830_sdvo.c | 93 |
2 files changed, 94 insertions, 0 deletions
diff --git a/src/i810_reg.h b/src/i810_reg.h index 59b60793..d5d41b3e 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -1300,6 +1300,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SDVO_ENCODING_HDMI (0x2 << 10) /** Requird for HDMI operation */ #define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) +#define SDVO_COLOR_NOT_FULL_RANGE (1 << 8) #define SDVO_BORDER_ENABLE (1 << 7) #define SDVO_AUDIO_ENABLE (1 << 6) /** New with 965, default is to be set */ diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index a7b5171e..29ccd4e5 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -49,6 +49,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830_display.h" #include "i810_reg.h" #include "i830_sdvo_regs.h" +#include "X11/Xatom.h" /** SDVO driver private structure. */ struct i830_sdvo_priv { @@ -110,6 +111,8 @@ struct i830_sdvo_priv { /** DDC bus used by this SDVO output */ uint8_t ddc_bus; + /* Default 0 for full RGB range 0-255, 1 is for RGB range 16-235 */ + uint32_t broadcast_rgb; /** State for save/restore */ /** @{ */ @@ -121,6 +124,8 @@ struct i830_sdvo_priv { /** @} */ }; +static Atom broadcast_atom; + /** * Writes the SDVOB or SDVOC with the given value, but always writes both * SDVOB and SDVOC to work around apparent hardware issues (according to @@ -1927,7 +1932,94 @@ i830_sdvo_get_crtc(xf86OutputPtr output) } #endif +static void +i830_sdvo_create_resources(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + INT32 broadcast_range[2]; + int err; + + /* only R G B are 8bit color mode */ + if (pScrn->depth != 24 || + /* only 965G and G4X platform */ + !(IS_I965G(pI830) || IS_G4X(pI830)) || + /* only TMDS encoding */ + !(strstr(output->name, "TMDS") || strstr(output->name, "HDMI"))) + return; + + broadcast_atom = + MakeAtom("BROADCAST_RGB", sizeof("BROADCAST_RGB") - 1, TRUE); + + broadcast_range[0] = 0; + broadcast_range[1] = 1; + err = RRConfigureOutputProperty(output->randr_output, + broadcast_atom, + FALSE, TRUE, FALSE, 2, broadcast_range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + return; + } + /* Set the current value of the broadcast property as full range */ + dev_priv->broadcast_rgb = 0; + err = RRChangeOutputProperty(output->randr_output, + broadcast_atom, + XA_INTEGER, 32, PropModeReplace, + 1, &dev_priv->broadcast_rgb, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + return; + } +} + +static Bool +i830_sdvo_set_property(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + uint32_t temp; + + if (property == broadcast_atom) { + uint32_t val; + + if (value->type != XA_INTEGER || value->format != 32 || + value->size != 1) + { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < 0 || val > 1) + { + return FALSE; + } + if (val == dev_priv->broadcast_rgb) + return TRUE; + + temp = INREG(dev_priv->output_device); + + if (val == 1) + temp |= SDVO_COLOR_NOT_FULL_RANGE; + else if (val == 0) + temp &= ~SDVO_COLOR_NOT_FULL_RANGE; + + i830_sdvo_write_sdvox(output, temp); + + dev_priv->broadcast_rgb = val; + } + return TRUE; +} + static const xf86OutputFuncsRec i830_sdvo_output_funcs = { + .create_resources = i830_sdvo_create_resources, .dpms = i830_sdvo_dpms, .save = i830_sdvo_save, .restore = i830_sdvo_restore, @@ -1938,6 +2030,7 @@ static const xf86OutputFuncsRec i830_sdvo_output_funcs = { .commit = i830_output_commit, .detect = i830_sdvo_detect, .get_modes = i830_sdvo_get_modes, + .set_property = i830_sdvo_set_property, .destroy = i830_sdvo_destroy, #ifdef RANDR_GET_CRTC_INTERFACE .get_crtc = i830_sdvo_get_crtc, |