<br><br>2011³â 11¿ù 9ÀÏ ¼ö¿äÀÏ¿¡ Jesse Barnes&lt;<a href="mailto:jbarnes@virtuousgeek.org">jbarnes@virtuousgeek.org</a>&gt;´ÔÀÌ ÀÛ¼º:<br>&gt; Planes are a bit like half-CRTCs. &nbsp;They have a location and fb, but<br>&gt; don&#39;t drive outputs directly. &nbsp;Add support for handling them to the core<br>
&gt; KMS code.<br>&gt;<br>&gt; Acked-by: Alan Cox &lt;<a href="mailto:alan@lxorguk.ukuu.org.uk">alan@lxorguk.ukuu.org.uk</a>&gt;<br>&gt; Reviewed-by: Rob Clark &lt;<a href="mailto:rob.clark@linaro.org">rob.clark@linaro.org</a>&gt;<br>
&gt; Reviewed-by: Daniel Vetter &lt;<a href="mailto:daniel.vetter@ffwll.ch">daniel.vetter@ffwll.ch</a>&gt;<br>&gt; Signed-off-by: Jesse Barnes &lt;<a href="mailto:jbarnes@virtuousgeek.org">jbarnes@virtuousgeek.org</a>&gt;<br>
<br>Reviewed-by: Joonyoung Shim &lt;<a href="mailto:jy0922.shim@samsung.com">jy0922.shim@samsung.com</a>&gt;<br><br>Thanks.<br><br>&gt; ---<br>&gt; &nbsp;drivers/gpu/drm/drm_crtc.c | &nbsp;257 +++++++++++++++++++++++++++++++++++++++++++-<br>
&gt; &nbsp;drivers/gpu/drm/drm_drv.c &nbsp;| &nbsp; &nbsp;3 +<br>&gt; &nbsp;include/drm/drm.h &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp;3 +<br>&gt; &nbsp;include/drm/drm_crtc.h &nbsp; &nbsp; | &nbsp; 75 +++++++++++++-<br>&gt; &nbsp;include/drm/drm_mode.h &nbsp; &nbsp; | &nbsp; 33 ++++++<br>&gt; &nbsp;5 files changed, 368 insertions(+), 3 deletions(-)<br>
&gt;<br>&gt; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c<br>&gt; index fe738f0..804ef12 100644<br>&gt; --- a/drivers/gpu/drm/drm_crtc.c<br>&gt; +++ b/drivers/gpu/drm/drm_crtc.c<br>&gt; @@ -321,6 +321,7 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)<br>
&gt; &nbsp;{<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;struct drm_device *dev = fb-&gt;dev;<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;struct drm_crtc *crtc;<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_plane *plane;<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;struct drm_mode_set set;<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;int ret;<br>&gt;<br>&gt; @@ -337,6 +338,15 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;}<br>&gt;<br>&gt; + &nbsp; &nbsp; &nbsp; list_for_each_entry(plane, &amp;dev-&gt;mode_config.plane_list, head) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (plane-&gt;fb == fb) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* should turn off the crtc */<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = plane-&gt;funcs-&gt;disable_plane(plane);<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ret)<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DRM_ERROR(&quot;failed to disable plane with busy fb\n&quot;);<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; +<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;drm_mode_object_put(dev, &amp;fb-&gt;base);<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;list_del(&amp;fb-&gt;head);<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;dev-&gt;mode_config.num_fb--;<br>&gt; @@ -535,6 +545,50 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)<br>
&gt; &nbsp;}<br>&gt; &nbsp;EXPORT_SYMBOL(drm_encoder_cleanup);<br>&gt;<br>&gt; +int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unsigned long possible_crtcs,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;const struct drm_plane_funcs *funcs,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;uint32_t *formats, uint32_t format_count)<br>&gt; +{<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_lock(&amp;dev-&gt;mode_config.mutex);<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; plane-&gt;dev = dev;<br>&gt; + &nbsp; &nbsp; &nbsp; drm_mode_object_get(dev, &amp;plane-&gt;base, DRM_MODE_OBJECT_PLANE);<br>
&gt; + &nbsp; &nbsp; &nbsp; plane-&gt;funcs = funcs;<br>&gt; + &nbsp; &nbsp; &nbsp; plane-&gt;format_types = kmalloc(sizeof(uint32_t) * format_count,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GFP_KERNEL);<br>&gt; + &nbsp; &nbsp; &nbsp; if (!plane-&gt;format_types) {<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DRM_DEBUG_KMS(&quot;out of memory when allocating plane\n&quot;);<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drm_mode_object_put(dev, &amp;plane-&gt;base);<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return -ENOMEM;<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; memcpy(plane-&gt;format_types, formats, format_count);<br>&gt; + &nbsp; &nbsp; &nbsp; plane-&gt;format_count = format_count;<br>&gt; + &nbsp; &nbsp; &nbsp; plane-&gt;possible_crtcs = possible_crtcs;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; list_add_tail(&amp;plane-&gt;head, &amp;dev-&gt;mode_config.plane_list);<br>
&gt; + &nbsp; &nbsp; &nbsp; dev-&gt;mode_config.num_plane++;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_unlock(&amp;dev-&gt;mode_config.mutex);<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; return 0;<br>&gt; +}<br>&gt; +EXPORT_SYMBOL(drm_plane_init);<br>&gt; +<br>&gt; +void drm_plane_cleanup(struct drm_plane *plane)<br>
&gt; +{<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_device *dev = plane-&gt;dev;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_lock(&amp;dev-&gt;mode_config.mutex);<br>&gt; + &nbsp; &nbsp; &nbsp; kfree(plane-&gt;format_types);<br>&gt; + &nbsp; &nbsp; &nbsp; drm_mode_object_put(dev, &amp;plane-&gt;base);<br>
&gt; + &nbsp; &nbsp; &nbsp; list_del(&amp;plane-&gt;head);<br>&gt; + &nbsp; &nbsp; &nbsp; dev-&gt;mode_config.num_plane--;<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_unlock(&amp;dev-&gt;mode_config.mutex);<br>&gt; +}<br>&gt; +EXPORT_SYMBOL(drm_plane_cleanup);<br>&gt; +<br>
&gt; &nbsp;/**<br>&gt; &nbsp;* drm_mode_create - create a new display mode<br>&gt; &nbsp;* @dev: DRM device<br>&gt; @@ -866,6 +920,7 @@ void drm_mode_config_init(struct drm_device *dev)<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;INIT_LIST_HEAD(&amp;dev-&gt;mode_config.encoder_list);<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp;INIT_LIST_HEAD(&amp;dev-&gt;mode_config.property_list);<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;INIT_LIST_HEAD(&amp;dev-&gt;mode_config.property_blob_list);<br>&gt; + &nbsp; &nbsp; &nbsp; INIT_LIST_HEAD(&amp;dev-&gt;mode_config.plane_list);<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;idr_init(&amp;dev-&gt;mode_config.crtc_idr);<br>
&gt;<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;mutex_lock(&amp;dev-&gt;mode_config.mutex);<br>&gt; @@ -942,6 +997,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;struct drm_encoder *encoder, *enct;<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;struct drm_framebuffer *fb, *fbt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp;struct drm_property *property, *pt;<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_plane *plane, *plt;<br>&gt;<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;list_for_each_entry_safe(encoder, enct, &amp;dev-&gt;mode_config.encoder_list,<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; head) {<br>
&gt; @@ -966,6 +1022,10 @@ void drm_mode_config_cleanup(struct drm_device *dev)<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;crtc-&gt;funcs-&gt;destroy(crtc);<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;}<br>&gt;<br>&gt; + &nbsp; &nbsp; &nbsp; list_for_each_entry_safe(plane, plt, &amp;dev-&gt;mode_config.plane_list,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;head) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane-&gt;funcs-&gt;destroy(plane);<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; &nbsp;}<br>&gt; &nbsp;EXPORT_SYMBOL(drm_mode_config_cleanup);<br>&gt;<br>&gt; @@ -1466,6 +1526,197 @@ out:<br>
&gt; &nbsp;}<br>&gt;<br>&gt; &nbsp;/**<br>&gt; + * drm_mode_getplane_res - get plane info<br>&gt; + * @dev: DRM device<br>&gt; + * @data: ioctl data<br>&gt; + * @file_priv: DRM file info<br>&gt; + *<br>&gt; + * Return an plane count and set of IDs.<br>
&gt; + */<br>&gt; +int drm_mode_getplane_res(struct drm_device *dev, void *data,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; struct drm_file *file_priv)<br>&gt; +{<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_mode_get_plane_res *plane_resp = data;<br>
&gt; + &nbsp; &nbsp; &nbsp; struct drm_mode_config *config;<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_plane *plane;<br>&gt; + &nbsp; &nbsp; &nbsp; uint32_t __user *plane_ptr;<br>&gt; + &nbsp; &nbsp; &nbsp; int copied = 0, ret = 0;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; if (!drm_core_check_feature(dev, DRIVER_MODESET))<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return -EINVAL;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_lock(&amp;dev-&gt;mode_config.mutex);<br>&gt; + &nbsp; &nbsp; &nbsp; config = &amp;dev-&gt;mode_config;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; /*<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp;* This ioctl is called twice, once to determine how much space is<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp;* needed, and the 2nd time to fill it.<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp;*/<br>&gt; + &nbsp; &nbsp; &nbsp; if (config-&gt;num_plane &amp;&amp;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (plane_resp-&gt;count_planes &gt;= config-&gt;num_plane)) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane_ptr = (uint32_t *)(unsigned long)plane_resp-&gt;plane_id_ptr;<br>
&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; list_for_each_entry(plane, &amp;config-&gt;plane_list, head) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (put_user(plane-&gt;<a href="http://base.id">base.id</a>, plane_ptr + copied)) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = -EFAULT;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto out;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; copied++;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; + &nbsp; &nbsp; &nbsp; plane_resp-&gt;count_planes = config-&gt;num_plane;<br>
&gt; +<br>&gt; +out:<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_unlock(&amp;dev-&gt;mode_config.mutex);<br>&gt; + &nbsp; &nbsp; &nbsp; return ret;<br>&gt; +}<br>&gt; +<br>&gt; +/**<br>&gt; + * drm_mode_getplane - get plane info<br>&gt; + * @dev: DRM device<br>
&gt; + * @data: ioctl data<br>&gt; + * @file_priv: DRM file info<br>&gt; + *<br>&gt; + * Return plane info, including formats supported, gamma size, any<br>&gt; + * current fb, etc.<br>&gt; + */<br>&gt; +int drm_mode_getplane(struct drm_device *dev, void *data,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; struct drm_file *file_priv)<br>&gt; +{<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_mode_get_plane *plane_resp = data;<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_mode_object *obj;<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_plane *plane;<br>&gt; + &nbsp; &nbsp; &nbsp; uint32_t __user *format_ptr;<br>
&gt; + &nbsp; &nbsp; &nbsp; int ret = 0;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; if (!drm_core_check_feature(dev, DRIVER_MODESET))<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return -EINVAL;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_lock(&amp;dev-&gt;mode_config.mutex);<br>&gt; + &nbsp; &nbsp; &nbsp; obj = drm_mode_object_find(dev, plane_resp-&gt;plane_id,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DRM_MODE_OBJECT_PLANE);<br>&gt; + &nbsp; &nbsp; &nbsp; if (!obj) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = -ENOENT;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto out;<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; + &nbsp; &nbsp; &nbsp; plane = obj_to_plane(obj);<br>
&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; if (plane-&gt;crtc)<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane_resp-&gt;crtc_id = plane-&gt;crtc-&gt;<a href="http://base.id">base.id</a>;<br>&gt; + &nbsp; &nbsp; &nbsp; else<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane_resp-&gt;crtc_id = 0;<br>
&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; if (plane-&gt;fb)<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane_resp-&gt;fb_id = plane-&gt;fb-&gt;<a href="http://base.id">base.id</a>;<br>&gt; + &nbsp; &nbsp; &nbsp; else<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane_resp-&gt;fb_id = 0;<br>&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; plane_resp-&gt;plane_id = plane-&gt;<a href="http://base.id">base.id</a>;<br>&gt; + &nbsp; &nbsp; &nbsp; plane_resp-&gt;possible_crtcs = plane-&gt;possible_crtcs;<br>&gt; + &nbsp; &nbsp; &nbsp; plane_resp-&gt;gamma_size = plane-&gt;gamma_size;<br>
&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; /*<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp;* This ioctl is called twice, once to determine how much space is<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp;* needed, and the 2nd time to fill it.<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp;*/<br>&gt; + &nbsp; &nbsp; &nbsp; if (plane-&gt;format_count &amp;&amp;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (plane_resp-&gt;count_format_types &gt;= plane-&gt;format_count)) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; format_ptr = (uint32_t *)(unsigned long)plane_resp-&gt;format_type_ptr;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (copy_to_user(format_ptr,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;plane-&gt;format_types,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sizeof(uint32_t) * plane-&gt;format_count)) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = -EFAULT;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto out;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; + &nbsp; &nbsp; &nbsp; plane_resp-&gt;count_format_types = plane-&gt;format_count;<br>&gt; +<br>&gt; +out:<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_unlock(&amp;dev-&gt;mode_config.mutex);<br>&gt; + &nbsp; &nbsp; &nbsp; return ret;<br>
&gt; +}<br>&gt; +<br>&gt; +/**<br>&gt; + * drm_mode_setplane - set up or tear down an plane<br>&gt; + * @dev: DRM device<br>&gt; + * @data: ioctl data*<br>&gt; + * @file_prive: DRM file info<br>&gt; + *<br>&gt; + * Set plane info, including placement, fb, scaling, and other factors.<br>
&gt; + * Or pass a NULL fb to disable.<br>&gt; + */<br>&gt; +int drm_mode_setplane(struct drm_device *dev, void *data,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; struct drm_file *file_priv)<br>&gt; +{<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_mode_set_plane *plane_req = data;<br>
&gt; + &nbsp; &nbsp; &nbsp; struct drm_mode_object *obj;<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_plane *plane;<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_crtc *crtc;<br>&gt; + &nbsp; &nbsp; &nbsp; struct drm_framebuffer *fb;<br>&gt; + &nbsp; &nbsp; &nbsp; int ret = 0;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; if (!drm_core_check_feature(dev, DRIVER_MODESET))<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return -EINVAL;<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_lock(&amp;dev-&gt;mode_config.mutex);<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; /*<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp;* First, find the plane, crtc, and fb objects. &nbsp;If not available,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp;* we don&#39;t bother to call the driver.<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp;*/<br>&gt; + &nbsp; &nbsp; &nbsp; obj = drm_mode_object_find(dev, plane_req-&gt;plane_id,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DRM_MODE_OBJECT_PLANE);<br>&gt; + &nbsp; &nbsp; &nbsp; if (!obj) {<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DRM_DEBUG_KMS(&quot;Unknown plane ID %d\n&quot;,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane_req-&gt;plane_id);<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = -ENOENT;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto out;<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>
&gt; + &nbsp; &nbsp; &nbsp; plane = obj_to_plane(obj);<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; /* No fb means shut it down */<br>&gt; + &nbsp; &nbsp; &nbsp; if (!plane_req-&gt;fb_id) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane-&gt;funcs-&gt;disable_plane(plane);<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto out;<br>
&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; obj = drm_mode_object_find(dev, plane_req-&gt;crtc_id,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DRM_MODE_OBJECT_CRTC);<br>&gt; + &nbsp; &nbsp; &nbsp; if (!obj) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DRM_DEBUG_KMS(&quot;Unknown crtc ID %d\n&quot;,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane_req-&gt;crtc_id);<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = -ENOENT;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto out;<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; + &nbsp; &nbsp; &nbsp; crtc = obj_to_crtc(obj);<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; obj = drm_mode_object_find(dev, plane_req-&gt;fb_id,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DRM_MODE_OBJECT_FB);<br>&gt; + &nbsp; &nbsp; &nbsp; if (!obj) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DRM_DEBUG_KMS(&quot;Unknown framebuffer ID %d\n&quot;,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane_req-&gt;fb_id);<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret = -ENOENT;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; goto out;<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; + &nbsp; &nbsp; &nbsp; fb = obj_to_fb(obj);<br>&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; ret = plane-&gt;funcs-&gt;update_plane(plane, crtc, fb,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;plane_req-&gt;crtc_x, plane_req-&gt;crtc_y,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;plane_req-&gt;crtc_w, plane_req-&gt;crtc_h,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;plane_req-&gt;src_x, plane_req-&gt;src_y,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;plane_req-&gt;src_w, plane_req-&gt;src_h);<br>
&gt; + &nbsp; &nbsp; &nbsp; if (!ret) {<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane-&gt;crtc = crtc;<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; plane-&gt;fb = fb;<br>&gt; + &nbsp; &nbsp; &nbsp; }<br>&gt; +<br>&gt; +out:<br>&gt; + &nbsp; &nbsp; &nbsp; mutex_unlock(&amp;dev-&gt;mode_config.mutex);<br>
&gt; +<br>&gt; + &nbsp; &nbsp; &nbsp; return ret;<br>&gt; +}<br>&gt; +<br>&gt; +/**<br>&gt; &nbsp;* drm_mode_setcrtc - set CRTC configuration<br>&gt; &nbsp;* @inode: inode from the ioctl<br>&gt; &nbsp;* @filp: file * from the ioctl<br>&gt; @@ -1688,11 +1939,13 @@ int drm_mode_addfb(struct drm_device *dev,<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return -EINVAL;<br>&gt;<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp;if ((config-&gt;min_width &gt; r-&gt;width) || (r-&gt;width &gt; config-&gt;max_width)) {<br>&gt; - &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DRM_ERROR(&quot;mode new framebuffer width not within limits\n&quot;);<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DRM_ERROR(&quot;bad framebuffer width %d, should be &gt;= %d &amp;&amp; &lt;= %d\n&quot;,<br>&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r-&gt;width, config-&gt;min_width, config-&gt;max_width);<br>&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return -EINVAL;<br>
&gt; index 8020798..e20867e 100644<br>&gt; --- a/include/drm/drm_crtc.h<br>&gt; +++ b/include/drm/drm_crtc.h<br>&gt; @@ -44,6 +44,7 @@ struct drm_framebuffer;<br>&gt; &nbsp;#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0<br>&gt; &nbsp;#define DRM_MODE_OBJECT_+extern int drm_pl<br>
<br>-- <br>- Joonyoung Shim<br>