[Intel-gfx] [PATCH 3/3 V3] drm/i915: adjust mode line to fit our requirement
Ma Ling
ling_ma at linux.intel.com
Mon Jun 8 13:40:25 CEST 2009
Sorry, please ignore this duplicate one, which is delayed by mail server
and I misunderstood it failed to send out, so re-send one.
Thanks
Ma Ling
On Mon, 2009-06-08 at 19:21 +0800, Ma Ling wrote:
> According to fixed mode line, adjust input mode to fit our requirement
>
> Signed-off-by: Ma Ling <ling.ma at intel.com>
> ---
> drivers/gpu/drm/i915/intel_sdvo.c | 76 ++++++++++++++++++++++++++++++++-----
> 1 files changed, 66 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index b062473..37f3990 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -73,6 +73,10 @@ struct intel_sdvo_priv {
> * This is set if we detect output of sdvo device as LVDS.
> */
> bool is_lvds;
> + /**
> + * This is sdvo flags for input timing.
> + */
> + uint8_t sdvo_flags;
>
> struct drm_display_mode *sdvo_lvds_fixed_mode;
>
> @@ -593,6 +597,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output,
> uint16_t height)
> {
> struct intel_sdvo_preferred_input_timing_args args;
> + struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
> uint8_t status;
>
> memset(&args, 0, sizeof(args));
> @@ -600,7 +605,12 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output,
> args.width = width;
> args.height = height;
> args.interlace = 0;
> - args.scaled = 0;
> +
> + if (sdvo_priv->is_lvds &&
> + (sdvo_priv->sdvo_lvds_fixed_mode->hdisplay != width ||
> + sdvo_priv->sdvo_lvds_fixed_mode->vdisplay != height))
> + args.scaled = 1;
> +
> intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
> &args, sizeof(args));
> status = intel_sdvo_read_response(output, NULL, 0);
> @@ -945,12 +955,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
> struct intel_output *output = enc_to_intel_output(encoder);
> struct intel_sdvo_priv *dev_priv = output->dev_priv;
>
> - if (!dev_priv->is_tv) {
> - /* Make the CRTC code factor in the SDVO pixel multiplier. The
> - * SDVO device will be told of the multiplier during mode_set.
> - */
> - adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode);
> - } else {
> + if (dev_priv->is_tv) {
> struct intel_sdvo_dtd output_dtd;
> bool success;
>
> @@ -981,6 +986,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
> intel_sdvo_get_preferred_input_timing(output,
> &input_dtd);
> intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
> + dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
>
> drm_mode_set_crtcinfo(adjusted_mode, 0);
>
> @@ -991,10 +997,57 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
> } else {
> return false;
> }
> + } else if (dev_priv->is_lvds) {
> + struct intel_sdvo_dtd output_dtd;
> + bool success;
> +
> + drm_mode_set_crtcinfo(dev_priv->sdvo_lvds_fixed_mode, 0);
> + /* Set output timings */
> + intel_sdvo_get_dtd_from_mode(&output_dtd,
> + dev_priv->sdvo_lvds_fixed_mode);
> +
> + intel_sdvo_set_target_output(output,
> + dev_priv->controlled_output);
> + intel_sdvo_set_output_timing(output, &output_dtd);
> +
> + /* Set the input timing to the screen. Assume always input 0. */
> + intel_sdvo_set_target_input(output, true, false);
> +
> +
> + success = intel_sdvo_create_preferred_input_timing(
> + output,
> + mode->clock / 10,
> + mode->hdisplay,
> + mode->vdisplay);
> +
> + if (success) {
> + struct intel_sdvo_dtd input_dtd;
> +
> + intel_sdvo_get_preferred_input_timing(output,
> + &input_dtd);
> + intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
> + dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
> +
> + drm_mode_set_crtcinfo(adjusted_mode, 0);
> +
> + mode->clock = adjusted_mode->clock;
> +
> + adjusted_mode->clock *=
> + intel_sdvo_get_pixel_multiplier(mode);
> + } else {
> + return false;
> + }
> +
> + } else {
> + /* Make the CRTC code factor in the SDVO pixel multiplier. The
> + * SDVO device will be told of the multiplier during mode_set.
> + */
> + adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode);
> }
> return true;
> }
>
> +#define SDVO_NEED_TO_STALL (1 << 7)
> static void intel_sdvo_mode_set(struct drm_encoder *encoder,
> struct drm_display_mode *mode,
> struct drm_display_mode *adjusted_mode)
> @@ -1034,15 +1087,16 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
>
> /* We have tried to get input timing in mode_fixup, and filled into
> adjusted_mode */
> - if (sdvo_priv->is_tv)
> + if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
> intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
> - else
> + input_dtd.part2.sdvo_flags = sdvo_priv->sdvo_flags;
> + } else
> intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
>
> /* If it's a TV, we already set the output timing in mode_fixup.
> * Otherwise, the output timing is equal to the input timing.
> */
> - if (!sdvo_priv->is_tv) {
> + if (!sdvo_priv->is_tv && !sdvo_priv->is_lvds) {
> /* Set the output timing to the screen */
> intel_sdvo_set_target_output(output,
> sdvo_priv->controlled_output);
> @@ -1117,6 +1171,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
> sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
> }
>
> + if (sdvo_priv->sdvo_flags & SDVO_NEED_TO_STALL)
> + sdvox |= SDVO_STALL_SELECT;
> intel_sdvo_write_sdvox(output, sdvox);
> }
>
More information about the Intel-gfx
mailing list