From patchwork Wed May 5 01:12:15 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Airlie X-Patchwork-Id: 96949 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o451FgDu006433 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 5 May 2010 01:16:18 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-1.v29.ch3.sourceforge.com) by sfs-ml-1.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1O9TBP-00055D-Uq; Wed, 05 May 2010 01:13:51 +0000 Received: from sfi-mx-4.v28.ch3.sourceforge.com ([172.29.28.124] helo=mx.sourceforge.net) by sfs-ml-1.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1O9TBN-00054c-Ug for dri-devel@lists.sourceforge.net; Wed, 05 May 2010 01:13:49 +0000 Received-SPF: neutral (sfi-mx-4.v28.ch3.sourceforge.com: 209.132.183.28 is neither permitted nor denied by domain of gmail.com) client-ip=209.132.183.28; envelope-from=airlied@gmail.com; helo=mx1.redhat.com; Received: from mx1.redhat.com ([209.132.183.28]) by sfi-mx-4.v28.ch3.sourceforge.com with esmtp (Exim 4.69) id 1O9TBN-0007Kr-48 for dri-devel@lists.sourceforge.net; Wed, 05 May 2010 01:13:49 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o451Dhd9029988 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 4 May 2010 21:13:43 -0400 Received: from localhost.localdomain (dhcp-0-222.bne.redhat.com [10.64.0.222]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o451DdMR024465 for ; Tue, 4 May 2010 21:13:42 -0400 From: Dave Airlie To: dri-devel@lists.sf.net Subject: [PATCH 2/2] drm: create fake disconnected connector for use when nothing is plugged in. Date: Wed, 5 May 2010 11:12:15 +1000 Message-Id: <1273021935-15478-3-git-send-email-airlied@gmail.com> In-Reply-To: <1273021935-15478-2-git-send-email-airlied@gmail.com> References: <1273021935-15478-1-git-send-email-airlied@gmail.com> <1273021935-15478-2-git-send-email-airlied@gmail.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-Spam-Score: 1.2 (+) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.2 SPF_NEUTRAL SPF: sender does not match SPF record (neutral) -0.0 AWL AWL: From: address is in the auto white-list X-Headers-End: 1O9TBN-0007Kr-48 X-BeenThere: dri-devel@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 05 May 2010 01:16:18 +0000 (UTC) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 994d23b..3b880ca 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -499,6 +499,7 @@ void drm_connector_cleanup(struct drm_connector *connector) drm_mode_object_put(dev, &connector->base); list_del(&connector->head); mutex_unlock(&dev->mode_config.mutex); + connector->dev = NULL; } EXPORT_SYMBOL(drm_connector_cleanup); @@ -1560,6 +1561,11 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; } + if (out_id == dev->mode_config.disconnected_connector.base.id) { + ret = 0; + goto out; + } + obj = drm_mode_object_find(dev, out_id, DRM_MODE_OBJECT_CONNECTOR); if (!obj) { @@ -2655,3 +2661,37 @@ out: mutex_unlock(&dev->mode_config.mutex); return ret; } + +static void drm_connector_disconnected_dpms(struct drm_connector *connector, int mode) +{ + return; +} + +static enum drm_connector_status drm_connector_disconnected_detect(struct drm_connector *connector) +{ + return connector_status_disconnected; +} + +static int drm_connector_disconnected_fill_modes(struct drm_connector *connector, u32 max_width, u32 max_height) +{ + return 0; +} + +static struct drm_connector_funcs drm_disconnected_funcs = { + .dpms = drm_connector_disconnected_dpms, + .detect = drm_connector_disconnected_detect, + .fill_modes = drm_connector_disconnected_fill_modes, + .destroy = drm_connector_cleanup, +}; + +int drm_mode_add_disconnected_connector(struct drm_device *dev) +{ + if (dev->mode_config.disconnected_connector.dev == NULL) { + drm_connector_init(dev, &dev->mode_config.disconnected_connector, + &drm_disconnected_funcs, + DRM_MODE_CONNECTOR_Unknown); + dev->mode_config.disconnected_connector.status = connector_status_disconnected; + } + return 0; +} +EXPORT_SYMBOL(drm_mode_add_disconnected_connector); diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index ebb7a0c..665febb 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -819,11 +819,20 @@ static void output_poll_execute(struct slow_work *work) enum drm_connector_status old_status, status; bool repoll = false, changed = false; int ret; + bool connected = false; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - /* if this is HPD or polled don't check it - TV out for instance */ - if (!connector->polled) + + /* skip the special disconnected connector */ + if (&dev->mode_config.disconnected_connector == connector) + continue; + /* if this is HPD or polled don't check it - + TV out for instance */ + if (!connector->polled) { + if (connector->status == connector_status_connected) + connected = true; continue; + } else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) repoll = true; @@ -832,8 +841,10 @@ static void output_poll_execute(struct slow_work *work) skip it */ if (old_status == connector_status_connected && !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) && - !(connector->polled & DRM_CONNECTOR_POLL_HPD)) + !(connector->polled & DRM_CONNECTOR_POLL_HPD)) { + connected = true; continue; + } status = connector->funcs->detect(connector); if (old_status != status) @@ -843,6 +854,14 @@ static void output_poll_execute(struct slow_work *work) connected = true; } + /* if we have the disconnected connector */ + if (dev->mode_config.disconnected_connector.dev != NULL) { + /* if nothing connected at all we need to force disconnected connector to connected */ + if (!connected) + dev->mode_config.disconnected_connector.status = connector_status_connected; + else + dev->mode_config.disconnected_connector.status = connector_status_disconnected; + } if (changed) { /* send a uevent + call fbdev */ drm_sysfs_hotplug_event(dev); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d198b82..f7eb3f0 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1283,6 +1283,8 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) */ if (count == 0) { printk(KERN_INFO "No connectors reported connected with modes\n"); + /* create fake connector to hang disconnected X operation off */ + drm_mode_add_disconnected_connector(dev); } drm_setup_crtcs(fb_helper); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 2e4bf92..5dd3aad 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -625,6 +625,8 @@ struct drm_mode_config { struct drm_property *scaling_mode_property; struct drm_property *dithering_mode_property; struct drm_property *dirty_info_property; + + struct drm_connector disconnected_connector; }; #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) @@ -804,4 +806,6 @@ extern int drm_add_modes_noedid(struct drm_connector *connector, int hdisplay, int vdisplay); extern bool drm_edid_is_valid(struct edid *edid); + +extern int drm_mode_add_disconnected_connector(struct drm_device *dev); #endif /* __DRM_CRTC_H__ */