Commit 6b62b3e1 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'topic/drm-misc-2015-10-08' of git://anongit.freedesktop.org/drm-intel into drm-next

Another round of drm-misc. Unfortunately the DRM_UNLOCKED removal for
DRIVER_MODESET isn't complete yet for lack of review on 1-2 patches.
Otherwise just various stuff all over.

* tag 'topic/drm-misc-2015-10-08' of git://anongit.freedesktop.org/drm-intel:
  drm: Stop using drm_vblank_count() as the hw frame counter
  drm/irq: Use unsigned int pipe in public API
  drm: Use DRM_ROTATE_MASK and DRM_REFLECT_MASK
  drm: Add DRM_ROTATE_MASK and DRM_REFLECT_MASK
  vga_switcheroo: Add missing locking
  vgaarb: use kzalloc in vga_arbiter_add_pci_device()
  drm: Don't zero vblank timestamps from the irq handler
  drm: Hack around CONFIG_AGP=m build failures
  drm/i915: Remove setparam ioctl
  drm: Remove dummy agp ioctl wrappers
  drm/vmwgfx: Stop checking for DRM_UNLOCKED
  drm/drm_ioctl.c: kerneldoc
  drm: Define a drm_invalid_op ioctl implementation
  drm: Remove __OS_HAS_AGP
  drm/doc: Update docs about device instance setup
parents b3127855 b44f8408
Loading
Loading
Loading
Loading
+19 −81
Original line number Diff line number Diff line
@@ -138,14 +138,10 @@
    <para>
      At the core of every DRM driver is a <structname>drm_driver</structname>
      structure. Drivers typically statically initialize a drm_driver structure,
      and then pass it to one of the <function>drm_*_init()</function> functions
      to register it with the DRM subsystem.
    </para>
    <para>
      Newer drivers that no longer require a <structname>drm_bus</structname>
      structure can alternatively use the low-level device initialization and
      registration functions such as <function>drm_dev_alloc()</function> and
      <function>drm_dev_register()</function> directly.
      and then pass it to <function>drm_dev_alloc()</function> to allocate a
      device instance. After the device instance is fully initialized it can be
      registered (which makes it accessible from userspace) using
      <function>drm_dev_register()</function>.
    </para>
    <para>
      The <structname>drm_driver</structname> structure contains static
@@ -296,83 +292,12 @@ char *date;</synopsis>
      </sect3>
    </sect2>
    <sect2>
      <title>Device Registration</title>
      <para>
        A number of functions are provided to help with device registration.
        The functions deal with PCI and platform devices, respectively.
      </para>
!Edrivers/gpu/drm/drm_pci.c
!Edrivers/gpu/drm/drm_platform.c
      <para>
        New drivers that no longer rely on the services provided by the
        <structname>drm_bus</structname> structure can call the low-level
        device registration functions directly. The
        <function>drm_dev_alloc()</function> function can be used to allocate
        and initialize a new <structname>drm_device</structname> structure.
        Drivers will typically want to perform some additional setup on this
        structure, such as allocating driver-specific data and storing a
        pointer to it in the DRM device's <structfield>dev_private</structfield>
        field. Drivers should also set the device's unique name using the
        <function>drm_dev_set_unique()</function> function. After it has been
        set up a device can be registered with the DRM subsystem by calling
        <function>drm_dev_register()</function>. This will cause the device to
        be exposed to userspace and will call the driver's
        <structfield>.load()</structfield> implementation. When a device is
        removed, the DRM device can safely be unregistered and freed by calling
        <function>drm_dev_unregister()</function> followed by a call to
        <function>drm_dev_unref()</function>.
      </para>
      <title>Device Instance and Driver Handling</title>
!Pdrivers/gpu/drm/drm_drv.c driver instance overview
!Edrivers/gpu/drm/drm_drv.c
    </sect2>
    <sect2>
      <title>Driver Load</title>
      <para>
        The <methodname>load</methodname> method is the driver and device
        initialization entry point. The method is responsible for allocating and
	initializing driver private data, performing resource allocation and
	mapping (e.g. acquiring
        clocks, mapping registers or allocating command buffers), initializing
        the memory manager (<xref linkend="drm-memory-management"/>), installing
        the IRQ handler (<xref linkend="drm-irq-registration"/>), setting up
        vertical blanking handling (<xref linkend="drm-vertical-blank"/>), mode
	setting (<xref linkend="drm-mode-setting"/>) and initial output
	configuration (<xref linkend="drm-kms-init"/>).
      </para>
      <note><para>
        If compatibility is a concern (e.g. with drivers converted over from
        User Mode Setting to Kernel Mode Setting), care must be taken to prevent
        device initialization and control that is incompatible with currently
        active userspace drivers. For instance, if user level mode setting
        drivers are in use, it would be problematic to perform output discovery
        &amp; configuration at load time. Likewise, if user-level drivers
        unaware of memory management are in use, memory management and command
        buffer setup may need to be omitted. These requirements are
        driver-specific, and care needs to be taken to keep both old and new
        applications and libraries working.
      </para></note>
      <synopsis>int (*load) (struct drm_device *, unsigned long flags);</synopsis>
      <para>
        The method takes two arguments, a pointer to the newly created
	<structname>drm_device</structname> and flags. The flags are used to
	pass the <structfield>driver_data</structfield> field of the device id
	corresponding to the device passed to <function>drm_*_init()</function>.
	Only PCI devices currently use this, USB and platform DRM drivers have
	their <methodname>load</methodname> method called with flags to 0.
      </para>
      <sect3>
        <title>Driver Private Data</title>
        <para>
          The driver private hangs off the main
          <structname>drm_device</structname> structure and can be used for
          tracking various device-specific bits of information, like register
          offsets, command buffer status, register state for suspend/resume, etc.
          At load time, a driver may simply allocate one and set
          <structname>drm_device</structname>.<structfield>dev_priv</structfield>
          appropriately; it should be freed and
          <structname>drm_device</structname>.<structfield>dev_priv</structfield>
          set to NULL when the driver is unloaded.
        </para>
      </sect3>
      <sect3 id="drm-irq-registration">
        <title>IRQ Registration</title>
        <para>
@@ -465,6 +390,18 @@ char *date;</synopsis>
        </para>
      </sect3>
    </sect2>
    <sect2>
      <title>Bus-specific Device Registration and PCI Support</title>
      <para>
        A number of functions are provided to help with device registration.
	The functions deal with PCI and platform devices respectively and are
	only provided for historical reasons. These are all deprecated and
	shouldn't be used in new drivers. Besides that there's a few
	helpers for pci drivers.
      </para>
!Edrivers/gpu/drm/drm_pci.c
!Edrivers/gpu/drm/drm_platform.c
    </sect2>
  </sect1>

  <!-- Internals: memory management -->
@@ -3752,6 +3689,7 @@ int num_ioctls;</synopsis>
	  </itemizedlist>
	</para>
      </para>
!Edrivers/gpu/drm/drm_ioctl.c
    </sect2>
  </sect1>
  <sect1>
+4 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
		drm_context.o drm_dma.o \
		drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
		drm_lock.o drm_memory.o drm_drv.o drm_vm.o \
		drm_agpsupport.o drm_scatter.o drm_pci.o \
		drm_scatter.o drm_pci.o \
		drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
		drm_crtc.o drm_modes.o drm_edid.o \
		drm_info.o drm_debugfs.o drm_encoder_slave.o \
@@ -19,6 +19,9 @@ drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
drm-$(CONFIG_PCI) += ati_pcigart.o
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
drm-$(CONFIG_OF) += drm_of.o
drm-$(CONFIG_AGP) += drm_agpsupport.o

drm-y += $(drm-m)

drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
		drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o
+4 −4
Original line number Diff line number Diff line
@@ -2362,10 +2362,10 @@ void amdgpu_driver_preclose_kms(struct drm_device *dev,
				struct drm_file *file_priv);
int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, int crtc);
int amdgpu_enable_vblank_kms(struct drm_device *dev, int crtc);
void amdgpu_disable_vblank_kms(struct drm_device *dev, int crtc);
int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe);
int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
				    int *max_error,
				    struct timeval *vblank_time,
				    unsigned flags);
+5 −4
Original line number Diff line number Diff line
@@ -721,7 +721,7 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
 * an optional accurate timestamp of when query happened.
 *
 * \param dev Device to query.
 * \param crtc Crtc to query.
 * \param pipe Crtc to query.
 * \param flags Flags from caller (DRM_CALLED_FROM_VBLIRQ or 0).
 * \param *vpos Location where vertical scanout position should be stored.
 * \param *hpos Location where horizontal scanout position should go.
@@ -744,8 +744,9 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
 * unknown small number of scanlines wrt. real scanout position.
 *
 */
int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags,
			       int *vpos, int *hpos, ktime_t *stime, ktime_t *etime,
int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
			       unsigned int flags, int *vpos, int *hpos,
			       ktime_t *stime, ktime_t *etime,
			       const struct drm_display_mode *mode)
{
	u32 vbl = 0, position = 0;
@@ -760,7 +761,7 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
	if (stime)
		*stime = ktime_get();

	if (amdgpu_display_page_flip_get_scanoutpos(adev, crtc, &vbl, &position) == 0)
	if (amdgpu_display_page_flip_get_scanoutpos(adev, pipe, &vbl, &position) == 0)
		ret |= DRM_SCANOUTPOS_VALID;

	/* Get optional system timestamp after query. */
+18 −18
Original line number Diff line number Diff line
@@ -600,36 +600,36 @@ void amdgpu_driver_preclose_kms(struct drm_device *dev,
 * amdgpu_get_vblank_counter_kms - get frame count
 *
 * @dev: drm dev pointer
 * @crtc: crtc to get the frame count from
 * @pipe: crtc to get the frame count from
 *
 * Gets the frame count on the requested crtc (all asics).
 * Returns frame count on success, -EINVAL on failure.
 */
u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, int crtc)
u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe)
{
	struct amdgpu_device *adev = dev->dev_private;

	if (crtc < 0 || crtc >= adev->mode_info.num_crtc) {
		DRM_ERROR("Invalid crtc %d\n", crtc);
	if (pipe >= adev->mode_info.num_crtc) {
		DRM_ERROR("Invalid crtc %u\n", pipe);
		return -EINVAL;
	}

	return amdgpu_display_vblank_get_counter(adev, crtc);
	return amdgpu_display_vblank_get_counter(adev, pipe);
}

/**
 * amdgpu_enable_vblank_kms - enable vblank interrupt
 *
 * @dev: drm dev pointer
 * @crtc: crtc to enable vblank interrupt for
 * @pipe: crtc to enable vblank interrupt for
 *
 * Enable the interrupt on the requested crtc (all asics).
 * Returns 0 on success, -EINVAL on failure.
 */
int amdgpu_enable_vblank_kms(struct drm_device *dev, int crtc)
int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe)
{
	struct amdgpu_device *adev = dev->dev_private;
	int idx = amdgpu_crtc_idx_to_irq_type(adev, crtc);
	int idx = amdgpu_crtc_idx_to_irq_type(adev, pipe);

	return amdgpu_irq_get(adev, &adev->crtc_irq, idx);
}
@@ -638,14 +638,14 @@ int amdgpu_enable_vblank_kms(struct drm_device *dev, int crtc)
 * amdgpu_disable_vblank_kms - disable vblank interrupt
 *
 * @dev: drm dev pointer
 * @crtc: crtc to disable vblank interrupt for
 * @pipe: crtc to disable vblank interrupt for
 *
 * Disable the interrupt on the requested crtc (all asics).
 */
void amdgpu_disable_vblank_kms(struct drm_device *dev, int crtc)
void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe)
{
	struct amdgpu_device *adev = dev->dev_private;
	int idx = amdgpu_crtc_idx_to_irq_type(adev, crtc);
	int idx = amdgpu_crtc_idx_to_irq_type(adev, pipe);

	amdgpu_irq_put(adev, &adev->crtc_irq, idx);
}
@@ -663,26 +663,26 @@ void amdgpu_disable_vblank_kms(struct drm_device *dev, int crtc)
 * scanout position.  (all asics).
 * Returns postive status flags on success, negative error on failure.
 */
int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
int amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
				    int *max_error,
				    struct timeval *vblank_time,
				    unsigned flags)
{
	struct drm_crtc *drmcrtc;
	struct drm_crtc *crtc;
	struct amdgpu_device *adev = dev->dev_private;

	if (crtc < 0 || crtc >= dev->num_crtcs) {
		DRM_ERROR("Invalid crtc %d\n", crtc);
	if (pipe >= dev->num_crtcs) {
		DRM_ERROR("Invalid crtc %u\n", pipe);
		return -EINVAL;
	}

	/* Get associated drm_crtc: */
	drmcrtc = &adev->mode_info.crtcs[crtc]->base;
	crtc = &adev->mode_info.crtcs[pipe]->base;

	/* Helper routine in DRM core does all the work: */
	return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
	return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
						     vblank_time, flags,
						     &drmcrtc->hwmode);
						     &crtc->hwmode);
}

const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
Loading