Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Sep 2009 03:31:02 +0000 (17:31 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Sep 2009 03:31:02 +0000 (17:31 -1000)
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6:
  V4L/DVB (12564a): MAINTAINERS: Update gspca sn9c20x name style
  V4L/DVB (12502): gspca - sn9c20x: Fix gscpa sn9c20x build errors.
  V4L/DVB (12495): em28xx: Don't call em28xx_ir_init when disable_ir is true
  V4L/DVB (12457): zr364: wrong indexes
  V4L/DVB (12451): Update KConfig File to enable SDIO and USB interfaces
  V4L/DVB (12450): Siano: Fixed SDIO compilation bugs
  V4L/DVB (12449): adds webcam for Micron device MT9M111 0x143A to em28xx
  V4L/DVB (12446): sms1xxx: restore GPIO functionality for all Hauppauge devices

14 files changed:
drivers/ata/ata_piix.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c
include/linux/lmb.h

index 56b8a3f..9ac4e37 100644 (file)
@@ -664,6 +664,8 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
        return ata_sff_prereset(link, deadline);
 }
 
+static DEFINE_SPINLOCK(piix_lock);
+
 /**
  *     piix_set_piomode - Initialize host controller PATA PIO timings
  *     @ap: Port whose timings we are configuring
@@ -677,8 +679,9 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
 
 static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-       unsigned int pio        = adev->pio_mode - XFER_PIO_0;
        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
+       unsigned long flags;
+       unsigned int pio        = adev->pio_mode - XFER_PIO_0;
        unsigned int is_slave   = (adev->devno != 0);
        unsigned int master_port= ap->port_no ? 0x42 : 0x40;
        unsigned int slave_port = 0x44;
@@ -708,6 +711,8 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
        if (adev->class == ATA_DEV_ATA)
                control |= 4;   /* PPE enable */
 
+       spin_lock_irqsave(&piix_lock, flags);
+
        /* PIO configuration clears DTE unconditionally.  It will be
         * programmed in set_dmamode which is guaranteed to be called
         * after set_piomode if any DMA mode is available.
@@ -747,6 +752,8 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
                udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
                pci_write_config_byte(dev, 0x48, udma_enable);
        }
+
+       spin_unlock_irqrestore(&piix_lock, flags);
 }
 
 /**
@@ -764,6 +771,7 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
 static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich)
 {
        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
+       unsigned long flags;
        u8 master_port          = ap->port_no ? 0x42 : 0x40;
        u16 master_data;
        u8 speed                = adev->dma_mode;
@@ -777,6 +785,8 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in
                            { 2, 1 },
                            { 2, 3 }, };
 
+       spin_lock_irqsave(&piix_lock, flags);
+
        pci_read_config_word(dev, master_port, &master_data);
        if (ap->udma_mask)
                pci_read_config_byte(dev, 0x48, &udma_enable);
@@ -867,6 +877,8 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in
        /* Don't scribble on 0x48 if the controller does not support UDMA */
        if (ap->udma_mask)
                pci_write_config_byte(dev, 0x48, udma_enable);
+
+       spin_unlock_irqrestore(&piix_lock, flags);
 }
 
 /**
index 7537f57..5b4f87e 100644 (file)
@@ -222,6 +222,7 @@ typedef struct drm_i915_private {
        unsigned int edp_support:1;
        int lvds_ssc_freq;
 
+       int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */
        struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
        int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
        int num_fence_regs; /* 8 on pre-965, 16 otherwise */
@@ -384,6 +385,9 @@ typedef struct drm_i915_private {
                 */
                struct list_head inactive_list;
 
+               /** LRU list of objects with fence regs on them. */
+               struct list_head fence_list;
+
                /**
                 * List of breadcrumbs associated with GPU requests currently
                 * outstanding.
@@ -451,6 +455,9 @@ struct drm_i915_gem_object {
        /** This object's place on the active/flushing/inactive lists */
        struct list_head list;
 
+       /** This object's place on the fenced object LRU */
+       struct list_head fence_list;
+
        /**
         * This is set if the object is on the active or flushing lists
         * (has pending rendering), and is not set if it's on inactive (ready
index 140bee1..0c07a75 100644 (file)
@@ -978,6 +978,7 @@ int
 i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_set_domain *args = data;
        struct drm_gem_object *obj;
        uint32_t read_domains = args->read_domains;
@@ -1010,8 +1011,18 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
                 obj, obj->size, read_domains, write_domain);
 #endif
        if (read_domains & I915_GEM_DOMAIN_GTT) {
+               struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
                ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
 
+               /* Update the LRU on the fence for the CPU access that's
+                * about to occur.
+                */
+               if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
+                       list_move_tail(&obj_priv->fence_list,
+                                      &dev_priv->mm.fence_list);
+               }
+
                /* Silently promote "you're not bound, there was nothing to do"
                 * to success, since the client was just asking us to
                 * make sure everything was done.
@@ -1155,8 +1166,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        }
 
        /* Need a new fence register? */
-       if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-           obj_priv->tiling_mode != I915_TILING_NONE) {
+       if (obj_priv->tiling_mode != I915_TILING_NONE) {
                ret = i915_gem_object_get_fence_reg(obj);
                if (ret) {
                        mutex_unlock(&dev->struct_mutex);
@@ -2208,6 +2218,12 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
        struct drm_i915_gem_object *old_obj_priv = NULL;
        int i, ret, avail;
 
+       /* Just update our place in the LRU if our fence is getting used. */
+       if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
+               list_move_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
+               return 0;
+       }
+
        switch (obj_priv->tiling_mode) {
        case I915_TILING_NONE:
                WARN(1, "allocating a fence for non-tiled object?\n");
@@ -2229,7 +2245,6 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
        }
 
        /* First try to find a free reg */
-try_again:
        avail = 0;
        for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
                reg = &dev_priv->fence_regs[i];
@@ -2243,52 +2258,41 @@ try_again:
 
        /* None available, try to steal one or wait for a user to finish */
        if (i == dev_priv->num_fence_regs) {
-               uint32_t seqno = dev_priv->mm.next_gem_seqno;
+               struct drm_gem_object *old_obj = NULL;
 
                if (avail == 0)
                        return -ENOSPC;
 
-               for (i = dev_priv->fence_reg_start;
-                    i < dev_priv->num_fence_regs; i++) {
-                       uint32_t this_seqno;
+               list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list,
+                                   fence_list) {
+                       old_obj = old_obj_priv->obj;
 
-                       reg = &dev_priv->fence_regs[i];
-                       old_obj_priv = reg->obj->driver_private;
+                       reg = &dev_priv->fence_regs[old_obj_priv->fence_reg];
 
                        if (old_obj_priv->pin_count)
                                continue;
 
+                       /* Take a reference, as otherwise the wait_rendering
+                        * below may cause the object to get freed out from
+                        * under us.
+                        */
+                       drm_gem_object_reference(old_obj);
+
                        /* i915 uses fences for GPU access to tiled buffers */
                        if (IS_I965G(dev) || !old_obj_priv->active)
                                break;
 
-                       /* find the seqno of the first available fence */
-                       this_seqno = old_obj_priv->last_rendering_seqno;
-                       if (this_seqno != 0 &&
-                           reg->obj->write_domain == 0 &&
-                           i915_seqno_passed(seqno, this_seqno))
-                               seqno = this_seqno;
-               }
-
-               /*
-                * Now things get ugly... we have to wait for one of the
-                * objects to finish before trying again.
-                */
-               if (i == dev_priv->num_fence_regs) {
-                       if (seqno == dev_priv->mm.next_gem_seqno) {
-                               i915_gem_flush(dev,
-                                              I915_GEM_GPU_DOMAINS,
-                                              I915_GEM_GPU_DOMAINS);
-                               seqno = i915_add_request(dev, NULL,
-                                                        I915_GEM_GPU_DOMAINS);
-                               if (seqno == 0)
-                                       return -ENOMEM;
-                       }
-
-                       ret = i915_wait_request(dev, seqno);
-                       if (ret)
+                       /* This brings the object to the head of the LRU if it
+                        * had been written to.  The only way this should
+                        * result in us waiting longer than the expected
+                        * optimal amount of time is if there was a
+                        * fence-using buffer later that was read-only.
+                        */
+                       i915_gem_object_flush_gpu_write_domain(old_obj);
+                       ret = i915_gem_object_wait_rendering(old_obj);
+                       if (ret != 0)
                                return ret;
-                       goto try_again;
+                       break;
                }
 
                /*
@@ -2296,10 +2300,15 @@ try_again:
                 * for this object next time we need it.
                 */
                i915_gem_release_mmap(reg->obj);
+               i = old_obj_priv->fence_reg;
                old_obj_priv->fence_reg = I915_FENCE_REG_NONE;
+               list_del_init(&old_obj_priv->fence_list);
+               drm_gem_object_unreference(old_obj);
        }
 
        obj_priv->fence_reg = i;
+       list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
+
        reg->obj = obj;
 
        if (IS_I965G(dev))
@@ -2342,6 +2351,7 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
 
        dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
        obj_priv->fence_reg = I915_FENCE_REG_NONE;
+       list_del_init(&obj_priv->fence_list);
 }
 
 /**
@@ -3595,9 +3605,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
         * Pre-965 chips need a fence register set up in order to
         * properly handle tiled surfaces.
         */
-       if (!IS_I965G(dev) &&
-           obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-           obj_priv->tiling_mode != I915_TILING_NONE) {
+       if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) {
                ret = i915_gem_object_get_fence_reg(obj);
                if (ret != 0) {
                        if (ret != -EBUSY && ret != -ERESTARTSYS)
@@ -3806,6 +3814,7 @@ int i915_gem_init_object(struct drm_gem_object *obj)
        obj_priv->obj = obj;
        obj_priv->fence_reg = I915_FENCE_REG_NONE;
        INIT_LIST_HEAD(&obj_priv->list);
+       INIT_LIST_HEAD(&obj_priv->fence_list);
 
        return 0;
 }
@@ -4253,6 +4262,7 @@ i915_gem_load(struct drm_device *dev)
        INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
        INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
        INIT_LIST_HEAD(&dev_priv->mm.request_list);
+       INIT_LIST_HEAD(&dev_priv->mm.fence_list);
        INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
                          i915_gem_retire_work_handler);
        dev_priv->mm.next_gem_seqno = 1;
index 300aee3..f806fcc 100644 (file)
@@ -59,6 +59,16 @@ find_section(struct bdb_header *bdb, int section_id)
        return NULL;
 }
 
+static u16
+get_blocksize(void *p)
+{
+       u16 *block_ptr, block_size;
+
+       block_ptr = (u16 *)((char *)p - 2);
+       block_size = *block_ptr;
+       return block_size;
+}
+
 static void
 fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
                        struct lvds_dvo_timing *dvo_timing)
@@ -214,6 +224,41 @@ parse_general_features(struct drm_i915_private *dev_priv,
        }
 }
 
+static void
+parse_general_definitions(struct drm_i915_private *dev_priv,
+                         struct bdb_header *bdb)
+{
+       struct bdb_general_definitions *general;
+       const int crt_bus_map_table[] = {
+               GPIOB,
+               GPIOA,
+               GPIOC,
+               GPIOD,
+               GPIOE,
+               GPIOF,
+       };
+
+       /* Set sensible defaults in case we can't find the general block
+          or it is the wrong chipset */
+       dev_priv->crt_ddc_bus = -1;
+
+       general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+       if (general) {
+               u16 block_size = get_blocksize(general);
+               if (block_size >= sizeof(*general)) {
+                       int bus_pin = general->crt_ddc_gmbus_pin;
+                       DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin);
+                       if ((bus_pin >= 1) && (bus_pin <= 6)) {
+                               dev_priv->crt_ddc_bus =
+                                       crt_bus_map_table[bus_pin-1];
+                       }
+               } else {
+                       DRM_DEBUG("BDB_GD too small (%d). Invalid.\n",
+                                 block_size);
+               }
+       }
+}
+
 static void
 parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
                       struct bdb_header *bdb)
@@ -222,7 +267,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
        struct bdb_general_definitions *p_defs;
        struct child_device_config *p_child;
        int i, child_device_num, count;
-       u16     block_size, *block_ptr;
+       u16     block_size;
 
        p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
        if (!p_defs) {
@@ -240,8 +285,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
                return;
        }
        /* get the block size of general definitions */
-       block_ptr = (u16 *)((char *)p_defs - 2);
-       block_size = *block_ptr;
+       block_size = get_blocksize(p_defs);
        /* get the number of child device */
        child_device_num = (block_size - sizeof(*p_defs)) /
                                sizeof(*p_child);
@@ -362,6 +406,7 @@ intel_init_bios(struct drm_device *dev)
 
        /* Grab useful general definitions */
        parse_general_features(dev_priv, bdb);
+       parse_general_definitions(dev_priv, bdb);
        parse_lfp_panel_data(dev_priv, bdb);
        parse_sdvo_panel_data(dev_priv, bdb);
        parse_sdvo_device_mapping(dev_priv, bdb);
index 4cf8e2e..590f81c 100644 (file)
@@ -508,6 +508,7 @@ void intel_crt_init(struct drm_device *dev)
 {
        struct drm_connector *connector;
        struct intel_output *intel_output;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        u32 i2c_reg;
 
        intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
@@ -527,8 +528,12 @@ void intel_crt_init(struct drm_device *dev)
        /* Set up the DDC bus. */
        if (IS_IGDNG(dev))
                i2c_reg = PCH_GPIOA;
-       else
+       else {
                i2c_reg = GPIOA;
+               /* Use VBT information for CRT DDC if available */
+               if (dev_priv->crt_ddc_bus != -1)
+                       i2c_reg = dev_priv->crt_ddc_bus;
+       }
        intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
        if (!intel_output->ddc_bus) {
                dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
@@ -537,6 +542,10 @@ void intel_crt_init(struct drm_device *dev)
        }
 
        intel_output->type = INTEL_OUTPUT_ANALOG;
+       intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+                                  (1 << INTEL_ANALOG_CLONE_BIT) |
+                                  (1 << INTEL_SDVO_LVDS_CLONE_BIT);
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;
 
index d6fce21..3fadb53 100644 (file)
@@ -666,7 +666,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
        intel_clock_t clock;
        int err = target;
 
-       if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
            (I915_READ(LVDS)) != 0) {
                /*
                 * For LVDS, if the panel is on, just rely on its current
@@ -2396,7 +2396,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                if (is_sdvo) {
                        dpll |= DPLL_DVO_HIGH_SPEED;
                        sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
-                       if (IS_I945G(dev) || IS_I945GM(dev))
+                       if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
                                dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
                        else if (IS_IGDNG(dev))
                                dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
@@ -3170,7 +3170,7 @@ static int intel_connector_clones(struct drm_device *dev, int type_mask)
 
         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct intel_output *intel_output = to_intel_output(connector);
-               if (type_mask & (1 << intel_output->type))
+               if (type_mask & intel_output->clone_mask)
                        index_mask |= (1 << entry);
                entry++;
        }
@@ -3218,30 +3218,30 @@ static void intel_setup_outputs(struct drm_device *dev)
                        intel_dp_init(dev, PCH_DP_D);
 
        } else if (IS_I9XX(dev)) {
-               int found;
-               u32 reg;
+               bool found = false;
 
                if (I915_READ(SDVOB) & SDVO_DETECTED) {
                        found = intel_sdvo_init(dev, SDVOB);
                        if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
                                intel_hdmi_init(dev, SDVOB);
+
                        if (!found && SUPPORTS_INTEGRATED_DP(dev))
                                intel_dp_init(dev, DP_B);
                }
 
                /* Before G4X SDVOC doesn't have its own detect register */
-               if (IS_G4X(dev))
-                       reg = SDVOC;
-               else
-                       reg = SDVOB;
 
-               if (I915_READ(reg) & SDVO_DETECTED) {
+               if (I915_READ(SDVOB) & SDVO_DETECTED)
                        found = intel_sdvo_init(dev, SDVOC);
-                       if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
+
+               if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
+
+                       if (SUPPORTS_INTEGRATED_HDMI(dev))
                                intel_hdmi_init(dev, SDVOC);
-                       if (!found && SUPPORTS_INTEGRATED_DP(dev))
+                       if (SUPPORTS_INTEGRATED_DP(dev))
                                intel_dp_init(dev, DP_C);
                }
+
                if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
                        intel_dp_init(dev, DP_D);
        } else
@@ -3253,51 +3253,10 @@ static void intel_setup_outputs(struct drm_device *dev)
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct intel_output *intel_output = to_intel_output(connector);
                struct drm_encoder *encoder = &intel_output->enc;
-               int crtc_mask = 0, clone_mask = 0;
 
-               /* valid crtcs */
-               switch(intel_output->type) {
-               case INTEL_OUTPUT_HDMI:
-                       crtc_mask = ((1 << 0)|
-                                    (1 << 1));
-                       clone_mask = ((1 << INTEL_OUTPUT_HDMI));
-                       break;
-               case INTEL_OUTPUT_DVO:
-               case INTEL_OUTPUT_SDVO:
-                       crtc_mask = ((1 << 0)|
-                                    (1 << 1));
-                       clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
-                                     (1 << INTEL_OUTPUT_DVO) |
-                                     (1 << INTEL_OUTPUT_SDVO));
-                       break;
-               case INTEL_OUTPUT_ANALOG:
-                       crtc_mask = ((1 << 0)|
-                                    (1 << 1));
-                       clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
-                                     (1 << INTEL_OUTPUT_DVO) |
-                                     (1 << INTEL_OUTPUT_SDVO));
-                       break;
-               case INTEL_OUTPUT_LVDS:
-                       crtc_mask = (1 << 1);
-                       clone_mask = (1 << INTEL_OUTPUT_LVDS);
-                       break;
-               case INTEL_OUTPUT_TVOUT:
-                       crtc_mask = ((1 << 0) |
-                                    (1 << 1));
-                       clone_mask = (1 << INTEL_OUTPUT_TVOUT);
-                       break;
-               case INTEL_OUTPUT_DISPLAYPORT:
-                       crtc_mask = ((1 << 0) |
-                                    (1 << 1));
-                       clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT);
-                       break;
-               case INTEL_OUTPUT_EDP:
-                       crtc_mask = (1 << 1);
-                       clone_mask = (1 << INTEL_OUTPUT_EDP);
-                       break;
-               }
-               encoder->possible_crtcs = crtc_mask;
-               encoder->possible_clones = intel_connector_clones(dev, clone_mask);
+               encoder->possible_crtcs = intel_output->crtc_mask;
+               encoder->possible_clones = intel_connector_clones(dev,
+                                               intel_output->clone_mask);
        }
 }
 
index a6ff15a..f2afc4a 100644 (file)
@@ -1254,6 +1254,18 @@ intel_dp_init(struct drm_device *dev, int output_reg)
        else
                intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
 
+       if (output_reg == DP_B)
+               intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
+       else if (output_reg == DP_C)
+               intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
+       else if (output_reg == DP_D)
+               intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+
+       if (IS_eDP(intel_output)) {
+               intel_output->crtc_mask = (1 << 1);
+               intel_output->clone_mask = (1 << INTEL_OUTPUT_EDP);
+       } else
+               intel_output->crtc_mask = (1 << 0) | (1 << 1);
        connector->interlace_allowed = true;
        connector->doublescan_allowed = 0;
 
index d6f92ea..25aa6fa 100644 (file)
 #define INTEL_OUTPUT_DISPLAYPORT 7
 #define INTEL_OUTPUT_EDP 8
 
+/* Intel Pipe Clone Bit */
+#define INTEL_HDMIB_CLONE_BIT 1
+#define INTEL_HDMIC_CLONE_BIT 2
+#define INTEL_HDMID_CLONE_BIT 3
+#define INTEL_HDMIE_CLONE_BIT 4
+#define INTEL_HDMIF_CLONE_BIT 5
+#define INTEL_SDVO_NON_TV_CLONE_BIT 6
+#define INTEL_SDVO_TV_CLONE_BIT 7
+#define INTEL_SDVO_LVDS_CLONE_BIT 8
+#define INTEL_ANALOG_CLONE_BIT 9
+#define INTEL_TV_CLONE_BIT 10
+#define INTEL_DP_B_CLONE_BIT 11
+#define INTEL_DP_C_CLONE_BIT 12
+#define INTEL_DP_D_CLONE_BIT 13
+#define INTEL_LVDS_CLONE_BIT 14
+#define INTEL_DVO_TMDS_CLONE_BIT 15
+#define INTEL_DVO_LVDS_CLONE_BIT 16
+
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
 #define INTEL_DVO_CHIP_TMDS 2
@@ -86,6 +104,8 @@ struct intel_output {
        bool needs_tv_clock;
        void *dev_priv;
        void (*hot_plug)(struct intel_output *);
+       int crtc_mask;
+       int clone_mask;
 };
 
 struct intel_crtc {
index 13bff20..a4d2606 100644 (file)
@@ -435,14 +435,20 @@ void intel_dvo_init(struct drm_device *dev)
                        continue;
 
                intel_output->type = INTEL_OUTPUT_DVO;
+               intel_output->crtc_mask = (1 << 0) | (1 << 1);
                switch (dvo->type) {
                case INTEL_DVO_CHIP_TMDS:
+                       intel_output->clone_mask =
+                               (1 << INTEL_DVO_TMDS_CLONE_BIT) |
+                               (1 << INTEL_ANALOG_CLONE_BIT);
                        drm_connector_init(dev, connector,
                                           &intel_dvo_connector_funcs,
                                           DRM_MODE_CONNECTOR_DVII);
                        encoder_type = DRM_MODE_ENCODER_TMDS;
                        break;
                case INTEL_DVO_CHIP_LVDS:
+                       intel_output->clone_mask =
+                               (1 << INTEL_DVO_LVDS_CLONE_BIT);
                        drm_connector_init(dev, connector,
                                           &intel_dvo_connector_funcs,
                                           DRM_MODE_CONNECTOR_LVDS);
index 1842290..fa304e1 100644 (file)
@@ -230,22 +230,28 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
 
        /* Set up the DDC bus. */
-       if (sdvox_reg == SDVOB)
+       if (sdvox_reg == SDVOB) {
+               intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
-       else if (sdvox_reg == SDVOC)
+       } else if (sdvox_reg == SDVOC) {
+               intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
-       else if (sdvox_reg == HDMIB)
+       } else if (sdvox_reg == HDMIB) {
+               intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
                                                                "HDMIB");
-       else if (sdvox_reg == HDMIC)
+       } else if (sdvox_reg == HDMIC) {
+               intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
                                                                "HDMIC");
-       else if (sdvox_reg == HDMID)
+       } else if (sdvox_reg == HDMID) {
+               intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
                                                                "HDMID");
-
+       }
        if (!intel_output->ddc_bus)
                goto err_connector;
 
index 3f445a8..8df02ef 100644 (file)
@@ -916,6 +916,8 @@ void intel_lvds_init(struct drm_device *dev)
        drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
        intel_output->type = INTEL_OUTPUT_LVDS;
 
+       intel_output->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
+       intel_output->crtc_mask = (1 << 1);
        drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
        drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
index 5371d93..d3b74ba 100644 (file)
@@ -1458,7 +1458,7 @@ intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
                (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1))
                caps++;
        if (sdvo_priv->caps.output_flags &
-               (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID0))
+               (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID1))
                caps++;
        if (sdvo_priv->caps.output_flags &
                (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1))
@@ -1967,6 +1967,9 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
                        intel_sdvo_set_colorimetry(intel_output,
                                                   SDVO_COLORIMETRY_RGB256);
                        connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
+                       intel_output->clone_mask =
+                                       (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+                                       (1 << INTEL_ANALOG_CLONE_BIT);
                }
        } else if (flags & SDVO_OUTPUT_SVID0) {
 
@@ -1975,11 +1978,14 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
                connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
                sdvo_priv->is_tv = true;
                intel_output->needs_tv_clock = true;
+               intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
        } else if (flags & SDVO_OUTPUT_RGB0) {
 
                sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0;
                encoder->encoder_type = DRM_MODE_ENCODER_DAC;
                connector->connector_type = DRM_MODE_CONNECTOR_VGA;
+               intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+                                       (1 << INTEL_ANALOG_CLONE_BIT);
        } else if (flags & SDVO_OUTPUT_RGB1) {
 
                sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1;
@@ -1991,12 +1997,16 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
                encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
                connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
                sdvo_priv->is_lvds = true;
+               intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+                                       (1 << INTEL_SDVO_LVDS_CLONE_BIT);
        } else if (flags & SDVO_OUTPUT_LVDS1) {
 
                sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1;
                encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
                connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
                sdvo_priv->is_lvds = true;
+               intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+                                       (1 << INTEL_SDVO_LVDS_CLONE_BIT);
        } else {
 
                unsigned char bytes[2];
@@ -2009,6 +2019,7 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
                                  bytes[0], bytes[1]);
                ret = false;
        }
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
 
        if (ret && registered)
                ret = drm_sysfs_connector_add(connector) == 0 ? true : false;
index da4ab4d..2fbe13a 100644 (file)
@@ -1718,6 +1718,7 @@ intel_tv_init(struct drm_device *dev)
        if (!intel_output) {
                return;
        }
+
        connector = &intel_output->base;
 
        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
@@ -1729,6 +1730,7 @@ intel_tv_init(struct drm_device *dev)
        drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
        tv_priv = (struct intel_tv_priv *)(intel_output + 1);
        intel_output->type = INTEL_OUTPUT_TVOUT;
+       intel_output->clone_mask = (1 << INTEL_TV_CLONE_BIT);
        intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1));
        intel_output->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
        intel_output->dev_priv = tv_priv;
index c46c895..2442e3f 100644 (file)
@@ -51,7 +51,7 @@ extern u64 __init lmb_alloc_base(u64 size,
 extern u64 __init __lmb_alloc_base(u64 size,
                u64 align, u64 max_addr);
 extern u64 __init lmb_phys_mem_size(void);
-extern u64 __init lmb_end_of_DRAM(void);
+extern u64 lmb_end_of_DRAM(void);
 extern void __init lmb_enforce_memory_limit(u64 memory_limit);
 extern int __init lmb_is_reserved(u64 addr);
 extern int lmb_find(struct lmb_property *res);