mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
DRM: add mode setting support
Add mode setting support to the DRM layer.
This is a fairly big chunk of work that allows DRM drivers to provide
full output control and configuration capabilities to userspace. It was
motivated by several factors:
- the fb layer's APIs aren't suited for anything but simple
configurations
- coordination between the fb layer, DRM layer, and various userspace
drivers is poor to non-existent (radeonfb excepted)
- user level mode setting drivers makes displaying panic & oops
messages more difficult
- suspend/resume of graphics state is possible in many more
configurations with kernel level support
This commit just adds the core DRM part of the mode setting APIs.
Driver specific commits using these new structure and APIs will follow.
Co-authors: Jesse Barnes <jbarnes@virtuousgeek.org>, Jakob Bornecrantz <jakob@tungstengraphics.com>
Contributors: Alan Hourihane <alanh@tungstengraphics.com>, Maarten Maathuis <madman2003@gmail.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
@@ -9,7 +9,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
|
||||
drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
|
||||
drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
|
||||
drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
|
||||
drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
|
||||
drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
|
||||
drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o
|
||||
|
||||
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
||||
|
||||
|
||||
2497
drivers/gpu/drm/drm_crtc.c
Normal file
2497
drivers/gpu/drm/drm_crtc.c
Normal file
File diff suppressed because it is too large
Load Diff
822
drivers/gpu/drm/drm_crtc_helper.c
Normal file
822
drivers/gpu/drm/drm_crtc_helper.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -126,6 +126,26 @@ static struct drm_ioctl_desc drm_ioctls[] = {
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_REPLACEFB, drm_mode_replacefb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER),
|
||||
};
|
||||
|
||||
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
|
||||
@@ -150,7 +170,7 @@ int drm_lastclose(struct drm_device * dev)
|
||||
dev->driver->lastclose(dev);
|
||||
DRM_DEBUG("driver lastclose completed\n");
|
||||
|
||||
if (dev->irq_enabled)
|
||||
if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
@@ -160,7 +180,8 @@ int drm_lastclose(struct drm_device * dev)
|
||||
del_timer(&dev->timer);
|
||||
|
||||
/* Clear AGP information */
|
||||
if (drm_core_has_AGP(dev) && dev->agp) {
|
||||
if (drm_core_has_AGP(dev) && dev->agp &&
|
||||
!drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
struct drm_agp_mem *entry, *tempe;
|
||||
|
||||
/* Remove AGP resources, but leave dev->agp
|
||||
@@ -179,7 +200,8 @@ int drm_lastclose(struct drm_device * dev)
|
||||
dev->agp->acquired = 0;
|
||||
dev->agp->enabled = 0;
|
||||
}
|
||||
if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
|
||||
if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg &&
|
||||
!drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
drm_sg_cleanup(dev->sg);
|
||||
dev->sg = NULL;
|
||||
}
|
||||
@@ -206,7 +228,8 @@ int drm_lastclose(struct drm_device * dev)
|
||||
}
|
||||
dev->queue_count = 0;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
|
||||
!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_dma_takedown(dev);
|
||||
|
||||
dev->dev_mapping = NULL;
|
||||
@@ -307,6 +330,9 @@ static void drm_cleanup(struct drm_device * dev)
|
||||
drm_ht_remove(&dev->map_hash);
|
||||
drm_ctxbitmap_cleanup(dev);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_put_minor(&dev->control);
|
||||
|
||||
if (driver->driver_features & DRIVER_GEM)
|
||||
drm_gem_destroy(dev);
|
||||
|
||||
|
||||
732
drivers/gpu/drm/drm_edid.c
Normal file
732
drivers/gpu/drm/drm_edid.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,6 @@
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm_sarea.h"
|
||||
#include <linux/poll.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
||||
@@ -55,10 +54,12 @@ static int drm_setup(struct drm_device * dev)
|
||||
|
||||
atomic_set(&dev->ioctl_count, 0);
|
||||
atomic_set(&dev->vma_count, 0);
|
||||
dev->buf_use = 0;
|
||||
atomic_set(&dev->buf_alloc, 0);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
|
||||
if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
|
||||
!drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
dev->buf_use = 0;
|
||||
atomic_set(&dev->buf_alloc, 0);
|
||||
|
||||
i = drm_dma_setup(dev);
|
||||
if (i < 0)
|
||||
return i;
|
||||
@@ -138,14 +139,14 @@ int drm_open(struct inode *inode, struct file *filp)
|
||||
}
|
||||
spin_unlock(&dev->count_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (dev->dev_mapping == NULL)
|
||||
dev->dev_mapping = inode->i_mapping;
|
||||
else if (dev->dev_mapping != inode->i_mapping)
|
||||
WARN(1, "dev->dev_mapping not inode mapping (%p expected %p)\n",
|
||||
dev->dev_mapping, inode->i_mapping);
|
||||
if (minor->type == DRM_MINOR_LEGACY) {
|
||||
BUG_ON((dev->dev_mapping != NULL) &&
|
||||
(dev->dev_mapping != inode->i_mapping));
|
||||
if (dev->dev_mapping == NULL)
|
||||
dev->dev_mapping = inode->i_mapping;
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return retcode;
|
||||
@@ -251,6 +252,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
priv->lock_count = 0;
|
||||
|
||||
INIT_LIST_HEAD(&priv->lhead);
|
||||
INIT_LIST_HEAD(&priv->fbs);
|
||||
|
||||
if (dev->driver->driver_features & DRIVER_GEM)
|
||||
drm_gem_open(dev, priv);
|
||||
|
||||
@@ -305,6 +305,8 @@ int drm_control(struct drm_device *dev, void *data,
|
||||
case DRM_INST_HANDLER:
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return 0;
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return 0;
|
||||
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
|
||||
ctl->irq != dev->pdev->irq)
|
||||
return -EINVAL;
|
||||
@@ -312,6 +314,8 @@ int drm_control(struct drm_device *dev, void *data,
|
||||
case DRM_UNINST_HANDLER:
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return 0;
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return 0;
|
||||
return drm_irq_uninstall(dev);
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -426,6 +430,45 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_put);
|
||||
|
||||
/**
|
||||
* drm_vblank_pre_modeset - account for vblanks across mode sets
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC in question
|
||||
* @post: post or pre mode set?
|
||||
*
|
||||
* Account for vblank events across mode setting events, which will likely
|
||||
* reset the hardware frame counter.
|
||||
*/
|
||||
void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
|
||||
{
|
||||
/*
|
||||
* To avoid all the problems that might happen if interrupts
|
||||
* were enabled/disabled around or between these calls, we just
|
||||
* have the kernel take a reference on the CRTC (just once though
|
||||
* to avoid corrupting the count if multiple, mismatch calls occur),
|
||||
* so that interrupts remain enabled in the interim.
|
||||
*/
|
||||
if (!dev->vblank_inmodeset[crtc]) {
|
||||
dev->vblank_inmodeset[crtc] = 1;
|
||||
drm_vblank_get(dev, crtc);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_pre_modeset);
|
||||
|
||||
void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
|
||||
if (dev->vblank_inmodeset[crtc]) {
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
dev->vblank_disable_allowed = 1;
|
||||
dev->vblank_inmodeset[crtc] = 0;
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
drm_vblank_put(dev, crtc);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_post_modeset);
|
||||
|
||||
/**
|
||||
* drm_modeset_ctl - handle vblank event counter changes across mode switch
|
||||
* @DRM_IOCTL_ARGS: standard ioctl arguments
|
||||
@@ -441,7 +484,6 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_modeset_ctl *modeset = data;
|
||||
unsigned long irqflags;
|
||||
int crtc, ret = 0;
|
||||
|
||||
/* If drm_vblank_init() hasn't been called yet, just no-op */
|
||||
@@ -454,28 +496,12 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* To avoid all the problems that might happen if interrupts
|
||||
* were enabled/disabled around or between these calls, we just
|
||||
* have the kernel take a reference on the CRTC (just once though
|
||||
* to avoid corrupting the count if multiple, mismatch calls occur),
|
||||
* so that interrupts remain enabled in the interim.
|
||||
*/
|
||||
switch (modeset->cmd) {
|
||||
case _DRM_PRE_MODESET:
|
||||
if (!dev->vblank_inmodeset[crtc]) {
|
||||
dev->vblank_inmodeset[crtc] = 1;
|
||||
drm_vblank_get(dev, crtc);
|
||||
}
|
||||
drm_vblank_pre_modeset(dev, crtc);
|
||||
break;
|
||||
case _DRM_POST_MODESET:
|
||||
if (dev->vblank_inmodeset[crtc]) {
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
dev->vblank_disable_allowed = 1;
|
||||
dev->vblank_inmodeset[crtc] = 0;
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
drm_vblank_put(dev, crtc);
|
||||
}
|
||||
drm_vblank_post_modeset(dev, crtc);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
||||
@@ -296,3 +296,4 @@ void drm_mm_takedown(struct drm_mm * mm)
|
||||
|
||||
drm_free(entry, sizeof(*entry), DRM_MEM_MM);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_takedown);
|
||||
|
||||
576
drivers/gpu/drm/drm_modes.c
Normal file
576
drivers/gpu/drm/drm_modes.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -57,6 +57,14 @@ static int drm_minor_get_id(struct drm_device *dev, int type)
|
||||
int ret;
|
||||
int base = 0, limit = 63;
|
||||
|
||||
if (type == DRM_MINOR_CONTROL) {
|
||||
base += 64;
|
||||
limit = base + 127;
|
||||
} else if (type == DRM_MINOR_RENDER) {
|
||||
base += 128;
|
||||
limit = base + 255;
|
||||
}
|
||||
|
||||
again:
|
||||
if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
|
||||
DRM_ERROR("Out of memory expanding drawable idr\n");
|
||||
@@ -362,12 +370,28 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
||||
printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
|
||||
goto err_g2;
|
||||
}
|
||||
if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
|
||||
goto err_g2;
|
||||
|
||||
if (dev->driver->load)
|
||||
if ((ret = dev->driver->load(dev, ent->driver_data)))
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
|
||||
if (ret)
|
||||
goto err_g2;
|
||||
}
|
||||
|
||||
if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
|
||||
goto err_g3;
|
||||
|
||||
if (dev->driver->load) {
|
||||
ret = dev->driver->load(dev, ent->driver_data);
|
||||
if (ret)
|
||||
goto err_g3;
|
||||
}
|
||||
|
||||
/* setup the grouping for the legacy output */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
|
||||
if (ret)
|
||||
goto err_g3;
|
||||
}
|
||||
|
||||
list_add_tail(&dev->driver_item, &driver->device_list);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "drmP.h"
|
||||
|
||||
#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
|
||||
#define to_drm_connector(d) container_of(d, struct drm_connector, kdev)
|
||||
|
||||
/**
|
||||
* drm_sysfs_suspend - DRM class suspend hook
|
||||
@@ -34,7 +35,7 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
|
||||
struct drm_minor *drm_minor = to_drm_minor(dev);
|
||||
struct drm_device *drm_dev = drm_minor->dev;
|
||||
|
||||
if (drm_dev->driver->suspend)
|
||||
if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->suspend)
|
||||
return drm_dev->driver->suspend(drm_dev, state);
|
||||
|
||||
return 0;
|
||||
@@ -52,7 +53,7 @@ static int drm_sysfs_resume(struct device *dev)
|
||||
struct drm_minor *drm_minor = to_drm_minor(dev);
|
||||
struct drm_device *drm_dev = drm_minor->dev;
|
||||
|
||||
if (drm_dev->driver->resume)
|
||||
if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->resume)
|
||||
return drm_dev->driver->resume(drm_dev);
|
||||
|
||||
return 0;
|
||||
@@ -144,6 +145,323 @@ static void drm_sysfs_device_release(struct device *dev)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connector properties
|
||||
*/
|
||||
static ssize_t status_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_connector *connector = to_drm_connector(device);
|
||||
enum drm_connector_status status;
|
||||
|
||||
status = connector->funcs->detect(connector);
|
||||
return snprintf(buf, PAGE_SIZE, "%s",
|
||||
drm_get_connector_status_name(status));
|
||||
}
|
||||
|
||||
static ssize_t dpms_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_connector *connector = to_drm_connector(device);
|
||||
struct drm_device *dev = connector->dev;
|
||||
uint64_t dpms_status;
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_property_get_value(connector,
|
||||
dev->mode_config.dpms_property,
|
||||
&dpms_status);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s",
|
||||
drm_get_dpms_name((int)dpms_status));
|
||||
}
|
||||
|
||||
static ssize_t enabled_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_connector *connector = to_drm_connector(device);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, connector->encoder ? "enabled" :
|
||||
"disabled");
|
||||
}
|
||||
|
||||
static ssize_t edid_show(struct kobject *kobj, struct bin_attribute *attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
struct device *connector_dev = container_of(kobj, struct device, kobj);
|
||||
struct drm_connector *connector = to_drm_connector(connector_dev);
|
||||
unsigned char *edid;
|
||||
size_t size;
|
||||
|
||||
if (!connector->edid_blob_ptr)
|
||||
return 0;
|
||||
|
||||
edid = connector->edid_blob_ptr->data;
|
||||
size = connector->edid_blob_ptr->length;
|
||||
if (!edid)
|
||||
return 0;
|
||||
|
||||
if (off >= size)
|
||||
return 0;
|
||||
|
||||
if (off + count > size)
|
||||
count = size - off;
|
||||
memcpy(buf, edid + off, count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t modes_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_connector *connector = to_drm_connector(device);
|
||||
struct drm_display_mode *mode;
|
||||
int written = 0;
|
||||
|
||||
list_for_each_entry(mode, &connector->modes, head) {
|
||||
written += snprintf(buf + written, PAGE_SIZE - written, "%s\n",
|
||||
mode->name);
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static ssize_t subconnector_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_connector *connector = to_drm_connector(device);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_property *prop = NULL;
|
||||
uint64_t subconnector;
|
||||
int is_tv = 0;
|
||||
int ret;
|
||||
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
prop = dev->mode_config.dvi_i_subconnector_property;
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_Composite:
|
||||
case DRM_MODE_CONNECTOR_SVIDEO:
|
||||
case DRM_MODE_CONNECTOR_Component:
|
||||
prop = dev->mode_config.tv_subconnector_property;
|
||||
is_tv = 1;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Wrong connector type for this property\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!prop) {
|
||||
DRM_ERROR("Unable to find subconnector property\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = drm_connector_property_get_value(connector, prop, &subconnector);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s", is_tv ?
|
||||
drm_get_tv_subconnector_name((int)subconnector) :
|
||||
drm_get_dvi_i_subconnector_name((int)subconnector));
|
||||
}
|
||||
|
||||
static ssize_t select_subconnector_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct drm_connector *connector = to_drm_connector(device);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_property *prop = NULL;
|
||||
uint64_t subconnector;
|
||||
int is_tv = 0;
|
||||
int ret;
|
||||
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
prop = dev->mode_config.dvi_i_select_subconnector_property;
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_Composite:
|
||||
case DRM_MODE_CONNECTOR_SVIDEO:
|
||||
case DRM_MODE_CONNECTOR_Component:
|
||||
prop = dev->mode_config.tv_select_subconnector_property;
|
||||
is_tv = 1;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Wrong connector type for this property\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!prop) {
|
||||
DRM_ERROR("Unable to find select subconnector property\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = drm_connector_property_get_value(connector, prop, &subconnector);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s", is_tv ?
|
||||
drm_get_tv_select_name((int)subconnector) :
|
||||
drm_get_dvi_i_select_name((int)subconnector));
|
||||
}
|
||||
|
||||
static struct device_attribute connector_attrs[] = {
|
||||
__ATTR_RO(status),
|
||||
__ATTR_RO(enabled),
|
||||
__ATTR_RO(dpms),
|
||||
__ATTR_RO(modes),
|
||||
};
|
||||
|
||||
/* These attributes are for both DVI-I connectors and all types of tv-out. */
|
||||
static struct device_attribute connector_attrs_opt1[] = {
|
||||
__ATTR_RO(subconnector),
|
||||
__ATTR_RO(select_subconnector),
|
||||
};
|
||||
|
||||
static struct bin_attribute edid_attr = {
|
||||
.attr.name = "edid",
|
||||
.size = 128,
|
||||
.read = edid_show,
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_sysfs_connector_add - add an connector to sysfs
|
||||
* @connector: connector to add
|
||||
*
|
||||
* Create an connector device in sysfs, along with its associated connector
|
||||
* properties (so far, connection status, dpms, mode list & edid) and
|
||||
* generate a hotplug event so userspace knows there's a new connector
|
||||
* available.
|
||||
*
|
||||
* Note:
|
||||
* This routine should only be called *once* for each DRM minor registered.
|
||||
* A second call for an already registered device will trigger the BUG_ON
|
||||
* below.
|
||||
*/
|
||||
int drm_sysfs_connector_add(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
int ret = 0, i, j;
|
||||
|
||||
/* We shouldn't get called more than once for the same connector */
|
||||
BUG_ON(device_is_registered(&connector->kdev));
|
||||
|
||||
connector->kdev.parent = &dev->primary->kdev;
|
||||
connector->kdev.class = drm_class;
|
||||
connector->kdev.release = drm_sysfs_device_release;
|
||||
|
||||
DRM_DEBUG("adding \"%s\" to sysfs\n",
|
||||
drm_get_connector_name(connector));
|
||||
|
||||
snprintf(connector->kdev.bus_id, BUS_ID_SIZE, "card%d-%s",
|
||||
dev->primary->index, drm_get_connector_name(connector));
|
||||
ret = device_register(&connector->kdev);
|
||||
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to register connector device: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Standard attributes */
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(connector_attrs); i++) {
|
||||
ret = device_create_file(&connector->kdev, &connector_attrs[i]);
|
||||
if (ret)
|
||||
goto err_out_files;
|
||||
}
|
||||
|
||||
/* Optional attributes */
|
||||
/*
|
||||
* In the long run it maybe a good idea to make one set of
|
||||
* optionals per connector type.
|
||||
*/
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
case DRM_MODE_CONNECTOR_Composite:
|
||||
case DRM_MODE_CONNECTOR_SVIDEO:
|
||||
case DRM_MODE_CONNECTOR_Component:
|
||||
for (i = 0; i < ARRAY_SIZE(connector_attrs_opt1); i++) {
|
||||
ret = device_create_file(&connector->kdev, &connector_attrs_opt1[i]);
|
||||
if (ret)
|
||||
goto err_out_files;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = sysfs_create_bin_file(&connector->kdev.kobj, &edid_attr);
|
||||
if (ret)
|
||||
goto err_out_files;
|
||||
|
||||
/* Let userspace know we have a new connector */
|
||||
drm_sysfs_hotplug_event(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_files:
|
||||
if (i > 0)
|
||||
for (j = 0; j < i; j++)
|
||||
device_remove_file(&connector->kdev,
|
||||
&connector_attrs[i]);
|
||||
device_unregister(&connector->kdev);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_sysfs_connector_add);
|
||||
|
||||
/**
|
||||
* drm_sysfs_connector_remove - remove an connector device from sysfs
|
||||
* @connector: connector to remove
|
||||
*
|
||||
* Remove @connector and its associated attributes from sysfs. Note that
|
||||
* the device model core will take care of sending the "remove" uevent
|
||||
* at this time, so we don't need to do it.
|
||||
*
|
||||
* Note:
|
||||
* This routine should only be called if the connector was previously
|
||||
* successfully registered. If @connector hasn't been registered yet,
|
||||
* you'll likely see a panic somewhere deep in sysfs code when called.
|
||||
*/
|
||||
void drm_sysfs_connector_remove(struct drm_connector *connector)
|
||||
{
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("removing \"%s\" from sysfs\n",
|
||||
drm_get_connector_name(connector));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(connector_attrs); i++)
|
||||
device_remove_file(&connector->kdev, &connector_attrs[i]);
|
||||
sysfs_remove_bin_file(&connector->kdev.kobj, &edid_attr);
|
||||
device_unregister(&connector->kdev);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_sysfs_connector_remove);
|
||||
|
||||
/**
|
||||
* drm_sysfs_hotplug_event - generate a DRM uevent
|
||||
* @dev: DRM device
|
||||
*
|
||||
* Send a uevent for the DRM device specified by @dev. Currently we only
|
||||
* set HOTPLUG=1 in the uevent environment, but this could be expanded to
|
||||
* deal with other types of events.
|
||||
*/
|
||||
void drm_sysfs_hotplug_event(struct drm_device *dev)
|
||||
{
|
||||
char *event_string = "HOTPLUG=1";
|
||||
char *envp[] = { event_string, NULL };
|
||||
|
||||
DRM_DEBUG("generating hotplug event\n");
|
||||
|
||||
kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_sysfs_device_add - adds a class device to sysfs for a character driver
|
||||
* @dev: DRM device to be added
|
||||
@@ -163,7 +481,12 @@ int drm_sysfs_device_add(struct drm_minor *minor)
|
||||
minor->kdev.class = drm_class;
|
||||
minor->kdev.release = drm_sysfs_device_release;
|
||||
minor->kdev.devt = minor->device;
|
||||
minor_str = "card%d";
|
||||
if (minor->type == DRM_MINOR_CONTROL)
|
||||
minor_str = "controlD%d";
|
||||
else if (minor->type == DRM_MINOR_RENDER)
|
||||
minor_str = "renderD%d";
|
||||
else
|
||||
minor_str = "card%d";
|
||||
|
||||
snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
|
||||
|
||||
|
||||
@@ -112,6 +112,23 @@ static int vga_video_font_height;
|
||||
static int vga_scan_lines __read_mostly;
|
||||
static unsigned int vga_rolled_over;
|
||||
|
||||
int vgacon_text_mode_force = 0;
|
||||
|
||||
bool vgacon_text_force(void)
|
||||
{
|
||||
return vgacon_text_mode_force ? true : false;
|
||||
}
|
||||
EXPORT_SYMBOL(vgacon_text_force);
|
||||
|
||||
static int __init text_mode(char *str)
|
||||
{
|
||||
vgacon_text_mode_force = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* force text mode - used by kernel modesetting */
|
||||
__setup("nomodeset", text_mode);
|
||||
|
||||
static int __init no_scroll(char *str)
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
unifdef-y += drm.h drm_sarea.h
|
||||
unifdef-y += drm.h drm_sarea.h drm_mode.h
|
||||
unifdef-y += i810_drm.h
|
||||
unifdef-y += i830_drm.h
|
||||
unifdef-y += i915_drm.h
|
||||
|
||||
@@ -599,6 +599,8 @@ struct drm_gem_open {
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
#include "drm_mode.h"
|
||||
|
||||
#define DRM_IOCTL_BASE 'd'
|
||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
|
||||
@@ -668,6 +670,25 @@ struct drm_gem_open {
|
||||
|
||||
#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw)
|
||||
|
||||
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
|
||||
#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
|
||||
#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc)
|
||||
#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor)
|
||||
#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut)
|
||||
#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut)
|
||||
#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder)
|
||||
#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector)
|
||||
#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd)
|
||||
#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
|
||||
|
||||
#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property)
|
||||
#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property)
|
||||
#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob)
|
||||
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
|
||||
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
|
||||
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
|
||||
#define DRM_IOCTL_MODE_REPLACEFB DRM_IOWR(0xB0, struct drm_mode_fb_cmd)
|
||||
|
||||
/**
|
||||
* Device specific ioctls should only be in their respective headers
|
||||
* The device specific ioctl range is from 0x40 to 0x99.
|
||||
|
||||
@@ -105,6 +105,7 @@ struct drm_device;
|
||||
#define DRIVER_FB_DMA 0x400
|
||||
#define DRIVER_IRQ_VBL2 0x800
|
||||
#define DRIVER_GEM 0x1000
|
||||
#define DRIVER_MODESET 0x2000
|
||||
|
||||
/***********************************************************************/
|
||||
/** \name Begin the DRM... */
|
||||
@@ -276,6 +277,7 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
|
||||
#define DRM_AUTH 0x1
|
||||
#define DRM_MASTER 0x2
|
||||
#define DRM_ROOT_ONLY 0x4
|
||||
#define DRM_CONTROL_ALLOW 0x8
|
||||
|
||||
struct drm_ioctl_desc {
|
||||
unsigned int cmd;
|
||||
@@ -398,6 +400,7 @@ struct drm_file {
|
||||
int is_master; /* this file private is a master for a minor */
|
||||
struct drm_master *master; /* master this node is currently associated with
|
||||
N.B. not always minor->master */
|
||||
struct list_head fbs;
|
||||
};
|
||||
|
||||
/** Wait queue */
|
||||
@@ -629,6 +632,8 @@ struct drm_gem_object {
|
||||
void *driver_private;
|
||||
};
|
||||
|
||||
#include "drm_crtc.h"
|
||||
|
||||
/* per-master structure */
|
||||
struct drm_master {
|
||||
|
||||
@@ -792,6 +797,8 @@ struct drm_driver {
|
||||
|
||||
#define DRM_MINOR_UNASSIGNED 0
|
||||
#define DRM_MINOR_LEGACY 1
|
||||
#define DRM_MINOR_CONTROL 2
|
||||
#define DRM_MINOR_RENDER 3
|
||||
|
||||
/**
|
||||
* DRM minor structure. This structure represents a drm minor number.
|
||||
@@ -805,6 +812,7 @@ struct drm_minor {
|
||||
struct proc_dir_entry *dev_root; /**< proc directory entry */
|
||||
struct drm_master *master; /* currently active master for this node */
|
||||
struct list_head master_list;
|
||||
struct drm_mode_group mode_group;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -855,6 +863,7 @@ struct drm_device {
|
||||
struct idr ctx_idr;
|
||||
|
||||
struct list_head vmalist; /**< List of vmas (for debugging) */
|
||||
|
||||
/*@} */
|
||||
|
||||
/** \name DMA queues (contexts) */
|
||||
@@ -933,6 +942,7 @@ struct drm_device {
|
||||
struct drm_driver *driver;
|
||||
drm_local_map_t *agp_buffer_map;
|
||||
unsigned int agp_buffer_token;
|
||||
struct drm_minor *control; /**< Control node for card */
|
||||
struct drm_minor *primary; /**< render type primary screen head */
|
||||
|
||||
/** \name Drawable information */
|
||||
@@ -941,6 +951,8 @@ struct drm_device {
|
||||
struct idr drw_idr;
|
||||
/*@} */
|
||||
|
||||
struct drm_mode_config mode_config; /**< Current mode config */
|
||||
|
||||
/** \name GEM information */
|
||||
/*@{ */
|
||||
spinlock_t object_name_lock;
|
||||
@@ -1201,6 +1213,8 @@ extern int drm_vblank_get(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_put(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_cleanup(struct drm_device *dev);
|
||||
/* Modesetting support */
|
||||
extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
|
||||
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
@@ -1286,7 +1300,11 @@ struct drm_sysfs_class;
|
||||
extern struct class *drm_sysfs_create(struct module *owner, char *name);
|
||||
extern void drm_sysfs_destroy(void);
|
||||
extern int drm_sysfs_device_add(struct drm_minor *minor);
|
||||
extern void drm_sysfs_hotplug_event(struct drm_device *dev);
|
||||
extern void drm_sysfs_device_remove(struct drm_minor *minor);
|
||||
extern char *drm_get_connector_status_name(enum drm_connector_status status);
|
||||
extern int drm_sysfs_connector_add(struct drm_connector *connector);
|
||||
extern void drm_sysfs_connector_remove(struct drm_connector *connector);
|
||||
|
||||
/*
|
||||
* Basic memory manager support (drm_mm.c)
|
||||
|
||||
737
include/drm/drm_crtc.h
Normal file
737
include/drm/drm_crtc.h
Normal file
File diff suppressed because it is too large
Load Diff
121
include/drm/drm_crtc_helper.h
Normal file
121
include/drm/drm_crtc_helper.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright © 2006 Keith Packard
|
||||
* Copyright © 2007-2008 Dave Airlie
|
||||
* Copyright © 2007-2008 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The DRM mode setting helper functions are common code for drivers to use if
|
||||
* they wish. Drivers are not forced to use this code in their
|
||||
* implementations but it would be useful if they code they do use at least
|
||||
* provides a consistent interface and operation to userspace
|
||||
*/
|
||||
|
||||
#ifndef __DRM_CRTC_HELPER_H__
|
||||
#define __DRM_CRTC_HELPER_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
struct drm_crtc_helper_funcs {
|
||||
/*
|
||||
* Control power levels on the CRTC. If the mode passed in is
|
||||
* unsupported, the provider must use the next lowest power level.
|
||||
*/
|
||||
void (*dpms)(struct drm_crtc *crtc, int mode);
|
||||
void (*prepare)(struct drm_crtc *crtc);
|
||||
void (*commit)(struct drm_crtc *crtc);
|
||||
|
||||
/* Provider can fixup or change mode timings before modeset occurs */
|
||||
bool (*mode_fixup)(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
/* Actually set the mode */
|
||||
void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode, int x, int y);
|
||||
|
||||
/* Move the crtc on the current fb to the given position *optional* */
|
||||
void (*mode_set_base)(struct drm_crtc *crtc, int x, int y);
|
||||
};
|
||||
|
||||
struct drm_encoder_helper_funcs {
|
||||
void (*dpms)(struct drm_encoder *encoder, int mode);
|
||||
void (*save)(struct drm_encoder *encoder);
|
||||
void (*restore)(struct drm_encoder *encoder);
|
||||
|
||||
bool (*mode_fixup)(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
void (*prepare)(struct drm_encoder *encoder);
|
||||
void (*commit)(struct drm_encoder *encoder);
|
||||
void (*mode_set)(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
/* detect for DAC style encoders */
|
||||
enum drm_connector_status (*detect)(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector);
|
||||
};
|
||||
|
||||
struct drm_connector_helper_funcs {
|
||||
int (*get_modes)(struct drm_connector *connector);
|
||||
int (*mode_valid)(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
|
||||
};
|
||||
|
||||
extern void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);
|
||||
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
|
||||
extern int drm_helper_hotplug_stage_two(struct drm_device *dev);
|
||||
extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow);
|
||||
extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
|
||||
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
int x, int y);
|
||||
extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
|
||||
|
||||
extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
|
||||
struct drm_mode_fb_cmd *mode_cmd);
|
||||
|
||||
static inline void drm_crtc_helper_add(struct drm_crtc *crtc,
|
||||
const struct drm_crtc_helper_funcs *funcs)
|
||||
{
|
||||
crtc->helper_private = (void *)funcs;
|
||||
}
|
||||
|
||||
static inline void drm_encoder_helper_add(struct drm_encoder *encoder,
|
||||
const struct drm_encoder_helper_funcs *funcs)
|
||||
{
|
||||
encoder->helper_private = (void *)funcs;
|
||||
}
|
||||
|
||||
static inline void drm_connector_helper_add(struct drm_connector *connector,
|
||||
const struct drm_connector_helper_funcs *funcs)
|
||||
{
|
||||
connector->helper_private = (void *)funcs;
|
||||
}
|
||||
|
||||
extern int drm_helper_resume_force_mode(struct drm_device *dev);
|
||||
#endif
|
||||
202
include/drm/drm_edid.h
Normal file
202
include/drm/drm_edid.h
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright © 2007-2008 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __DRM_EDID_H__
|
||||
#define __DRM_EDID_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define EDID_LENGTH 128
|
||||
#define DDC_ADDR 0x50
|
||||
|
||||
#ifdef BIG_ENDIAN
|
||||
#error "EDID structure is little endian, need big endian versions"
|
||||
#else
|
||||
|
||||
struct est_timings {
|
||||
u8 t1;
|
||||
u8 t2;
|
||||
u8 mfg_rsvd;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct std_timing {
|
||||
u8 hsize; /* need to multiply by 8 then add 248 */
|
||||
u8 vfreq:6; /* need to add 60 */
|
||||
u8 aspect_ratio:2; /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* If detailed data is pixel timing */
|
||||
struct detailed_pixel_timing {
|
||||
u8 hactive_lo;
|
||||
u8 hblank_lo;
|
||||
u8 hblank_hi:4;
|
||||
u8 hactive_hi:4;
|
||||
u8 vactive_lo;
|
||||
u8 vblank_lo;
|
||||
u8 vblank_hi:4;
|
||||
u8 vactive_hi:4;
|
||||
u8 hsync_offset_lo;
|
||||
u8 hsync_pulse_width_lo;
|
||||
u8 vsync_pulse_width_lo:4;
|
||||
u8 vsync_offset_lo:4;
|
||||
u8 hsync_pulse_width_hi:2;
|
||||
u8 hsync_offset_hi:2;
|
||||
u8 vsync_pulse_width_hi:2;
|
||||
u8 vsync_offset_hi:2;
|
||||
u8 width_mm_lo;
|
||||
u8 height_mm_lo;
|
||||
u8 height_mm_hi:4;
|
||||
u8 width_mm_hi:4;
|
||||
u8 hborder;
|
||||
u8 vborder;
|
||||
u8 unknown0:1;
|
||||
u8 vsync_positive:1;
|
||||
u8 hsync_positive:1;
|
||||
u8 separate_sync:2;
|
||||
u8 stereo:1;
|
||||
u8 unknown6:1;
|
||||
u8 interlaced:1;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* If it's not pixel timing, it'll be one of the below */
|
||||
struct detailed_data_string {
|
||||
u8 str[13];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_monitor_range {
|
||||
u8 min_vfreq;
|
||||
u8 max_vfreq;
|
||||
u8 min_hfreq_khz;
|
||||
u8 max_hfreq_khz;
|
||||
u8 pixel_clock_mhz; /* need to multiply by 10 */
|
||||
u16 sec_gtf_toggle; /* A000=use above, 20=use below */ /* FIXME: byte order */
|
||||
u8 hfreq_start_khz; /* need to multiply by 2 */
|
||||
u8 c; /* need to divide by 2 */
|
||||
u16 m; /* FIXME: byte order */
|
||||
u8 k;
|
||||
u8 j; /* need to divide by 2 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_wpindex {
|
||||
u8 white_y_lo:2;
|
||||
u8 white_x_lo:2;
|
||||
u8 pad:4;
|
||||
u8 white_x_hi;
|
||||
u8 white_y_hi;
|
||||
u8 gamma; /* need to divide by 100 then add 1 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_color_point {
|
||||
u8 windex1;
|
||||
u8 wpindex1[3];
|
||||
u8 windex2;
|
||||
u8 wpindex2[3];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_non_pixel {
|
||||
u8 pad1;
|
||||
u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name
|
||||
fb=color point data, fa=standard timing data,
|
||||
f9=undefined, f8=mfg. reserved */
|
||||
u8 pad2;
|
||||
union {
|
||||
struct detailed_data_string str;
|
||||
struct detailed_data_monitor_range range;
|
||||
struct detailed_data_wpindex color;
|
||||
struct std_timing timings[5];
|
||||
} data;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define EDID_DETAIL_STD_MODES 0xfa
|
||||
#define EDID_DETAIL_MONITOR_CPDATA 0xfb
|
||||
#define EDID_DETAIL_MONITOR_NAME 0xfc
|
||||
#define EDID_DETAIL_MONITOR_RANGE 0xfd
|
||||
#define EDID_DETAIL_MONITOR_STRING 0xfe
|
||||
#define EDID_DETAIL_MONITOR_SERIAL 0xff
|
||||
|
||||
struct detailed_timing {
|
||||
u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */
|
||||
union {
|
||||
struct detailed_pixel_timing pixel_data;
|
||||
struct detailed_non_pixel other_data;
|
||||
} data;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct edid {
|
||||
u8 header[8];
|
||||
/* Vendor & product info */
|
||||
u8 mfg_id[2];
|
||||
u8 prod_code[2];
|
||||
u32 serial; /* FIXME: byte order */
|
||||
u8 mfg_week;
|
||||
u8 mfg_year;
|
||||
/* EDID version */
|
||||
u8 version;
|
||||
u8 revision;
|
||||
/* Display info: */
|
||||
/* input definition */
|
||||
u8 serration_vsync:1;
|
||||
u8 sync_on_green:1;
|
||||
u8 composite_sync:1;
|
||||
u8 separate_syncs:1;
|
||||
u8 blank_to_black:1;
|
||||
u8 video_level:2;
|
||||
u8 digital:1; /* bits below must be zero if set */
|
||||
u8 width_cm;
|
||||
u8 height_cm;
|
||||
u8 gamma;
|
||||
/* feature support */
|
||||
u8 default_gtf:1;
|
||||
u8 preferred_timing:1;
|
||||
u8 standard_color:1;
|
||||
u8 display_type:2; /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
|
||||
u8 pm_active_off:1;
|
||||
u8 pm_suspend:1;
|
||||
u8 pm_standby:1;
|
||||
/* Color characteristics */
|
||||
u8 red_green_lo;
|
||||
u8 black_white_lo;
|
||||
u8 red_x;
|
||||
u8 red_y;
|
||||
u8 green_x;
|
||||
u8 green_y;
|
||||
u8 blue_x;
|
||||
u8 blue_y;
|
||||
u8 white_x;
|
||||
u8 white_y;
|
||||
/* Est. timings and mfg rsvd timings*/
|
||||
struct est_timings established_timings;
|
||||
/* Standard timings 1-8*/
|
||||
struct std_timing standard_timings[8];
|
||||
/* Detailing timings 1-4 */
|
||||
struct detailed_timing detailed_timings[4];
|
||||
/* Number of 128 byte ext. blocks */
|
||||
u8 extensions;
|
||||
/* Checksum */
|
||||
u8 checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif /* little endian structs */
|
||||
|
||||
#define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
|
||||
|
||||
#endif /* __DRM_EDID_H__ */
|
||||
278
include/drm/drm_mode.h
Normal file
278
include/drm/drm_mode.h
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
|
||||
* Copyright (c) 2007 Jakob Bornecrantz <wallbraker@gmail.com>
|
||||
* Copyright (c) 2008 Red Hat Inc.
|
||||
* Copyright (c) 2007-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
|
||||
* Copyright (c) 2007-2008 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _DRM_MODE_H
|
||||
#define _DRM_MODE_H
|
||||
|
||||
#if !defined(__KERNEL__) && !defined(_KERNEL)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <linux/kernel.h>
|
||||
#endif
|
||||
|
||||
#define DRM_DISPLAY_INFO_LEN 32
|
||||
#define DRM_CONNECTOR_NAME_LEN 32
|
||||
#define DRM_DISPLAY_MODE_LEN 32
|
||||
#define DRM_PROP_NAME_LEN 32
|
||||
|
||||
#define DRM_MODE_TYPE_BUILTIN (1<<0)
|
||||
#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN)
|
||||
#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN)
|
||||
#define DRM_MODE_TYPE_PREFERRED (1<<3)
|
||||
#define DRM_MODE_TYPE_DEFAULT (1<<4)
|
||||
#define DRM_MODE_TYPE_USERDEF (1<<5)
|
||||
#define DRM_MODE_TYPE_DRIVER (1<<6)
|
||||
|
||||
/* Video mode flags */
|
||||
/* bit compatible with the xorg definitions. */
|
||||
#define DRM_MODE_FLAG_PHSYNC (1<<0)
|
||||
#define DRM_MODE_FLAG_NHSYNC (1<<1)
|
||||
#define DRM_MODE_FLAG_PVSYNC (1<<2)
|
||||
#define DRM_MODE_FLAG_NVSYNC (1<<3)
|
||||
#define DRM_MODE_FLAG_INTERLACE (1<<4)
|
||||
#define DRM_MODE_FLAG_DBLSCAN (1<<5)
|
||||
#define DRM_MODE_FLAG_CSYNC (1<<6)
|
||||
#define DRM_MODE_FLAG_PCSYNC (1<<7)
|
||||
#define DRM_MODE_FLAG_NCSYNC (1<<8)
|
||||
#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */
|
||||
#define DRM_MODE_FLAG_BCAST (1<<10)
|
||||
#define DRM_MODE_FLAG_PIXMUX (1<<11)
|
||||
#define DRM_MODE_FLAG_DBLCLK (1<<12)
|
||||
#define DRM_MODE_FLAG_CLKDIV2 (1<<13)
|
||||
|
||||
/* DPMS flags */
|
||||
/* bit compatible with the xorg definitions. */
|
||||
#define DRM_MODE_DPMS_ON 0
|
||||
#define DRM_MODE_DPMS_STANDBY 1
|
||||
#define DRM_MODE_DPMS_SUSPEND 2
|
||||
#define DRM_MODE_DPMS_OFF 3
|
||||
|
||||
/* Scaling mode options */
|
||||
#define DRM_MODE_SCALE_NON_GPU 0
|
||||
#define DRM_MODE_SCALE_FULLSCREEN 1
|
||||
#define DRM_MODE_SCALE_NO_SCALE 2
|
||||
#define DRM_MODE_SCALE_ASPECT 3
|
||||
|
||||
/* Dithering mode options */
|
||||
#define DRM_MODE_DITHERING_OFF 0
|
||||
#define DRM_MODE_DITHERING_ON 1
|
||||
|
||||
struct drm_mode_modeinfo {
|
||||
unsigned int clock;
|
||||
unsigned short hdisplay, hsync_start, hsync_end, htotal, hskew;
|
||||
unsigned short vdisplay, vsync_start, vsync_end, vtotal, vscan;
|
||||
|
||||
unsigned int vrefresh; /* vertical refresh * 1000 */
|
||||
|
||||
unsigned int flags;
|
||||
unsigned int type;
|
||||
char name[DRM_DISPLAY_MODE_LEN];
|
||||
};
|
||||
|
||||
struct drm_mode_card_res {
|
||||
uint64_t fb_id_ptr;
|
||||
uint64_t crtc_id_ptr;
|
||||
uint64_t connector_id_ptr;
|
||||
uint64_t encoder_id_ptr;
|
||||
int count_fbs;
|
||||
int count_crtcs;
|
||||
int count_connectors;
|
||||
int count_encoders;
|
||||
int min_width, max_width;
|
||||
int min_height, max_height;
|
||||
};
|
||||
|
||||
struct drm_mode_crtc {
|
||||
uint64_t set_connectors_ptr;
|
||||
int count_connectors;
|
||||
|
||||
unsigned int crtc_id; /**< Id */
|
||||
unsigned int fb_id; /**< Id of framebuffer */
|
||||
|
||||
int x, y; /**< Position on the frameuffer */
|
||||
|
||||
uint32_t gamma_size;
|
||||
int mode_valid;
|
||||
struct drm_mode_modeinfo mode;
|
||||
};
|
||||
|
||||
#define DRM_MODE_ENCODER_NONE 0
|
||||
#define DRM_MODE_ENCODER_DAC 1
|
||||
#define DRM_MODE_ENCODER_TMDS 2
|
||||
#define DRM_MODE_ENCODER_LVDS 3
|
||||
#define DRM_MODE_ENCODER_TVDAC 4
|
||||
|
||||
struct drm_mode_get_encoder {
|
||||
unsigned int encoder_id;
|
||||
unsigned int encoder_type;
|
||||
|
||||
unsigned int crtc_id; /**< Id of crtc */
|
||||
|
||||
uint32_t possible_crtcs;
|
||||
uint32_t possible_clones;
|
||||
};
|
||||
|
||||
/* This is for connectors with multiple signal types. */
|
||||
/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */
|
||||
#define DRM_MODE_SUBCONNECTOR_Automatic 0
|
||||
#define DRM_MODE_SUBCONNECTOR_Unknown 0
|
||||
#define DRM_MODE_SUBCONNECTOR_DVID 3
|
||||
#define DRM_MODE_SUBCONNECTOR_DVIA 4
|
||||
#define DRM_MODE_SUBCONNECTOR_Composite 5
|
||||
#define DRM_MODE_SUBCONNECTOR_SVIDEO 6
|
||||
#define DRM_MODE_SUBCONNECTOR_Component 8
|
||||
|
||||
#define DRM_MODE_CONNECTOR_Unknown 0
|
||||
#define DRM_MODE_CONNECTOR_VGA 1
|
||||
#define DRM_MODE_CONNECTOR_DVII 2
|
||||
#define DRM_MODE_CONNECTOR_DVID 3
|
||||
#define DRM_MODE_CONNECTOR_DVIA 4
|
||||
#define DRM_MODE_CONNECTOR_Composite 5
|
||||
#define DRM_MODE_CONNECTOR_SVIDEO 6
|
||||
#define DRM_MODE_CONNECTOR_LVDS 7
|
||||
#define DRM_MODE_CONNECTOR_Component 8
|
||||
#define DRM_MODE_CONNECTOR_9PinDIN 9
|
||||
#define DRM_MODE_CONNECTOR_DisplayPort 10
|
||||
#define DRM_MODE_CONNECTOR_HDMIA 11
|
||||
#define DRM_MODE_CONNECTOR_HDMIB 12
|
||||
|
||||
struct drm_mode_get_connector {
|
||||
|
||||
uint64_t encoders_ptr;
|
||||
uint64_t modes_ptr;
|
||||
uint64_t props_ptr;
|
||||
uint64_t prop_values_ptr;
|
||||
|
||||
int count_modes;
|
||||
int count_props;
|
||||
int count_encoders;
|
||||
|
||||
unsigned int encoder_id; /**< Current Encoder */
|
||||
unsigned int connector_id; /**< Id */
|
||||
unsigned int connector_type;
|
||||
unsigned int connector_type_id;
|
||||
|
||||
unsigned int connection;
|
||||
unsigned int mm_width, mm_height; /**< HxW in millimeters */
|
||||
unsigned int subpixel;
|
||||
};
|
||||
|
||||
#define DRM_MODE_PROP_PENDING (1<<0)
|
||||
#define DRM_MODE_PROP_RANGE (1<<1)
|
||||
#define DRM_MODE_PROP_IMMUTABLE (1<<2)
|
||||
#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */
|
||||
#define DRM_MODE_PROP_BLOB (1<<4)
|
||||
|
||||
struct drm_mode_property_enum {
|
||||
uint64_t value;
|
||||
unsigned char name[DRM_PROP_NAME_LEN];
|
||||
};
|
||||
|
||||
struct drm_mode_get_property {
|
||||
uint64_t values_ptr; /* values and blob lengths */
|
||||
uint64_t enum_blob_ptr; /* enum and blob id ptrs */
|
||||
|
||||
unsigned int prop_id;
|
||||
unsigned int flags;
|
||||
unsigned char name[DRM_PROP_NAME_LEN];
|
||||
|
||||
int count_values;
|
||||
int count_enum_blobs;
|
||||
};
|
||||
|
||||
struct drm_mode_connector_set_property {
|
||||
uint64_t value;
|
||||
unsigned int prop_id;
|
||||
unsigned int connector_id;
|
||||
};
|
||||
|
||||
struct drm_mode_get_blob {
|
||||
uint32_t blob_id;
|
||||
uint32_t length;
|
||||
uint64_t data;
|
||||
};
|
||||
|
||||
struct drm_mode_fb_cmd {
|
||||
unsigned int buffer_id;
|
||||
unsigned int width, height;
|
||||
unsigned int pitch;
|
||||
unsigned int bpp;
|
||||
unsigned int depth;
|
||||
|
||||
unsigned int handle;
|
||||
};
|
||||
|
||||
struct drm_mode_mode_cmd {
|
||||
unsigned int connector_id;
|
||||
struct drm_mode_modeinfo mode;
|
||||
};
|
||||
|
||||
#define DRM_MODE_CURSOR_BO 0x01
|
||||
#define DRM_MODE_CURSOR_MOVE 0x02
|
||||
|
||||
/*
|
||||
* depending on the value in flags diffrent members are used.
|
||||
*
|
||||
* CURSOR_BO uses
|
||||
* crtc
|
||||
* width
|
||||
* height
|
||||
* handle - if 0 turns the cursor of
|
||||
*
|
||||
* CURSOR_MOVE uses
|
||||
* crtc
|
||||
* x
|
||||
* y
|
||||
*/
|
||||
struct drm_mode_cursor {
|
||||
unsigned int flags;
|
||||
unsigned int crtc;
|
||||
int x;
|
||||
int y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
unsigned int handle;
|
||||
};
|
||||
|
||||
/*
|
||||
* oh so ugly hotplug
|
||||
*/
|
||||
struct drm_mode_hotplug {
|
||||
uint32_t counter;
|
||||
};
|
||||
|
||||
struct drm_mode_crtc_lut {
|
||||
|
||||
uint32_t crtc_id;
|
||||
uint32_t gamma_size;
|
||||
|
||||
/* pointers to arrays */
|
||||
uint64_t red;
|
||||
uint64_t green;
|
||||
uint64_t blue;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -153,4 +153,8 @@ void vcs_remove_sysfs(struct tty_struct *tty);
|
||||
#define VESA_HSYNC_SUSPEND 2
|
||||
#define VESA_POWERDOWN 3
|
||||
|
||||
#ifdef CONFIG_VGA_CONSOLE
|
||||
extern bool vgacon_text_force(void);
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_CONSOLE_H */
|
||||
|
||||
Reference in New Issue
Block a user