]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/gpu/drm/i915/intel_tv.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
[net-next-2.6.git] / drivers / gpu / drm / i915 / intel_tv.c
index cc3726a4a1cb12cf0acb69baf1bce7f81586b111..c671f60ce80bac917a61c1c60cdb02e692afcb85 100644 (file)
@@ -44,7 +44,9 @@ enum tv_margin {
 };
 
 /** Private structure for the integrated TV support */
-struct intel_tv_priv {
+struct intel_tv {
+       struct intel_encoder base;
+
        int type;
        char *tv_format;
        int margin[4];
@@ -896,6 +898,11 @@ static const struct tv_mode tv_modes[] = {
        },
 };
 
+static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder)
+{
+       return container_of(enc_to_intel_encoder(encoder), struct intel_tv, base);
+}
+
 static void
 intel_tv_dpms(struct drm_encoder *encoder, int mode)
 {
@@ -929,19 +936,17 @@ intel_tv_mode_lookup (char *tv_format)
 }
 
 static const struct tv_mode *
-intel_tv_mode_find (struct intel_encoder *intel_encoder)
+intel_tv_mode_find (struct intel_tv *intel_tv)
 {
-       struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
-
-       return intel_tv_mode_lookup(tv_priv->tv_format);
+       return intel_tv_mode_lookup(intel_tv->tv_format);
 }
 
 static enum drm_mode_status
 intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode)
 {
        struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
+       struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
+       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
 
        /* Ensure TV refresh is close to desired refresh */
        if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
@@ -957,8 +962,8 @@ intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
 {
        struct drm_device *dev = encoder->dev;
        struct drm_mode_config *drm_config = &dev->mode_config;
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-       const struct tv_mode *tv_mode = intel_tv_mode_find (intel_encoder);
+       struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
+       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
        struct drm_encoder *other_encoder;
 
        if (!tv_mode)
@@ -983,9 +988,8 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc = encoder->crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-       struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
-       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
+       struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
+       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
        u32 tv_ctl;
        u32 hctl1, hctl2, hctl3;
        u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
@@ -1001,7 +1005,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
        tv_ctl = I915_READ(TV_CTL);
        tv_ctl &= TV_CTL_SAVE;
 
-       switch (tv_priv->type) {
+       switch (intel_tv->type) {
        default:
        case DRM_MODE_CONNECTOR_Unknown:
        case DRM_MODE_CONNECTOR_Composite:
@@ -1154,11 +1158,11 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 
                /* Wait for vblank for the disable to take effect */
                if (!IS_I9XX(dev))
-                       intel_wait_for_vblank(dev);
+                       intel_wait_for_vblank(dev, intel_crtc->pipe);
 
                I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
                /* Wait for vblank for the disable to take effect. */
-               intel_wait_for_vblank(dev);
+               intel_wait_for_vblank(dev, intel_crtc->pipe);
 
                /* Filter ctl must be set before TV_WIN_SIZE */
                I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE);
@@ -1168,12 +1172,12 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                else
                        ysize = 2*tv_mode->nbr_end + 1;
 
-               xpos += tv_priv->margin[TV_MARGIN_LEFT];
-               ypos += tv_priv->margin[TV_MARGIN_TOP];
-               xsize -= (tv_priv->margin[TV_MARGIN_LEFT] +
-                         tv_priv->margin[TV_MARGIN_RIGHT]);
-               ysize -= (tv_priv->margin[TV_MARGIN_TOP] +
-                         tv_priv->margin[TV_MARGIN_BOTTOM]);
+               xpos += intel_tv->margin[TV_MARGIN_LEFT];
+               ypos += intel_tv->margin[TV_MARGIN_TOP];
+               xsize -= (intel_tv->margin[TV_MARGIN_LEFT] +
+                         intel_tv->margin[TV_MARGIN_RIGHT]);
+               ysize -= (intel_tv->margin[TV_MARGIN_TOP] +
+                         intel_tv->margin[TV_MARGIN_BOTTOM]);
                I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos);
                I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize);
 
@@ -1222,9 +1226,9 @@ static const struct drm_display_mode reported_modes[] = {
  * \return false if TV is disconnected.
  */
 static int
-intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder)
+intel_tv_detect_type (struct intel_tv *intel_tv)
 {
-       struct drm_encoder *encoder = &intel_encoder->enc;
+       struct drm_encoder *encoder = &intel_tv->base.enc;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long irqflags;
@@ -1263,11 +1267,15 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder
                   DAC_C_0_7_V);
        I915_WRITE(TV_CTL, tv_ctl);
        I915_WRITE(TV_DAC, tv_dac);
-       intel_wait_for_vblank(dev);
+       POSTING_READ(TV_DAC);
+       msleep(20);
+
        tv_dac = I915_READ(TV_DAC);
        I915_WRITE(TV_DAC, save_tv_dac);
        I915_WRITE(TV_CTL, save_tv_ctl);
-       intel_wait_for_vblank(dev);
+       POSTING_READ(TV_CTL);
+       msleep(20);
+
        /*
         *  A B C
         *  0 1 1 Composite
@@ -1304,12 +1312,11 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder
 static void intel_tv_find_better_format(struct drm_connector *connector)
 {
        struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-       struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
-       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
+       struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
+       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
        int i;
 
-       if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) ==
+       if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
                tv_mode->component_only)
                return;
 
@@ -1317,12 +1324,12 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
        for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) {
                tv_mode = tv_modes + i;
 
-               if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) ==
+               if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
                        tv_mode->component_only)
                        break;
        }
 
-       tv_priv->tv_format = tv_mode->name;
+       intel_tv->tv_format = tv_mode->name;
        drm_connector_property_set_value(connector,
                connector->dev->mode_config.tv_mode_property, i);
 }
@@ -1336,31 +1343,31 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
 static enum drm_connector_status
 intel_tv_detect(struct drm_connector *connector)
 {
-       struct drm_crtc *crtc;
        struct drm_display_mode mode;
        struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-       struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
-       int dpms_mode;
-       int type = tv_priv->type;
+       struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
+       int type;
 
        mode = reported_modes[0];
        drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
 
        if (encoder->crtc && encoder->crtc->enabled) {
-               type = intel_tv_detect_type(encoder->crtc, intel_encoder);
+               type = intel_tv_detect_type(intel_tv);
        } else {
-               crtc = intel_get_load_detect_pipe(intel_encoder, connector,
+               struct drm_crtc *crtc;
+               int dpms_mode;
+
+               crtc = intel_get_load_detect_pipe(&intel_tv->base, connector,
                                                  &mode, &dpms_mode);
                if (crtc) {
-                       type = intel_tv_detect_type(crtc, intel_encoder);
-                       intel_release_load_detect_pipe(intel_encoder, connector,
+                       type = intel_tv_detect_type(intel_tv);
+                       intel_release_load_detect_pipe(&intel_tv->base, connector,
                                                       dpms_mode);
                } else
                        type = -1;
        }
 
-       tv_priv->type = type;
+       intel_tv->type = type;
 
        if (type < 0)
                return connector_status_disconnected;
@@ -1391,8 +1398,8 @@ intel_tv_chose_preferred_modes(struct drm_connector *connector,
                               struct drm_display_mode *mode_ptr)
 {
        struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
+       struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
+       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
 
        if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
                mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
@@ -1417,8 +1424,8 @@ intel_tv_get_modes(struct drm_connector *connector)
 {
        struct drm_display_mode *mode_ptr;
        struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
+       struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
+       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
        int j, count = 0;
        u64 tmp;
 
@@ -1483,8 +1490,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
 {
        struct drm_device *dev = connector->dev;
        struct drm_encoder *encoder = intel_attached_encoder(connector);
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-       struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
+       struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
        struct drm_crtc *crtc = encoder->crtc;
        int ret = 0;
        bool changed = false;
@@ -1494,30 +1500,30 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
                goto out;
 
        if (property == dev->mode_config.tv_left_margin_property &&
-               tv_priv->margin[TV_MARGIN_LEFT] != val) {
-               tv_priv->margin[TV_MARGIN_LEFT] = val;
+               intel_tv->margin[TV_MARGIN_LEFT] != val) {
+               intel_tv->margin[TV_MARGIN_LEFT] = val;
                changed = true;
        } else if (property == dev->mode_config.tv_right_margin_property &&
-               tv_priv->margin[TV_MARGIN_RIGHT] != val) {
-               tv_priv->margin[TV_MARGIN_RIGHT] = val;
+               intel_tv->margin[TV_MARGIN_RIGHT] != val) {
+               intel_tv->margin[TV_MARGIN_RIGHT] = val;
                changed = true;
        } else if (property == dev->mode_config.tv_top_margin_property &&
-               tv_priv->margin[TV_MARGIN_TOP] != val) {
-               tv_priv->margin[TV_MARGIN_TOP] = val;
+               intel_tv->margin[TV_MARGIN_TOP] != val) {
+               intel_tv->margin[TV_MARGIN_TOP] = val;
                changed = true;
        } else if (property == dev->mode_config.tv_bottom_margin_property &&
-               tv_priv->margin[TV_MARGIN_BOTTOM] != val) {
-               tv_priv->margin[TV_MARGIN_BOTTOM] = val;
+               intel_tv->margin[TV_MARGIN_BOTTOM] != val) {
+               intel_tv->margin[TV_MARGIN_BOTTOM] = val;
                changed = true;
        } else if (property == dev->mode_config.tv_mode_property) {
                if (val >= ARRAY_SIZE(tv_modes)) {
                        ret = -EINVAL;
                        goto out;
                }
-               if (!strcmp(tv_priv->tv_format, tv_modes[val].name))
+               if (!strcmp(intel_tv->tv_format, tv_modes[val].name))
                        goto out;
 
-               tv_priv->tv_format = tv_modes[val].name;
+               intel_tv->tv_format = tv_modes[val].name;
                changed = true;
        } else {
                ret = -EINVAL;
@@ -1553,16 +1559,8 @@ static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs =
        .best_encoder = intel_attached_encoder,
 };
 
-static void intel_tv_enc_destroy(struct drm_encoder *encoder)
-{
-       struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
-
-       drm_encoder_cleanup(encoder);
-       kfree(intel_encoder);
-}
-
 static const struct drm_encoder_funcs intel_tv_enc_funcs = {
-       .destroy = intel_tv_enc_destroy,
+       .destroy = intel_encoder_destroy,
 };
 
 /*
@@ -1606,9 +1604,9 @@ intel_tv_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_connector *connector;
+       struct intel_tv *intel_tv;
        struct intel_encoder *intel_encoder;
        struct intel_connector *intel_connector;
-       struct intel_tv_priv *tv_priv;
        u32 tv_dac_on, tv_dac_off, save_tv_dac;
        char **tv_format_names;
        int i, initial_mode = 0;
@@ -1647,18 +1645,18 @@ intel_tv_init(struct drm_device *dev)
            (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
                return;
 
-       intel_encoder = kzalloc(sizeof(struct intel_encoder) +
-                              sizeof(struct intel_tv_priv), GFP_KERNEL);
-       if (!intel_encoder) {
+       intel_tv = kzalloc(sizeof(struct intel_tv), GFP_KERNEL);
+       if (!intel_tv) {
                return;
        }
 
        intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
        if (!intel_connector) {
-               kfree(intel_encoder);
+               kfree(intel_tv);
                return;
        }
 
+       intel_encoder = &intel_tv->base;
        connector = &intel_connector->base;
 
        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
@@ -1668,22 +1666,20 @@ intel_tv_init(struct drm_device *dev)
                         DRM_MODE_ENCODER_TVDAC);
 
        drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc);
-       tv_priv = (struct intel_tv_priv *)(intel_encoder + 1);
        intel_encoder->type = INTEL_OUTPUT_TVOUT;
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
        intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
        intel_encoder->enc.possible_crtcs = ((1 << 0) | (1 << 1));
        intel_encoder->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
-       intel_encoder->dev_priv = tv_priv;
-       tv_priv->type = DRM_MODE_CONNECTOR_Unknown;
+       intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
 
        /* BIOS margin values */
-       tv_priv->margin[TV_MARGIN_LEFT] = 54;
-       tv_priv->margin[TV_MARGIN_TOP] = 36;
-       tv_priv->margin[TV_MARGIN_RIGHT] = 46;
-       tv_priv->margin[TV_MARGIN_BOTTOM] = 37;
+       intel_tv->margin[TV_MARGIN_LEFT] = 54;
+       intel_tv->margin[TV_MARGIN_TOP] = 36;
+       intel_tv->margin[TV_MARGIN_RIGHT] = 46;
+       intel_tv->margin[TV_MARGIN_BOTTOM] = 37;
 
-       tv_priv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
+       intel_tv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
 
        drm_encoder_helper_add(&intel_encoder->enc, &intel_tv_helper_funcs);
        drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
@@ -1703,16 +1699,16 @@ intel_tv_init(struct drm_device *dev)
                                   initial_mode);
        drm_connector_attach_property(connector,
                                   dev->mode_config.tv_left_margin_property,
-                                  tv_priv->margin[TV_MARGIN_LEFT]);
+                                  intel_tv->margin[TV_MARGIN_LEFT]);
        drm_connector_attach_property(connector,
                                   dev->mode_config.tv_top_margin_property,
-                                  tv_priv->margin[TV_MARGIN_TOP]);
+                                  intel_tv->margin[TV_MARGIN_TOP]);
        drm_connector_attach_property(connector,
                                   dev->mode_config.tv_right_margin_property,
-                                  tv_priv->margin[TV_MARGIN_RIGHT]);
+                                  intel_tv->margin[TV_MARGIN_RIGHT]);
        drm_connector_attach_property(connector,
                                   dev->mode_config.tv_bottom_margin_property,
-                                  tv_priv->margin[TV_MARGIN_BOTTOM]);
+                                  intel_tv->margin[TV_MARGIN_BOTTOM]);
 out:
        drm_sysfs_connector_add(connector);
 }