Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: drm: ignore EDID with really tiny modes. drm: don't associate _DRM_DRIVER maps with a master drm/i915: intel_lvds.c fix section mismatch drm: Hook up DPMS property handling in drm_crtc.c. Add drm_helper_connector_dpms. drm: set permissions on edid file to 0444 drm: add newlines to text sysfs files drm/radeon: fix ring free alignment calculations drm: fix irq naming for kms drivers.
This commit is contained in:
commit
b63254c71a
17 changed files with 151 additions and 32 deletions
|
@ -371,7 +371,8 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
|
|||
list->user_token = list->hash.key << PAGE_SHIFT;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
list->master = dev->primary->master;
|
||||
if (!(map->flags & _DRM_DRIVER))
|
||||
list->master = dev->primary->master;
|
||||
*maplist = list;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2294,7 +2294,12 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
if (connector->funcs->set_property)
|
||||
/* Do DPMS ourselves */
|
||||
if (property == connector->dev->mode_config.dpms_property) {
|
||||
if (connector->funcs->dpms)
|
||||
(*connector->funcs->dpms)(connector, (int) out_resp->value);
|
||||
ret = 0;
|
||||
} else if (connector->funcs->set_property)
|
||||
ret = connector->funcs->set_property(connector, property, out_resp->value);
|
||||
|
||||
/* store the property value if succesful */
|
||||
|
|
|
@ -198,6 +198,29 @@ static void drm_helper_add_std_modes(struct drm_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_helper_encoder_in_use - check if a given encoder is in use
|
||||
* @encoder: encoder to check
|
||||
*
|
||||
* LOCKING:
|
||||
* Caller must hold mode config lock.
|
||||
*
|
||||
* Walk @encoders's DRM device's mode_config and see if it's in use.
|
||||
*
|
||||
* RETURNS:
|
||||
* True if @encoder is part of the mode_config, false otherwise.
|
||||
*/
|
||||
bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
|
||||
if (connector->encoder == encoder)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_encoder_in_use);
|
||||
|
||||
/**
|
||||
* drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
|
||||
* @crtc: CRTC to check
|
||||
|
@ -216,7 +239,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
|
|||
struct drm_device *dev = crtc->dev;
|
||||
/* FIXME: Locking around list access? */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
|
||||
if (encoder->crtc == crtc)
|
||||
if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -240,7 +263,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
|
|||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
encoder_funcs = encoder->helper_private;
|
||||
if (!encoder->crtc)
|
||||
if (!drm_helper_encoder_in_use(encoder))
|
||||
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
|
||||
|
@ -935,6 +958,88 @@ bool drm_helper_initial_config(struct drm_device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_helper_initial_config);
|
||||
|
||||
static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
|
||||
{
|
||||
int dpms = DRM_MODE_DPMS_OFF;
|
||||
struct drm_connector *connector;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
|
||||
if (connector->encoder == encoder)
|
||||
if (connector->dpms < dpms)
|
||||
dpms = connector->dpms;
|
||||
return dpms;
|
||||
}
|
||||
|
||||
static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
|
||||
{
|
||||
int dpms = DRM_MODE_DPMS_OFF;
|
||||
struct drm_connector *connector;
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
|
||||
if (connector->encoder && connector->encoder->crtc == crtc)
|
||||
if (connector->dpms < dpms)
|
||||
dpms = connector->dpms;
|
||||
return dpms;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_helper_connector_dpms
|
||||
* @connector affected connector
|
||||
* @mode DPMS mode
|
||||
*
|
||||
* Calls the low-level connector DPMS function, then
|
||||
* calls appropriate encoder and crtc DPMS functions as well
|
||||
*/
|
||||
void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
|
||||
{
|
||||
struct drm_encoder *encoder = connector->encoder;
|
||||
struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
|
||||
int old_dpms;
|
||||
|
||||
if (mode == connector->dpms)
|
||||
return;
|
||||
|
||||
old_dpms = connector->dpms;
|
||||
connector->dpms = mode;
|
||||
|
||||
/* from off to on, do crtc then encoder */
|
||||
if (mode < old_dpms) {
|
||||
if (crtc) {
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
if (crtc_funcs->dpms)
|
||||
(*crtc_funcs->dpms) (crtc,
|
||||
drm_helper_choose_crtc_dpms(crtc));
|
||||
}
|
||||
if (encoder) {
|
||||
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
|
||||
if (encoder_funcs->dpms)
|
||||
(*encoder_funcs->dpms) (encoder,
|
||||
drm_helper_choose_encoder_dpms(encoder));
|
||||
}
|
||||
}
|
||||
|
||||
/* from on to off, do encoder then crtc */
|
||||
if (mode > old_dpms) {
|
||||
if (encoder) {
|
||||
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
|
||||
if (encoder_funcs->dpms)
|
||||
(*encoder_funcs->dpms) (encoder,
|
||||
drm_helper_choose_encoder_dpms(encoder));
|
||||
}
|
||||
if (crtc) {
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
if (crtc_funcs->dpms)
|
||||
(*crtc_funcs->dpms) (crtc,
|
||||
drm_helper_choose_crtc_dpms(crtc));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_connector_dpms);
|
||||
|
||||
/**
|
||||
* drm_hotplug_stage_two
|
||||
* @dev DRM device
|
||||
|
|
|
@ -289,6 +289,11 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
|
|||
struct drm_display_mode *mode;
|
||||
struct detailed_pixel_timing *pt = &timing->data.pixel_data;
|
||||
|
||||
/* ignore tiny modes */
|
||||
if (((pt->hactive_hi << 8) | pt->hactive_lo) < 64 ||
|
||||
((pt->vactive_hi << 8) | pt->hactive_lo) < 64)
|
||||
return NULL;
|
||||
|
||||
if (pt->stereo) {
|
||||
printk(KERN_WARNING "stereo mode not supported\n");
|
||||
return NULL;
|
||||
|
|
|
@ -196,6 +196,7 @@ int drm_irq_install(struct drm_device *dev)
|
|||
{
|
||||
int ret = 0;
|
||||
unsigned long sh_flags = 0;
|
||||
char *irqname;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return -EINVAL;
|
||||
|
@ -227,8 +228,13 @@ int drm_irq_install(struct drm_device *dev)
|
|||
if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
|
||||
sh_flags = IRQF_SHARED;
|
||||
|
||||
if (dev->devname)
|
||||
irqname = dev->devname;
|
||||
else
|
||||
irqname = dev->driver->name;
|
||||
|
||||
ret = request_irq(drm_dev_to_irq(dev), dev->driver->irq_handler,
|
||||
sh_flags, dev->devname, dev);
|
||||
sh_flags, irqname, dev);
|
||||
|
||||
if (ret < 0) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
|
|
@ -147,7 +147,7 @@ static ssize_t status_show(struct device *device,
|
|||
enum drm_connector_status status;
|
||||
|
||||
status = connector->funcs->detect(connector);
|
||||
return snprintf(buf, PAGE_SIZE, "%s",
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
drm_get_connector_status_name(status));
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ static ssize_t dpms_show(struct device *device,
|
|||
if (ret)
|
||||
return 0;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s",
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
drm_get_dpms_name((int)dpms_status));
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ static ssize_t enabled_show(struct device *device,
|
|||
{
|
||||
struct drm_connector *connector = to_drm_connector(device);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, connector->encoder ? "enabled" :
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", connector->encoder ? "enabled" :
|
||||
"disabled");
|
||||
}
|
||||
|
||||
|
@ -317,6 +317,7 @@ static struct device_attribute connector_attrs_opt1[] = {
|
|||
|
||||
static struct bin_attribute edid_attr = {
|
||||
.attr.name = "edid",
|
||||
.attr.mode = 0444,
|
||||
.size = 128,
|
||||
.read = edid_show,
|
||||
};
|
||||
|
|
|
@ -987,12 +987,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
|||
int fb_bar = IS_I9XX(dev) ? 2 : 0;
|
||||
int ret = 0;
|
||||
|
||||
dev->devname = kstrdup(DRIVER_NAME, GFP_KERNEL);
|
||||
if (!dev->devname) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
|
||||
0xff000000;
|
||||
|
||||
|
@ -1006,7 +1000,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
|||
|
||||
ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
|
||||
if (ret)
|
||||
goto kfree_devname;
|
||||
goto out;
|
||||
|
||||
/* Basic memrange allocator for stolen space (aka vram) */
|
||||
drm_mm_init(&dev_priv->vram, 0, prealloc_size);
|
||||
|
@ -1024,7 +1018,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
|||
|
||||
ret = i915_gem_init_ringbuffer(dev);
|
||||
if (ret)
|
||||
goto kfree_devname;
|
||||
goto out;
|
||||
|
||||
/* Allow hardware batchbuffers unless told otherwise.
|
||||
*/
|
||||
|
@ -1056,8 +1050,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
|||
|
||||
destroy_ringbuffer:
|
||||
i915_gem_cleanup_ringbuffer(dev);
|
||||
kfree_devname:
|
||||
kfree(dev->devname);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -381,11 +381,6 @@ static int intel_crt_set_property(struct drm_connector *connector,
|
|||
struct drm_property *property,
|
||||
uint64_t value)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
if (property == dev->mode_config.dpms_property && connector->encoder)
|
||||
intel_crt_dpms(connector->encoder, (uint32_t)(value & 0xf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -402,6 +397,7 @@ static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = {
|
|||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_crt_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.detect = intel_crt_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = intel_crt_destroy,
|
||||
|
|
|
@ -316,6 +316,7 @@ static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
|
|||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_dvo_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.save = intel_dvo_save,
|
||||
.restore = intel_dvo_restore,
|
||||
.detect = intel_dvo_detect,
|
||||
|
|
|
@ -219,6 +219,7 @@ static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
|
|||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.save = intel_hdmi_save,
|
||||
.restore = intel_hdmi_restore,
|
||||
.detect = intel_hdmi_detect,
|
||||
|
|
|
@ -343,11 +343,6 @@ static int intel_lvds_set_property(struct drm_connector *connector,
|
|||
struct drm_property *property,
|
||||
uint64_t value)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
if (property == dev->mode_config.dpms_property && connector->encoder)
|
||||
intel_lvds_dpms(connector->encoder, (uint32_t)(value & 0xf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -366,6 +361,7 @@ static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs
|
|||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_lvds_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.save = intel_lvds_save,
|
||||
.restore = intel_lvds_restore,
|
||||
.detect = intel_lvds_detect,
|
||||
|
@ -391,7 +387,7 @@ static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
|
|||
}
|
||||
|
||||
/* These systems claim to have LVDS, but really don't */
|
||||
static const struct dmi_system_id __initdata intel_no_lvds[] = {
|
||||
static const struct dmi_system_id intel_no_lvds[] = {
|
||||
{
|
||||
.callback = intel_no_lvds_dmi_callback,
|
||||
.ident = "Apple Mac Mini (Core series)",
|
||||
|
|
|
@ -1616,6 +1616,7 @@ static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
|
|||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.save = intel_sdvo_save,
|
||||
.restore = intel_sdvo_restore,
|
||||
.detect = intel_sdvo_detect,
|
||||
|
|
|
@ -1626,6 +1626,7 @@ static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
|
|||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_tv_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.save = intel_tv_save,
|
||||
.restore = intel_tv_restore,
|
||||
.detect = intel_tv_detect,
|
||||
|
|
|
@ -2185,9 +2185,9 @@ void radeon_commit_ring(drm_radeon_private_t *dev_priv)
|
|||
|
||||
/* check if the ring is padded out to 16-dword alignment */
|
||||
|
||||
tail_aligned = dev_priv->ring.tail & 0xf;
|
||||
tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN-1);
|
||||
if (tail_aligned) {
|
||||
int num_p2 = 16 - tail_aligned;
|
||||
int num_p2 = RADEON_RING_ALIGN - tail_aligned;
|
||||
|
||||
ring = dev_priv->ring.start;
|
||||
/* pad with some CP_PACKET2 */
|
||||
|
|
|
@ -1964,11 +1964,14 @@ do { \
|
|||
|
||||
#define RING_LOCALS int write, _nr, _align_nr; unsigned int mask; u32 *ring;
|
||||
|
||||
#define RADEON_RING_ALIGN 16
|
||||
|
||||
#define BEGIN_RING( n ) do { \
|
||||
if ( RADEON_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_RING( %d )\n", (n)); \
|
||||
} \
|
||||
_align_nr = (n + 0xf) & ~0xf; \
|
||||
_align_nr = RADEON_RING_ALIGN - ((dev_priv->ring.tail + n) & (RADEON_RING_ALIGN-1)); \
|
||||
_align_nr += n; \
|
||||
if (dev_priv->ring.space <= (_align_nr * sizeof(u32))) { \
|
||||
COMMIT_RING(); \
|
||||
radeon_wait_ring( dev_priv, _align_nr * sizeof(u32)); \
|
||||
|
|
|
@ -471,6 +471,9 @@ struct drm_connector {
|
|||
u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY];
|
||||
uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY];
|
||||
|
||||
/* requested DPMS state */
|
||||
int dpms;
|
||||
|
||||
void *helper_private;
|
||||
|
||||
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
|
||||
|
|
|
@ -99,6 +99,8 @@ extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
|||
struct drm_framebuffer *old_fb);
|
||||
extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
|
||||
|
||||
extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode);
|
||||
|
||||
extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
|
||||
struct drm_mode_fb_cmd *mode_cmd);
|
||||
|
||||
|
|
Loading…
Reference in a new issue