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); |