diff --git a/src/i830_tv.c b/src/i830_tv.c index ee2538a..674a725 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -57,6 +57,10 @@ struct i830_tv_priv { int type; char *tv_format; int margin[4]; + unsigned char brightness; + unsigned char contrast; + unsigned char saturation; + unsigned char hue; CARD32 save_TV_H_CTL_1; CARD32 save_TV_H_CTL_2; CARD32 save_TV_H_CTL_3; @@ -1019,6 +1023,42 @@ i830_float_to_luma (float f) } static void +i830_tv_update_brightness(I830Ptr pI830, unsigned char brightness) +{ + CARD32 val = INREG(TV_CLR_KNOBS) & ~TV_BRIGHTNESS_MASK; + + val |= (brightness << TV_BRIGHTNESS_SHIFT) & TV_BRIGHTNESS_MASK; + OUTREG(TV_CLR_KNOBS, val); +} + +static void +i830_tv_update_contrast(I830Ptr pI830, unsigned char contrast) +{ + CARD32 val = INREG(TV_CLR_KNOBS) & ~TV_CONTRAST_MASK;; + + val |= (contrast << TV_CONTRAST_SHIFT) & TV_CONTRAST_MASK; + OUTREG(TV_CLR_KNOBS, val); +} + +static void +i830_tv_update_saturation(I830Ptr pI830, unsigned char saturation) +{ + CARD32 val = INREG(TV_CLR_KNOBS) & ~TV_SATURATION_MASK; + + val |= (saturation << TV_SATURATION_SHIFT) & TV_SATURATION_MASK; + OUTREG(TV_CLR_KNOBS, val); +} + +static void +i830_tv_update_hue(I830Ptr pI830, unsigned char hue) +{ + CARD32 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) { @@ -1178,7 +1218,6 @@ i830_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode, (i830_float_to_csc(color_conversion->bv) << 16) | (i830_float_to_luma(color_conversion->av))); - OUTREG(TV_CLR_KNOBS, 0x10606000); OUTREG(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) | (video_levels->blank << TV_BLANK_LEVEL_SHIFT))); { @@ -1476,6 +1515,15 @@ static char *margin_names[4] = { "LEFT", "TOP", "RIGHT", "BOTTOM" }; +#define TV_BRIGHTNESS_NAME "TV_BRIGHTNESS" +static Atom brightness_atom; +#define TV_CONTRAST_NAME "TV_CONTRAST" +static Atom contrast_atom; +#define TV_SATURATION_NAME "TV_SATURATION" +static Atom saturation_atom; +#define TV_HUE_NAME "TV_HUE" +static Atom hue_atom; + static Bool i830_tv_format_set_property (xf86OutputPtr output) { @@ -1493,7 +1541,6 @@ i830_tv_format_set_property (xf86OutputPtr output) return err == Success; } - /** * Configure the TV_FORMAT property to list only supported formats * @@ -1522,6 +1569,59 @@ i830_tv_format_configure_property (xf86OutputPtr output) num_atoms, (INT32 *) current_atoms); } +static void +i830_tv_color_set_property(xf86OutputPtr output, Atom property, + unsigned char 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, int val) +{ + ScrnInfoPtr pScrn = output->scrn; + INT32 range[] = { 0, 0xff }; + int err = 0; + + *property = MakeAtom(name, name_len - 1, TRUE); + 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, 8, PropModeReplace, 1, &val, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } +out: + return; +} + #endif /* RANDR_12_INTERFACE */ static void @@ -1531,8 +1631,7 @@ i830_tv_create_resources(xf86OutputPtr output) ScrnInfoPtr pScrn = output->scrn; 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 @@ -1580,6 +1679,17 @@ 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), 0); + i830_tv_color_create_property(output, &contrast_atom, TV_CONTRAST_NAME, + sizeof(TV_CONTRAST_NAME), 0x40); + i830_tv_color_create_property(output, &saturation_atom, + TV_SATURATION_NAME, + sizeof(TV_SATURATION_NAME), 0x40); + i830_tv_color_create_property(output, &hue_atom, TV_HUE_NAME, + sizeof(TV_HUE_NAME), 0); #endif /* RANDR_12_INTERFACE */ } @@ -1634,6 +1744,18 @@ i830_tv_set_property(xf86OutputPtr output, Atom property, return TRUE; } } + if (property == brightness_atom || property == contrast_atom || + property == saturation_atom || property == hue_atom) { + unsigned char val; + + /* Make sure value is sane */ + if (value->type != XA_INTEGER || value->format != 8 || + value->size != 1) + return FALSE; + + memcpy (&val, value->data, 1); + i830_tv_color_set_property(output, property, val); + } return TRUE; }