diff options
author | Zhenyu Wang <zhenyu.z.wang@intel.com> | 2009-03-03 22:55:35 +0800 |
---|---|---|
committer | Zhenyu Wang <zhenyu.z.wang@intel.com> | 2009-03-03 22:55:35 +0800 |
commit | 42e34e90e2e4048b38481cab61cef46f932eada7 (patch) | |
tree | f30be7ebf912daedb9dd17436ca80aef4ed45bc4 | |
parent | aa9da5e393c804019720503fe58bdd247fe1eabd (diff) |
TV: add property control for TV attributes
This is based on Jesse's origin patch for bug #12763.
But export integer range to user instead of hardware float
point format, and fix different real format on 965G and 945G
for contrast and saturation.
-rw-r--r-- | man/intel.man | 24 | ||||
-rw-r--r-- | src/i830_tv.c | 211 |
2 files changed, 225 insertions, 10 deletions
diff --git a/man/intel.man b/man/intel.man index 22d998a2..e38cc545 100644 --- a/man/intel.man +++ b/man/intel.man @@ -273,6 +273,30 @@ Integrated TV output. Available properties include: Adjusting these properties allows you to control the placement of your TV output buffer on the screen. The options with the same name can also be set in xorg.conf with integer value. .PP +.B BRIGHTNESS +- TV brightness, range 0-255 +.TP 2 +Adjust TV brightness, default value is 128. + +.PP +.B CONTRAST +- TV contrast, range 0-255 +.TP 2 +Adjust TV contrast, default value is 1.0 in chipset specific format. + +.PP +.B SATURATION +- TV saturation, range 0-255 +.TP 2 +Adjust TV saturation, default value is 1.0 in chipset specific format. + +.PP +.B HUE +- TV hue, range 0-255 +.TP 2 +Adjust TV hue, default value is 0. + +.PP .B TV_FORMAT - output standard .TP 2 diff --git a/src/i830_tv.c b/src/i830_tv.c index e7766515..1e3cf7b6 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -59,6 +59,10 @@ struct i830_tv_priv { Bool force_type; char *tv_format; int margin[4]; + uint8_t brightness; + uint8_t contrast; + uint8_t saturation; + uint8_t hue; uint32_t save_TV_H_CTL_1; uint32_t save_TV_H_CTL_2; uint32_t save_TV_H_CTL_3; @@ -1020,6 +1024,96 @@ i830_float_to_luma (float f) return ret; } +static uint8_t +float_to_float_2_6(float fin) +{ + uint8_t exp; + uint8_t mant; + float f = fin; + uint32_t tmp; + + if (f < 0) f = -f; + + tmp = f; + for (exp = 0; exp <= 3 && tmp > 0; exp++) + tmp /= 2; + + mant = (f * (1 << 6) + 0.5); + mant >>= exp; + if (mant > (1 << 6)) + mant = (1 << 6) - 1; + + return (exp << 6) | mant; +} + +static uint8_t +float_to_fix_2_6(float f) +{ + uint8_t ret; + + ret = f * (1 << 6); + return ret; +} + +static void +i830_tv_update_brightness(I830Ptr pI830, uint8_t brightness) +{ + /* brightness in 2's comp value */ + uint32_t val = INREG(TV_CLR_KNOBS) & ~TV_BRIGHTNESS_MASK; + int8_t bri = brightness - 128; /* remove bias */ + + val |= (bri << TV_BRIGHTNESS_SHIFT) & TV_BRIGHTNESS_MASK; + OUTREG(TV_CLR_KNOBS, val); +} + +static void +i830_tv_update_contrast(I830Ptr pI830, uint8_t contrast) +{ + uint32_t val = INREG(TV_CLR_KNOBS) & ~TV_CONTRAST_MASK;; + float con; + uint8_t c; + + if (IS_I965G(pI830)) { + /* 2.6 fixed point */ + con = 3.0 * ((float) contrast / 255); + c = float_to_fix_2_6(con); + } else { + /* 2.6 floating point */ + con = 8.875 * ((float) contrast / 255); + c = float_to_float_2_6(con); + } + val |= (c << TV_CONTRAST_SHIFT) & TV_CONTRAST_MASK; + OUTREG(TV_CLR_KNOBS, val); +} + +static void +i830_tv_update_saturation(I830Ptr pI830, uint8_t saturation) +{ + uint32_t val = INREG(TV_CLR_KNOBS) & ~TV_SATURATION_MASK; + float sat; + uint8_t s; + + /* same as contrast */ + if (IS_I965G(pI830)) { + sat = 3.0 * ((float) saturation / 255); + s = float_to_fix_2_6(sat); + } else { + sat = 8.875 * ((float) saturation / 255); + s = float_to_float_2_6(sat); + } + val |= (s << TV_SATURATION_SHIFT) & TV_SATURATION_MASK; + OUTREG(TV_CLR_KNOBS, val); +} + +static void +i830_tv_update_hue(I830Ptr pI830, uint8_t hue) +{ + uint32_t val = INREG(TV_CLR_KNOBS) & ~TV_HUE_MASK; + + val |= (hue << TV_HUE_SHIFT) & TV_HUE_MASK; + OUTREG(TV_CLR_KNOBS, val); +} + static void i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) @@ -1181,14 +1275,6 @@ i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode, (i830_float_to_csc(color_conversion->bv) << 16) | (i830_float_to_luma(color_conversion->av))); - if (IS_I965G(pI830)) { - /* 2.6 fixed point value for contrast and saturation modifier, - use 1 as default */ - OUTREG(TV_CLR_KNOBS, 0x00404000); - } else { - /* 915/945 uses 2 bits exponent and 6 bits mantissa format */ - OUTREG(TV_CLR_KNOBS, 0x00606000); - } OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) | (video_levels->blank << TV_BLANK_LEVEL_SHIFT))); { @@ -1496,6 +1582,26 @@ static char *margin_names[4] = { "LEFT", "TOP", "RIGHT", "BOTTOM" }; +/** + * contrast and saturation has different format on 915/945 with 965. + * On 915/945, it's 2.6 floating point number. + * On 965, it's 2.6 fixed point number. + */ +#define TV_BRIGHTNESS_NAME "BRIGHTNESS" +#define TV_BRIGHTNESS_DEFAULT 128 /* bias */ +static Atom brightness_atom; +#define TV_CONTRAST_NAME "CONTRAST" +#define TV_CONTRAST_DEFAULT 0x40 +#define TV_CONTRAST_DEFAULT_945G 0x60 +static Atom contrast_atom; +#define TV_SATURATION_NAME "SATURATION" +#define TV_SATURATION_DEFAULT 0x40 +#define TV_SATURATION_DEFAULT_945G 0x60 +static Atom saturation_atom; +#define TV_HUE_NAME "HUE" +#define TV_HUE_DEFAULT 0 +static Atom hue_atom; + static Bool i830_tv_format_set_property (xf86OutputPtr output) { @@ -1541,6 +1647,62 @@ i830_tv_format_configure_property (xf86OutputPtr output) num_atoms, (INT32 *) current_atoms); } +static void +i830_tv_color_set_property(xf86OutputPtr output, Atom property, + uint8_t val) +{ + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_tv_priv *dev_priv = intel_output->dev_priv; + + if (property == brightness_atom) { + dev_priv->brightness = val; + i830_tv_update_brightness(pI830, val); + } else if (property == contrast_atom) { + dev_priv->contrast = val; + i830_tv_update_contrast(pI830, val); + } else if (property == saturation_atom) { + dev_priv->saturation = val; + i830_tv_update_saturation(pI830, val); + } else if (property == hue_atom) { + dev_priv->hue = val; + i830_tv_update_hue(pI830, val); + } +} + +static void +i830_tv_color_create_property(xf86OutputPtr output, Atom *property, + char *name, int name_len, uint8_t val) +{ + ScrnInfoPtr pScrn = output->scrn; + INT32 range[2]; + int err = 0; + + *property = MakeAtom(name, name_len - 1, TRUE); + range[0] = 0; + range[1] = 255; + err = RRConfigureOutputProperty(output->randr_output, *property, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + goto out; + } + /* Set the current value */ + i830_tv_color_set_property(output, *property, val); + + err = RRChangeOutputProperty(output->randr_output, *property, + XA_INTEGER, 32, PropModeReplace, 1, &val, + FALSE, FALSE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } +out: + return; +} + #endif /* RANDR_12_INTERFACE */ static void @@ -1548,10 +1710,10 @@ i830_tv_create_resources(xf86OutputPtr output) { #ifdef RANDR_12_INTERFACE ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); I830OutputPrivatePtr intel_output = output->driver_private; struct i830_tv_priv *dev_priv = intel_output->dev_priv; - int err; - int i; + int err, i; /* Set up the tv_format property, which takes effect on mode set * and accepts strings that match exactly @@ -1599,6 +1761,23 @@ i830_tv_create_resources(xf86OutputPtr output) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RRChangeOutputProperty error, %d\n", err); } + + i830_tv_color_create_property(output, &brightness_atom, + TV_BRIGHTNESS_NAME, + sizeof(TV_BRIGHTNESS_NAME), + TV_BRIGHTNESS_DEFAULT); + i830_tv_color_create_property(output, &contrast_atom, + TV_CONTRAST_NAME, + sizeof(TV_CONTRAST_NAME), + IS_I965G(pI830) ? TV_CONTRAST_DEFAULT : + TV_CONTRAST_DEFAULT_945G); + i830_tv_color_create_property(output, &saturation_atom, + TV_SATURATION_NAME, + sizeof(TV_SATURATION_NAME), + IS_I965G(pI830) ? TV_SATURATION_DEFAULT : + TV_SATURATION_DEFAULT_945G); + i830_tv_color_create_property(output, &hue_atom, TV_HUE_NAME, + sizeof(TV_HUE_NAME), TV_HUE_DEFAULT); #endif /* RANDR_12_INTERFACE */ } @@ -1703,6 +1882,18 @@ i830_tv_set_property(xf86OutputPtr output, Atom property, return TRUE; } } + if (property == brightness_atom || property == contrast_atom || + property == saturation_atom || property == hue_atom) { + uint8_t val; + + /* Make sure value is sane */ + if (value->type != XA_INTEGER || value->format != 32 || + value->size != 1) + return FALSE; + + memcpy (&val, value->data, 1); + i830_tv_color_set_property(output, property, val); + } return TRUE; } |