xref: /gfx-drm/usr/src/uts/intel/io/i915/intel_fb.c (revision e49fc716)
1 /*
2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3  */
4 
5 /*
6  * Copyright (c) 2012, 2013, Intel Corporation.  All rights reserved.
7  */
8 
9 /*
10  * Copyright © 2007 David Airlie
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice (including the next
20  * paragraph) shall be included in all copies or substantial portions of the
21  * Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
26  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29  * DEALINGS IN THE SOFTWARE.
30  *
31  * Authors:
32  *     David Airlie
33  */
34 
35 #include "drmP.h"
36 #include "drm.h"
37 #include "drm_crtc.h"
38 #include "drm_fb_helper.h"
39 #include "intel_drv.h"
40 #include "i915_drm.h"
41 #include "i915_drv.h"
42 
intelfb_create(struct drm_fb_helper * helper,struct drm_fb_helper_surface_size * sizes)43 static int intelfb_create(struct drm_fb_helper *helper,
44 			  struct drm_fb_helper_surface_size *sizes)
45 {
46 	struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper;
47 	struct drm_device *dev = ifbdev->helper.dev;
48 	struct drm_i915_private *dev_priv = dev->dev_private;
49 	struct drm_framebuffer *fb;
50 	struct drm_mode_fb_cmd2 mode_cmd;
51 	struct drm_i915_gem_object *obj;
52 	int size, ret;
53 
54 	/* we don't do packed 24bpp */
55 	if (sizes->surface_bpp == 24)
56 		sizes->surface_bpp = 32;
57 
58 	(void) memset(&mode_cmd, 0, sizeof(struct drm_mode_fb_cmd2));
59 
60 	mode_cmd.width = sizes->surface_width;
61 	mode_cmd.height = sizes->surface_height;
62 
63 	mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) /
64 						      8), 64);
65 	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
66 							  sizes->surface_depth);
67 
68 	size = mode_cmd.pitches[0] * mode_cmd.height;
69 	size = ALIGN(size, PAGE_SIZE);
70 
71 	obj = dev_priv->fbcon_obj;
72 
73 	if (!obj) {
74 		DRM_ERROR("There is no framebuffer for console");
75 		ret = -ENOMEM;
76 		goto out;
77 	}
78 
79 	mutex_lock(&dev->struct_mutex);
80 
81 	ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
82 	if (ret)
83 		goto out_unpin;
84 
85 	fb = &ifbdev->ifb.base;
86 
87 	ifbdev->helper.fb = fb;
88 
89 	mutex_unlock(&dev->struct_mutex);
90 
91 	return 0;
92 
93 out_unpin:
94 	i915_gem_object_unpin(obj);
95 	drm_gem_object_unreference(&obj->base);
96 	mutex_unlock(&dev->struct_mutex);
97 out:
98 	return ret;
99 }
100 
101 static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
102 	.gamma_set = intel_crtc_fb_gamma_set,
103 	.gamma_get = intel_crtc_fb_gamma_get,
104 	.fb_probe = intelfb_create,
105 };
106 
intel_fbdev_destroy(struct drm_device * dev,struct intel_fbdev * ifbdev)107 static void intel_fbdev_destroy(struct drm_device *dev,
108 				struct intel_fbdev *ifbdev)
109 {
110 	struct intel_framebuffer *ifb = &ifbdev->ifb;
111 
112 	drm_fb_helper_fini(&ifbdev->helper);
113 
114 	drm_framebuffer_unregister_private(&ifb->base);
115 	drm_framebuffer_cleanup(&ifb->base);
116 	if (ifb->obj) {
117 		drm_gem_object_unreference_unlocked(&ifb->obj->base);
118 		ifb->obj = NULL;
119 	}
120 }
121 
intel_fbdev_init(struct drm_device * dev)122 int intel_fbdev_init(struct drm_device *dev)
123 {
124 	struct intel_fbdev *ifbdev;
125 	struct drm_i915_private *dev_priv = dev->dev_private;
126 	int ret;
127 
128 	ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
129 	if (!ifbdev)
130 		return -ENOMEM;
131 
132 	dev_priv->fbdev = ifbdev;
133 	ifbdev->helper.funcs = &intel_fb_helper_funcs;
134 
135 	ret = drm_fb_helper_init(dev, &ifbdev->helper,
136 				 INTEL_INFO(dev)->num_pipes,
137 				 INTELFB_CONN_LIMIT);
138 	if (ret) {
139 		kfree(ifbdev, sizeof(struct intel_fbdev));
140 		return ret;
141 	}
142 
143 	(void) drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
144 	return 0;
145 }
146 
intel_fbdev_initial_config(struct drm_device * dev)147 void intel_fbdev_initial_config(struct drm_device *dev)
148 {
149 	struct drm_i915_private *dev_priv = dev->dev_private;
150 
151 	/* Due to peculiar init order wrt to hpd handling this is separate. */
152 	(void) drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 16);
153 }
154 
intel_fbdev_fini(struct drm_device * dev)155 void intel_fbdev_fini(struct drm_device *dev)
156 {
157 	struct drm_i915_private *dev_priv = dev->dev_private;
158 	if (!dev_priv->fbdev)
159 		return;
160 
161 	intel_fbdev_destroy(dev, dev_priv->fbdev);
162 	kfree(dev_priv->fbdev, sizeof(struct intel_fbdev));
163 	dev_priv->fbdev = NULL;
164 }
165 
intel_fb_output_poll_changed(struct drm_device * dev)166 void intel_fb_output_poll_changed(struct drm_device *dev)
167 {
168 	struct drm_i915_private *dev_priv = dev->dev_private;
169 	if (dev_priv->fbdev != NULL)
170 		(void) drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
171 }
172 
intel_fb_restore_mode(struct drm_device * dev)173 void intel_fb_restore_mode(struct drm_device *dev)
174 {
175 	int ret;
176 	struct drm_i915_private *dev_priv = dev->dev_private;
177 
178 	if (INTEL_INFO(dev)->num_pipes == 0)
179 		return;
180 
181 	drm_modeset_lock_all(dev);
182 
183 	ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
184 	if (ret)
185 		DRM_DEBUG("failed to restore crtc mode\n");
186 
187 	drm_modeset_unlock_all(dev);
188 }
189