Deleted Added
full compact
drm_fb_helper.c (279488) drm_fb_helper.c (280183)
1/*
2 * Copyright (c) 2006-2009 Red Hat Inc.
3 * Copyright (c) 2006-2008 Intel Corporation
4 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
5 *
6 * DRM framebuffer helper functions
7 *
8 * Permission to use, copy, modify, distribute, and sell this software and its

--- 15 unchanged lines hidden (view full) ---

24 * OF THIS SOFTWARE.
25 *
26 * Authors:
27 * Dave Airlie <airlied@linux.ie>
28 * Jesse Barnes <jesse.barnes@intel.com>
29 */
30
31#include <sys/cdefs.h>
1/*
2 * Copyright (c) 2006-2009 Red Hat Inc.
3 * Copyright (c) 2006-2008 Intel Corporation
4 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
5 *
6 * DRM framebuffer helper functions
7 *
8 * Permission to use, copy, modify, distribute, and sell this software and its

--- 15 unchanged lines hidden (view full) ---

24 * OF THIS SOFTWARE.
25 *
26 * Authors:
27 * Dave Airlie <airlied@linux.ie>
28 * Jesse Barnes <jesse.barnes@intel.com>
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/drm2/drm_fb_helper.c 279488 2015-03-01 12:54:22Z dumbbell $");
32__FBSDID("$FreeBSD: head/sys/dev/drm2/drm_fb_helper.c 280183 2015-03-17 18:50:33Z dumbbell $");
33
33
34#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
35
34#include <dev/drm2/drmP.h>
35#include <dev/drm2/drm_crtc.h>
36#include <dev/drm2/drm_fb_helper.h>
37#include <dev/drm2/drm_crtc_helper.h>
38
36#include <dev/drm2/drmP.h>
37#include <dev/drm2/drm_crtc.h>
38#include <dev/drm2/drm_fb_helper.h>
39#include <dev/drm2/drm_crtc_helper.h>
40
41MODULE_AUTHOR("David Airlie, Jesse Barnes");
42MODULE_DESCRIPTION("DRM KMS helper");
43MODULE_LICENSE("GPL and additional rights");
44
45static DRM_LIST_HEAD(kernel_fb_helper_list);
46
39#include <sys/kdb.h>
40#include <sys/param.h>
41#include <sys/systm.h>
42
43struct vt_kms_softc {
47#include <sys/kdb.h>
48#include <sys/param.h>
49#include <sys/systm.h>
50
51struct vt_kms_softc {
44 struct drm_fb_helper *fb_helper;
45 struct task fb_mode_task;
52 struct drm_fb_helper *fb_helper;
53 struct task fb_mode_task;
46};
47
54};
55
48static fb_enter_t vt_kms_postswitch;
49static void vt_restore_fbdev_mode(void *, int);
50
51/* Call restore out of vt(9) locks. */
52static void
53vt_restore_fbdev_mode(void *arg, int pending)
54{
55 struct drm_fb_helper *fb_helper;
56 struct vt_kms_softc *sc;
57
58 sc = (struct vt_kms_softc *)arg;

--- 13 unchanged lines hidden (view full) ---

72 if (!kdb_active && panicstr == NULL)
73 taskqueue_enqueue_fast(taskqueue_thread, &sc->fb_mode_task);
74 else
75 drm_fb_helper_restore_fbdev_mode(sc->fb_helper);
76
77 return (0);
78}
79
56/* Call restore out of vt(9) locks. */
57static void
58vt_restore_fbdev_mode(void *arg, int pending)
59{
60 struct drm_fb_helper *fb_helper;
61 struct vt_kms_softc *sc;
62
63 sc = (struct vt_kms_softc *)arg;

--- 13 unchanged lines hidden (view full) ---

77 if (!kdb_active && panicstr == NULL)
78 taskqueue_enqueue_fast(taskqueue_thread, &sc->fb_mode_task);
79 else
80 drm_fb_helper_restore_fbdev_mode(sc->fb_helper);
81
82 return (0);
83}
84
80static DRM_LIST_HEAD(kernel_fb_helper_list);
81
82/* simple single crtc case helper function */
83int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
85struct fb_info *
86framebuffer_alloc()
84{
87{
85 struct drm_device *dev = fb_helper->dev;
86 struct drm_connector *connector;
88 struct fb_info *info;
89 struct vt_kms_softc *sc;
87
90
88 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
89 struct drm_fb_helper_connector *fb_helper_connector;
91 info = malloc(sizeof(*info), DRM_MEM_KMS, M_WAITOK | M_ZERO);
90
92
91 fb_helper_connector = malloc(
92 sizeof(struct drm_fb_helper_connector), DRM_MEM_KMS,
93 M_WAITOK | M_ZERO);
93 sc = malloc(sizeof(*sc), DRM_MEM_KMS, M_WAITOK | M_ZERO);
94 TASK_INIT(&sc->fb_mode_task, 0, vt_restore_fbdev_mode, sc);
94
95
95 fb_helper_connector->connector = connector;
96 fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
97 }
98 return 0;
96 info->fb_priv = sc;
97 info->enter = &vt_kms_postswitch;
98
99 return (info);
99}
100
100}
101
102void
103framebuffer_release(struct fb_info *info)
104{
105
106 free(info->fb_priv, DRM_MEM_KMS);
107 free(info, DRM_MEM_KMS);
108}
109
101static int
102fb_get_options(const char *connector_name, char **option)
103{
104 char tunable[64];
105
106 /*
107 * A user may use loader tunables to set a specific mode for the
108 * console. Tunables are read in the following order:

--- 11 unchanged lines hidden (view full) ---

120 connector_name);
121 DRM_INFO("Connector %s: get mode from tunables:\n", connector_name);
122 DRM_INFO(" - %s\n", tunable);
123 DRM_INFO(" - kern.vt.fb.default_mode\n");
124 *option = kern_getenv(tunable);
125 if (*option == NULL)
126 *option = kern_getenv("kern.vt.fb.default_mode");
127
110static int
111fb_get_options(const char *connector_name, char **option)
112{
113 char tunable[64];
114
115 /*
116 * A user may use loader tunables to set a specific mode for the
117 * console. Tunables are read in the following order:

--- 11 unchanged lines hidden (view full) ---

129 connector_name);
130 DRM_INFO("Connector %s: get mode from tunables:\n", connector_name);
131 DRM_INFO(" - %s\n", tunable);
132 DRM_INFO(" - kern.vt.fb.default_mode\n");
133 *option = kern_getenv(tunable);
134 if (*option == NULL)
135 *option = kern_getenv("kern.vt.fb.default_mode");
136
128 return (*option != NULL ? 0 : 1);
137 return (*option != NULL ? 0 : -ENOENT);
129}
130
138}
139
140/**
141 * DOC: fbdev helpers
142 *
143 * The fb helper functions are useful to provide an fbdev on top of a drm kernel
144 * mode setting driver. They can be used mostly independantely from the crtc
145 * helper functions used by many drivers to implement the kernel mode setting
146 * interfaces.
147 */
148
149/* simple single crtc case helper function */
150int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
151{
152 struct drm_device *dev = fb_helper->dev;
153 struct drm_connector *connector;
154 int i;
155
156 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
157 struct drm_fb_helper_connector *fb_helper_connector;
158
159 fb_helper_connector = malloc(sizeof(struct drm_fb_helper_connector),
160 DRM_MEM_KMS, M_NOWAIT | M_ZERO);
161 if (!fb_helper_connector)
162 goto fail;
163
164 fb_helper_connector->connector = connector;
165 fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
166 }
167 return 0;
168fail:
169 for (i = 0; i < fb_helper->connector_count; i++) {
170 free(fb_helper->connector_info[i], DRM_MEM_KMS);
171 fb_helper->connector_info[i] = NULL;
172 }
173 fb_helper->connector_count = 0;
174 return -ENOMEM;
175}
176EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
177
131static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
132{
133 struct drm_fb_helper_connector *fb_helper_conn;
134 int i;
135
136 for (i = 0; i < fb_helper->connector_count; i++) {
137 struct drm_cmdline_mode *mode;
138 struct drm_connector *connector;

--- 25 unchanged lines hidden (view full) ---

164 break;
165 }
166
167 DRM_INFO("forcing %s connector %s\n",
168 drm_get_connector_name(connector), s);
169 connector->force = mode->force;
170 }
171
178static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
179{
180 struct drm_fb_helper_connector *fb_helper_conn;
181 int i;
182
183 for (i = 0; i < fb_helper->connector_count; i++) {
184 struct drm_cmdline_mode *mode;
185 struct drm_connector *connector;

--- 25 unchanged lines hidden (view full) ---

211 break;
212 }
213
214 DRM_INFO("forcing %s connector %s\n",
215 drm_get_connector_name(connector), s);
216 connector->force = mode->force;
217 }
218
172 DRM_INFO("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
219 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
173 drm_get_connector_name(connector),
174 mode->xres, mode->yres,
175 mode->refresh_specified ? mode->refresh : 60,
176 mode->rb ? " reduced blanking" : "",
177 mode->margins ? " with margins" : "",
178 mode->interlace ? " interlaced" : "");
179 }
180
181 freeenv(option);
220 drm_get_connector_name(connector),
221 mode->xres, mode->yres,
222 mode->refresh_specified ? mode->refresh : 60,
223 mode->rb ? " reduced blanking" : "",
224 mode->margins ? " with margins" : "",
225 mode->interlace ? " interlaced" : "");
226 }
227
228 freeenv(option);
182
183 }
184 return 0;
185}
186
229 }
230 return 0;
231}
232
187#if 0
233#if 0 && defined(FREEBSD_NOTYET)
188static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
189{
190 uint16_t *r_base, *g_base, *b_base;
191 int i;
192
193 r_base = crtc->gamma_store;
194 g_base = r_base + crtc->gamma_size;
195 b_base = g_base + crtc->gamma_size;

--- 10 unchanged lines hidden (view full) ---

206 return;
207
208 r_base = crtc->gamma_store;
209 g_base = r_base + crtc->gamma_size;
210 b_base = g_base + crtc->gamma_size;
211
212 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
213}
234static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
235{
236 uint16_t *r_base, *g_base, *b_base;
237 int i;
238
239 r_base = crtc->gamma_store;
240 g_base = r_base + crtc->gamma_size;
241 b_base = g_base + crtc->gamma_size;

--- 10 unchanged lines hidden (view full) ---

252 return;
253
254 r_base = crtc->gamma_store;
255 g_base = r_base + crtc->gamma_size;
256 b_base = g_base + crtc->gamma_size;
257
258 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
259}
214#endif
215
260
216#if 0
217int drm_fb_helper_debug_enter(struct fb_info *info)
218{
219 struct drm_fb_helper *helper = info->par;
220 struct drm_crtc_helper_funcs *funcs;
221 int i;
222
223 if (list_empty(&kernel_fb_helper_list))
224 return false;

--- 13 unchanged lines hidden (view full) ---

238 mode_set->x,
239 mode_set->y,
240 ENTER_ATOMIC_MODE_SET);
241 }
242 }
243
244 return 0;
245}
261int drm_fb_helper_debug_enter(struct fb_info *info)
262{
263 struct drm_fb_helper *helper = info->par;
264 struct drm_crtc_helper_funcs *funcs;
265 int i;
266
267 if (list_empty(&kernel_fb_helper_list))
268 return false;

--- 13 unchanged lines hidden (view full) ---

282 mode_set->x,
283 mode_set->y,
284 ENTER_ATOMIC_MODE_SET);
285 }
286 }
287
288 return 0;
289}
246#endif
290EXPORT_SYMBOL(drm_fb_helper_debug_enter);
247
291
248#if 0
249/* Find the real fb for a given fb helper CRTC */
250static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
251{
252 struct drm_device *dev = crtc->dev;
253 struct drm_crtc *c;
254
255 list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
256 if (crtc->base.id == c->base.id)
257 return c->fb;
258 }
259
260 return NULL;
261}
292/* Find the real fb for a given fb helper CRTC */
293static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
294{
295 struct drm_device *dev = crtc->dev;
296 struct drm_crtc *c;
297
298 list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
299 if (crtc->base.id == c->base.id)
300 return c->fb;
301 }
302
303 return NULL;
304}
262#endif
263
305
264#if 0
265int drm_fb_helper_debug_leave(struct fb_info *info)
266{
267 struct drm_fb_helper *helper = info->par;
268 struct drm_crtc *crtc;
269 struct drm_crtc_helper_funcs *funcs;
270 struct drm_framebuffer *fb;
271 int i;
272

--- 13 unchanged lines hidden (view full) ---

286
287 drm_fb_helper_restore_lut_atomic(mode_set->crtc);
288 funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
289 crtc->y, LEAVE_ATOMIC_MODE_SET);
290 }
291
292 return 0;
293}
306int drm_fb_helper_debug_leave(struct fb_info *info)
307{
308 struct drm_fb_helper *helper = info->par;
309 struct drm_crtc *crtc;
310 struct drm_crtc_helper_funcs *funcs;
311 struct drm_framebuffer *fb;
312 int i;
313

--- 13 unchanged lines hidden (view full) ---

327
328 drm_fb_helper_restore_lut_atomic(mode_set->crtc);
329 funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
330 crtc->y, LEAVE_ATOMIC_MODE_SET);
331 }
332
333 return 0;
334}
294#endif
335EXPORT_SYMBOL(drm_fb_helper_debug_leave);
336#endif /* FREEBSD_NOTYET */
295
296bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
297{
298 bool error = false;
299 int i, ret;
300 for (i = 0; i < fb_helper->crtc_count; i++) {
301 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
337
338bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
339{
340 bool error = false;
341 int i, ret;
342 for (i = 0; i < fb_helper->crtc_count; i++) {
343 struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
302 ret = drm_crtc_helper_set_config(mode_set);
344 ret = mode_set->crtc->funcs->set_config(mode_set);
303 if (ret)
304 error = true;
305 }
306 return error;
307}
345 if (ret)
346 error = true;
347 }
348 return error;
349}
350EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
308
351
309#if 0
310bool drm_fb_helper_force_kernel_mode(void)
352static bool drm_fb_helper_force_kernel_mode(void)
311{
312 bool ret, error = false;
313 struct drm_fb_helper *helper;
314
315 if (list_empty(&kernel_fb_helper_list))
316 return false;
317
318 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
319 if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF)
320 continue;
321
322 ret = drm_fb_helper_restore_fbdev_mode(helper);
323 if (ret)
324 error = true;
325 }
326 return error;
327}
353{
354 bool ret, error = false;
355 struct drm_fb_helper *helper;
356
357 if (list_empty(&kernel_fb_helper_list))
358 return false;
359
360 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
361 if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF)
362 continue;
363
364 ret = drm_fb_helper_restore_fbdev_mode(helper);
365 if (ret)
366 error = true;
367 }
368 return error;
369}
328#endif
329
370
330#if 0
371#if 0 && defined(FREEBSD_NOTYET)
331int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
332 void *panic_str)
333{
372int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
373 void *panic_str)
374{
334 printf("panic occurred, switching back to text console\n");
375 /*
376 * It's a waste of time and effort to switch back to text console
377 * if the kernel should reboot before panic messages can be seen.
378 */
379 if (panic_timeout < 0)
380 return 0;
381
382 pr_err("panic occurred, switching back to text console\n");
335 return drm_fb_helper_force_kernel_mode();
383 return drm_fb_helper_force_kernel_mode();
336 return 0;
337}
384}
385EXPORT_SYMBOL(drm_fb_helper_panic);
338
339static struct notifier_block paniced = {
340 .notifier_call = drm_fb_helper_panic,
341};
386
387static struct notifier_block paniced = {
388 .notifier_call = drm_fb_helper_panic,
389};
390#endif /* FREEBSD_NOTYET */
342
343/**
344 * drm_fb_helper_restore - restore the framebuffer console (kernel) config
345 *
346 * Restore's the kernel's fbcon mode, used for lastclose & panic paths.
347 */
348void drm_fb_helper_restore(void)
349{
350 bool ret;
351 ret = drm_fb_helper_force_kernel_mode();
352 if (ret == true)
353 DRM_ERROR("Failed to restore crtc configuration\n");
354}
391
392/**
393 * drm_fb_helper_restore - restore the framebuffer console (kernel) config
394 *
395 * Restore's the kernel's fbcon mode, used for lastclose & panic paths.
396 */
397void drm_fb_helper_restore(void)
398{
399 bool ret;
400 ret = drm_fb_helper_force_kernel_mode();
401 if (ret == true)
402 DRM_ERROR("Failed to restore crtc configuration\n");
403}
404EXPORT_SYMBOL(drm_fb_helper_restore);
355
405
406#ifdef __linux__
356#ifdef CONFIG_MAGIC_SYSRQ
357static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
358{
359 drm_fb_helper_restore();
360}
361static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
362
363static void drm_fb_helper_sysrq(int dummy1)

--- 6 unchanged lines hidden (view full) ---

370 .help_msg = "force-fb(V)",
371 .action_msg = "Restore framebuffer console",
372};
373#else
374static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
375#endif
376#endif
377
407#ifdef CONFIG_MAGIC_SYSRQ
408static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
409{
410 drm_fb_helper_restore();
411}
412static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
413
414static void drm_fb_helper_sysrq(int dummy1)

--- 6 unchanged lines hidden (view full) ---

421 .help_msg = "force-fb(V)",
422 .action_msg = "Restore framebuffer console",
423};
424#else
425static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
426#endif
427#endif
428
378#if 0
379static void drm_fb_helper_on(struct fb_info *info)
429#if 0 && defined(FREEBSD_NOTYET)
430static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
380{
381 struct drm_fb_helper *fb_helper = info->par;
382 struct drm_device *dev = fb_helper->dev;
383 struct drm_crtc *crtc;
431{
432 struct drm_fb_helper *fb_helper = info->par;
433 struct drm_device *dev = fb_helper->dev;
434 struct drm_crtc *crtc;
384 struct drm_crtc_helper_funcs *crtc_funcs;
385 struct drm_connector *connector;
435 struct drm_connector *connector;
386 struct drm_encoder *encoder;
387 int i, j;
388
389 /*
436 int i, j;
437
438 /*
390 * For each CRTC in this fb, turn the crtc on then,
391 * find all associated encoders and turn them on.
439 * For each CRTC in this fb, turn the connectors on/off.
392 */
393 sx_xlock(&dev->mode_config.mutex);
394 for (i = 0; i < fb_helper->crtc_count; i++) {
395 crtc = fb_helper->crtc_info[i].mode_set.crtc;
440 */
441 sx_xlock(&dev->mode_config.mutex);
442 for (i = 0; i < fb_helper->crtc_count; i++) {
443 crtc = fb_helper->crtc_info[i].mode_set.crtc;
396 crtc_funcs = crtc->helper_private;
397
398 if (!crtc->enabled)
399 continue;
400
444
445 if (!crtc->enabled)
446 continue;
447
401 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
402
403 /* Walk the connectors & encoders on this fb turning them on */
448 /* Walk the connectors & encoders on this fb turning them on/off */
404 for (j = 0; j < fb_helper->connector_count; j++) {
405 connector = fb_helper->connector_info[j]->connector;
449 for (j = 0; j < fb_helper->connector_count; j++) {
450 connector = fb_helper->connector_info[j]->connector;
406 connector->dpms = DRM_MODE_DPMS_ON;
407 drm_connector_property_set_value(connector,
408 dev->mode_config.dpms_property,
409 DRM_MODE_DPMS_ON);
451 connector->funcs->dpms(connector, dpms_mode);
452 drm_object_property_set_value(&connector->base,
453 dev->mode_config.dpms_property, dpms_mode);
410 }
454 }
411 /* Found a CRTC on this fb, now find encoders */
412 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
413 if (encoder->crtc == crtc) {
414 struct drm_encoder_helper_funcs *encoder_funcs;
415
416 encoder_funcs = encoder->helper_private;
417 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
418 }
419 }
420 }
421 sx_xunlock(&dev->mode_config.mutex);
422}
455 }
456 sx_xunlock(&dev->mode_config.mutex);
457}
423#endif
424
458
425#if 0
426static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
427{
428 struct drm_fb_helper *fb_helper = info->par;
429 struct drm_device *dev = fb_helper->dev;
430 struct drm_crtc *crtc;
431 struct drm_crtc_helper_funcs *crtc_funcs;
432 struct drm_connector *connector;
433 struct drm_encoder *encoder;
434 int i, j;
435
436 /*
437 * For each CRTC in this fb, find all associated encoders
438 * and turn them off, then turn off the CRTC.
439 */
440 sx_xlock(&dev->mode_config.mutex);
441 for (i = 0; i < fb_helper->crtc_count; i++) {
442 crtc = fb_helper->crtc_info[i].mode_set.crtc;
443 crtc_funcs = crtc->helper_private;
444
445 if (!crtc->enabled)
446 continue;
447
448 /* Walk the connectors on this fb and mark them off */
449 for (j = 0; j < fb_helper->connector_count; j++) {
450 connector = fb_helper->connector_info[j]->connector;
451 connector->dpms = dpms_mode;
452 drm_connector_property_set_value(connector,
453 dev->mode_config.dpms_property,
454 dpms_mode);
455 }
456 /* Found a CRTC on this fb, now find encoders */
457 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
458 if (encoder->crtc == crtc) {
459 struct drm_encoder_helper_funcs *encoder_funcs;
460
461 encoder_funcs = encoder->helper_private;
462 encoder_funcs->dpms(encoder, dpms_mode);
463 }
464 }
465 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
466 }
467 sx_xunlock(&dev->mode_config.mutex);
468}
469#endif
470
471#if 0
472int drm_fb_helper_blank(int blank, struct fb_info *info)
473{
474 switch (blank) {
475 /* Display: On; HSync: On, VSync: On */
476 case FB_BLANK_UNBLANK:
459int drm_fb_helper_blank(int blank, struct fb_info *info)
460{
461 switch (blank) {
462 /* Display: On; HSync: On, VSync: On */
463 case FB_BLANK_UNBLANK:
477 drm_fb_helper_on(info);
464 drm_fb_helper_dpms(info, DRM_MODE_DPMS_ON);
478 break;
479 /* Display: Off; HSync: On, VSync: On */
480 case FB_BLANK_NORMAL:
465 break;
466 /* Display: Off; HSync: On, VSync: On */
467 case FB_BLANK_NORMAL:
481 drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
468 drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY);
482 break;
483 /* Display: Off; HSync: Off, VSync: On */
484 case FB_BLANK_HSYNC_SUSPEND:
469 break;
470 /* Display: Off; HSync: Off, VSync: On */
471 case FB_BLANK_HSYNC_SUSPEND:
485 drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
472 drm_fb_helper_dpms(info, DRM_MODE_DPMS_STANDBY);
486 break;
487 /* Display: Off; HSync: On, VSync: Off */
488 case FB_BLANK_VSYNC_SUSPEND:
473 break;
474 /* Display: Off; HSync: On, VSync: Off */
475 case FB_BLANK_VSYNC_SUSPEND:
489 drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
476 drm_fb_helper_dpms(info, DRM_MODE_DPMS_SUSPEND);
490 break;
491 /* Display: Off; HSync: Off, VSync: Off */
492 case FB_BLANK_POWERDOWN:
477 break;
478 /* Display: Off; HSync: Off, VSync: Off */
479 case FB_BLANK_POWERDOWN:
493 drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
480 drm_fb_helper_dpms(info, DRM_MODE_DPMS_OFF);
494 break;
495 }
496 return 0;
497}
481 break;
482 }
483 return 0;
484}
498#endif
485EXPORT_SYMBOL(drm_fb_helper_blank);
486#endif /* FREEBSD_NOTYET */
499
500static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
501{
502 int i;
503
504 for (i = 0; i < helper->connector_count; i++)
505 free(helper->connector_info[i], DRM_MEM_KMS);
506 free(helper->connector_info, DRM_MEM_KMS);

--- 11 unchanged lines hidden (view full) ---

518{
519 struct drm_crtc *crtc;
520 int i;
521
522 fb_helper->dev = dev;
523
524 INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
525
487
488static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
489{
490 int i;
491
492 for (i = 0; i < helper->connector_count; i++)
493 free(helper->connector_info[i], DRM_MEM_KMS);
494 free(helper->connector_info, DRM_MEM_KMS);

--- 11 unchanged lines hidden (view full) ---

506{
507 struct drm_crtc *crtc;
508 int i;
509
510 fb_helper->dev = dev;
511
512 INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
513
526 fb_helper->crtc_info = malloc(crtc_count *
527 sizeof(struct drm_fb_helper_crtc), DRM_MEM_KMS, M_WAITOK | M_ZERO);
514 fb_helper->crtc_info = malloc(crtc_count * sizeof(struct drm_fb_helper_crtc),
515 DRM_MEM_KMS, M_NOWAIT | M_ZERO);
516 if (!fb_helper->crtc_info)
517 return -ENOMEM;
528
529 fb_helper->crtc_count = crtc_count;
518
519 fb_helper->crtc_count = crtc_count;
530 fb_helper->connector_info = malloc(dev->mode_config.num_connector *
531 sizeof(struct drm_fb_helper_connector *), DRM_MEM_KMS,
532 M_WAITOK | M_ZERO);
520 fb_helper->connector_info = malloc(dev->mode_config.num_connector * sizeof(struct drm_fb_helper_connector *),
521 DRM_MEM_KMS, M_NOWAIT | M_ZERO);
522 if (!fb_helper->connector_info) {
523 free(fb_helper->crtc_info, DRM_MEM_KMS);
524 return -ENOMEM;
525 }
533 fb_helper->connector_count = 0;
534
535 for (i = 0; i < crtc_count; i++) {
536 fb_helper->crtc_info[i].mode_set.connectors =
526 fb_helper->connector_count = 0;
527
528 for (i = 0; i < crtc_count; i++) {
529 fb_helper->crtc_info[i].mode_set.connectors =
537 malloc(max_conn_count * sizeof(struct drm_connector *),
538 DRM_MEM_KMS, M_WAITOK | M_ZERO);
530 malloc(max_conn_count *
531 sizeof(struct drm_connector *),
532 DRM_MEM_KMS, M_NOWAIT | M_ZERO);
539
533
534 if (!fb_helper->crtc_info[i].mode_set.connectors)
535 goto out_free;
540 fb_helper->crtc_info[i].mode_set.num_connectors = 0;
541 }
542
543 i = 0;
544 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
536 fb_helper->crtc_info[i].mode_set.num_connectors = 0;
537 }
538
539 i = 0;
540 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
545 fb_helper->crtc_info[i].crtc_id = crtc->base.id;
546 fb_helper->crtc_info[i].mode_set.crtc = crtc;
547 i++;
548 }
541 fb_helper->crtc_info[i].mode_set.crtc = crtc;
542 i++;
543 }
549 fb_helper->conn_limit = max_conn_count;
544
550 return 0;
545 return 0;
546out_free:
547 drm_fb_helper_crtc_free(fb_helper);
548 return -ENOMEM;
551}
549}
550EXPORT_SYMBOL(drm_fb_helper_init);
552
553void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
554{
555 if (!list_empty(&fb_helper->kernel_fb_list)) {
556 list_del(&fb_helper->kernel_fb_list);
551
552void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
553{
554 if (!list_empty(&fb_helper->kernel_fb_list)) {
555 list_del(&fb_helper->kernel_fb_list);
556#if 0 && defined(FREEBSD_NOTYET)
557 if (list_empty(&kernel_fb_helper_list)) {
557 if (list_empty(&kernel_fb_helper_list)) {
558#if 0
559 printk(KERN_INFO "drm: unregistered panic notifier\n");
558 pr_info("drm: unregistered panic notifier\n");
560 atomic_notifier_chain_unregister(&panic_notifier_list,
561 &paniced);
562 unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
559 atomic_notifier_chain_unregister(&panic_notifier_list,
560 &paniced);
561 unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
563#endif
564 }
562 }
563#endif /* FREEBSD_NOTYET */
565 }
566
567 drm_fb_helper_crtc_free(fb_helper);
568
569}
564 }
565
566 drm_fb_helper_crtc_free(fb_helper);
567
568}
569EXPORT_SYMBOL(drm_fb_helper_fini);
570
570
571#if 0
571#if 0 && defined(FREEBSD_NOTYET)
572static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
573 u16 blue, u16 regno, struct fb_info *info)
574{
575 struct drm_fb_helper *fb_helper = info->par;
576 struct drm_framebuffer *fb = fb_helper->fb;
577 int pindex;
578
572static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
573 u16 blue, u16 regno, struct fb_info *info)
574{
575 struct drm_fb_helper *fb_helper = info->par;
576 struct drm_framebuffer *fb = fb_helper->fb;
577 int pindex;
578
579 if (info->fix.visual == FB_VISUAL_trueCOLOR) {
579 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
580 u32 *palette;
581 u32 value;
582 /* place color in psuedopalette */
583 if (regno > 16)
584 return -EINVAL;
585 palette = (u32 *)info->pseudo_palette;
586 red >>= (16 - info->var.red.length);
587 green >>= (16 - info->var.green.length);

--- 39 unchanged lines hidden (view full) ---

627 (pindex >> 1) + i);
628 }
629 }
630
631 if (fb->depth != 16)
632 fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
633 return 0;
634}
580 u32 *palette;
581 u32 value;
582 /* place color in psuedopalette */
583 if (regno > 16)
584 return -EINVAL;
585 palette = (u32 *)info->pseudo_palette;
586 red >>= (16 - info->var.red.length);
587 green >>= (16 - info->var.green.length);

--- 39 unchanged lines hidden (view full) ---

627 (pindex >> 1) + i);
628 }
629 }
630
631 if (fb->depth != 16)
632 fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
633 return 0;
634}
635#endif
636
635
637#if 0
638int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
639{
640 struct drm_fb_helper *fb_helper = info->par;
641 struct drm_crtc_helper_funcs *crtc_funcs;
642 u16 *red, *green, *blue, *transp;
643 struct drm_crtc *crtc;
644 int i, j, rc = 0;
645 int start;

--- 21 unchanged lines hidden (view full) ---

667 rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
668 if (rc)
669 return rc;
670 }
671 crtc_funcs->load_lut(crtc);
672 }
673 return rc;
674}
636int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
637{
638 struct drm_fb_helper *fb_helper = info->par;
639 struct drm_crtc_helper_funcs *crtc_funcs;
640 u16 *red, *green, *blue, *transp;
641 struct drm_crtc *crtc;
642 int i, j, rc = 0;
643 int start;

--- 21 unchanged lines hidden (view full) ---

665 rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
666 if (rc)
667 return rc;
668 }
669 crtc_funcs->load_lut(crtc);
670 }
671 return rc;
672}
675#endif
673EXPORT_SYMBOL(drm_fb_helper_setcmap);
676
674
677#if 0
678int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
679 struct fb_info *info)
680{
681 struct drm_fb_helper *fb_helper = info->par;
682 struct drm_framebuffer *fb = fb_helper->fb;
683 int depth;
684
685 if (var->pixclock != 0 || in_dbg_master())

--- 74 unchanged lines hidden (view full) ---

760 var->transp.length = 8;
761 var->transp.offset = 24;
762 break;
763 default:
764 return -EINVAL;
765 }
766 return 0;
767}
675int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
676 struct fb_info *info)
677{
678 struct drm_fb_helper *fb_helper = info->par;
679 struct drm_framebuffer *fb = fb_helper->fb;
680 int depth;
681
682 if (var->pixclock != 0 || in_dbg_master())

--- 74 unchanged lines hidden (view full) ---

757 var->transp.length = 8;
758 var->transp.offset = 24;
759 break;
760 default:
761 return -EINVAL;
762 }
763 return 0;
764}
768#endif
765EXPORT_SYMBOL(drm_fb_helper_check_var);
769
766
770#if 0
771/* this will let fbcon do the mode init */
772int drm_fb_helper_set_par(struct fb_info *info)
773{
774 struct drm_fb_helper *fb_helper = info->par;
775 struct drm_device *dev = fb_helper->dev;
776 struct fb_var_screeninfo *var = &info->var;
777 struct drm_crtc *crtc;
778 int ret;
779 int i;
780
781 if (var->pixclock != 0) {
782 DRM_ERROR("PIXEL CLOCK SET\n");
783 return -EINVAL;
784 }
785
767/* this will let fbcon do the mode init */
768int drm_fb_helper_set_par(struct fb_info *info)
769{
770 struct drm_fb_helper *fb_helper = info->par;
771 struct drm_device *dev = fb_helper->dev;
772 struct fb_var_screeninfo *var = &info->var;
773 struct drm_crtc *crtc;
774 int ret;
775 int i;
776
777 if (var->pixclock != 0) {
778 DRM_ERROR("PIXEL CLOCK SET\n");
779 return -EINVAL;
780 }
781
786 mutex_lock(&dev->mode_config.mutex);
782 sx_xlock(&dev->mode_config.mutex);
787 for (i = 0; i < fb_helper->crtc_count; i++) {
788 crtc = fb_helper->crtc_info[i].mode_set.crtc;
789 ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
790 if (ret) {
783 for (i = 0; i < fb_helper->crtc_count; i++) {
784 crtc = fb_helper->crtc_info[i].mode_set.crtc;
785 ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
786 if (ret) {
791 mutex_unlock(&dev->mode_config.mutex);
787 sx_xunlock(&dev->mode_config.mutex);
792 return ret;
793 }
794 }
788 return ret;
789 }
790 }
795 mutex_unlock(&dev->mode_config.mutex);
791 sx_xunlock(&dev->mode_config.mutex);
796
797 if (fb_helper->delayed_hotplug) {
798 fb_helper->delayed_hotplug = false;
799 drm_fb_helper_hotplug_event(fb_helper);
800 }
801 return 0;
802}
792
793 if (fb_helper->delayed_hotplug) {
794 fb_helper->delayed_hotplug = false;
795 drm_fb_helper_hotplug_event(fb_helper);
796 }
797 return 0;
798}
803#endif
799EXPORT_SYMBOL(drm_fb_helper_set_par);
804
800
805#if 0
806int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
807 struct fb_info *info)
808{
809 struct drm_fb_helper *fb_helper = info->par;
810 struct drm_device *dev = fb_helper->dev;
811 struct drm_mode_set *modeset;
812 struct drm_crtc *crtc;
813 int ret = 0;
814 int i;
815
801int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
802 struct fb_info *info)
803{
804 struct drm_fb_helper *fb_helper = info->par;
805 struct drm_device *dev = fb_helper->dev;
806 struct drm_mode_set *modeset;
807 struct drm_crtc *crtc;
808 int ret = 0;
809 int i;
810
816 mutex_lock(&dev->mode_config.mutex);
811 sx_xlock(&dev->mode_config.mutex);
817 for (i = 0; i < fb_helper->crtc_count; i++) {
818 crtc = fb_helper->crtc_info[i].mode_set.crtc;
819
820 modeset = &fb_helper->crtc_info[i].mode_set;
821
822 modeset->x = var->xoffset;
823 modeset->y = var->yoffset;
824
825 if (modeset->num_connectors) {
826 ret = crtc->funcs->set_config(modeset);
827 if (!ret) {
828 info->var.xoffset = var->xoffset;
829 info->var.yoffset = var->yoffset;
830 }
831 }
832 }
812 for (i = 0; i < fb_helper->crtc_count; i++) {
813 crtc = fb_helper->crtc_info[i].mode_set.crtc;
814
815 modeset = &fb_helper->crtc_info[i].mode_set;
816
817 modeset->x = var->xoffset;
818 modeset->y = var->yoffset;
819
820 if (modeset->num_connectors) {
821 ret = crtc->funcs->set_config(modeset);
822 if (!ret) {
823 info->var.xoffset = var->xoffset;
824 info->var.yoffset = var->yoffset;
825 }
826 }
827 }
833 mutex_unlock(&dev->mode_config.mutex);
828 sx_xunlock(&dev->mode_config.mutex);
834 return ret;
835}
829 return ret;
830}
836#endif
831EXPORT_SYMBOL(drm_fb_helper_pan_display);
832#endif /* FREEBSD_NOTYET */
837
838int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
839 int preferred_bpp)
840{
841 int new_fb = 0;
842 int crtc_count = 0;
843 int i;
844 struct fb_info *info;
845 struct drm_fb_helper_surface_size sizes;
846 int gamma_size = 0;
833
834int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
835 int preferred_bpp)
836{
837 int new_fb = 0;
838 int crtc_count = 0;
839 int i;
840 struct fb_info *info;
841 struct drm_fb_helper_surface_size sizes;
842 int gamma_size = 0;
847 struct vt_kms_softc *sc;
843#if defined(__FreeBSD__)
848 device_t kdev;
844 device_t kdev;
845#endif
849
850 memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
851 sizes.surface_depth = 24;
852 sizes.surface_bpp = 32;
853 sizes.fb_width = (unsigned)-1;
854 sizes.fb_height = (unsigned)-1;
855
856 /* if driver picks 8 or 16 by default use that
857 for both depth/bpp */
846
847 memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
848 sizes.surface_depth = 24;
849 sizes.surface_bpp = 32;
850 sizes.fb_width = (unsigned)-1;
851 sizes.fb_height = (unsigned)-1;
852
853 /* if driver picks 8 or 16 by default use that
854 for both depth/bpp */
858 if (preferred_bpp != sizes.surface_bpp) {
855 if (preferred_bpp != sizes.surface_bpp)
859 sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
856 sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
860 }
857
861 /* first up get a count of crtcs now in use and new min/maxes width/heights */
862 for (i = 0; i < fb_helper->connector_count; i++) {
863 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
864 struct drm_cmdline_mode *cmdline_mode;
865
866 cmdline_mode = &fb_helper_conn->cmdline_mode;
867
868 if (cmdline_mode->bpp_specified) {

--- 48 unchanged lines hidden (view full) ---

917 sizes.fb_height = sizes.surface_height = 768;
918 }
919
920 /* push down into drivers */
921 new_fb = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
922 if (new_fb < 0)
923 return new_fb;
924
858 /* first up get a count of crtcs now in use and new min/maxes width/heights */
859 for (i = 0; i < fb_helper->connector_count; i++) {
860 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
861 struct drm_cmdline_mode *cmdline_mode;
862
863 cmdline_mode = &fb_helper_conn->cmdline_mode;
864
865 if (cmdline_mode->bpp_specified) {

--- 48 unchanged lines hidden (view full) ---

914 sizes.fb_height = sizes.surface_height = 768;
915 }
916
917 /* push down into drivers */
918 new_fb = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
919 if (new_fb < 0)
920 return new_fb;
921
925 sc = malloc(sizeof(struct vt_kms_softc), DRM_MEM_KMS,
926 M_WAITOK | M_ZERO);
927 sc->fb_helper = fb_helper;
928 TASK_INIT(&sc->fb_mode_task, 0, vt_restore_fbdev_mode, sc);
929
930 info = fb_helper->fbdev;
931
922 info = fb_helper->fbdev;
923
932 info->fb_name = device_get_nameunit(fb_helper->dev->device);
933 info->fb_depth = fb_helper->fb->bits_per_pixel;
934 info->fb_height = fb_helper->fb->height;
935 info->fb_width = fb_helper->fb->width;
936 info->fb_stride = fb_helper->fb->pitches[0];
937 info->fb_priv = sc;
938 info->enter = &vt_kms_postswitch;
939
940 kdev = fb_helper->dev->device;
924 kdev = fb_helper->dev->dev;
941 info->fb_video_dev = device_get_parent(kdev);
942
943 /* set the fb pointer */
925 info->fb_video_dev = device_get_parent(kdev);
926
927 /* set the fb pointer */
944 for (i = 0; i < fb_helper->crtc_count; i++) {
928 for (i = 0; i < fb_helper->crtc_count; i++)
945 fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
929 fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
946 }
947
930
931#if defined(__FreeBSD__)
948 if (new_fb) {
949 int ret;
950
951 info->fb_fbd_dev = device_add_child(kdev, "fbd",
952 device_get_unit(kdev));
953 if (info->fb_fbd_dev != NULL)
954 ret = device_probe_and_attach(info->fb_fbd_dev);
955 else
956 ret = ENODEV;
957#ifdef DEV_VT
958 if (ret != 0)
959 DRM_ERROR("Failed to attach fbd device: %d\n", ret);
960#endif
961 }
932 if (new_fb) {
933 int ret;
934
935 info->fb_fbd_dev = device_add_child(kdev, "fbd",
936 device_get_unit(kdev));
937 if (info->fb_fbd_dev != NULL)
938 ret = device_probe_and_attach(info->fb_fbd_dev);
939 else
940 ret = ENODEV;
941#ifdef DEV_VT
942 if (ret != 0)
943 DRM_ERROR("Failed to attach fbd device: %d\n", ret);
944#endif
945 }
946#else
947 if (new_fb) {
948 info->var.pixclock = 0;
949 if (register_framebuffer(info) < 0)
950 return -EINVAL;
951
952 dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n",
953 info->node, info->fix.id);
954
955 } else {
956 drm_fb_helper_set_par(info);
957 }
958#endif
959
960#if 0 && defined(FREEBSD_NOTYET)
961 /* Switch back to kernel console on panic */
962 /* multi card linked list maybe */
963 if (list_empty(&kernel_fb_helper_list)) {
964 dev_info(fb_helper->dev->dev, "registered panic notifier\n");
965 atomic_notifier_chain_register(&panic_notifier_list,
966 &paniced);
967 register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
968 }
969#endif /* FREEBSD_NOTYET */
970 if (new_fb)
971 list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
972
962 return 0;
963}
973 return 0;
974}
975EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
964
976
965#if 0
966void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
967 uint32_t depth)
968{
977void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
978 uint32_t depth)
979{
969 info->fix.type = FB_TYPE_PACKED_PIXELS;
970 info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
971 FB_VISUAL_trueCOLOR;
972 info->fix.mmio_start = 0;
973 info->fix.mmio_len = 0;
974 info->fix.type_aux = 0;
975 info->fix.xpanstep = 1; /* doing it in hw */
976 info->fix.ypanstep = 1; /* doing it in hw */
977 info->fix.ywrapstep = 0;
978 info->fix.accel = FB_ACCEL_NONE;
979 info->fix.type_aux = 0;
980 info->fb_stride = pitch;
980
981
981 info->fix.line_length = pitch;
982 return;
983}
982 return;
983}
984EXPORT_SYMBOL(drm_fb_helper_fill_fix);
984
985void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
986 uint32_t fb_width, uint32_t fb_height)
987{
988 struct drm_framebuffer *fb = fb_helper->fb;
985
986void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
987 uint32_t fb_width, uint32_t fb_height)
988{
989 struct drm_framebuffer *fb = fb_helper->fb;
989 info->pseudo_palette = fb_helper->pseudo_palette;
990 info->var.xres_virtual = fb->width;
991 info->var.yres_virtual = fb->height;
992 info->var.bits_per_pixel = fb->bits_per_pixel;
993 info->var.accel_flags = FB_ACCELF_TEXT;
994 info->var.xoffset = 0;
995 info->var.yoffset = 0;
996 info->var.activate = FB_ACTIVATE_NOW;
997 info->var.height = -1;
998 info->var.width = -1;
990 struct vt_kms_softc *sc;
999
991
1000 switch (fb->depth) {
1001 case 8:
1002 info->var.red.offset = 0;
1003 info->var.green.offset = 0;
1004 info->var.blue.offset = 0;
1005 info->var.red.length = 8; /* 8bit DAC */
1006 info->var.green.length = 8;
1007 info->var.blue.length = 8;
1008 info->var.transp.offset = 0;
1009 info->var.transp.length = 0;
1010 break;
1011 case 15:
1012 info->var.red.offset = 10;
1013 info->var.green.offset = 5;
1014 info->var.blue.offset = 0;
1015 info->var.red.length = 5;
1016 info->var.green.length = 5;
1017 info->var.blue.length = 5;
1018 info->var.transp.offset = 15;
1019 info->var.transp.length = 1;
1020 break;
1021 case 16:
1022 info->var.red.offset = 11;
1023 info->var.green.offset = 5;
1024 info->var.blue.offset = 0;
1025 info->var.red.length = 5;
1026 info->var.green.length = 6;
1027 info->var.blue.length = 5;
1028 info->var.transp.offset = 0;
1029 break;
1030 case 24:
1031 info->var.red.offset = 16;
1032 info->var.green.offset = 8;
1033 info->var.blue.offset = 0;
1034 info->var.red.length = 8;
1035 info->var.green.length = 8;
1036 info->var.blue.length = 8;
1037 info->var.transp.offset = 0;
1038 info->var.transp.length = 0;
1039 break;
1040 case 32:
1041 info->var.red.offset = 16;
1042 info->var.green.offset = 8;
1043 info->var.blue.offset = 0;
1044 info->var.red.length = 8;
1045 info->var.green.length = 8;
1046 info->var.blue.length = 8;
1047 info->var.transp.offset = 24;
1048 info->var.transp.length = 8;
1049 break;
1050 default:
1051 break;
1052 }
992 info->fb_name = device_get_nameunit(fb_helper->dev->dev);
993 info->fb_width = fb->width;
994 info->fb_height = fb->height;
995 info->fb_depth = fb->bits_per_pixel;
1053
996
1054 info->var.xres = fb_width;
1055 info->var.yres = fb_height;
997 sc = (struct vt_kms_softc *)info->fb_priv;
998 sc->fb_helper = fb_helper;
1056}
999}
1057#endif
1000EXPORT_SYMBOL(drm_fb_helper_fill_var);
1058
1059static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
1060 uint32_t maxX,
1061 uint32_t maxY)
1062{
1063 struct drm_connector *connector;
1064 int count = 0;
1065 int i;

--- 30 unchanged lines hidden (view full) ---

1096static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
1097 int width, int height)
1098{
1099 struct drm_cmdline_mode *cmdline_mode;
1100 struct drm_display_mode *mode = NULL;
1101
1102 cmdline_mode = &fb_helper_conn->cmdline_mode;
1103 if (cmdline_mode->specified == false)
1001
1002static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
1003 uint32_t maxX,
1004 uint32_t maxY)
1005{
1006 struct drm_connector *connector;
1007 int count = 0;
1008 int i;

--- 30 unchanged lines hidden (view full) ---

1039static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
1040 int width, int height)
1041{
1042 struct drm_cmdline_mode *cmdline_mode;
1043 struct drm_display_mode *mode = NULL;
1044
1045 cmdline_mode = &fb_helper_conn->cmdline_mode;
1046 if (cmdline_mode->specified == false)
1104 return (NULL);
1047 return mode;
1105
1106 /* attempt to find a matching mode in the list of modes
1107 * we have gotten so far, if not add a CVT mode that conforms
1108 */
1109 if (cmdline_mode->rb || cmdline_mode->margins)
1110 goto create_mode;
1111
1112 list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {

--- 10 unchanged lines hidden (view full) ---

1123 if (cmdline_mode->interlace) {
1124 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
1125 continue;
1126 }
1127 return mode;
1128 }
1129
1130create_mode:
1048
1049 /* attempt to find a matching mode in the list of modes
1050 * we have gotten so far, if not add a CVT mode that conforms
1051 */
1052 if (cmdline_mode->rb || cmdline_mode->margins)
1053 goto create_mode;
1054
1055 list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {

--- 10 unchanged lines hidden (view full) ---

1066 if (cmdline_mode->interlace) {
1067 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
1068 continue;
1069 }
1070 return mode;
1071 }
1072
1073create_mode:
1131 if (cmdline_mode->cvt)
1132 mode = drm_cvt_mode(fb_helper_conn->connector->dev,
1133 cmdline_mode->xres, cmdline_mode->yres,
1134 cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
1135 cmdline_mode->rb, cmdline_mode->interlace,
1136 cmdline_mode->margins);
1137 else
1138 mode = drm_gtf_mode(fb_helper_conn->connector->dev,
1139 cmdline_mode->xres, cmdline_mode->yres,
1140 cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
1141 cmdline_mode->interlace,
1142 cmdline_mode->margins);
1143 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1074 mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
1075 cmdline_mode);
1144 list_add(&mode->head, &fb_helper_conn->connector->modes);
1145 return mode;
1146}
1147
1148static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
1149{
1150 bool enable;
1151
1076 list_add(&mode->head, &fb_helper_conn->connector->modes);
1077 return mode;
1078}
1079
1080static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
1081{
1082 bool enable;
1083
1152 if (strict) {
1084 if (strict)
1153 enable = connector->status == connector_status_connected;
1085 enable = connector->status == connector_status_connected;
1154 } else {
1086 else
1155 enable = connector->status != connector_status_disconnected;
1087 enable = connector->status != connector_status_disconnected;
1156 }
1088
1157 return enable;
1158}
1159
1160static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
1161 bool *enabled)
1162{
1163 bool any_enabled = false;
1164 struct drm_connector *connector;

--- 146 unchanged lines hidden (view full) ---

1311
1312 best_crtcs[n] = NULL;
1313 best_crtc = NULL;
1314 best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height);
1315 if (modes[n] == NULL)
1316 return best_score;
1317
1318 crtcs = malloc(dev->mode_config.num_connector *
1089 return enable;
1090}
1091
1092static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
1093 bool *enabled)
1094{
1095 bool any_enabled = false;
1096 struct drm_connector *connector;

--- 146 unchanged lines hidden (view full) ---

1243
1244 best_crtcs[n] = NULL;
1245 best_crtc = NULL;
1246 best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height);
1247 if (modes[n] == NULL)
1248 return best_score;
1249
1250 crtcs = malloc(dev->mode_config.num_connector *
1319 sizeof(struct drm_fb_helper_crtc *), DRM_MEM_KMS,
1320 M_WAITOK | M_ZERO);
1251 sizeof(struct drm_fb_helper_crtc *), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
1252 if (!crtcs)
1253 return best_score;
1321
1322 my_score = 1;
1323 if (connector->status == connector_status_connected)
1324 my_score++;
1325 if (drm_has_cmdline_mode(fb_helper_conn))
1326 my_score++;
1327 if (drm_has_preferred_mode(fb_helper_conn, width, height))
1328 my_score++;
1329
1330 connector_funcs = connector->helper_private;
1331 encoder = connector_funcs->best_encoder(connector);
1332 if (!encoder)
1333 goto out;
1334
1335 /* select a crtc for this connector and then attempt to configure
1336 remaining connectors */
1337 for (c = 0; c < fb_helper->crtc_count; c++) {
1338 crtc = &fb_helper->crtc_info[c];
1339
1254
1255 my_score = 1;
1256 if (connector->status == connector_status_connected)
1257 my_score++;
1258 if (drm_has_cmdline_mode(fb_helper_conn))
1259 my_score++;
1260 if (drm_has_preferred_mode(fb_helper_conn, width, height))
1261 my_score++;
1262
1263 connector_funcs = connector->helper_private;
1264 encoder = connector_funcs->best_encoder(connector);
1265 if (!encoder)
1266 goto out;
1267
1268 /* select a crtc for this connector and then attempt to configure
1269 remaining connectors */
1270 for (c = 0; c < fb_helper->crtc_count; c++) {
1271 crtc = &fb_helper->crtc_info[c];
1272
1340 if ((encoder->possible_crtcs & (1 << c)) == 0) {
1273 if ((encoder->possible_crtcs & (1 << c)) == 0)
1341 continue;
1274 continue;
1342 }
1343
1344 for (o = 0; o < n; o++)
1345 if (best_crtcs[o] == crtc)
1346 break;
1347
1348 if (o < n) {
1349 /* ignore cloning unless only a single crtc */
1350 if (fb_helper->crtc_count > 1)

--- 20 unchanged lines hidden (view full) ---

1371 return best_score;
1372}
1373
1374static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
1375{
1376 struct drm_device *dev = fb_helper->dev;
1377 struct drm_fb_helper_crtc **crtcs;
1378 struct drm_display_mode **modes;
1275
1276 for (o = 0; o < n; o++)
1277 if (best_crtcs[o] == crtc)
1278 break;
1279
1280 if (o < n) {
1281 /* ignore cloning unless only a single crtc */
1282 if (fb_helper->crtc_count > 1)

--- 20 unchanged lines hidden (view full) ---

1303 return best_score;
1304}
1305
1306static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
1307{
1308 struct drm_device *dev = fb_helper->dev;
1309 struct drm_fb_helper_crtc **crtcs;
1310 struct drm_display_mode **modes;
1379 struct drm_encoder *encoder;
1380 struct drm_mode_set *modeset;
1381 bool *enabled;
1382 int width, height;
1383 int i, ret;
1384
1385 DRM_DEBUG_KMS("\n");
1386
1387 width = dev->mode_config.max_width;
1388 height = dev->mode_config.max_height;
1389
1311 struct drm_mode_set *modeset;
1312 bool *enabled;
1313 int width, height;
1314 int i, ret;
1315
1316 DRM_DEBUG_KMS("\n");
1317
1318 width = dev->mode_config.max_width;
1319 height = dev->mode_config.max_height;
1320
1390 /* clean out all the encoder/crtc combos */
1391 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1392 encoder->crtc = NULL;
1393 }
1394
1395 crtcs = malloc(dev->mode_config.num_connector *
1321 crtcs = malloc(dev->mode_config.num_connector *
1396 sizeof(struct drm_fb_helper_crtc *), DRM_MEM_KMS,
1397 M_WAITOK | M_ZERO);
1322 sizeof(struct drm_fb_helper_crtc *), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
1398 modes = malloc(dev->mode_config.num_connector *
1323 modes = malloc(dev->mode_config.num_connector *
1399 sizeof(struct drm_display_mode *), DRM_MEM_KMS,
1400 M_WAITOK | M_ZERO);
1324 sizeof(struct drm_display_mode *), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
1401 enabled = malloc(dev->mode_config.num_connector *
1325 enabled = malloc(dev->mode_config.num_connector *
1402 sizeof(bool), DRM_MEM_KMS, M_WAITOK | M_ZERO);
1326 sizeof(bool), DRM_MEM_KMS, M_NOWAIT | M_ZERO);
1327 if (!crtcs || !modes || !enabled) {
1328 DRM_ERROR("Memory allocation failed\n");
1329 goto out;
1330 }
1403
1331
1332
1404 drm_enable_connectors(fb_helper, enabled);
1405
1406 ret = drm_target_cloned(fb_helper, modes, enabled, width, height);
1407 if (!ret) {
1408 ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
1409 if (!ret)
1410 DRM_ERROR("Unable to find initial modes\n");
1411 }

--- 21 unchanged lines hidden (view full) ---

1433 if (modeset->mode)
1434 drm_mode_destroy(dev, modeset->mode);
1435 modeset->mode = drm_mode_duplicate(dev,
1436 fb_crtc->desired_mode);
1437 modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
1438 }
1439 }
1440
1333 drm_enable_connectors(fb_helper, enabled);
1334
1335 ret = drm_target_cloned(fb_helper, modes, enabled, width, height);
1336 if (!ret) {
1337 ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
1338 if (!ret)
1339 DRM_ERROR("Unable to find initial modes\n");
1340 }

--- 21 unchanged lines hidden (view full) ---

1362 if (modeset->mode)
1363 drm_mode_destroy(dev, modeset->mode);
1364 modeset->mode = drm_mode_duplicate(dev,
1365 fb_crtc->desired_mode);
1366 modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
1367 }
1368 }
1369
1370out:
1441 free(crtcs, DRM_MEM_KMS);
1442 free(modes, DRM_MEM_KMS);
1443 free(enabled, DRM_MEM_KMS);
1444}
1445
1446/**
1447 * drm_helper_initial_config - setup a sane initial connector configuration
1371 free(crtcs, DRM_MEM_KMS);
1372 free(modes, DRM_MEM_KMS);
1373 free(enabled, DRM_MEM_KMS);
1374}
1375
1376/**
1377 * drm_helper_initial_config - setup a sane initial connector configuration
1448 * @dev: DRM device
1378 * @fb_helper: fb_helper device struct
1379 * @bpp_sel: bpp value to use for the framebuffer configuration
1449 *
1450 * LOCKING:
1380 *
1381 * LOCKING:
1451 * Called at init time, must take mode config lock.
1382 * Called at init time by the driver to set up the @fb_helper initial
1383 * configuration, must take the mode config lock.
1452 *
1384 *
1453 * Scan the CRTCs and connectors and try to put together an initial setup.
1385 * Scans the CRTCs and connectors and tries to put together an initial setup.
1454 * At the moment, this is a cloned configuration across all heads with
1455 * a new framebuffer object as the backing store.
1456 *
1457 * RETURNS:
1458 * Zero if everything went ok, nonzero otherwise.
1459 */
1460bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
1461{

--- 6 unchanged lines hidden (view full) ---

1468 drm_fb_helper_parse_command_line(fb_helper);
1469
1470 count = drm_fb_helper_probe_connector_modes(fb_helper,
1471 dev->mode_config.max_width,
1472 dev->mode_config.max_height);
1473 /*
1474 * we shouldn't end up with no modes here.
1475 */
1386 * At the moment, this is a cloned configuration across all heads with
1387 * a new framebuffer object as the backing store.
1388 *
1389 * RETURNS:
1390 * Zero if everything went ok, nonzero otherwise.
1391 */
1392bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
1393{

--- 6 unchanged lines hidden (view full) ---

1400 drm_fb_helper_parse_command_line(fb_helper);
1401
1402 count = drm_fb_helper_probe_connector_modes(fb_helper,
1403 dev->mode_config.max_width,
1404 dev->mode_config.max_height);
1405 /*
1406 * we shouldn't end up with no modes here.
1407 */
1476 if (count == 0) {
1477 printf("No connectors reported connected with modes\n");
1478 }
1408 if (count == 0)
1409 dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n");
1410
1479 drm_setup_crtcs(fb_helper);
1480
1481 return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
1482}
1411 drm_setup_crtcs(fb_helper);
1412
1413 return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
1414}
1415EXPORT_SYMBOL(drm_fb_helper_initial_config);
1483
1416
1417/**
1418 * drm_fb_helper_hotplug_event - respond to a hotplug notification by
1419 * probing all the outputs attached to the fb
1420 * @fb_helper: the drm_fb_helper
1421 *
1422 * LOCKING:
1423 * Called at runtime, must take mode config lock.
1424 *
1425 * Scan the connectors attached to the fb_helper and try to put together a
1426 * setup after *notification of a change in output configuration.
1427 *
1428 * RETURNS:
1429 * 0 on success and a non-zero error code otherwise.
1430 */
1484int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
1485{
1486 struct drm_device *dev = fb_helper->dev;
1487 int count = 0;
1488 u32 max_width, max_height, bpp_sel;
1431int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
1432{
1433 struct drm_device *dev = fb_helper->dev;
1434 int count = 0;
1435 u32 max_width, max_height, bpp_sel;
1489 bool bound = false, crtcs_bound = false;
1436 int bound = 0, crtcs_bound = 0;
1490 struct drm_crtc *crtc;
1491
1492 if (!fb_helper->fb)
1493 return 0;
1494
1495 sx_xlock(&dev->mode_config.mutex);
1496 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1497 if (crtc->fb)
1437 struct drm_crtc *crtc;
1438
1439 if (!fb_helper->fb)
1440 return 0;
1441
1442 sx_xlock(&dev->mode_config.mutex);
1443 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1444 if (crtc->fb)
1498 crtcs_bound = true;
1445 crtcs_bound++;
1499 if (crtc->fb == fb_helper->fb)
1446 if (crtc->fb == fb_helper->fb)
1500 bound = true;
1447 bound++;
1501 }
1502
1448 }
1449
1503 if (!bound && crtcs_bound) {
1450 if (bound < crtcs_bound) {
1504 fb_helper->delayed_hotplug = true;
1505 sx_xunlock(&dev->mode_config.mutex);
1506 return 0;
1507 }
1508 DRM_DEBUG_KMS("\n");
1509
1510 max_width = fb_helper->fb->width;
1511 max_height = fb_helper->fb->height;
1512 bpp_sel = fb_helper->fb->bits_per_pixel;
1513
1514 count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
1515 max_height);
1516 drm_setup_crtcs(fb_helper);
1517 sx_xunlock(&dev->mode_config.mutex);
1518
1519 return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
1520}
1451 fb_helper->delayed_hotplug = true;
1452 sx_xunlock(&dev->mode_config.mutex);
1453 return 0;
1454 }
1455 DRM_DEBUG_KMS("\n");
1456
1457 max_width = fb_helper->fb->width;
1458 max_height = fb_helper->fb->height;
1459 bpp_sel = fb_helper->fb->bits_per_pixel;
1460
1461 count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
1462 max_height);
1463 drm_setup_crtcs(fb_helper);
1464 sx_xunlock(&dev->mode_config.mutex);
1465
1466 return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
1467}
1521
1468EXPORT_SYMBOL(drm_fb_helper_hotplug_event);