1 // SPDX-License-Identifier: GPL-2.0-only
2 /**************************************************************************
3 * Copyright (c) 2007-2011, Intel Corporation.
4 * All Rights Reserved.
5 *
6 **************************************************************************/
7
8 #include <drm/drm_framebuffer.h>
9 #include <drm/drm_gem_framebuffer_helper.h>
10 #include <drm/drm_modeset_helper.h>
11
12 #include "framebuffer.h"
13 #include "psb_drv.h"
14
15 static const struct drm_framebuffer_funcs psb_fb_funcs = {
16 .destroy = drm_gem_fb_destroy,
17 .create_handle = drm_gem_fb_create_handle,
18 };
19
20 /**
21 * psb_framebuffer_init - initialize a framebuffer
22 * @dev: our DRM device
23 * @fb: framebuffer to set up
24 * @mode_cmd: mode description
25 * @obj: backing object
26 *
27 * Configure and fill in the boilerplate for our frame buffer. Return
28 * 0 on success or an error code if we fail.
29 */
psb_framebuffer_init(struct drm_device * dev,struct drm_framebuffer * fb,const struct drm_format_info * info,const struct drm_mode_fb_cmd2 * mode_cmd,struct drm_gem_object * obj)30 static int psb_framebuffer_init(struct drm_device *dev,
31 struct drm_framebuffer *fb,
32 const struct drm_format_info *info,
33 const struct drm_mode_fb_cmd2 *mode_cmd,
34 struct drm_gem_object *obj)
35 {
36 int ret;
37
38 /*
39 * Reject unknown formats, YUV formats, and formats with more than
40 * 4 bytes per pixel.
41 */
42 if (!info->depth || info->cpp[0] > 4)
43 return -EINVAL;
44
45 if (mode_cmd->pitches[0] & 63)
46 return -EINVAL;
47
48 drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd);
49 fb->obj[0] = obj;
50 ret = drm_framebuffer_init(dev, fb, &psb_fb_funcs);
51 if (ret) {
52 dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
53 return ret;
54 }
55 return 0;
56 }
57
58 /**
59 * psb_framebuffer_create - create a framebuffer backed by gt
60 * @dev: our DRM device
61 * @info: pixel format information
62 * @mode_cmd: the description of the requested mode
63 * @obj: the backing object
64 *
65 * Create a framebuffer object backed by the gt, and fill in the
66 * boilerplate required
67 *
68 * TODO: review object references
69 */
psb_framebuffer_create(struct drm_device * dev,const struct drm_format_info * info,const struct drm_mode_fb_cmd2 * mode_cmd,struct drm_gem_object * obj)70 struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev,
71 const struct drm_format_info *info,
72 const struct drm_mode_fb_cmd2 *mode_cmd,
73 struct drm_gem_object *obj)
74 {
75 struct drm_framebuffer *fb;
76 int ret;
77
78 fb = kzalloc(sizeof(*fb), GFP_KERNEL);
79 if (!fb)
80 return ERR_PTR(-ENOMEM);
81
82 ret = psb_framebuffer_init(dev, fb, info, mode_cmd, obj);
83 if (ret) {
84 kfree(fb);
85 return ERR_PTR(ret);
86 }
87 return fb;
88 }
89
90 /**
91 * psb_user_framebuffer_create - create framebuffer
92 * @dev: our DRM device
93 * @filp: client file
94 * @cmd: mode request
95 *
96 * Create a new framebuffer backed by a userspace GEM object
97 */
psb_user_framebuffer_create(struct drm_device * dev,struct drm_file * filp,const struct drm_format_info * info,const struct drm_mode_fb_cmd2 * cmd)98 static struct drm_framebuffer *psb_user_framebuffer_create
99 (struct drm_device *dev, struct drm_file *filp,
100 const struct drm_format_info *info,
101 const struct drm_mode_fb_cmd2 *cmd)
102 {
103 struct drm_gem_object *obj;
104 struct drm_framebuffer *fb;
105
106 /*
107 * Find the GEM object and thus the gtt range object that is
108 * to back this space
109 */
110 obj = drm_gem_object_lookup(filp, cmd->handles[0]);
111 if (obj == NULL)
112 return ERR_PTR(-ENOENT);
113
114 /* Let the core code do all the work */
115 fb = psb_framebuffer_create(dev, info, cmd, obj);
116 if (IS_ERR(fb))
117 drm_gem_object_put(obj);
118
119 return fb;
120 }
121
122 static const struct drm_mode_config_funcs psb_mode_funcs = {
123 .fb_create = psb_user_framebuffer_create,
124 };
125
psb_setup_outputs(struct drm_device * dev)126 static void psb_setup_outputs(struct drm_device *dev)
127 {
128 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
129 struct drm_connector_list_iter conn_iter;
130 struct drm_connector *connector;
131
132 drm_mode_create_scaling_mode_property(dev);
133
134 /* It is ok for this to fail - we just don't get backlight control */
135 if (!dev_priv->backlight_property)
136 dev_priv->backlight_property = drm_property_create_range(dev, 0,
137 "backlight", 0, 100);
138 dev_priv->ops->output_init(dev);
139
140 drm_connector_list_iter_begin(dev, &conn_iter);
141 drm_for_each_connector_iter(connector, &conn_iter) {
142 struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
143 struct drm_encoder *encoder = &gma_encoder->base;
144 int crtc_mask = 0, clone_mask = 0;
145
146 /* valid crtcs */
147 switch (gma_encoder->type) {
148 case INTEL_OUTPUT_ANALOG:
149 crtc_mask = (1 << 0);
150 clone_mask = (1 << INTEL_OUTPUT_ANALOG);
151 break;
152 case INTEL_OUTPUT_SDVO:
153 crtc_mask = dev_priv->ops->sdvo_mask;
154 clone_mask = 0;
155 break;
156 case INTEL_OUTPUT_LVDS:
157 crtc_mask = dev_priv->ops->lvds_mask;
158 clone_mask = 0;
159 break;
160 case INTEL_OUTPUT_MIPI:
161 crtc_mask = (1 << 0);
162 clone_mask = 0;
163 break;
164 case INTEL_OUTPUT_MIPI2:
165 crtc_mask = (1 << 2);
166 clone_mask = 0;
167 break;
168 case INTEL_OUTPUT_HDMI:
169 crtc_mask = dev_priv->ops->hdmi_mask;
170 clone_mask = (1 << INTEL_OUTPUT_HDMI);
171 break;
172 case INTEL_OUTPUT_DISPLAYPORT:
173 crtc_mask = (1 << 0) | (1 << 1);
174 clone_mask = 0;
175 break;
176 case INTEL_OUTPUT_EDP:
177 crtc_mask = (1 << 1);
178 clone_mask = 0;
179 }
180 encoder->possible_crtcs = crtc_mask;
181 encoder->possible_clones =
182 gma_connector_clones(dev, clone_mask);
183 }
184 drm_connector_list_iter_end(&conn_iter);
185 }
186
psb_modeset_init(struct drm_device * dev)187 void psb_modeset_init(struct drm_device *dev)
188 {
189 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
190 struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
191 int i;
192
193 if (drmm_mode_config_init(dev))
194 return;
195
196 dev->mode_config.min_width = 0;
197 dev->mode_config.min_height = 0;
198
199 dev->mode_config.funcs = &psb_mode_funcs;
200
201 /* num pipes is 2 for PSB but 1 for Mrst */
202 for (i = 0; i < dev_priv->num_pipe; i++)
203 psb_intel_crtc_init(dev, i, mode_dev);
204
205 dev->mode_config.max_width = 4096;
206 dev->mode_config.max_height = 4096;
207
208 psb_setup_outputs(dev);
209
210 if (dev_priv->ops->errata)
211 dev_priv->ops->errata(dev);
212
213 dev_priv->modeset = true;
214 }
215
psb_modeset_cleanup(struct drm_device * dev)216 void psb_modeset_cleanup(struct drm_device *dev)
217 {
218 struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
219 if (dev_priv->modeset) {
220 drm_kms_helper_poll_fini(dev);
221 }
222 }
223