diff mbox

[1/2] DRM/I915: Add the enhancement property for SDVO-TV

Message ID 1251687432-15345-1-git-send-email-yakui.zhao@intel.com (mailing list archive)
State Accepted
Headers show

Commit Message

Zhao, Yakui Aug. 31, 2009, 2:57 a.m. UTC
From: Zhao Yakui <yakui.zhao@intel.com>

When the sdvo device is detected as SDVO-TV, we will check whether the
sepecific picture enhancement is supported. If it is supported, we will
add the corresponnding property for SDVO-TV. We will add the following
property for the SDVO-TV enhancements if they are supported:
   Contrast/Brightness/Saturation/Hue:
   left/right/top/bottom margin: This is implemented by using the horizontal/
vertical overscan enhancements. When the overscan enhancements are supported,
the above properties will be added. This is to be compatible with what we have
done in integrated-TV.
   horizontal pos/vertical pos:  

http://bugs.freedesktop.org/show_bug.cgi?id=22891

Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
---
 drivers/gpu/drm/i915/intel_sdvo.c |  482 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 478 insertions(+), 4 deletions(-)

Comments

Zhao, Yakui Aug. 31, 2009, 3:02 a.m. UTC | #1
On Mon, 2009-08-31 at 10:57 +0800, Zhao, Yakui wrote:
> From: Zhao Yakui <yakui.zhao@intel.com>

Hi, Eric
    It seems that you already pick up two patches about TV
property(select TV format according to connector type, Enable PAL and
SECAM format and add the TV format propery for SDVO-TV)
    Will you please also pick up the two patches that add the property
for SDVO-TV/LVDS?
    Patch 1:  add the property for SDVO-TV(window
control/saturation/hue/brightness/contrast, which is similar to what we
have done for integrated TV)
    Patch 2: add the brightness property for SDVO-LVDS

Thanks.
> 
> When the sdvo device is detected as SDVO-TV, we will check whether the
> sepecific picture enhancement is supported. If it is supported, we will
> add the corresponnding property for SDVO-TV. We will add the following
> property for the SDVO-TV enhancements if they are supported:
>    Contrast/Brightness/Saturation/Hue:
>    left/right/top/bottom margin: This is implemented by using the horizontal/
> vertical overscan enhancements. When the overscan enhancements are supported,
> the above properties will be added. This is to be compatible with what we have
> done in integrated-TV.
>    horizontal pos/vertical pos:
> 
> http://bugs.freedesktop.org/show_bug.cgi?id=22891
> 
> Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_sdvo.c |  482 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 478 insertions(+), 4 deletions(-)
> 
> Index: linux-2.6/drivers/gpu/drm/i915/intel_sdvo.c
> ===================================================================
> --- linux-2.6.orig/drivers/gpu/drm/i915/intel_sdvo.c    2009-08-31 10:36:49.000000000 +0800
> +++ linux-2.6/drivers/gpu/drm/i915/intel_sdvo.c 2009-08-31 10:53:12.000000000 +0800
> @@ -132,6 +132,30 @@
>         struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
>         struct intel_sdvo_dtd save_output_dtd[16];
>         u32 save_SDVOX;
> +       /* add the property for the SDVO-TV */
> +       struct drm_property *left_property;
> +       struct drm_property *right_property;
> +       struct drm_property *top_property;
> +       struct drm_property *bottom_property;
> +       struct drm_property *hpos_property;
> +       struct drm_property *vpos_property;
> +
> +       /* add the property for the SDVO-TV/LVDS */
> +       struct drm_property *brightness_property;
> +       struct drm_property *contrast_property;
> +       struct drm_property *saturation_property;
> +       struct drm_property *hue_property;
> +
> +       /* Add variable to record current setting for the above property */
> +       u32     left_margin, right_margin, top_margin, bottom_margin;
> +       /* this is to get the range of margin.*/
> +       u32     max_hscan,  max_vscan;
> +       u32     max_hpos, cur_hpos;
> +       u32     max_vpos, cur_vpos;
> +       u32     cur_brightness, max_brightness;
> +       u32     cur_contrast,   max_contrast;
> +       u32     cur_saturation, max_saturation;
> +       u32     cur_hue,        max_hue;
>  };
> 
>  static bool
> @@ -278,6 +302,31 @@
>      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
>      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT),
>      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
> +    /* Add the op code for SDVO enhancements */
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_POSITION_H),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POSITION_H),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_POSITION_H),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_POSITION_V),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POSITION_V),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_POSITION_V),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V),
> +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V),
>      /* HDMI op code */
>      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
>      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
> @@ -1749,6 +1798,42 @@
>         return 1;
>  }
> 
> +static
> +void intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
> +{
> +       struct intel_output *intel_output = to_intel_output(connector);
> +       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
> +       struct drm_device *dev = connector->dev;
> +
> +       if (sdvo_priv->is_tv) {
> +               if (sdvo_priv->left_property)
> +                       drm_property_destroy(dev, sdvo_priv->left_property);
> +               if (sdvo_priv->right_property)
> +                       drm_property_destroy(dev, sdvo_priv->right_property);
> +               if (sdvo_priv->top_property)
> +                       drm_property_destroy(dev, sdvo_priv->top_property);
> +               if (sdvo_priv->bottom_property)
> +                       drm_property_destroy(dev, sdvo_priv->bottom_property);
> +               if (sdvo_priv->hpos_property)
> +                       drm_property_destroy(dev, sdvo_priv->hpos_property);
> +               if (sdvo_priv->vpos_property)
> +                       drm_property_destroy(dev, sdvo_priv->vpos_property);
> +       }
> +       if (sdvo_priv->is_tv) {
> +               if (sdvo_priv->saturation_property)
> +                       drm_property_destroy(dev, sdvo_priv->saturation_property);
> +               if (sdvo_priv->contrast_property)
> +                       drm_property_destroy(dev, sdvo_priv->contrast_property);
> +               if (sdvo_priv->hue_property)
> +                       drm_property_destroy(dev, sdvo_priv->hue_property);
> +       }
> +       if (sdvo_priv->is_tv) {
> +               if (sdvo_priv->brightness_property)
> +                       drm_property_destroy(dev, sdvo_priv->brightness_property);
> +       }
> +       return;
> +}
> +
>  static void intel_sdvo_destroy(struct drm_connector *connector)
>  {
>         struct intel_output *intel_output = to_intel_output(connector);
> @@ -1767,6 +1852,9 @@
>                 drm_property_destroy(connector->dev,
>                                      sdvo_priv->tv_format_property);
> 
> +       if (sdvo_priv->is_tv)
> +               intel_sdvo_destroy_enhance_property(connector);
> +
>         drm_sysfs_connector_remove(connector);
>         drm_connector_cleanup(connector);
> 
> @@ -1784,6 +1872,8 @@
>         struct drm_crtc *crtc = encoder->crtc;
>         int ret = 0;
>         bool changed = false;
> +       uint8_t cmd, status;
> +       uint16_t temp_value;
> 
>         ret = drm_connector_property_set_value(connector, property, val);
>         if (ret < 0)
> @@ -1800,11 +1890,101 @@
> 
>                 sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[val];
>                 changed = true;
> -       } else {
> -               ret = -EINVAL;
> -               goto out;
>         }
> 
> +       if (sdvo_priv->is_tv) {
> +               cmd = 0;
> +               temp_value = val;
> +               if (sdvo_priv->left_property == property) {
> +                       drm_connector_property_set_value(connector,
> +                               sdvo_priv->right_property, val);
> +                       if (sdvo_priv->left_margin == temp_value)
> +                               goto out;
> +
> +                       sdvo_priv->left_margin = temp_value;
> +                       sdvo_priv->right_margin = temp_value;
> +                       temp_value = sdvo_priv->max_hscan -
> +                                       sdvo_priv->left_margin;
> +                       cmd = SDVO_CMD_SET_OVERSCAN_H;
> +               } else if (sdvo_priv->right_property == property) {
> +                       drm_connector_property_set_value(connector,
> +                               sdvo_priv->left_property, val);
> +                       if (sdvo_priv->right_margin == temp_value)
> +                               goto out;
> +
> +                       sdvo_priv->left_margin = temp_value;
> +                       sdvo_priv->right_margin = temp_value;
> +                       temp_value = sdvo_priv->max_hscan -
> +                               sdvo_priv->left_margin;
> +                       cmd = SDVO_CMD_SET_OVERSCAN_H;
> +               } else if (sdvo_priv->top_property == property) {
> +                       drm_connector_property_set_value(connector,
> +                               sdvo_priv->bottom_property, val);
> +                       if (sdvo_priv->top_margin == temp_value)
> +                               goto out;
> +
> +                       sdvo_priv->top_margin = temp_value;
> +                       sdvo_priv->bottom_margin = temp_value;
> +                       temp_value = sdvo_priv->max_vscan -
> +                                       sdvo_priv->top_margin;
> +                       cmd = SDVO_CMD_SET_OVERSCAN_V;
> +               } else if (sdvo_priv->bottom_property == property) {
> +                       drm_connector_property_set_value(connector,
> +                               sdvo_priv->top_property, val);
> +                       if (sdvo_priv->bottom_margin == temp_value)
> +                               goto out;
> +                       sdvo_priv->top_margin = temp_value;
> +                       sdvo_priv->bottom_margin = temp_value;
> +                       temp_value = sdvo_priv->max_vscan -
> +                                       sdvo_priv->top_margin;
> +                       cmd = SDVO_CMD_SET_OVERSCAN_V;
> +               } else if (sdvo_priv->hpos_property == property) {
> +                       if (sdvo_priv->cur_hpos == temp_value)
> +                               goto out;
> +
> +                       cmd = SDVO_CMD_SET_POSITION_H;
> +                       sdvo_priv->cur_hpos = temp_value;
> +               } else if (sdvo_priv->vpos_property == property) {
> +                       if (sdvo_priv->cur_vpos == temp_value)
> +                               goto out;
> +
> +                       cmd = SDVO_CMD_SET_POSITION_V;
> +                       sdvo_priv->cur_vpos = temp_value;
> +               } else if (sdvo_priv->saturation_property == property) {
> +                       if (sdvo_priv->cur_saturation == temp_value)
> +                               goto out;
> +
> +                       cmd = SDVO_CMD_SET_SATURATION;
> +                       sdvo_priv->cur_saturation = temp_value;
> +               } else if (sdvo_priv->contrast_property == property) {
> +                       if (sdvo_priv->cur_contrast == temp_value)
> +                               goto out;
> +
> +                       cmd = SDVO_CMD_SET_CONTRAST;
> +                       sdvo_priv->cur_contrast = temp_value;
> +               } else if (sdvo_priv->hue_property == property) {
> +                       if (sdvo_priv->cur_hue == temp_value)
> +                               goto out;
> +
> +                       cmd = SDVO_CMD_SET_HUE;
> +                       sdvo_priv->cur_hue = temp_value;
> +               } else if (sdvo_priv->brightness_property == property) {
> +                       if (sdvo_priv->cur_brightness == temp_value)
> +                               goto out;
> +
> +                       cmd = SDVO_CMD_SET_BRIGHTNESS;
> +                       sdvo_priv->cur_brightness = temp_value;
> +               }
> +               if (cmd) {
> +                       intel_sdvo_write_cmd(intel_output, cmd, &temp_value, 2);
> +                       status = intel_sdvo_read_response(intel_output, NULL, 0);
> +                       if (status != SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO command \n");
> +                               return -EINVAL;
> +                       }
> +                       changed = true;
> +               }
> +       }
>         if (changed && crtc)
>                 drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
>                                 crtc->y, crtc->fb);
> @@ -2132,6 +2312,298 @@
> 
>  }
> 
> +static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
> +{
> +        struct intel_output *intel_output = to_intel_output(connector);
> +       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
> +       struct intel_sdvo_enhancements_reply sdvo_data;
> +       struct drm_device *dev = connector->dev;
> +       uint8_t status;
> +       uint16_t response, data_value[2];
> +
> +       intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
> +                                               NULL, 0);
> +       status = intel_sdvo_read_response(intel_output, &sdvo_data,
> +                                       sizeof(sdvo_data));
> +       if (status != SDVO_CMD_STATUS_SUCCESS) {
> +               DRM_DEBUG(" incorrect response is returned\n");
> +               return;
> +       }
> +       response = *((uint16_t *)&sdvo_data);
> +       if (!response) {
> +               DRM_DEBUG("No enhancement is supported\n");
> +               return;
> +       }
> +       if (sdvo_priv->is_tv) {
> +               /* when horizontal overscan is supported, Add the left/right
> +                * property
> +                */
> +               if (sdvo_data.overscan_h) {
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_MAX_OVERSCAN_H, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &data_value, 4);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO h_overscan\n");
> +                               return;
> +                       }
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_OVERSCAN_H, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &response, 2);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO h_overscan\n");
> +                               return;
> +                       }
> +                       sdvo_priv->max_hscan = data_value[0];
> +                       sdvo_priv->left_margin = data_value[0] - response;
> +                       sdvo_priv->right_margin = sdvo_priv->left_margin;
> +                       sdvo_priv->left_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "left_margin", 2);
> +                       sdvo_priv->left_property->values[0] = 0;
> +                       sdvo_priv->left_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->left_property,
> +                                               sdvo_priv->left_margin);
> +                       sdvo_priv->right_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "right_margin", 2);
> +                       sdvo_priv->right_property->values[0] = 0;
> +                       sdvo_priv->right_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->right_property,
> +                                               sdvo_priv->right_margin);
> +                       DRM_DEBUG("h_overscan: max %d, default %d, current %d\n",
> +                                       data_value[0], data_value[1], response);
> +               }
> +               if (sdvo_data.overscan_v) {
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_MAX_OVERSCAN_V, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &data_value, 4);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO v_overscan\n");
> +                               return;
> +                       }
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_OVERSCAN_V, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &response, 2);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO v_overscan\n");
> +                               return;
> +                       }
> +                       sdvo_priv->max_vscan = data_value[0];
> +                       sdvo_priv->top_margin = data_value[0] - response;
> +                       sdvo_priv->bottom_margin = sdvo_priv->top_margin;
> +                       sdvo_priv->top_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "top_margin", 2);
> +                       sdvo_priv->top_property->values[0] = 0;
> +                       sdvo_priv->top_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->top_property,
> +                                               sdvo_priv->top_margin);
> +                       sdvo_priv->bottom_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "bottom_margin", 2);
> +                       sdvo_priv->bottom_property->values[0] = 0;
> +                       sdvo_priv->bottom_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->bottom_property,
> +                                               sdvo_priv->bottom_margin);
> +                       DRM_DEBUG("v_overscan: max %d, default %d, current %d\n",
> +                                       data_value[0], data_value[1], response);
> +               }
> +               if (sdvo_data.position_h) {
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_MAX_POSITION_H, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &data_value, 4);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> +                               return;
> +                       }
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_POSITION_H, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &response, 2);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> +                               return;
> +                       }
> +                       sdvo_priv->max_hpos = data_value[0];
> +                       sdvo_priv->cur_hpos = response;
> +                       sdvo_priv->hpos_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "hpos", 2);
> +                       sdvo_priv->hpos_property->values[0] = 0;
> +                       sdvo_priv->hpos_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->hpos_property,
> +                                               sdvo_priv->cur_hpos);
> +                       DRM_DEBUG("h_position: max %d, default %d, current %d\n",
> +                                       data_value[0], data_value[1], response);
> +               }
> +               if (sdvo_data.position_v) {
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_MAX_POSITION_V, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &data_value, 4);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> +                               return;
> +                       }
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_POSITION_V, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &response, 2);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> +                               return;
> +                       }
> +                       sdvo_priv->max_vpos = data_value[0];
> +                       sdvo_priv->cur_vpos = response;
> +                       sdvo_priv->vpos_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "vpos", 2);
> +                       sdvo_priv->vpos_property->values[0] = 0;
> +                       sdvo_priv->vpos_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->vpos_property,
> +                                               sdvo_priv->cur_vpos);
> +                       DRM_DEBUG("v_position: max %d, default %d, current %d\n",
> +                                       data_value[0], data_value[1], response);
> +               }
> +       }
> +       if (sdvo_priv->is_tv) {
> +               if (sdvo_data.saturation) {
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_MAX_SATURATION, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &data_value, 4);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> +                               return;
> +                       }
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_SATURATION, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &response, 2);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> +                               return;
> +                       }
> +                       sdvo_priv->max_saturation = data_value[0];
> +                       sdvo_priv->cur_saturation = response;
> +                       sdvo_priv->saturation_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "saturation", 2);
> +                       sdvo_priv->saturation_property->values[0] = 0;
> +                       sdvo_priv->saturation_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->saturation_property,
> +                                               sdvo_priv->cur_saturation);
> +                       DRM_DEBUG("saturation: max %d, default %d, current %d\n",
> +                                       data_value[0], data_value[1], response);
> +               }
> +               if (sdvo_data.contrast) {
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_MAX_CONTRAST, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &data_value, 4);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> +                               return;
> +                       }
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_CONTRAST, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &response, 2);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> +                               return;
> +                       }
> +                       sdvo_priv->max_contrast = data_value[0];
> +                       sdvo_priv->cur_contrast = response;
> +                       sdvo_priv->contrast_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "contrast", 2);
> +                       sdvo_priv->contrast_property->values[0] = 0;
> +                       sdvo_priv->contrast_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->contrast_property,
> +                                               sdvo_priv->cur_contrast);
> +                       DRM_DEBUG("contrast: max %d, default %d, current %d\n",
> +                                       data_value[0], data_value[1], response);
> +               }
> +               if (sdvo_data.hue) {
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_MAX_HUE, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &data_value, 4);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> +                               return;
> +                       }
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_HUE, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &response, 2);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> +                               return;
> +                       }
> +                       sdvo_priv->max_hue = data_value[0];
> +                       sdvo_priv->cur_hue = response;
> +                       sdvo_priv->hue_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "hue", 2);
> +                       sdvo_priv->hue_property->values[0] = 0;
> +                       sdvo_priv->hue_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->hue_property,
> +                                               sdvo_priv->cur_hue);
> +                       DRM_DEBUG("hue: max %d, default %d, current %d\n",
> +                                       data_value[0], data_value[1], response);
> +               }
> +       }
> +       if (sdvo_priv->is_tv) {
> +               if (sdvo_data.brightness) {
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_MAX_BRIGHTNESS, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &data_value, 4);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> +                               return;
> +                       }
> +                       intel_sdvo_write_cmd(intel_output,
> +                               SDVO_CMD_GET_BRIGHTNESS, NULL, 0);
> +                       status = intel_sdvo_read_response(intel_output,
> +                               &response, 2);
> +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> +                               return;
> +                       }
> +                       sdvo_priv->max_brightness = data_value[0];
> +                       sdvo_priv->cur_brightness = response;
> +                       sdvo_priv->brightness_property =
> +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> +                                               "brightness", 2);
> +                       sdvo_priv->brightness_property->values[0] = 0;
> +                       sdvo_priv->brightness_property->values[1] = data_value[0];
> +                       drm_connector_attach_property(connector,
> +                                               sdvo_priv->brightness_property,
> +                                               sdvo_priv->cur_brightness);
> +                       DRM_DEBUG("brightness: max %d, default %d, current %d\n",
> +                                       data_value[0], data_value[1], response);
> +               }
> +       }
> +       return;
> +}
> +
>  bool intel_sdvo_init(struct drm_device *dev, int output_device)
>  {
>         struct drm_connector *connector;
> @@ -2214,8 +2686,10 @@
>         drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
> 
>         drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
> -       if (sdvo_priv->is_tv)
> +       if (sdvo_priv->is_tv) {
>                 intel_sdvo_tv_create_property(connector);
> +               intel_sdvo_create_enhance_property(connector);
> +       }
>         drm_sysfs_connector_add(connector);
> 
>         intel_sdvo_select_ddc_bus(sdvo_priv);
Zhao, Yakui Sept. 4, 2009, 5:30 a.m. UTC | #2
On Mon, 2009-08-31 at 11:02 +0800, ykzhao wrote:
> On Mon, 2009-08-31 at 10:57 +0800, Zhao, Yakui wrote:
> > From: Zhao Yakui <yakui.zhao@intel.com>
> 
> Hi, Eric
>     It seems that you already pick up two patches about TV
> property(select TV format according to connector type, Enable PAL and
> SECAM format and add the TV format propery for SDVO-TV)
>     Will you please also pick up the two patches that add the property
> for SDVO-TV/LVDS?
>     Patch 1:  add the property for SDVO-TV(window
> control/saturation/hue/brightness/contrast, which is similar to what we
> have done for integrated TV)
>     Patch 2: add the brightness property for SDVO-LVDS
Hi, Eric
    How about the two patches about adding the property for
SDVO-TV/LVDS?
    One bug with P1 priority is blocked by this patch.

thanks.
> 
> Thanks.
> >
> > When the sdvo device is detected as SDVO-TV, we will check whether the
> > sepecific picture enhancement is supported. If it is supported, we will
> > add the corresponnding property for SDVO-TV. We will add the following
> > property for the SDVO-TV enhancements if they are supported:
> >    Contrast/Brightness/Saturation/Hue:
> >    left/right/top/bottom margin: This is implemented by using the horizontal/
> > vertical overscan enhancements. When the overscan enhancements are supported,
> > the above properties will be added. This is to be compatible with what we have
> > done in integrated-TV.
> >    horizontal pos/vertical pos:
> >
> > http://bugs.freedesktop.org/show_bug.cgi?id=22891
> >
> > Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_sdvo.c |  482 +++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 478 insertions(+), 4 deletions(-)
> >
> > Index: linux-2.6/drivers/gpu/drm/i915/intel_sdvo.c
> > ===================================================================
> > --- linux-2.6.orig/drivers/gpu/drm/i915/intel_sdvo.c    2009-08-31 10:36:49.000000000 +0800
> > +++ linux-2.6/drivers/gpu/drm/i915/intel_sdvo.c 2009-08-31 10:53:12.000000000 +0800
> > @@ -132,6 +132,30 @@
> >         struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
> >         struct intel_sdvo_dtd save_output_dtd[16];
> >         u32 save_SDVOX;
> > +       /* add the property for the SDVO-TV */
> > +       struct drm_property *left_property;
> > +       struct drm_property *right_property;
> > +       struct drm_property *top_property;
> > +       struct drm_property *bottom_property;
> > +       struct drm_property *hpos_property;
> > +       struct drm_property *vpos_property;
> > +
> > +       /* add the property for the SDVO-TV/LVDS */
> > +       struct drm_property *brightness_property;
> > +       struct drm_property *contrast_property;
> > +       struct drm_property *saturation_property;
> > +       struct drm_property *hue_property;
> > +
> > +       /* Add variable to record current setting for the above property */
> > +       u32     left_margin, right_margin, top_margin, bottom_margin;
> > +       /* this is to get the range of margin.*/
> > +       u32     max_hscan,  max_vscan;
> > +       u32     max_hpos, cur_hpos;
> > +       u32     max_vpos, cur_vpos;
> > +       u32     cur_brightness, max_brightness;
> > +       u32     cur_contrast,   max_contrast;
> > +       u32     cur_saturation, max_saturation;
> > +       u32     cur_hue,        max_hue;
> >  };
> >
> >  static bool
> > @@ -278,6 +302,31 @@
> >      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
> >      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT),
> >      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
> > +    /* Add the op code for SDVO enhancements */
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_POSITION_H),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POSITION_H),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_POSITION_H),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_POSITION_V),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POSITION_V),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_POSITION_V),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V),
> > +    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V),
> >      /* HDMI op code */
> >      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
> >      SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
> > @@ -1749,6 +1798,42 @@
> >         return 1;
> >  }
> >
> > +static
> > +void intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
> > +{
> > +       struct intel_output *intel_output = to_intel_output(connector);
> > +       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
> > +       struct drm_device *dev = connector->dev;
> > +
> > +       if (sdvo_priv->is_tv) {
> > +               if (sdvo_priv->left_property)
> > +                       drm_property_destroy(dev, sdvo_priv->left_property);
> > +               if (sdvo_priv->right_property)
> > +                       drm_property_destroy(dev, sdvo_priv->right_property);
> > +               if (sdvo_priv->top_property)
> > +                       drm_property_destroy(dev, sdvo_priv->top_property);
> > +               if (sdvo_priv->bottom_property)
> > +                       drm_property_destroy(dev, sdvo_priv->bottom_property);
> > +               if (sdvo_priv->hpos_property)
> > +                       drm_property_destroy(dev, sdvo_priv->hpos_property);
> > +               if (sdvo_priv->vpos_property)
> > +                       drm_property_destroy(dev, sdvo_priv->vpos_property);
> > +       }
> > +       if (sdvo_priv->is_tv) {
> > +               if (sdvo_priv->saturation_property)
> > +                       drm_property_destroy(dev, sdvo_priv->saturation_property);
> > +               if (sdvo_priv->contrast_property)
> > +                       drm_property_destroy(dev, sdvo_priv->contrast_property);
> > +               if (sdvo_priv->hue_property)
> > +                       drm_property_destroy(dev, sdvo_priv->hue_property);
> > +       }
> > +       if (sdvo_priv->is_tv) {
> > +               if (sdvo_priv->brightness_property)
> > +                       drm_property_destroy(dev, sdvo_priv->brightness_property);
> > +       }
> > +       return;
> > +}
> > +
> >  static void intel_sdvo_destroy(struct drm_connector *connector)
> >  {
> >         struct intel_output *intel_output = to_intel_output(connector);
> > @@ -1767,6 +1852,9 @@
> >                 drm_property_destroy(connector->dev,
> >                                      sdvo_priv->tv_format_property);
> >
> > +       if (sdvo_priv->is_tv)
> > +               intel_sdvo_destroy_enhance_property(connector);
> > +
> >         drm_sysfs_connector_remove(connector);
> >         drm_connector_cleanup(connector);
> >
> > @@ -1784,6 +1872,8 @@
> >         struct drm_crtc *crtc = encoder->crtc;
> >         int ret = 0;
> >         bool changed = false;
> > +       uint8_t cmd, status;
> > +       uint16_t temp_value;
> >
> >         ret = drm_connector_property_set_value(connector, property, val);
> >         if (ret < 0)
> > @@ -1800,11 +1890,101 @@
> >
> >                 sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[val];
> >                 changed = true;
> > -       } else {
> > -               ret = -EINVAL;
> > -               goto out;
> >         }
> >
> > +       if (sdvo_priv->is_tv) {
> > +               cmd = 0;
> > +               temp_value = val;
> > +               if (sdvo_priv->left_property == property) {
> > +                       drm_connector_property_set_value(connector,
> > +                               sdvo_priv->right_property, val);
> > +                       if (sdvo_priv->left_margin == temp_value)
> > +                               goto out;
> > +
> > +                       sdvo_priv->left_margin = temp_value;
> > +                       sdvo_priv->right_margin = temp_value;
> > +                       temp_value = sdvo_priv->max_hscan -
> > +                                       sdvo_priv->left_margin;
> > +                       cmd = SDVO_CMD_SET_OVERSCAN_H;
> > +               } else if (sdvo_priv->right_property == property) {
> > +                       drm_connector_property_set_value(connector,
> > +                               sdvo_priv->left_property, val);
> > +                       if (sdvo_priv->right_margin == temp_value)
> > +                               goto out;
> > +
> > +                       sdvo_priv->left_margin = temp_value;
> > +                       sdvo_priv->right_margin = temp_value;
> > +                       temp_value = sdvo_priv->max_hscan -
> > +                               sdvo_priv->left_margin;
> > +                       cmd = SDVO_CMD_SET_OVERSCAN_H;
> > +               } else if (sdvo_priv->top_property == property) {
> > +                       drm_connector_property_set_value(connector,
> > +                               sdvo_priv->bottom_property, val);
> > +                       if (sdvo_priv->top_margin == temp_value)
> > +                               goto out;
> > +
> > +                       sdvo_priv->top_margin = temp_value;
> > +                       sdvo_priv->bottom_margin = temp_value;
> > +                       temp_value = sdvo_priv->max_vscan -
> > +                                       sdvo_priv->top_margin;
> > +                       cmd = SDVO_CMD_SET_OVERSCAN_V;
> > +               } else if (sdvo_priv->bottom_property == property) {
> > +                       drm_connector_property_set_value(connector,
> > +                               sdvo_priv->top_property, val);
> > +                       if (sdvo_priv->bottom_margin == temp_value)
> > +                               goto out;
> > +                       sdvo_priv->top_margin = temp_value;
> > +                       sdvo_priv->bottom_margin = temp_value;
> > +                       temp_value = sdvo_priv->max_vscan -
> > +                                       sdvo_priv->top_margin;
> > +                       cmd = SDVO_CMD_SET_OVERSCAN_V;
> > +               } else if (sdvo_priv->hpos_property == property) {
> > +                       if (sdvo_priv->cur_hpos == temp_value)
> > +                               goto out;
> > +
> > +                       cmd = SDVO_CMD_SET_POSITION_H;
> > +                       sdvo_priv->cur_hpos = temp_value;
> > +               } else if (sdvo_priv->vpos_property == property) {
> > +                       if (sdvo_priv->cur_vpos == temp_value)
> > +                               goto out;
> > +
> > +                       cmd = SDVO_CMD_SET_POSITION_V;
> > +                       sdvo_priv->cur_vpos = temp_value;
> > +               } else if (sdvo_priv->saturation_property == property) {
> > +                       if (sdvo_priv->cur_saturation == temp_value)
> > +                               goto out;
> > +
> > +                       cmd = SDVO_CMD_SET_SATURATION;
> > +                       sdvo_priv->cur_saturation = temp_value;
> > +               } else if (sdvo_priv->contrast_property == property) {
> > +                       if (sdvo_priv->cur_contrast == temp_value)
> > +                               goto out;
> > +
> > +                       cmd = SDVO_CMD_SET_CONTRAST;
> > +                       sdvo_priv->cur_contrast = temp_value;
> > +               } else if (sdvo_priv->hue_property == property) {
> > +                       if (sdvo_priv->cur_hue == temp_value)
> > +                               goto out;
> > +
> > +                       cmd = SDVO_CMD_SET_HUE;
> > +                       sdvo_priv->cur_hue = temp_value;
> > +               } else if (sdvo_priv->brightness_property == property) {
> > +                       if (sdvo_priv->cur_brightness == temp_value)
> > +                               goto out;
> > +
> > +                       cmd = SDVO_CMD_SET_BRIGHTNESS;
> > +                       sdvo_priv->cur_brightness = temp_value;
> > +               }
> > +               if (cmd) {
> > +                       intel_sdvo_write_cmd(intel_output, cmd, &temp_value, 2);
> > +                       status = intel_sdvo_read_response(intel_output, NULL, 0);
> > +                       if (status != SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO command \n");
> > +                               return -EINVAL;
> > +                       }
> > +                       changed = true;
> > +               }
> > +       }
> >         if (changed && crtc)
> >                 drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
> >                                 crtc->y, crtc->fb);
> > @@ -2132,6 +2312,298 @@
> >
> >  }
> >
> > +static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
> > +{
> > +        struct intel_output *intel_output = to_intel_output(connector);
> > +       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
> > +       struct intel_sdvo_enhancements_reply sdvo_data;
> > +       struct drm_device *dev = connector->dev;
> > +       uint8_t status;
> > +       uint16_t response, data_value[2];
> > +
> > +       intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
> > +                                               NULL, 0);
> > +       status = intel_sdvo_read_response(intel_output, &sdvo_data,
> > +                                       sizeof(sdvo_data));
> > +       if (status != SDVO_CMD_STATUS_SUCCESS) {
> > +               DRM_DEBUG(" incorrect response is returned\n");
> > +               return;
> > +       }
> > +       response = *((uint16_t *)&sdvo_data);
> > +       if (!response) {
> > +               DRM_DEBUG("No enhancement is supported\n");
> > +               return;
> > +       }
> > +       if (sdvo_priv->is_tv) {
> > +               /* when horizontal overscan is supported, Add the left/right
> > +                * property
> > +                */
> > +               if (sdvo_data.overscan_h) {
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_MAX_OVERSCAN_H, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &data_value, 4);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO h_overscan\n");
> > +                               return;
> > +                       }
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_OVERSCAN_H, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &response, 2);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO h_overscan\n");
> > +                               return;
> > +                       }
> > +                       sdvo_priv->max_hscan = data_value[0];
> > +                       sdvo_priv->left_margin = data_value[0] - response;
> > +                       sdvo_priv->right_margin = sdvo_priv->left_margin;
> > +                       sdvo_priv->left_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "left_margin", 2);
> > +                       sdvo_priv->left_property->values[0] = 0;
> > +                       sdvo_priv->left_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->left_property,
> > +                                               sdvo_priv->left_margin);
> > +                       sdvo_priv->right_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "right_margin", 2);
> > +                       sdvo_priv->right_property->values[0] = 0;
> > +                       sdvo_priv->right_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->right_property,
> > +                                               sdvo_priv->right_margin);
> > +                       DRM_DEBUG("h_overscan: max %d, default %d, current %d\n",
> > +                                       data_value[0], data_value[1], response);
> > +               }
> > +               if (sdvo_data.overscan_v) {
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_MAX_OVERSCAN_V, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &data_value, 4);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO v_overscan\n");
> > +                               return;
> > +                       }
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_OVERSCAN_V, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &response, 2);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO v_overscan\n");
> > +                               return;
> > +                       }
> > +                       sdvo_priv->max_vscan = data_value[0];
> > +                       sdvo_priv->top_margin = data_value[0] - response;
> > +                       sdvo_priv->bottom_margin = sdvo_priv->top_margin;
> > +                       sdvo_priv->top_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "top_margin", 2);
> > +                       sdvo_priv->top_property->values[0] = 0;
> > +                       sdvo_priv->top_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->top_property,
> > +                                               sdvo_priv->top_margin);
> > +                       sdvo_priv->bottom_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "bottom_margin", 2);
> > +                       sdvo_priv->bottom_property->values[0] = 0;
> > +                       sdvo_priv->bottom_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->bottom_property,
> > +                                               sdvo_priv->bottom_margin);
> > +                       DRM_DEBUG("v_overscan: max %d, default %d, current %d\n",
> > +                                       data_value[0], data_value[1], response);
> > +               }
> > +               if (sdvo_data.position_h) {
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_MAX_POSITION_H, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &data_value, 4);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> > +                               return;
> > +                       }
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_POSITION_H, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &response, 2);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> > +                               return;
> > +                       }
> > +                       sdvo_priv->max_hpos = data_value[0];
> > +                       sdvo_priv->cur_hpos = response;
> > +                       sdvo_priv->hpos_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "hpos", 2);
> > +                       sdvo_priv->hpos_property->values[0] = 0;
> > +                       sdvo_priv->hpos_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->hpos_property,
> > +                                               sdvo_priv->cur_hpos);
> > +                       DRM_DEBUG("h_position: max %d, default %d, current %d\n",
> > +                                       data_value[0], data_value[1], response);
> > +               }
> > +               if (sdvo_data.position_v) {
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_MAX_POSITION_V, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &data_value, 4);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> > +                               return;
> > +                       }
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_POSITION_V, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &response, 2);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> > +                               return;
> > +                       }
> > +                       sdvo_priv->max_vpos = data_value[0];
> > +                       sdvo_priv->cur_vpos = response;
> > +                       sdvo_priv->vpos_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "vpos", 2);
> > +                       sdvo_priv->vpos_property->values[0] = 0;
> > +                       sdvo_priv->vpos_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->vpos_property,
> > +                                               sdvo_priv->cur_vpos);
> > +                       DRM_DEBUG("v_position: max %d, default %d, current %d\n",
> > +                                       data_value[0], data_value[1], response);
> > +               }
> > +       }
> > +       if (sdvo_priv->is_tv) {
> > +               if (sdvo_data.saturation) {
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_MAX_SATURATION, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &data_value, 4);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> > +                               return;
> > +                       }
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_SATURATION, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &response, 2);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> > +                               return;
> > +                       }
> > +                       sdvo_priv->max_saturation = data_value[0];
> > +                       sdvo_priv->cur_saturation = response;
> > +                       sdvo_priv->saturation_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "saturation", 2);
> > +                       sdvo_priv->saturation_property->values[0] = 0;
> > +                       sdvo_priv->saturation_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->saturation_property,
> > +                                               sdvo_priv->cur_saturation);
> > +                       DRM_DEBUG("saturation: max %d, default %d, current %d\n",
> > +                                       data_value[0], data_value[1], response);
> > +               }
> > +               if (sdvo_data.contrast) {
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_MAX_CONTRAST, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &data_value, 4);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> > +                               return;
> > +                       }
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_CONTRAST, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &response, 2);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> > +                               return;
> > +                       }
> > +                       sdvo_priv->max_contrast = data_value[0];
> > +                       sdvo_priv->cur_contrast = response;
> > +                       sdvo_priv->contrast_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "contrast", 2);
> > +                       sdvo_priv->contrast_property->values[0] = 0;
> > +                       sdvo_priv->contrast_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->contrast_property,
> > +                                               sdvo_priv->cur_contrast);
> > +                       DRM_DEBUG("contrast: max %d, default %d, current %d\n",
> > +                                       data_value[0], data_value[1], response);
> > +               }
> > +               if (sdvo_data.hue) {
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_MAX_HUE, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &data_value, 4);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> > +                               return;
> > +                       }
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_HUE, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &response, 2);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> > +                               return;
> > +                       }
> > +                       sdvo_priv->max_hue = data_value[0];
> > +                       sdvo_priv->cur_hue = response;
> > +                       sdvo_priv->hue_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "hue", 2);
> > +                       sdvo_priv->hue_property->values[0] = 0;
> > +                       sdvo_priv->hue_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->hue_property,
> > +                                               sdvo_priv->cur_hue);
> > +                       DRM_DEBUG("hue: max %d, default %d, current %d\n",
> > +                                       data_value[0], data_value[1], response);
> > +               }
> > +       }
> > +       if (sdvo_priv->is_tv) {
> > +               if (sdvo_data.brightness) {
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_MAX_BRIGHTNESS, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &data_value, 4);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO Max h_positin\n");
> > +                               return;
> > +                       }
> > +                       intel_sdvo_write_cmd(intel_output,
> > +                               SDVO_CMD_GET_BRIGHTNESS, NULL, 0);
> > +                       status = intel_sdvo_read_response(intel_output,
> > +                               &response, 2);
> > +                       if (status !=SDVO_CMD_STATUS_SUCCESS) {
> > +                               DRM_DEBUG("Incorrect SDVO get h_postion\n");
> > +                               return;
> > +                       }
> > +                       sdvo_priv->max_brightness = data_value[0];
> > +                       sdvo_priv->cur_brightness = response;
> > +                       sdvo_priv->brightness_property =
> > +                               drm_property_create(dev, DRM_MODE_PROP_RANGE,
> > +                                               "brightness", 2);
> > +                       sdvo_priv->brightness_property->values[0] = 0;
> > +                       sdvo_priv->brightness_property->values[1] = data_value[0];
> > +                       drm_connector_attach_property(connector,
> > +                                               sdvo_priv->brightness_property,
> > +                                               sdvo_priv->cur_brightness);
> > +                       DRM_DEBUG("brightness: max %d, default %d, current %d\n",
> > +                                       data_value[0], data_value[1], response);
> > +               }
> > +       }
> > +       return;
> > +}
> > +
> >  bool intel_sdvo_init(struct drm_device *dev, int output_device)
> >  {
> >         struct drm_connector *connector;
> > @@ -2214,8 +2686,10 @@
> >         drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
> >
> >         drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
> > -       if (sdvo_priv->is_tv)
> > +       if (sdvo_priv->is_tv) {
> >                 intel_sdvo_tv_create_property(connector);
> > +               intel_sdvo_create_enhance_property(connector);
> > +       }
> >         drm_sysfs_connector_add(connector);
> >
> >         intel_sdvo_select_ddc_bus(sdvo_priv);
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff mbox

Patch

Index: linux-2.6/drivers/gpu/drm/i915/intel_sdvo.c
===================================================================
--- linux-2.6.orig/drivers/gpu/drm/i915/intel_sdvo.c	2009-08-31 10:36:49.000000000 +0800
+++ linux-2.6/drivers/gpu/drm/i915/intel_sdvo.c	2009-08-31 10:53:12.000000000 +0800
@@ -132,6 +132,30 @@ 
 	struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
 	struct intel_sdvo_dtd save_output_dtd[16];
 	u32 save_SDVOX;
+	/* add the property for the SDVO-TV */
+	struct drm_property *left_property;
+	struct drm_property *right_property;
+	struct drm_property *top_property;
+	struct drm_property *bottom_property;
+	struct drm_property *hpos_property;
+	struct drm_property *vpos_property;
+
+	/* add the property for the SDVO-TV/LVDS */
+	struct drm_property *brightness_property;
+	struct drm_property *contrast_property;
+	struct drm_property *saturation_property;
+	struct drm_property *hue_property;
+
+	/* Add variable to record current setting for the above property */
+	u32	left_margin, right_margin, top_margin, bottom_margin;
+	/* this is to get the range of margin.*/
+	u32	max_hscan,  max_vscan;
+	u32	max_hpos, cur_hpos;
+	u32	max_vpos, cur_vpos;
+	u32	cur_brightness, max_brightness;
+	u32	cur_contrast,	max_contrast;
+	u32	cur_saturation, max_saturation;
+	u32	cur_hue,	max_hue;
 };
 
 static bool
@@ -278,6 +302,31 @@ 
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS),
+    /* Add the op code for SDVO enhancements */
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_POSITION_H),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POSITION_H),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_POSITION_H),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_POSITION_V),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POSITION_V),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_POSITION_V),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_SATURATION),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SATURATION),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_SATURATION),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_HUE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HUE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HUE),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_CONTRAST),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CONTRAST),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTRAST),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_BRIGHTNESS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_BRIGHTNESS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_BRIGHTNESS),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_H),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_H),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_H),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_MAX_OVERSCAN_V),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OVERSCAN_V),
+    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OVERSCAN_V),
     /* HDMI op code */
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE),
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE),
@@ -1749,6 +1798,42 @@ 
 	return 1;
 }
 
+static
+void intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
+{
+	struct intel_output *intel_output = to_intel_output(connector);
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+	struct drm_device *dev = connector->dev;
+
+	if (sdvo_priv->is_tv) {
+		if (sdvo_priv->left_property)
+			drm_property_destroy(dev, sdvo_priv->left_property);
+		if (sdvo_priv->right_property)
+			drm_property_destroy(dev, sdvo_priv->right_property);
+		if (sdvo_priv->top_property)
+			drm_property_destroy(dev, sdvo_priv->top_property);
+		if (sdvo_priv->bottom_property)
+			drm_property_destroy(dev, sdvo_priv->bottom_property);
+		if (sdvo_priv->hpos_property)
+			drm_property_destroy(dev, sdvo_priv->hpos_property);
+		if (sdvo_priv->vpos_property)
+			drm_property_destroy(dev, sdvo_priv->vpos_property);
+	}
+	if (sdvo_priv->is_tv) {
+		if (sdvo_priv->saturation_property)
+			drm_property_destroy(dev, sdvo_priv->saturation_property);
+		if (sdvo_priv->contrast_property)
+			drm_property_destroy(dev, sdvo_priv->contrast_property);
+		if (sdvo_priv->hue_property)
+			drm_property_destroy(dev, sdvo_priv->hue_property);
+	}
+	if (sdvo_priv->is_tv) {
+		if (sdvo_priv->brightness_property)
+			drm_property_destroy(dev, sdvo_priv->brightness_property);
+	}
+	return;
+}
+
 static void intel_sdvo_destroy(struct drm_connector *connector)
 {
 	struct intel_output *intel_output = to_intel_output(connector);
@@ -1767,6 +1852,9 @@ 
 		drm_property_destroy(connector->dev,
 				     sdvo_priv->tv_format_property);
 
+	if (sdvo_priv->is_tv)
+		intel_sdvo_destroy_enhance_property(connector);
+
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
 
@@ -1784,6 +1872,8 @@ 
 	struct drm_crtc *crtc = encoder->crtc;
 	int ret = 0;
 	bool changed = false;
+	uint8_t cmd, status;
+	uint16_t temp_value;
 
 	ret = drm_connector_property_set_value(connector, property, val);
 	if (ret < 0)
@@ -1800,11 +1890,101 @@ 
 
 		sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[val];
 		changed = true;
-	} else {
-		ret = -EINVAL;
-		goto out;
 	}
 
+	if (sdvo_priv->is_tv) {
+		cmd = 0;
+		temp_value = val;
+		if (sdvo_priv->left_property == property) {
+			drm_connector_property_set_value(connector,
+				sdvo_priv->right_property, val);
+			if (sdvo_priv->left_margin == temp_value)
+				goto out;
+
+			sdvo_priv->left_margin = temp_value;
+			sdvo_priv->right_margin = temp_value;
+			temp_value = sdvo_priv->max_hscan -
+					sdvo_priv->left_margin;
+			cmd = SDVO_CMD_SET_OVERSCAN_H;
+		} else if (sdvo_priv->right_property == property) {
+			drm_connector_property_set_value(connector,
+				sdvo_priv->left_property, val);
+			if (sdvo_priv->right_margin == temp_value)
+				goto out;
+
+			sdvo_priv->left_margin = temp_value;
+			sdvo_priv->right_margin = temp_value;
+			temp_value = sdvo_priv->max_hscan -
+				sdvo_priv->left_margin;
+			cmd = SDVO_CMD_SET_OVERSCAN_H;
+		} else if (sdvo_priv->top_property == property) {
+			drm_connector_property_set_value(connector,
+				sdvo_priv->bottom_property, val);
+			if (sdvo_priv->top_margin == temp_value)
+				goto out;
+
+			sdvo_priv->top_margin = temp_value;
+			sdvo_priv->bottom_margin = temp_value;
+			temp_value = sdvo_priv->max_vscan -
+					sdvo_priv->top_margin;
+			cmd = SDVO_CMD_SET_OVERSCAN_V;
+		} else if (sdvo_priv->bottom_property == property) {
+			drm_connector_property_set_value(connector,
+				sdvo_priv->top_property, val);
+			if (sdvo_priv->bottom_margin == temp_value)
+				goto out;
+			sdvo_priv->top_margin = temp_value;
+			sdvo_priv->bottom_margin = temp_value;
+			temp_value = sdvo_priv->max_vscan -
+					sdvo_priv->top_margin;
+			cmd = SDVO_CMD_SET_OVERSCAN_V;
+		} else if (sdvo_priv->hpos_property == property) {
+			if (sdvo_priv->cur_hpos == temp_value)
+				goto out;
+
+			cmd = SDVO_CMD_SET_POSITION_H;
+			sdvo_priv->cur_hpos = temp_value;
+		} else if (sdvo_priv->vpos_property == property) {
+			if (sdvo_priv->cur_vpos == temp_value)
+				goto out;
+
+			cmd = SDVO_CMD_SET_POSITION_V;
+			sdvo_priv->cur_vpos = temp_value;
+		} else if (sdvo_priv->saturation_property == property) {
+			if (sdvo_priv->cur_saturation == temp_value)
+				goto out;
+
+			cmd = SDVO_CMD_SET_SATURATION;
+			sdvo_priv->cur_saturation = temp_value;
+		} else if (sdvo_priv->contrast_property == property) {
+			if (sdvo_priv->cur_contrast == temp_value)
+				goto out;
+
+			cmd = SDVO_CMD_SET_CONTRAST;
+			sdvo_priv->cur_contrast = temp_value;
+		} else if (sdvo_priv->hue_property == property) {
+			if (sdvo_priv->cur_hue == temp_value)
+				goto out;
+
+			cmd = SDVO_CMD_SET_HUE;
+			sdvo_priv->cur_hue = temp_value;
+		} else if (sdvo_priv->brightness_property == property) {
+			if (sdvo_priv->cur_brightness == temp_value)
+				goto out;
+
+			cmd = SDVO_CMD_SET_BRIGHTNESS;
+			sdvo_priv->cur_brightness = temp_value;
+		}
+		if (cmd) {
+			intel_sdvo_write_cmd(intel_output, cmd, &temp_value, 2);
+			status = intel_sdvo_read_response(intel_output, NULL, 0);
+			if (status != SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO command \n");
+				return -EINVAL;
+			}
+			changed = true;
+		}
+	}
 	if (changed && crtc)
 		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
 				crtc->y, crtc->fb);
@@ -2132,6 +2312,298 @@ 
 
 }
 
+static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
+{
+        struct intel_output *intel_output = to_intel_output(connector);
+	struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+	struct intel_sdvo_enhancements_reply sdvo_data;
+	struct drm_device *dev = connector->dev;
+	uint8_t status;
+	uint16_t response, data_value[2];
+
+	intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
+						NULL, 0);
+	status = intel_sdvo_read_response(intel_output, &sdvo_data,
+					sizeof(sdvo_data));
+	if (status != SDVO_CMD_STATUS_SUCCESS) {
+		DRM_DEBUG(" incorrect response is returned\n");
+		return;
+	}
+	response = *((uint16_t *)&sdvo_data);
+	if (!response) {
+		DRM_DEBUG("No enhancement is supported\n");
+		return;
+	}
+	if (sdvo_priv->is_tv) {
+		/* when horizontal overscan is supported, Add the left/right
+		 * property
+		 */
+		if (sdvo_data.overscan_h) {
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_MAX_OVERSCAN_H, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&data_value, 4);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO h_overscan\n");
+				return;
+			}
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_OVERSCAN_H, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&response, 2);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO h_overscan\n");
+				return;
+			}
+			sdvo_priv->max_hscan = data_value[0];
+			sdvo_priv->left_margin = data_value[0] - response;
+			sdvo_priv->right_margin = sdvo_priv->left_margin;
+			sdvo_priv->left_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"left_margin", 2);
+			sdvo_priv->left_property->values[0] = 0;
+			sdvo_priv->left_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->left_property,
+						sdvo_priv->left_margin);
+			sdvo_priv->right_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"right_margin", 2);
+			sdvo_priv->right_property->values[0] = 0;
+			sdvo_priv->right_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->right_property,
+						sdvo_priv->right_margin);
+			DRM_DEBUG("h_overscan: max %d, default %d, current %d\n",
+					data_value[0], data_value[1], response);
+		}
+		if (sdvo_data.overscan_v) {
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_MAX_OVERSCAN_V, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&data_value, 4);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO v_overscan\n");
+				return;
+			}
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_OVERSCAN_V, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&response, 2);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO v_overscan\n");
+				return;
+			}
+			sdvo_priv->max_vscan = data_value[0];
+			sdvo_priv->top_margin = data_value[0] - response;
+			sdvo_priv->bottom_margin = sdvo_priv->top_margin;
+			sdvo_priv->top_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"top_margin", 2);
+			sdvo_priv->top_property->values[0] = 0;
+			sdvo_priv->top_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->top_property,
+						sdvo_priv->top_margin);
+			sdvo_priv->bottom_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"bottom_margin", 2);
+			sdvo_priv->bottom_property->values[0] = 0;
+			sdvo_priv->bottom_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->bottom_property,
+						sdvo_priv->bottom_margin);
+			DRM_DEBUG("v_overscan: max %d, default %d, current %d\n",
+					data_value[0], data_value[1], response);
+		}
+		if (sdvo_data.position_h) {
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_MAX_POSITION_H, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&data_value, 4);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO Max h_positin\n");
+				return;
+			}
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_POSITION_H, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&response, 2);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO get h_postion\n");
+				return;
+			}
+			sdvo_priv->max_hpos = data_value[0];
+			sdvo_priv->cur_hpos = response;
+			sdvo_priv->hpos_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"hpos", 2);
+			sdvo_priv->hpos_property->values[0] = 0;
+			sdvo_priv->hpos_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->hpos_property,
+						sdvo_priv->cur_hpos);
+			DRM_DEBUG("h_position: max %d, default %d, current %d\n",
+					data_value[0], data_value[1], response);
+		}
+		if (sdvo_data.position_v) {
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_MAX_POSITION_V, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&data_value, 4);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO Max h_positin\n");
+				return;
+			}
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_POSITION_V, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&response, 2);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO get h_postion\n");
+				return;
+			}
+			sdvo_priv->max_vpos = data_value[0];
+			sdvo_priv->cur_vpos = response;
+			sdvo_priv->vpos_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"vpos", 2);
+			sdvo_priv->vpos_property->values[0] = 0;
+			sdvo_priv->vpos_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->vpos_property,
+						sdvo_priv->cur_vpos);
+			DRM_DEBUG("v_position: max %d, default %d, current %d\n",
+					data_value[0], data_value[1], response);
+		}
+	}
+	if (sdvo_priv->is_tv) {
+		if (sdvo_data.saturation) {
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_MAX_SATURATION, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&data_value, 4);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO Max h_positin\n");
+				return;
+			}
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_SATURATION, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&response, 2);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO get h_postion\n");
+				return;
+			}
+			sdvo_priv->max_saturation = data_value[0];
+			sdvo_priv->cur_saturation = response;
+			sdvo_priv->saturation_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"saturation", 2);
+			sdvo_priv->saturation_property->values[0] = 0;
+			sdvo_priv->saturation_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->saturation_property,
+						sdvo_priv->cur_saturation);
+			DRM_DEBUG("saturation: max %d, default %d, current %d\n",
+					data_value[0], data_value[1], response);
+		}
+		if (sdvo_data.contrast) {
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_MAX_CONTRAST, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&data_value, 4);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO Max h_positin\n");
+				return;
+			}
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_CONTRAST, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&response, 2);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO get h_postion\n");
+				return;
+			}
+			sdvo_priv->max_contrast = data_value[0];
+			sdvo_priv->cur_contrast = response;
+			sdvo_priv->contrast_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"contrast", 2);
+			sdvo_priv->contrast_property->values[0] = 0;
+			sdvo_priv->contrast_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->contrast_property,
+						sdvo_priv->cur_contrast);
+			DRM_DEBUG("contrast: max %d, default %d, current %d\n",
+					data_value[0], data_value[1], response);
+		}
+		if (sdvo_data.hue) {
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_MAX_HUE, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&data_value, 4);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO Max h_positin\n");
+				return;
+			}
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_HUE, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&response, 2);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO get h_postion\n");
+				return;
+			}
+			sdvo_priv->max_hue = data_value[0];
+			sdvo_priv->cur_hue = response;
+			sdvo_priv->hue_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"hue", 2);
+			sdvo_priv->hue_property->values[0] = 0;
+			sdvo_priv->hue_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->hue_property,
+						sdvo_priv->cur_hue);
+			DRM_DEBUG("hue: max %d, default %d, current %d\n",
+					data_value[0], data_value[1], response);
+		}
+	}
+	if (sdvo_priv->is_tv) {
+		if (sdvo_data.brightness) {
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_MAX_BRIGHTNESS, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&data_value, 4);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO Max h_positin\n");
+				return;
+			}
+			intel_sdvo_write_cmd(intel_output,
+				SDVO_CMD_GET_BRIGHTNESS, NULL, 0);
+			status = intel_sdvo_read_response(intel_output,
+				&response, 2);
+			if (status !=SDVO_CMD_STATUS_SUCCESS) {
+				DRM_DEBUG("Incorrect SDVO get h_postion\n");
+				return;
+			}
+			sdvo_priv->max_brightness = data_value[0];
+			sdvo_priv->cur_brightness = response;
+			sdvo_priv->brightness_property =
+				drm_property_create(dev, DRM_MODE_PROP_RANGE,
+						"brightness", 2);
+			sdvo_priv->brightness_property->values[0] = 0;
+			sdvo_priv->brightness_property->values[1] = data_value[0];
+			drm_connector_attach_property(connector,
+						sdvo_priv->brightness_property,
+						sdvo_priv->cur_brightness);
+			DRM_DEBUG("brightness: max %d, default %d, current %d\n",
+					data_value[0], data_value[1], response);
+		}
+	}
+	return;
+}
+
 bool intel_sdvo_init(struct drm_device *dev, int output_device)
 {
 	struct drm_connector *connector;
@@ -2214,8 +2686,10 @@ 
 	drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
 
 	drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
-	if (sdvo_priv->is_tv)
+	if (sdvo_priv->is_tv) {
 		intel_sdvo_tv_create_property(connector);
+		intel_sdvo_create_enhance_property(connector);
+	}
 	drm_sysfs_connector_add(connector);
 
 	intel_sdvo_select_ddc_bus(sdvo_priv);