--- src/i830_sdvo.c.orig 2009-09-27 23:23:24.929568558 +0400 +++ src/i830_sdvo.c 2009-09-27 23:48:43.786077231 +0400 @@ -41,6 +41,7 @@ #endif #include +#include #include "xf86.h" #include "xf86_OSproc.h" @@ -134,8 +135,54 @@ struct i830_sdvo_dtd save_output_dtd[16]; uint32_t save_SDVOX; /** @} */ + + /** Position and overscan properties */ + /** @{ */ + int16_t position_h; + int16_t position_v; + int8_t overscan_h; + int8_t overscan_v; + /** @} */ + + /** Picture parameters */ + /** @{ */ + uint8_t saturation; + uint8_t hue; + uint8_t brightness; + uint8_t contrast; + uint8_t sharpness; + uint8_t tv_chroma; + uint8_t tv_luma; + /** @} */ }; +#define POSITION_H_PROP "Position H" +#define POSITION_V_PROP "Position V" +#define OVERSCAN_H_PROP "Overscan H" +#define OVERSCAN_V_PROP "Overscan V" +#define SATURATION_PROP "Saturation" +#define HUE_PROP "Hue" +#define BRIGHTNESS_PROP "Brightness" +#define CONTRAST_PROP "Contrast" +#define SHARPNESS_PROP "Sharpness" +#define TV_CHROMA_PROP "TV Chroma" +#define TV_LUMA_PROP "TV Luma" + +#define POSITION_OFFSET 512 +#define OVERSCAN_BASE 32 + +static Atom position_h_atom; +static Atom position_v_atom; +static Atom overscan_h_atom; +static Atom overscan_v_atom; +static Atom saturation_atom; +static Atom hue_atom; +static Atom brightness_atom; +static Atom contrast_atom; +static Atom sharpness_atom; +static Atom tv_chroma_atom; +static Atom tv_luma_atom; + static Atom broadcast_atom; static void @@ -1017,6 +1064,357 @@ } static Bool +i830_sdvo_run_set_command(xf86OutputPtr output, uint8_t command, + void *val, size_t size) +{ + uint8_t status; + + i830_sdvo_write_cmd(output, command, val, size); + status = i830_sdvo_read_response(output, NULL, 0); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; + + return TRUE; +} + +static Bool +i830_sdvo_run_get_command(xf86OutputPtr output, uint8_t command, + void *result, size_t size) +{ + uint8_t status; + + i830_sdvo_write_cmd(output, command, NULL, 0); + status = i830_sdvo_read_response(output, result, size); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static uint8_t +i830_sdvo_run_get_command_u8(xf86OutputPtr output, uint8_t command, uint8_t default_value) +{ + uint8_t result; + if (i830_sdvo_run_get_command(output, command, &result, 1)) + return result; + return default_value; +} + +static uint16_t +i830_sdvo_run_get_command_u16(xf86OutputPtr output, uint8_t command, uint16_t default_value) +{ + uint16_t result; + if (i830_sdvo_run_get_command(output, command, &result, 2)) + return result; + return default_value; +} + +static void +i830_sdvo_set_position_and_overscan(xf86OutputPtr output) +{ + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + uint16_t pos_h = POSITION_OFFSET + dev_priv->position_h; + uint16_t pos_v = POSITION_OFFSET + dev_priv->position_v; + uint8_t ovscn_h = OVERSCAN_BASE + dev_priv->overscan_h; + uint8_t ovscn_v = OVERSCAN_BASE + dev_priv->overscan_v; + + uint16_t max_pos = i830_sdvo_run_get_command_u16(output, SDVO_CMD_GET_MAX_POSITION_H, 1023); + if (pos_h > max_pos) + pos_h = max_pos; + max_pos = i830_sdvo_run_get_command_u16(output, SDVO_CMD_GET_MAX_POSITION_V, 1023); + if (pos_v > max_pos) + pos_v = max_pos; + uint8_t max_ovscn = i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_OVERSCAN_H, 48); + if (ovscn_h > max_ovscn) + ovscn_h = max_ovscn; + max_ovscn = i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_OVERSCAN_V, 48); + if (ovscn_v > max_ovscn) + ovscn_v = max_ovscn; + + //xf86DrvMsg(output->scrn->scrnIndex, X_INFO, + // "Position H: %d, Position V: %d, Overscan H: %d, Overscan V %d\n", + // pos_h, pos_v, ovscn_h, ovscn_v); + + i830_sdvo_run_set_command(output, SDVO_CMD_SET_POSITION_H, + &pos_h, sizeof(pos_h)); + i830_sdvo_run_set_command(output, SDVO_CMD_SET_POSITION_V, + &pos_v, sizeof(pos_v)); + i830_sdvo_run_set_command(output, SDVO_CMD_SET_OVERSCAN_H, + &ovscn_h, sizeof(ovscn_h)); + i830_sdvo_run_set_command(output, SDVO_CMD_SET_OVERSCAN_V, + &ovscn_v, sizeof(ovscn_v)); +} + +static Bool +i830_sdvo_set_picture_param(xf86OutputPtr output, uint8_t set_cmd, + uint8_t get_max_cmd, int8_t param) +{ + uint8_t max; + if (i830_sdvo_run_get_command(output, get_max_cmd, &max, sizeof(max))) + if (param > max) + param = max; + return i830_sdvo_run_set_command(output, set_cmd, ¶m, sizeof(param)); +} + +static void +i830_sdvo_set_picture_params(xf86OutputPtr output) +{ + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + + i830_sdvo_set_picture_param(output, SDVO_CMD_SET_HUE, + SDVO_CMD_GET_MAX_HUE, dev_priv->hue); + i830_sdvo_set_picture_param(output, SDVO_CMD_SET_SATURATION, + SDVO_CMD_GET_MAX_SATURATION, dev_priv->saturation); + i830_sdvo_set_picture_param(output, SDVO_CMD_SET_BRIGHTNESS, + SDVO_CMD_GET_MAX_BRIGHTNESS, dev_priv->brightness); + i830_sdvo_set_picture_param(output, SDVO_CMD_SET_CONTRAST, + SDVO_CMD_GET_MAX_CONTRAST, dev_priv->contrast); + i830_sdvo_set_picture_param(output, SDVO_CMD_SET_SHARPNESS, + SDVO_CMD_GET_MAX_SHARPNESS_V, dev_priv->sharpness); + i830_sdvo_set_picture_param(output, SDVO_CMD_SET_TV_CHROMA, + SDVO_CMD_GET_MAX_TV_CHROMA, dev_priv->tv_chroma); + i830_sdvo_set_picture_param(output, SDVO_CMD_SET_TV_LUMA, + SDVO_CMD_GET_MAX_TV_LUMA, dev_priv->tv_luma); +} + +static void +i830_sdvo_create_property(xf86OutputPtr output, Atom *property, + char *name, INT32 val, INT32 min, INT32 max) +{ + ScrnInfoPtr pScrn = output->scrn; + INT32 range[2]; + int err = 0; + + *property = MakeAtom(name, strlen(name), TRUE); + range[0] = min; + range[1] = max; + err = RRConfigureOutputProperty(output->randr_output, *property, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + return; + } + + 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); + } +} + +static void +i830_sdvo_create_resources(xf86OutputPtr output) +{ + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + INT32 broadcast_range[2]; + int err; + + i830_sdvo_create_property(output, &position_h_atom, POSITION_H_PROP, + dev_priv->position_h, -POSITION_OFFSET, + i830_sdvo_run_get_command_u16(output, SDVO_CMD_GET_MAX_POSITION_H, 1023) - POSITION_OFFSET); + + i830_sdvo_create_property(output, &position_v_atom, POSITION_V_PROP, + dev_priv->position_v, -POSITION_OFFSET, + i830_sdvo_run_get_command_u16(output, SDVO_CMD_GET_MAX_POSITION_V, 1023) - POSITION_OFFSET); + + i830_sdvo_create_property(output, &overscan_h_atom, OVERSCAN_H_PROP, + dev_priv->overscan_h, -OVERSCAN_BASE, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_OVERSCAN_H, 48) - OVERSCAN_BASE); + + i830_sdvo_create_property(output, &overscan_v_atom, OVERSCAN_V_PROP, + dev_priv->overscan_v, -OVERSCAN_BASE, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_OVERSCAN_V, 48) - OVERSCAN_BASE); + + i830_sdvo_create_property(output, &saturation_atom, SATURATION_PROP, + dev_priv->saturation, 0, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_SATURATION, 255)); + i830_sdvo_create_property(output, &hue_atom, HUE_PROP, + dev_priv->hue, 0, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_HUE, 255)); + i830_sdvo_create_property(output, &brightness_atom, BRIGHTNESS_PROP, + dev_priv->brightness, 0, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_BRIGHTNESS, 255)); + i830_sdvo_create_property(output, &contrast_atom, CONTRAST_PROP, + dev_priv->contrast, 0, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_CONTRAST, 255)); + i830_sdvo_create_property(output, &sharpness_atom, SHARPNESS_PROP, + dev_priv->sharpness, 0, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_SHARPNESS_V, 255)); + i830_sdvo_create_property(output, &tv_chroma_atom, TV_CHROMA_PROP, + dev_priv->tv_chroma, 0, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_TV_CHROMA, 255)); + i830_sdvo_create_property(output, &tv_luma_atom, TV_LUMA_PROP, + dev_priv->tv_luma, 0, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_MAX_TV_LUMA, 255)); + + /* 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_update_picture_property(xf86OutputPtr output, uint8_t *storage, + RRPropertyValuePtr value, uint8_t command, uint8_t max_command) +{ + INT32 pv; + memcpy(&pv, value->data, 4); + *storage = (uint8_t)pv; + return i830_sdvo_set_picture_param(output, command, max_command, *storage); +} + +static Bool +i830_sdvo_update_postion_and_overscan(xf86OutputPtr output) +{ + return xf86CrtcSetMode(output->crtc, &output->crtc->mode, output->crtc->rotation, + output->crtc->x, output->crtc->y); +} + +static Bool +i830_sdvo_set_property(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + I830OutputPrivatePtr intel_output = output->driver_private; + struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; + Bool pos_over_changed = FALSE; + INT32 property_value; + uint32_t temp; + ScrnInfoPtr pScrn = output->scrn; + I830Ptr pI830 = I830PTR(pScrn); + + if (value->type != XA_INTEGER || value->format != 32 || value->size != 1) + { + return FALSE; + } + + 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; + } + else if (property == saturation_atom) + { + return i830_sdvo_update_picture_property(output, &dev_priv->saturation, value, + SDVO_CMD_SET_SATURATION, SDVO_CMD_GET_MAX_SATURATION); + } + else if (property == hue_atom) + { + return i830_sdvo_update_picture_property(output, &dev_priv->hue, value, + SDVO_CMD_SET_HUE, SDVO_CMD_GET_MAX_HUE); + } + else if (property == brightness_atom) + { + return i830_sdvo_update_picture_property(output, &dev_priv->brightness, value, + SDVO_CMD_SET_BRIGHTNESS, SDVO_CMD_GET_MAX_BRIGHTNESS); + } + else if (property == contrast_atom) + { + return i830_sdvo_update_picture_property(output, &dev_priv->contrast, value, + SDVO_CMD_SET_CONTRAST, SDVO_CMD_GET_MAX_CONTRAST); + } + else if (property == sharpness_atom) + { + return i830_sdvo_update_picture_property(output, &dev_priv->sharpness, value, + SDVO_CMD_SET_SHARPNESS, SDVO_CMD_GET_MAX_SHARPNESS_V); + } + else if (property == tv_chroma_atom) + { + return i830_sdvo_update_picture_property(output, &dev_priv->tv_chroma, value, + SDVO_CMD_SET_TV_CHROMA, SDVO_CMD_GET_MAX_TV_CHROMA); + } + else if (property == tv_luma_atom) + { + return i830_sdvo_update_picture_property(output, &dev_priv->tv_luma, value, + SDVO_CMD_SET_TV_LUMA, SDVO_CMD_GET_MAX_TV_LUMA); + } + else if (property == position_h_atom) + { + pos_over_changed = TRUE; + memcpy(&property_value, value->data, 4); + dev_priv->position_h = (int16_t)property_value; + } + else if (property == position_v_atom) + { + pos_over_changed = TRUE; + memcpy(&property_value, value->data, 4); + dev_priv->position_v = (int16_t)property_value; + } + else if (property == overscan_h_atom) + { + pos_over_changed = TRUE; + memcpy(&property_value, value->data, 4); + dev_priv->overscan_h = (int8_t)property_value; + } + else if (property == overscan_v_atom) + { + pos_over_changed = TRUE; + memcpy(&property_value, value->data, 4); + dev_priv->overscan_v = (int8_t)property_value; + } + if (pos_over_changed) + return i830_sdvo_update_postion_and_overscan(output); + return FALSE; +} + +static Bool i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) { @@ -1044,6 +1442,10 @@ /* Set the input timing to the screen. Assume always input 0. */ i830_sdvo_set_target_input(output, TRUE, FALSE); + + /* Since this affects prefered timings let it go before creating them */ + i830_sdvo_set_position_and_overscan(output); + success = i830_sdvo_create_preferred_input_timing(output, mode->Clock / 10, mode->HDisplay, @@ -1238,6 +1640,8 @@ i830_sdvo_write_sdvox(output, sdvox); + i830_sdvo_set_picture_params(output); + if (0) i830_sdvo_dump(pScrn); } @@ -1801,8 +2205,11 @@ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv; uint16_t response; uint8_t status; - + i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); + if (dev_priv->is_tv) { + usleep(30*1000); + } status = i830_sdvo_read_response(output, &response, 2); if (status != SDVO_CMD_STATUS_SUCCESS) @@ -2045,92 +2452,6 @@ } #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, @@ -2277,6 +2598,7 @@ unsigned char ch[0x40]; I2CBusPtr i2cbus = NULL, ddcbus; uint8_t slave_addr; + XF86OptionPtr mon_option_lst = NULL; slave_addr = 0; i830_find_sdvo_slave(pScrn, output_device, &slave_addr); @@ -2413,6 +2735,27 @@ SDVO_NAME(dev_priv), dev_priv->caps.sdvo_input_count, dev_priv->caps.sdvo_input_count >= 2 ? "s" : ""); + if (output->conf_monitor) + mon_option_lst = output->conf_monitor->mon_option_lst; + dev_priv->position_h = xf86SetIntOption(mon_option_lst, POSITION_H_PROP, 0); + dev_priv->position_v = xf86SetIntOption(mon_option_lst, POSITION_V_PROP, 0); + dev_priv->overscan_h = xf86SetIntOption(mon_option_lst, OVERSCAN_H_PROP, 0); + dev_priv->overscan_v = xf86SetIntOption(mon_option_lst, OVERSCAN_V_PROP, 0); + dev_priv->saturation = (uint8_t)xf86SetIntOption(mon_option_lst, SATURATION_PROP, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_SATURATION, 255)); + dev_priv->hue = (uint8_t)xf86SetIntOption(mon_option_lst, HUE_PROP, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_HUE, 255)); + dev_priv->brightness = (uint8_t)xf86SetIntOption(mon_option_lst, BRIGHTNESS_PROP, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_BRIGHTNESS, 255)); + dev_priv->contrast = (uint8_t)xf86SetIntOption(mon_option_lst, CONTRAST_PROP, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_CONTRAST, 255)); + dev_priv->sharpness = (uint8_t)xf86SetIntOption(mon_option_lst, SHARPNESS_PROP, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_SHARPNESS, 255)); + dev_priv->tv_chroma = (uint8_t)xf86SetIntOption(mon_option_lst, TV_CHROMA_PROP, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_TV_CHROMA, 255)); + dev_priv->tv_luma = (uint8_t)xf86SetIntOption(mon_option_lst, TV_LUMA_PROP, + i830_sdvo_run_get_command_u8(output, SDVO_CMD_GET_TV_LUMA, 255)); + #define REPORT_OUTPUT_FLAG(flag, name) do { \ if (dev_priv->caps.output_flags & flag) { \ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s: %s output reported\n", \