2 * Copyright (C) 2008 Maarten Maathuis.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include <acpi/video.h>
29 #include <drm/drm_atomic.h>
30 #include <drm/drm_atomic_helper.h>
31 #include <drm/drm_crtc_helper.h>
32 #include <drm/drm_fb_helper.h>
33 #include <drm/drm_fourcc.h>
34 #include <drm/drm_gem_framebuffer_helper.h>
35 #include <drm/drm_probe_helper.h>
36 #include <drm/drm_vblank.h>
38 #include "nouveau_crtc.h"
39 #include "nouveau_gem.h"
40 #include "nouveau_connector.h"
41 #include "nv50_display.h"
43 #include <nvif/class.h>
44 #include <nvif/if0011.h>
45 #include <nvif/if0013.h>
46 #include <dispnv50/crc.h>
49 nouveau_display_vblank_enable(struct drm_crtc
*crtc
)
51 struct nouveau_crtc
*nv_crtc
;
53 nv_crtc
= nouveau_crtc(crtc
);
54 nvif_event_allow(&nv_crtc
->vblank
);
60 nouveau_display_vblank_disable(struct drm_crtc
*crtc
)
62 struct nouveau_crtc
*nv_crtc
;
64 nv_crtc
= nouveau_crtc(crtc
);
65 nvif_event_block(&nv_crtc
->vblank
);
69 calc(int blanks
, int blanke
, int total
, int line
)
71 if (blanke
>= blanks
) {
83 nouveau_display_scanoutpos_head(struct drm_crtc
*crtc
, int *vpos
, int *hpos
,
84 ktime_t
*stime
, ktime_t
*etime
)
86 struct drm_vblank_crtc
*vblank
= &crtc
->dev
->vblank
[drm_crtc_index(crtc
)];
87 struct nvif_head
*head
= &nouveau_crtc(crtc
)->head
;
88 struct nvif_head_scanoutpos_v0 args
;
95 ret
= nvif_mthd(&head
->object
, NVIF_HEAD_V0_SCANOUTPOS
, &args
, sizeof(args
));
104 if (retry
) ndelay(vblank
->linedur_ns
);
108 *vpos
= calc(args
.vblanks
, args
.vblanke
, args
.vtotal
, args
.vline
);
109 if (stime
) *stime
= ns_to_ktime(args
.time
[0]);
110 if (etime
) *etime
= ns_to_ktime(args
.time
[1]);
116 nouveau_display_scanoutpos(struct drm_crtc
*crtc
,
117 bool in_vblank_irq
, int *vpos
, int *hpos
,
118 ktime_t
*stime
, ktime_t
*etime
,
119 const struct drm_display_mode
*mode
)
121 return nouveau_display_scanoutpos_head(crtc
, vpos
, hpos
,
125 static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs
= {
126 .destroy
= drm_gem_fb_destroy
,
127 .create_handle
= drm_gem_fb_create_handle
,
131 nouveau_decode_mod(struct nouveau_drm
*drm
,
136 struct nouveau_display
*disp
= nouveau_display(drm
->dev
);
137 BUG_ON(!tile_mode
|| !kind
);
139 if (modifier
== DRM_FORMAT_MOD_LINEAR
) {
140 /* tile_mode will not be used in this case */
145 * Extract the block height and kind from the corresponding
146 * modifier fields. See drm_fourcc.h for details.
149 if ((modifier
& (0xffull
<< 12)) == 0ull) {
150 /* Legacy modifier. Translate to this dev's 'kind.' */
151 modifier
|= disp
->format_modifiers
[0] & (0xffull
<< 12);
154 *tile_mode
= (uint32_t)(modifier
& 0xF);
155 *kind
= (uint8_t)((modifier
>> 12) & 0xFF);
157 if (drm
->client
.device
.info
.chipset
>= 0xc0)
163 nouveau_framebuffer_get_layout(struct drm_framebuffer
*fb
,
167 if (fb
->flags
& DRM_MODE_FB_MODIFIERS
) {
168 struct nouveau_drm
*drm
= nouveau_drm(fb
->dev
);
170 nouveau_decode_mod(drm
, fb
->modifier
, tile_mode
, kind
);
172 const struct nouveau_bo
*nvbo
= nouveau_gem_object(fb
->obj
[0]);
174 *tile_mode
= nvbo
->mode
;
179 static const u64 legacy_modifiers
[] = {
180 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
181 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
182 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
183 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
184 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
185 DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),
186 DRM_FORMAT_MOD_INVALID
190 nouveau_validate_decode_mod(struct nouveau_drm
*drm
,
195 struct nouveau_display
*disp
= nouveau_display(drm
->dev
);
198 if (drm
->client
.device
.info
.family
< NV_DEVICE_INFO_V0_TESLA
) {
202 BUG_ON(!disp
->format_modifiers
);
205 (disp
->format_modifiers
[mod
] != DRM_FORMAT_MOD_INVALID
) &&
206 (disp
->format_modifiers
[mod
] != modifier
);
209 if (disp
->format_modifiers
[mod
] == DRM_FORMAT_MOD_INVALID
) {
211 (legacy_modifiers
[mod
] != DRM_FORMAT_MOD_INVALID
) &&
212 (legacy_modifiers
[mod
] != modifier
);
214 if (legacy_modifiers
[mod
] == DRM_FORMAT_MOD_INVALID
)
218 nouveau_decode_mod(drm
, modifier
, tile_mode
, kind
);
223 static inline uint32_t
224 nouveau_get_width_in_blocks(uint32_t stride
)
226 /* GOBs per block in the x direction is always one, and GOBs are
229 static const uint32_t log_block_width
= 6;
231 return (stride
+ (1 << log_block_width
) - 1) >> log_block_width
;
234 static inline uint32_t
235 nouveau_get_height_in_blocks(struct nouveau_drm
*drm
,
237 uint32_t log_block_height_in_gobs
)
239 uint32_t log_gob_height
;
240 uint32_t log_block_height
;
242 BUG_ON(drm
->client
.device
.info
.family
< NV_DEVICE_INFO_V0_TESLA
);
244 if (drm
->client
.device
.info
.family
< NV_DEVICE_INFO_V0_FERMI
)
249 log_block_height
= log_block_height_in_gobs
+ log_gob_height
;
251 return (height
+ (1 << log_block_height
) - 1) >> log_block_height
;
255 nouveau_check_bl_size(struct nouveau_drm
*drm
, struct nouveau_bo
*nvbo
,
256 uint32_t offset
, uint32_t stride
, uint32_t h
,
259 uint32_t gob_size
, bw
, bh
;
262 BUG_ON(drm
->client
.device
.info
.family
< NV_DEVICE_INFO_V0_TESLA
);
264 if (drm
->client
.device
.info
.chipset
>= 0xc0) {
270 if (tile_mode
& 0xFFFFFFF0)
273 if (drm
->client
.device
.info
.family
< NV_DEVICE_INFO_V0_FERMI
)
278 bw
= nouveau_get_width_in_blocks(stride
);
279 bh
= nouveau_get_height_in_blocks(drm
, h
, tile_mode
);
281 bl_size
= bw
* bh
* (1 << tile_mode
) * gob_size
;
283 DRM_DEBUG_KMS("offset=%u stride=%u h=%u tile_mode=0x%02x bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n",
284 offset
, stride
, h
, tile_mode
, bw
, bh
, gob_size
, bl_size
,
287 if (bl_size
+ offset
> nvbo
->bo
.base
.size
)
294 nouveau_framebuffer_new(struct drm_device
*dev
,
295 const struct drm_mode_fb_cmd2
*mode_cmd
,
296 struct drm_gem_object
*gem
,
297 struct drm_framebuffer
**pfb
)
299 struct nouveau_drm
*drm
= nouveau_drm(dev
);
300 struct nouveau_bo
*nvbo
= nouveau_gem_object(gem
);
301 struct drm_framebuffer
*fb
;
302 const struct drm_format_info
*info
;
303 unsigned int height
, i
;
308 /* YUV overlays have special requirements pre-NV50 */
309 if (drm
->client
.device
.info
.family
< NV_DEVICE_INFO_V0_TESLA
&&
311 (mode_cmd
->pixel_format
== DRM_FORMAT_YUYV
||
312 mode_cmd
->pixel_format
== DRM_FORMAT_UYVY
||
313 mode_cmd
->pixel_format
== DRM_FORMAT_NV12
||
314 mode_cmd
->pixel_format
== DRM_FORMAT_NV21
) &&
315 (mode_cmd
->pitches
[0] & 0x3f || /* align 64 */
316 mode_cmd
->pitches
[0] >= 0x10000 || /* at most 64k pitch */
317 (mode_cmd
->pitches
[1] && /* pitches for planes must match */
318 mode_cmd
->pitches
[0] != mode_cmd
->pitches
[1]))) {
319 DRM_DEBUG_KMS("Unsuitable framebuffer: format: %p4cc; pitches: 0x%x\n 0x%x\n",
320 &mode_cmd
->pixel_format
,
321 mode_cmd
->pitches
[0], mode_cmd
->pitches
[1]);
325 if (mode_cmd
->flags
& DRM_MODE_FB_MODIFIERS
) {
326 if (nouveau_validate_decode_mod(drm
, mode_cmd
->modifier
[0],
327 &tile_mode
, &kind
)) {
328 DRM_DEBUG_KMS("Unsupported modifier: 0x%llx\n",
329 mode_cmd
->modifier
[0]);
333 tile_mode
= nvbo
->mode
;
337 info
= drm_get_format_info(dev
, mode_cmd
);
339 for (i
= 0; i
< info
->num_planes
; i
++) {
340 height
= drm_format_info_plane_height(info
,
345 ret
= nouveau_check_bl_size(drm
, nvbo
,
346 mode_cmd
->offsets
[i
],
347 mode_cmd
->pitches
[i
],
352 uint32_t size
= mode_cmd
->pitches
[i
] * height
;
354 if (size
+ mode_cmd
->offsets
[i
] > nvbo
->bo
.base
.size
)
359 if (!(fb
= *pfb
= kzalloc(sizeof(*fb
), GFP_KERNEL
)))
362 drm_helper_mode_fill_fb_struct(dev
, fb
, mode_cmd
);
365 ret
= drm_framebuffer_init(dev
, fb
, &nouveau_framebuffer_funcs
);
371 struct drm_framebuffer
*
372 nouveau_user_framebuffer_create(struct drm_device
*dev
,
373 struct drm_file
*file_priv
,
374 const struct drm_mode_fb_cmd2
*mode_cmd
)
376 struct drm_framebuffer
*fb
;
377 struct drm_gem_object
*gem
;
380 gem
= drm_gem_object_lookup(file_priv
, mode_cmd
->handles
[0]);
382 return ERR_PTR(-ENOENT
);
384 ret
= nouveau_framebuffer_new(dev
, mode_cmd
, gem
, &fb
);
388 drm_gem_object_put(gem
);
392 static const struct drm_mode_config_funcs nouveau_mode_config_funcs
= {
393 .fb_create
= nouveau_user_framebuffer_create
,
394 .output_poll_changed
= drm_fb_helper_output_poll_changed
,
398 struct nouveau_drm_prop_enum_list
{
404 static struct nouveau_drm_prop_enum_list underscan
[] = {
405 { 6, UNDERSCAN_AUTO
, "auto" },
406 { 6, UNDERSCAN_OFF
, "off" },
407 { 6, UNDERSCAN_ON
, "on" },
411 static struct nouveau_drm_prop_enum_list dither_mode
[] = {
412 { 7, DITHERING_MODE_AUTO
, "auto" },
413 { 7, DITHERING_MODE_OFF
, "off" },
414 { 1, DITHERING_MODE_ON
, "on" },
415 { 6, DITHERING_MODE_STATIC2X2
, "static 2x2" },
416 { 6, DITHERING_MODE_DYNAMIC2X2
, "dynamic 2x2" },
417 { 4, DITHERING_MODE_TEMPORAL
, "temporal" },
421 static struct nouveau_drm_prop_enum_list dither_depth
[] = {
422 { 6, DITHERING_DEPTH_AUTO
, "auto" },
423 { 6, DITHERING_DEPTH_6BPC
, "6 bpc" },
424 { 6, DITHERING_DEPTH_8BPC
, "8 bpc" },
428 #define PROP_ENUM(p,gen,n,list) do { \
429 struct nouveau_drm_prop_enum_list *l = (list); \
431 while (l->gen_mask) { \
432 if (l->gen_mask & (1 << (gen))) \
437 p = drm_property_create(dev, DRM_MODE_PROP_ENUM, n, c); \
439 while (p && l->gen_mask) { \
440 if (l->gen_mask & (1 << (gen))) { \
441 drm_property_add_enum(p, l->type, l->name); \
449 nouveau_display_hpd_resume(struct drm_device
*dev
)
451 struct nouveau_drm
*drm
= nouveau_drm(dev
);
453 spin_lock_irq(&drm
->hpd_lock
);
454 drm
->hpd_pending
= ~0;
455 spin_unlock_irq(&drm
->hpd_lock
);
457 schedule_work(&drm
->hpd_work
);
461 nouveau_display_hpd_work(struct work_struct
*work
)
463 struct nouveau_drm
*drm
= container_of(work
, typeof(*drm
), hpd_work
);
464 struct drm_device
*dev
= drm
->dev
;
465 struct drm_connector
*connector
;
466 struct drm_connector_list_iter conn_iter
;
469 struct drm_connector
*first_changed_connector
= NULL
;
471 pm_runtime_get_sync(dev
->dev
);
473 spin_lock_irq(&drm
->hpd_lock
);
474 pending
= drm
->hpd_pending
;
475 drm
->hpd_pending
= 0;
476 spin_unlock_irq(&drm
->hpd_lock
);
478 /* Nothing to do, exit early without updating the last busy counter */
482 mutex_lock(&dev
->mode_config
.mutex
);
483 drm_connector_list_iter_begin(dev
, &conn_iter
);
485 nouveau_for_each_non_mst_connector_iter(connector
, &conn_iter
) {
486 struct nouveau_connector
*nv_connector
= nouveau_connector(connector
);
487 enum drm_connector_status old_status
= connector
->status
;
488 u64 bits
, old_epoch_counter
= connector
->epoch_counter
;
490 if (!(pending
& drm_connector_mask(connector
)))
493 spin_lock_irq(&drm
->hpd_lock
);
494 bits
= nv_connector
->hpd_pending
;
495 nv_connector
->hpd_pending
= 0;
496 spin_unlock_irq(&drm
->hpd_lock
);
498 drm_dbg_kms(dev
, "[CONNECTOR:%d:%s] plug:%d unplug:%d irq:%d\n",
499 connector
->base
.id
, connector
->name
,
500 !!(bits
& NVIF_CONN_EVENT_V0_PLUG
),
501 !!(bits
& NVIF_CONN_EVENT_V0_UNPLUG
),
502 !!(bits
& NVIF_CONN_EVENT_V0_IRQ
));
504 if (bits
& NVIF_CONN_EVENT_V0_IRQ
) {
505 if (nouveau_dp_link_check(nv_connector
))
509 connector
->status
= drm_helper_probe_detect(connector
, NULL
, false);
510 if (old_epoch_counter
== connector
->epoch_counter
)
514 if (!first_changed_connector
) {
515 drm_connector_get(connector
);
516 first_changed_connector
= connector
;
519 drm_dbg_kms(dev
, "[CONNECTOR:%d:%s] status updated from %s to %s (epoch counter %llu->%llu)\n",
520 connector
->base
.id
, connector
->name
,
521 drm_get_connector_status_name(old_status
),
522 drm_get_connector_status_name(connector
->status
),
523 old_epoch_counter
, connector
->epoch_counter
);
526 drm_connector_list_iter_end(&conn_iter
);
527 mutex_unlock(&dev
->mode_config
.mutex
);
530 drm_kms_helper_connector_hotplug_event(first_changed_connector
);
531 else if (changed
> 0)
532 drm_kms_helper_hotplug_event(dev
);
534 if (first_changed_connector
)
535 drm_connector_put(first_changed_connector
);
537 pm_runtime_mark_last_busy(drm
->dev
->dev
);
539 pm_runtime_put_autosuspend(dev
->dev
);
545 nouveau_display_acpi_ntfy(struct notifier_block
*nb
, unsigned long val
,
548 struct nouveau_drm
*drm
= container_of(nb
, typeof(*drm
), acpi_nb
);
549 struct acpi_bus_event
*info
= data
;
552 if (!strcmp(info
->device_class
, ACPI_VIDEO_CLASS
)) {
553 if (info
->type
== ACPI_VIDEO_NOTIFY_PROBE
) {
554 ret
= pm_runtime_get(drm
->dev
->dev
);
555 if (ret
== 1 || ret
== -EACCES
) {
556 /* If the GPU is already awake, or in a state
557 * where we can't wake it up, it can handle
558 * it's own hotplug events.
560 pm_runtime_put_autosuspend(drm
->dev
->dev
);
561 } else if (ret
== 0 || ret
== -EINPROGRESS
) {
562 /* We've started resuming the GPU already, so
563 * it will handle scheduling a full reprobe
566 NV_DEBUG(drm
, "ACPI requested connector reprobe\n");
567 pm_runtime_put_noidle(drm
->dev
->dev
);
569 NV_WARN(drm
, "Dropped ACPI reprobe event due to RPM error: %d\n",
573 /* acpi-video should not generate keypresses for this */
583 nouveau_display_init(struct drm_device
*dev
, bool resume
, bool runtime
)
585 struct nouveau_display
*disp
= nouveau_display(dev
);
586 struct drm_connector
*connector
;
587 struct drm_connector_list_iter conn_iter
;
591 * Enable hotplug interrupts (done as early as possible, since we need
594 drm_connector_list_iter_begin(dev
, &conn_iter
);
595 nouveau_for_each_non_mst_connector_iter(connector
, &conn_iter
) {
596 struct nouveau_connector
*conn
= nouveau_connector(connector
);
597 nvif_event_allow(&conn
->hpd
);
598 nvif_event_allow(&conn
->irq
);
600 drm_connector_list_iter_end(&conn_iter
);
602 ret
= disp
->init(dev
, resume
, runtime
);
606 /* enable connector detection and polling for connectors without HPD
609 drm_kms_helper_poll_enable(dev
);
615 nouveau_display_fini(struct drm_device
*dev
, bool suspend
, bool runtime
)
617 struct nouveau_display
*disp
= nouveau_display(dev
);
618 struct nouveau_drm
*drm
= nouveau_drm(dev
);
619 struct drm_connector
*connector
;
620 struct drm_connector_list_iter conn_iter
;
623 if (drm_drv_uses_atomic_modeset(dev
))
624 drm_atomic_helper_shutdown(dev
);
626 drm_helper_force_disable_all(dev
);
629 /* disable hotplug interrupts */
630 drm_connector_list_iter_begin(dev
, &conn_iter
);
631 nouveau_for_each_non_mst_connector_iter(connector
, &conn_iter
) {
632 struct nouveau_connector
*conn
= nouveau_connector(connector
);
633 nvif_event_block(&conn
->irq
);
634 nvif_event_block(&conn
->hpd
);
636 drm_connector_list_iter_end(&conn_iter
);
639 cancel_work_sync(&drm
->hpd_work
);
641 drm_kms_helper_poll_disable(dev
);
642 disp
->fini(dev
, runtime
, suspend
);
646 nouveau_display_create_properties(struct drm_device
*dev
)
648 struct nouveau_display
*disp
= nouveau_display(dev
);
651 if (disp
->disp
.object
.oclass
< NV50_DISP
)
654 if (disp
->disp
.object
.oclass
< GF110_DISP
)
659 PROP_ENUM(disp
->dithering_mode
, gen
, "dithering mode", dither_mode
);
660 PROP_ENUM(disp
->dithering_depth
, gen
, "dithering depth", dither_depth
);
661 PROP_ENUM(disp
->underscan_property
, gen
, "underscan", underscan
);
663 disp
->underscan_hborder_property
=
664 drm_property_create_range(dev
, 0, "underscan hborder", 0, 128);
666 disp
->underscan_vborder_property
=
667 drm_property_create_range(dev
, 0, "underscan vborder", 0, 128);
673 disp
->vibrant_hue_property
=
674 drm_property_create_range(dev
, 0, "vibrant hue", 0, 180);
677 disp
->color_vibrance_property
=
678 drm_property_create_range(dev
, 0, "color vibrance", 0, 200);
682 nouveau_display_create(struct drm_device
*dev
)
684 struct nouveau_drm
*drm
= nouveau_drm(dev
);
685 struct nouveau_display
*disp
;
688 disp
= drm
->display
= kzalloc(sizeof(*disp
), GFP_KERNEL
);
692 drm_mode_config_init(dev
);
693 drm_mode_create_scaling_mode_property(dev
);
694 drm_mode_create_dvi_i_properties(dev
);
696 dev
->mode_config
.funcs
= &nouveau_mode_config_funcs
;
698 dev
->mode_config
.min_width
= 0;
699 dev
->mode_config
.min_height
= 0;
700 if (drm
->client
.device
.info
.family
< NV_DEVICE_INFO_V0_CELSIUS
) {
701 dev
->mode_config
.max_width
= 2048;
702 dev
->mode_config
.max_height
= 2048;
704 if (drm
->client
.device
.info
.family
< NV_DEVICE_INFO_V0_TESLA
) {
705 dev
->mode_config
.max_width
= 4096;
706 dev
->mode_config
.max_height
= 4096;
708 if (drm
->client
.device
.info
.family
< NV_DEVICE_INFO_V0_FERMI
) {
709 dev
->mode_config
.max_width
= 8192;
710 dev
->mode_config
.max_height
= 8192;
712 dev
->mode_config
.max_width
= 16384;
713 dev
->mode_config
.max_height
= 16384;
716 dev
->mode_config
.preferred_depth
= 24;
717 dev
->mode_config
.prefer_shadow
= 1;
719 if (drm
->client
.device
.info
.chipset
< 0x11)
720 dev
->mode_config
.async_page_flip
= false;
722 dev
->mode_config
.async_page_flip
= true;
724 drm_kms_helper_poll_init(dev
);
725 drm_kms_helper_poll_disable(dev
);
727 if (nouveau_modeset
!= 2) {
728 ret
= nvif_disp_ctor(&drm
->client
.device
, "kmsDisp", 0, &disp
->disp
);
730 if (ret
== -ENODEV
) {
732 goto disp_create_err
;
735 if (!ret
&& (disp
->disp
.outp_mask
|| drm
->vbios
.dcb
.entries
)) {
736 nouveau_display_create_properties(dev
);
737 if (disp
->disp
.object
.oclass
< NV50_DISP
) {
738 dev
->mode_config
.fb_modifiers_not_supported
= true;
739 ret
= nv04_display_create(dev
);
741 ret
= nv50_display_create(dev
);
749 goto disp_create_err
;
751 drm_mode_config_reset(dev
);
753 if (dev
->mode_config
.num_crtc
) {
754 ret
= drm_vblank_init(dev
, dev
->mode_config
.num_crtc
);
758 if (disp
->disp
.object
.oclass
>= NV50_DISP
)
762 INIT_WORK(&drm
->hpd_work
, nouveau_display_hpd_work
);
763 spin_lock_init(&drm
->hpd_lock
);
765 drm
->acpi_nb
.notifier_call
= nouveau_display_acpi_ntfy
;
766 register_acpi_notifier(&drm
->acpi_nb
);
774 drm_kms_helper_poll_fini(dev
);
775 drm_mode_config_cleanup(dev
);
780 nouveau_display_destroy(struct drm_device
*dev
)
782 struct nouveau_display
*disp
= nouveau_display(dev
);
783 struct nouveau_drm
*drm
= nouveau_drm(dev
);
786 unregister_acpi_notifier(&drm
->acpi_nb
);
789 drm_kms_helper_poll_fini(dev
);
790 drm_mode_config_cleanup(dev
);
795 nvif_disp_dtor(&disp
->disp
);
802 nouveau_display_suspend(struct drm_device
*dev
, bool runtime
)
804 struct nouveau_display
*disp
= nouveau_display(dev
);
806 /* Disable console. */
807 drm_fb_helper_set_suspend_unlocked(dev
->fb_helper
, true);
809 if (drm_drv_uses_atomic_modeset(dev
)) {
811 disp
->suspend
= drm_atomic_helper_suspend(dev
);
812 if (IS_ERR(disp
->suspend
)) {
813 int ret
= PTR_ERR(disp
->suspend
);
814 disp
->suspend
= NULL
;
820 nouveau_display_fini(dev
, true, runtime
);
825 nouveau_display_resume(struct drm_device
*dev
, bool runtime
)
827 struct nouveau_display
*disp
= nouveau_display(dev
);
829 nouveau_display_init(dev
, true, runtime
);
831 if (drm_drv_uses_atomic_modeset(dev
)) {
833 drm_atomic_helper_resume(dev
, disp
->suspend
);
834 disp
->suspend
= NULL
;
838 /* Enable console. */
839 drm_fb_helper_set_suspend_unlocked(dev
->fb_helper
, false);
843 nouveau_display_dumb_create(struct drm_file
*file_priv
, struct drm_device
*dev
,
844 struct drm_mode_create_dumb
*args
)
846 struct nouveau_cli
*cli
= nouveau_cli(file_priv
);
847 struct nouveau_bo
*bo
;
851 args
->pitch
= roundup(args
->width
* (args
->bpp
/ 8), 256);
852 args
->size
= args
->pitch
* args
->height
;
853 args
->size
= roundup(args
->size
, PAGE_SIZE
);
855 /* Use VRAM if there is any ; otherwise fallback to system memory */
856 if (nouveau_drm(dev
)->client
.device
.info
.ram_size
!= 0)
857 domain
= NOUVEAU_GEM_DOMAIN_VRAM
;
859 domain
= NOUVEAU_GEM_DOMAIN_GART
;
861 ret
= nouveau_gem_new(cli
, args
->size
, 0, domain
, 0, 0, &bo
);
865 ret
= drm_gem_handle_create(file_priv
, &bo
->bo
.base
, &args
->handle
);
866 drm_gem_object_put(&bo
->bo
.base
);