diff options
author | Dave Airlie <airlied@redhat.com> | 2016-02-18 19:57:44 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-02-18 19:57:44 -0500 |
commit | 08244c00859f25036417ea7b790cfa73e43443fc (patch) | |
tree | 051d7d2572f3a5569514d92407b9dd38e5c431c2 | |
parent | 5443ce86fa37e7d3cc63d2067d05e3388fdeec17 (diff) | |
parent | a6ddd2f1b99f1c00b4e00289b13c3e451c7130b0 (diff) |
Merge tag 'topic/drm-misc-2016-02-18' of git://anongit.freedesktop.org/drm-intel into drm-next
Misc stuff all over:
- more mode_fixup removal from Carlos, there's another final pile still
left.
- final bits of vgaswitcheroo from Lukas for apple gmux, we're still
discussing an api cleanup patch to make it a bit more abuse-safe as a
follow-up
- dp aux interface for userspace for tools&tests from Rafael Antognolli
- actual interface parts for dma-buf flushing for userspace mmap
- few small bits all over
- vgaswitcheroo support for apple gmux from Lukas Wunner
- checks for ->mode_fixup in non-atomic helpers from Carlos Palminha, plus
removing dummy funcs from drivers. Carlos promised to follow up with
more, since there's lots more silly dummy functions around.
- dma-buf patches from Tiago, except the ioctl itself (that needed a
respin to address review from David Herrmann)
- encoder mask for atomic from Maarten
- bunch of random things all over.
* tag 'topic/drm-misc-2016-02-18' of git://anongit.freedesktop.org/drm-intel: (57 commits)
drm/udl: Use module_usb_driver
drm: fixes crct set_mode when crtc mode_fixup is null.
drm/tilcdc: removed optional dummy encoder mode_fixup function.
drm/sti: removed optional dummy encoder mode_fixup function.
drm/rockchip: removed optional dummy encoder mode_fixup function.
drm/qxl: removed optional dummy encoder mode_fixup function.
drm/mgag200: removed optional dummy encoder mode_fixup function.
drm/msm/mdp: removed optional dummy encoder mode_fixup function.
drm/imx: removed optional dummy encoder mode_fixup function.
drm/gma500: removed optional dummy encoder mode_fixup function.
drm/radeon: removed optional dummy encoder mode_fixup function.
drm/cirrus: removed optional dummy encoder mode_fixup function.
drm/bochs: removed optional dummy encoder mode_fixup function.
drm/ast: removed optional dummy encoder mode_fixup function.
drm/amdgpu: removed optional dummy encoder mode_fixup function.
drm/exynos: removed optional dummy encoder mode_fixup function.
drm/udl: removed optional dummy encoder mode_fixup function.
drm/virtio: removed optional dummy encoder mode_fixup function.
drm/fb_helper: Use add_one_connector in add_all_connectors.
drm/fb_helper: Use correct allocation count for arrays.
...
83 files changed, 1260 insertions, 428 deletions
diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index 49c97913c5ae..fe6b36a2fd98 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl | |||
@@ -3422,6 +3422,7 @@ int num_ioctls;</synopsis> | |||
3422 | </sect1> | 3422 | </sect1> |
3423 | <sect1> | 3423 | <sect1> |
3424 | <title>Public constants</title> | 3424 | <title>Public constants</title> |
3425 | !Finclude/linux/vga_switcheroo.h vga_switcheroo_handler_flags_t | ||
3425 | !Finclude/linux/vga_switcheroo.h vga_switcheroo_client_id | 3426 | !Finclude/linux/vga_switcheroo.h vga_switcheroo_client_id |
3426 | !Finclude/linux/vga_switcheroo.h vga_switcheroo_state | 3427 | !Finclude/linux/vga_switcheroo.h vga_switcheroo_state |
3427 | </sect1> | 3428 | </sect1> |
@@ -3450,6 +3451,10 @@ int num_ioctls;</synopsis> | |||
3450 | <title>Backlight control</title> | 3451 | <title>Backlight control</title> |
3451 | !Pdrivers/platform/x86/apple-gmux.c Backlight control | 3452 | !Pdrivers/platform/x86/apple-gmux.c Backlight control |
3452 | </sect2> | 3453 | </sect2> |
3454 | <sect2> | ||
3455 | <title>Public functions</title> | ||
3456 | !Iinclude/linux/apple-gmux.h | ||
3457 | </sect2> | ||
3453 | </sect1> | 3458 | </sect1> |
3454 | </chapter> | 3459 | </chapter> |
3455 | 3460 | ||
diff --git a/Documentation/dma-buf-sharing.txt b/Documentation/dma-buf-sharing.txt index 480c8de3c2c4..32ac32e773e1 100644 --- a/Documentation/dma-buf-sharing.txt +++ b/Documentation/dma-buf-sharing.txt | |||
@@ -257,17 +257,15 @@ Access to a dma_buf from the kernel context involves three steps: | |||
257 | 257 | ||
258 | Interface: | 258 | Interface: |
259 | int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, | 259 | int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, |
260 | size_t start, size_t len, | ||
261 | enum dma_data_direction direction) | 260 | enum dma_data_direction direction) |
262 | 261 | ||
263 | This allows the exporter to ensure that the memory is actually available for | 262 | This allows the exporter to ensure that the memory is actually available for |
264 | cpu access - the exporter might need to allocate or swap-in and pin the | 263 | cpu access - the exporter might need to allocate or swap-in and pin the |
265 | backing storage. The exporter also needs to ensure that cpu access is | 264 | backing storage. The exporter also needs to ensure that cpu access is |
266 | coherent for the given range and access direction. The range and access | 265 | coherent for the access direction. The direction can be used by the exporter |
267 | direction can be used by the exporter to optimize the cache flushing, i.e. | 266 | to optimize the cache flushing, i.e. access with a different direction (read |
268 | access outside of the range or with a different direction (read instead of | 267 | instead of write) might return stale or even bogus data (e.g. when the |
269 | write) might return stale or even bogus data (e.g. when the exporter needs to | 268 | exporter needs to copy the data to temporary storage). |
270 | copy the data to temporary storage). | ||
271 | 269 | ||
272 | This step might fail, e.g. in oom conditions. | 270 | This step might fail, e.g. in oom conditions. |
273 | 271 | ||
@@ -322,14 +320,13 @@ Access to a dma_buf from the kernel context involves three steps: | |||
322 | 320 | ||
323 | 3. Finish access | 321 | 3. Finish access |
324 | 322 | ||
325 | When the importer is done accessing the range specified in begin_cpu_access, | 323 | When the importer is done accessing the CPU, it needs to announce this to |
326 | it needs to announce this to the exporter (to facilitate cache flushing and | 324 | the exporter (to facilitate cache flushing and unpinning of any pinned |
327 | unpinning of any pinned resources). The result of any dma_buf kmap calls | 325 | resources). The result of any dma_buf kmap calls after end_cpu_access is |
328 | after end_cpu_access is undefined. | 326 | undefined. |
329 | 327 | ||
330 | Interface: | 328 | Interface: |
331 | void dma_buf_end_cpu_access(struct dma_buf *dma_buf, | 329 | void dma_buf_end_cpu_access(struct dma_buf *dma_buf, |
332 | size_t start, size_t len, | ||
333 | enum dma_data_direction dir); | 330 | enum dma_data_direction dir); |
334 | 331 | ||
335 | 332 | ||
@@ -353,7 +350,26 @@ Being able to mmap an export dma-buf buffer object has 2 main use-cases: | |||
353 | handles, too). So it's beneficial to support this in a similar fashion on | 350 | handles, too). So it's beneficial to support this in a similar fashion on |
354 | dma-buf to have a good transition path for existing Android userspace. | 351 | dma-buf to have a good transition path for existing Android userspace. |
355 | 352 | ||
356 | No special interfaces, userspace simply calls mmap on the dma-buf fd. | 353 | No special interfaces, userspace simply calls mmap on the dma-buf fd, making |
354 | sure that the cache synchronization ioctl (DMA_BUF_IOCTL_SYNC) is *always* | ||
355 | used when the access happens. This is discussed next paragraphs. | ||
356 | |||
357 | Some systems might need some sort of cache coherency management e.g. when | ||
358 | CPU and GPU domains are being accessed through dma-buf at the same time. To | ||
359 | circumvent this problem there are begin/end coherency markers, that forward | ||
360 | directly to existing dma-buf device drivers vfunc hooks. Userspace can make | ||
361 | use of those markers through the DMA_BUF_IOCTL_SYNC ioctl. The sequence | ||
362 | would be used like following: | ||
363 | - mmap dma-buf fd | ||
364 | - for each drawing/upload cycle in CPU 1. SYNC_START ioctl, 2. read/write | ||
365 | to mmap area 3. SYNC_END ioctl. This can be repeated as often as you | ||
366 | want (with the new data being consumed by the GPU or say scanout device) | ||
367 | - munmap once you don't need the buffer any more | ||
368 | |||
369 | Therefore, for correctness and optimal performance, systems with the memory | ||
370 | cache shared by the GPU and CPU i.e. the "coherent" and also the | ||
371 | "incoherent" are always required to use SYNC_START and SYNC_END before and | ||
372 | after, respectively, when accessing the mapped address. | ||
357 | 373 | ||
358 | 2. Supporting existing mmap interfaces in importers | 374 | 2. Supporting existing mmap interfaces in importers |
359 | 375 | ||
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 155c1464948e..9810d1df0691 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/poll.h> | 34 | #include <linux/poll.h> |
35 | #include <linux/reservation.h> | 35 | #include <linux/reservation.h> |
36 | 36 | ||
37 | #include <uapi/linux/dma-buf.h> | ||
38 | |||
37 | static inline int is_dma_buf_file(struct file *); | 39 | static inline int is_dma_buf_file(struct file *); |
38 | 40 | ||
39 | struct dma_buf_list { | 41 | struct dma_buf_list { |
@@ -251,11 +253,54 @@ out: | |||
251 | return events; | 253 | return events; |
252 | } | 254 | } |
253 | 255 | ||
256 | static long dma_buf_ioctl(struct file *file, | ||
257 | unsigned int cmd, unsigned long arg) | ||
258 | { | ||
259 | struct dma_buf *dmabuf; | ||
260 | struct dma_buf_sync sync; | ||
261 | enum dma_data_direction direction; | ||
262 | |||
263 | dmabuf = file->private_data; | ||
264 | |||
265 | switch (cmd) { | ||
266 | case DMA_BUF_IOCTL_SYNC: | ||
267 | if (copy_from_user(&sync, (void __user *) arg, sizeof(sync))) | ||
268 | return -EFAULT; | ||
269 | |||
270 | if (sync.flags & ~DMA_BUF_SYNC_VALID_FLAGS_MASK) | ||
271 | return -EINVAL; | ||
272 | |||
273 | switch (sync.flags & DMA_BUF_SYNC_RW) { | ||
274 | case DMA_BUF_SYNC_READ: | ||
275 | direction = DMA_FROM_DEVICE; | ||
276 | break; | ||
277 | case DMA_BUF_SYNC_WRITE: | ||
278 | direction = DMA_TO_DEVICE; | ||
279 | break; | ||
280 | case DMA_BUF_SYNC_RW: | ||
281 | direction = DMA_BIDIRECTIONAL; | ||
282 | break; | ||
283 | default: | ||
284 | return -EINVAL; | ||
285 | } | ||
286 | |||
287 | if (sync.flags & DMA_BUF_SYNC_END) | ||
288 | dma_buf_end_cpu_access(dmabuf, direction); | ||
289 | else | ||
290 | dma_buf_begin_cpu_access(dmabuf, direction); | ||
291 | |||
292 | return 0; | ||
293 | default: | ||
294 | return -ENOTTY; | ||
295 | } | ||
296 | } | ||
297 | |||
254 | static const struct file_operations dma_buf_fops = { | 298 | static const struct file_operations dma_buf_fops = { |
255 | .release = dma_buf_release, | 299 | .release = dma_buf_release, |
256 | .mmap = dma_buf_mmap_internal, | 300 | .mmap = dma_buf_mmap_internal, |
257 | .llseek = dma_buf_llseek, | 301 | .llseek = dma_buf_llseek, |
258 | .poll = dma_buf_poll, | 302 | .poll = dma_buf_poll, |
303 | .unlocked_ioctl = dma_buf_ioctl, | ||
259 | }; | 304 | }; |
260 | 305 | ||
261 | /* | 306 | /* |
@@ -539,13 +584,11 @@ EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment); | |||
539 | * preparations. Coherency is only guaranteed in the specified range for the | 584 | * preparations. Coherency is only guaranteed in the specified range for the |
540 | * specified access direction. | 585 | * specified access direction. |
541 | * @dmabuf: [in] buffer to prepare cpu access for. | 586 | * @dmabuf: [in] buffer to prepare cpu access for. |
542 | * @start: [in] start of range for cpu access. | ||
543 | * @len: [in] length of range for cpu access. | ||
544 | * @direction: [in] length of range for cpu access. | 587 | * @direction: [in] length of range for cpu access. |
545 | * | 588 | * |
546 | * Can return negative error values, returns 0 on success. | 589 | * Can return negative error values, returns 0 on success. |
547 | */ | 590 | */ |
548 | int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len, | 591 | int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, |
549 | enum dma_data_direction direction) | 592 | enum dma_data_direction direction) |
550 | { | 593 | { |
551 | int ret = 0; | 594 | int ret = 0; |
@@ -554,8 +597,7 @@ int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len, | |||
554 | return -EINVAL; | 597 | return -EINVAL; |
555 | 598 | ||
556 | if (dmabuf->ops->begin_cpu_access) | 599 | if (dmabuf->ops->begin_cpu_access) |
557 | ret = dmabuf->ops->begin_cpu_access(dmabuf, start, | 600 | ret = dmabuf->ops->begin_cpu_access(dmabuf, direction); |
558 | len, direction); | ||
559 | 601 | ||
560 | return ret; | 602 | return ret; |
561 | } | 603 | } |
@@ -567,19 +609,17 @@ EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access); | |||
567 | * actions. Coherency is only guaranteed in the specified range for the | 609 | * actions. Coherency is only guaranteed in the specified range for the |
568 | * specified access direction. | 610 | * specified access direction. |
569 | * @dmabuf: [in] buffer to complete cpu access for. | 611 | * @dmabuf: [in] buffer to complete cpu access for. |
570 | * @start: [in] start of range for cpu access. | ||
571 | * @len: [in] length of range for cpu access. | ||
572 | * @direction: [in] length of range for cpu access. | 612 | * @direction: [in] length of range for cpu access. |
573 | * | 613 | * |
574 | * This call must always succeed. | 614 | * This call must always succeed. |
575 | */ | 615 | */ |
576 | void dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, size_t len, | 616 | void dma_buf_end_cpu_access(struct dma_buf *dmabuf, |
577 | enum dma_data_direction direction) | 617 | enum dma_data_direction direction) |
578 | { | 618 | { |
579 | WARN_ON(!dmabuf); | 619 | WARN_ON(!dmabuf); |
580 | 620 | ||
581 | if (dmabuf->ops->end_cpu_access) | 621 | if (dmabuf->ops->end_cpu_access) |
582 | dmabuf->ops->end_cpu_access(dmabuf, start, len, direction); | 622 | dmabuf->ops->end_cpu_access(dmabuf, direction); |
583 | } | 623 | } |
584 | EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access); | 624 | EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access); |
585 | 625 | ||
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 438e92d4c389..08706f064e6e 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
@@ -25,6 +25,14 @@ config DRM_MIPI_DSI | |||
25 | bool | 25 | bool |
26 | depends on DRM | 26 | depends on DRM |
27 | 27 | ||
28 | config DRM_DP_AUX_CHARDEV | ||
29 | bool "DRM DP AUX Interface" | ||
30 | depends on DRM | ||
31 | help | ||
32 | Choose this option to enable a /dev/drm_dp_auxN node that allows to | ||
33 | read and write values to arbitrary DPCD registers on the DP aux | ||
34 | channel. | ||
35 | |||
28 | config DRM_KMS_HELPER | 36 | config DRM_KMS_HELPER |
29 | tristate | 37 | tristate |
30 | depends on DRM | 38 | depends on DRM |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index f80fdbaeb641..6eb94fc561dc 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
@@ -22,10 +22,13 @@ drm-$(CONFIG_OF) += drm_of.o | |||
22 | drm-$(CONFIG_AGP) += drm_agpsupport.o | 22 | drm-$(CONFIG_AGP) += drm_agpsupport.o |
23 | 23 | ||
24 | drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ | 24 | drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ |
25 | drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o | 25 | drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \ |
26 | drm_kms_helper_common.o | ||
27 | |||
26 | drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o | 28 | drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o |
27 | drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o | 29 | drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o |
28 | drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o | 30 | drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o |
31 | drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o | ||
29 | 32 | ||
30 | obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o | 33 | obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o |
31 | 34 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index 3c895863fcf5..fa948dcbdd5d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | |||
@@ -552,13 +552,14 @@ static bool amdgpu_atpx_detect(void) | |||
552 | void amdgpu_register_atpx_handler(void) | 552 | void amdgpu_register_atpx_handler(void) |
553 | { | 553 | { |
554 | bool r; | 554 | bool r; |
555 | enum vga_switcheroo_handler_flags_t handler_flags = 0; | ||
555 | 556 | ||
556 | /* detect if we have any ATPX + 2 VGA in the system */ | 557 | /* detect if we have any ATPX + 2 VGA in the system */ |
557 | r = amdgpu_atpx_detect(); | 558 | r = amdgpu_atpx_detect(); |
558 | if (!r) | 559 | if (!r) |
559 | return; | 560 | return; |
560 | 561 | ||
561 | vga_switcheroo_register_handler(&amdgpu_atpx_handler); | 562 | vga_switcheroo_register_handler(&amdgpu_atpx_handler, handler_flags); |
562 | } | 563 | } |
563 | 564 | ||
564 | /** | 565 | /** |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 093599aba64b..34830189311e 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | |||
@@ -3624,16 +3624,8 @@ dce_v10_0_ext_dpms(struct drm_encoder *encoder, int mode) | |||
3624 | 3624 | ||
3625 | } | 3625 | } |
3626 | 3626 | ||
3627 | static bool dce_v10_0_ext_mode_fixup(struct drm_encoder *encoder, | ||
3628 | const struct drm_display_mode *mode, | ||
3629 | struct drm_display_mode *adjusted_mode) | ||
3630 | { | ||
3631 | return true; | ||
3632 | } | ||
3633 | |||
3634 | static const struct drm_encoder_helper_funcs dce_v10_0_ext_helper_funcs = { | 3627 | static const struct drm_encoder_helper_funcs dce_v10_0_ext_helper_funcs = { |
3635 | .dpms = dce_v10_0_ext_dpms, | 3628 | .dpms = dce_v10_0_ext_dpms, |
3636 | .mode_fixup = dce_v10_0_ext_mode_fixup, | ||
3637 | .prepare = dce_v10_0_ext_prepare, | 3629 | .prepare = dce_v10_0_ext_prepare, |
3638 | .mode_set = dce_v10_0_ext_mode_set, | 3630 | .mode_set = dce_v10_0_ext_mode_set, |
3639 | .commit = dce_v10_0_ext_commit, | 3631 | .commit = dce_v10_0_ext_commit, |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 8e67249d4367..36deea162779 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | |||
@@ -3619,16 +3619,8 @@ dce_v11_0_ext_dpms(struct drm_encoder *encoder, int mode) | |||
3619 | 3619 | ||
3620 | } | 3620 | } |
3621 | 3621 | ||
3622 | static bool dce_v11_0_ext_mode_fixup(struct drm_encoder *encoder, | ||
3623 | const struct drm_display_mode *mode, | ||
3624 | struct drm_display_mode *adjusted_mode) | ||
3625 | { | ||
3626 | return true; | ||
3627 | } | ||
3628 | |||
3629 | static const struct drm_encoder_helper_funcs dce_v11_0_ext_helper_funcs = { | 3622 | static const struct drm_encoder_helper_funcs dce_v11_0_ext_helper_funcs = { |
3630 | .dpms = dce_v11_0_ext_dpms, | 3623 | .dpms = dce_v11_0_ext_dpms, |
3631 | .mode_fixup = dce_v11_0_ext_mode_fixup, | ||
3632 | .prepare = dce_v11_0_ext_prepare, | 3624 | .prepare = dce_v11_0_ext_prepare, |
3633 | .mode_set = dce_v11_0_ext_mode_set, | 3625 | .mode_set = dce_v11_0_ext_mode_set, |
3634 | .commit = dce_v11_0_ext_commit, | 3626 | .commit = dce_v11_0_ext_commit, |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index d0e128c24813..25dd8b668ea5 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | |||
@@ -3554,16 +3554,8 @@ dce_v8_0_ext_dpms(struct drm_encoder *encoder, int mode) | |||
3554 | 3554 | ||
3555 | } | 3555 | } |
3556 | 3556 | ||
3557 | static bool dce_v8_0_ext_mode_fixup(struct drm_encoder *encoder, | ||
3558 | const struct drm_display_mode *mode, | ||
3559 | struct drm_display_mode *adjusted_mode) | ||
3560 | { | ||
3561 | return true; | ||
3562 | } | ||
3563 | |||
3564 | static const struct drm_encoder_helper_funcs dce_v8_0_ext_helper_funcs = { | 3557 | static const struct drm_encoder_helper_funcs dce_v8_0_ext_helper_funcs = { |
3565 | .dpms = dce_v8_0_ext_dpms, | 3558 | .dpms = dce_v8_0_ext_dpms, |
3566 | .mode_fixup = dce_v8_0_ext_mode_fixup, | ||
3567 | .prepare = dce_v8_0_ext_prepare, | 3559 | .prepare = dce_v8_0_ext_prepare, |
3568 | .mode_set = dce_v8_0_ext_mode_set, | 3560 | .mode_set = dce_v8_0_ext_mode_set, |
3569 | .commit = dce_v8_0_ext_commit, | 3561 | .commit = dce_v8_0_ext_commit, |
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 0123458cbd83..f221e2dc1b0d 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c | |||
@@ -710,13 +710,6 @@ static void ast_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
710 | 710 | ||
711 | } | 711 | } |
712 | 712 | ||
713 | static bool ast_mode_fixup(struct drm_encoder *encoder, | ||
714 | const struct drm_display_mode *mode, | ||
715 | struct drm_display_mode *adjusted_mode) | ||
716 | { | ||
717 | return true; | ||
718 | } | ||
719 | |||
720 | static void ast_encoder_mode_set(struct drm_encoder *encoder, | 713 | static void ast_encoder_mode_set(struct drm_encoder *encoder, |
721 | struct drm_display_mode *mode, | 714 | struct drm_display_mode *mode, |
722 | struct drm_display_mode *adjusted_mode) | 715 | struct drm_display_mode *adjusted_mode) |
@@ -736,7 +729,6 @@ static void ast_encoder_commit(struct drm_encoder *encoder) | |||
736 | 729 | ||
737 | static const struct drm_encoder_helper_funcs ast_enc_helper_funcs = { | 730 | static const struct drm_encoder_helper_funcs ast_enc_helper_funcs = { |
738 | .dpms = ast_encoder_dpms, | 731 | .dpms = ast_encoder_dpms, |
739 | .mode_fixup = ast_mode_fixup, | ||
740 | .prepare = ast_encoder_prepare, | 732 | .prepare = ast_encoder_prepare, |
741 | .commit = ast_encoder_commit, | 733 | .commit = ast_encoder_commit, |
742 | .mode_set = ast_encoder_mode_set, | 734 | .mode_set = ast_encoder_mode_set, |
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 2849f1b95eec..317c27f2a50b 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c | |||
@@ -152,13 +152,6 @@ static void bochs_crtc_init(struct drm_device *dev) | |||
152 | drm_crtc_helper_add(crtc, &bochs_helper_funcs); | 152 | drm_crtc_helper_add(crtc, &bochs_helper_funcs); |
153 | } | 153 | } |
154 | 154 | ||
155 | static bool bochs_encoder_mode_fixup(struct drm_encoder *encoder, | ||
156 | const struct drm_display_mode *mode, | ||
157 | struct drm_display_mode *adjusted_mode) | ||
158 | { | ||
159 | return true; | ||
160 | } | ||
161 | |||
162 | static void bochs_encoder_mode_set(struct drm_encoder *encoder, | 155 | static void bochs_encoder_mode_set(struct drm_encoder *encoder, |
163 | struct drm_display_mode *mode, | 156 | struct drm_display_mode *mode, |
164 | struct drm_display_mode *adjusted_mode) | 157 | struct drm_display_mode *adjusted_mode) |
@@ -179,7 +172,6 @@ static void bochs_encoder_commit(struct drm_encoder *encoder) | |||
179 | 172 | ||
180 | static const struct drm_encoder_helper_funcs bochs_encoder_helper_funcs = { | 173 | static const struct drm_encoder_helper_funcs bochs_encoder_helper_funcs = { |
181 | .dpms = bochs_encoder_dpms, | 174 | .dpms = bochs_encoder_dpms, |
182 | .mode_fixup = bochs_encoder_mode_fixup, | ||
183 | .mode_set = bochs_encoder_mode_set, | 175 | .mode_set = bochs_encoder_mode_set, |
184 | .prepare = bochs_encoder_prepare, | 176 | .prepare = bochs_encoder_prepare, |
185 | .commit = bochs_encoder_commit, | 177 | .commit = bochs_encoder_commit, |
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index b0aac4733020..9795b72472ba 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c | |||
@@ -1391,13 +1391,6 @@ static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge, | |||
1391 | mutex_unlock(&hdmi->mutex); | 1391 | mutex_unlock(&hdmi->mutex); |
1392 | } | 1392 | } |
1393 | 1393 | ||
1394 | static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, | ||
1395 | const struct drm_display_mode *mode, | ||
1396 | struct drm_display_mode *adjusted_mode) | ||
1397 | { | ||
1398 | return true; | ||
1399 | } | ||
1400 | |||
1401 | static void dw_hdmi_bridge_disable(struct drm_bridge *bridge) | 1394 | static void dw_hdmi_bridge_disable(struct drm_bridge *bridge) |
1402 | { | 1395 | { |
1403 | struct dw_hdmi *hdmi = bridge->driver_private; | 1396 | struct dw_hdmi *hdmi = bridge->driver_private; |
@@ -1546,7 +1539,6 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { | |||
1546 | .pre_enable = dw_hdmi_bridge_nop, | 1539 | .pre_enable = dw_hdmi_bridge_nop, |
1547 | .post_disable = dw_hdmi_bridge_nop, | 1540 | .post_disable = dw_hdmi_bridge_nop, |
1548 | .mode_set = dw_hdmi_bridge_mode_set, | 1541 | .mode_set = dw_hdmi_bridge_mode_set, |
1549 | .mode_fixup = dw_hdmi_bridge_mode_fixup, | ||
1550 | }; | 1542 | }; |
1551 | 1543 | ||
1552 | static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) | 1544 | static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id) |
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 4a02854a6963..432ce9440e09 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c | |||
@@ -430,14 +430,6 @@ void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
430 | *blue = cirrus_crtc->lut_b[regno]; | 430 | *blue = cirrus_crtc->lut_b[regno]; |
431 | } | 431 | } |
432 | 432 | ||
433 | |||
434 | static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder, | ||
435 | const struct drm_display_mode *mode, | ||
436 | struct drm_display_mode *adjusted_mode) | ||
437 | { | ||
438 | return true; | ||
439 | } | ||
440 | |||
441 | static void cirrus_encoder_mode_set(struct drm_encoder *encoder, | 433 | static void cirrus_encoder_mode_set(struct drm_encoder *encoder, |
442 | struct drm_display_mode *mode, | 434 | struct drm_display_mode *mode, |
443 | struct drm_display_mode *adjusted_mode) | 435 | struct drm_display_mode *adjusted_mode) |
@@ -466,7 +458,6 @@ static void cirrus_encoder_destroy(struct drm_encoder *encoder) | |||
466 | 458 | ||
467 | static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs = { | 459 | static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs = { |
468 | .dpms = cirrus_encoder_dpms, | 460 | .dpms = cirrus_encoder_dpms, |
469 | .mode_fixup = cirrus_encoder_mode_fixup, | ||
470 | .mode_set = cirrus_encoder_mode_set, | 461 | .mode_set = cirrus_encoder_mode_set, |
471 | .prepare = cirrus_encoder_prepare, | 462 | .prepare = cirrus_encoder_prepare, |
472 | .commit = cirrus_encoder_commit, | 463 | .commit = cirrus_encoder_commit, |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 0ab7c24cd7d6..2b430b05f35d 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -125,6 +125,47 @@ get_current_crtc_for_encoder(struct drm_device *dev, | |||
125 | return NULL; | 125 | return NULL; |
126 | } | 126 | } |
127 | 127 | ||
128 | static void | ||
129 | set_best_encoder(struct drm_atomic_state *state, | ||
130 | struct drm_connector_state *conn_state, | ||
131 | struct drm_encoder *encoder) | ||
132 | { | ||
133 | struct drm_crtc_state *crtc_state; | ||
134 | struct drm_crtc *crtc; | ||
135 | |||
136 | if (conn_state->best_encoder) { | ||
137 | /* Unset the encoder_mask in the old crtc state. */ | ||
138 | crtc = conn_state->connector->state->crtc; | ||
139 | |||
140 | /* A NULL crtc is an error here because we should have | ||
141 | * duplicated a NULL best_encoder when crtc was NULL. | ||
142 | * As an exception restoring duplicated atomic state | ||
143 | * during resume is allowed, so don't warn when | ||
144 | * best_encoder is equal to encoder we intend to set. | ||
145 | */ | ||
146 | WARN_ON(!crtc && encoder != conn_state->best_encoder); | ||
147 | if (crtc) { | ||
148 | crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); | ||
149 | |||
150 | crtc_state->encoder_mask &= | ||
151 | ~(1 << drm_encoder_index(conn_state->best_encoder)); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | if (encoder) { | ||
156 | crtc = conn_state->crtc; | ||
157 | WARN_ON(!crtc); | ||
158 | if (crtc) { | ||
159 | crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); | ||
160 | |||
161 | crtc_state->encoder_mask |= | ||
162 | 1 << drm_encoder_index(encoder); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | conn_state->best_encoder = encoder; | ||
167 | } | ||
168 | |||
128 | static int | 169 | static int |
129 | steal_encoder(struct drm_atomic_state *state, | 170 | steal_encoder(struct drm_atomic_state *state, |
130 | struct drm_encoder *encoder, | 171 | struct drm_encoder *encoder, |
@@ -134,7 +175,6 @@ steal_encoder(struct drm_atomic_state *state, | |||
134 | struct drm_crtc_state *crtc_state; | 175 | struct drm_crtc_state *crtc_state; |
135 | struct drm_connector *connector; | 176 | struct drm_connector *connector; |
136 | struct drm_connector_state *connector_state; | 177 | struct drm_connector_state *connector_state; |
137 | int ret; | ||
138 | 178 | ||
139 | /* | 179 | /* |
140 | * We can only steal an encoder coming from a connector, which means we | 180 | * We can only steal an encoder coming from a connector, which means we |
@@ -165,10 +205,10 @@ steal_encoder(struct drm_atomic_state *state, | |||
165 | if (IS_ERR(connector_state)) | 205 | if (IS_ERR(connector_state)) |
166 | return PTR_ERR(connector_state); | 206 | return PTR_ERR(connector_state); |
167 | 207 | ||
168 | ret = drm_atomic_set_crtc_for_connector(connector_state, NULL); | 208 | if (connector_state->best_encoder != encoder) |
169 | if (ret) | 209 | continue; |
170 | return ret; | 210 | |
171 | connector_state->best_encoder = NULL; | 211 | set_best_encoder(state, connector_state, NULL); |
172 | } | 212 | } |
173 | 213 | ||
174 | return 0; | 214 | return 0; |
@@ -216,7 +256,7 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) | |||
216 | connector->base.id, | 256 | connector->base.id, |
217 | connector->name); | 257 | connector->name); |
218 | 258 | ||
219 | connector_state->best_encoder = NULL; | 259 | set_best_encoder(state, connector_state, NULL); |
220 | 260 | ||
221 | return 0; | 261 | return 0; |
222 | } | 262 | } |
@@ -245,6 +285,8 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) | |||
245 | } | 285 | } |
246 | 286 | ||
247 | if (new_encoder == connector_state->best_encoder) { | 287 | if (new_encoder == connector_state->best_encoder) { |
288 | set_best_encoder(state, connector_state, new_encoder); | ||
289 | |||
248 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d:%s]\n", | 290 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d:%s]\n", |
249 | connector->base.id, | 291 | connector->base.id, |
250 | connector->name, | 292 | connector->name, |
@@ -279,7 +321,8 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx) | |||
279 | if (WARN_ON(!connector_state->crtc)) | 321 | if (WARN_ON(!connector_state->crtc)) |
280 | return -EINVAL; | 322 | return -EINVAL; |
281 | 323 | ||
282 | connector_state->best_encoder = new_encoder; | 324 | set_best_encoder(state, connector_state, new_encoder); |
325 | |||
283 | idx = drm_crtc_index(connector_state->crtc); | 326 | idx = drm_crtc_index(connector_state->crtc); |
284 | 327 | ||
285 | crtc_state = state->crtc_states[idx]; | 328 | crtc_state = state->crtc_states[idx]; |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 6e6514ef9968..65258acddb90 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -1161,6 +1161,29 @@ out_unlock: | |||
1161 | EXPORT_SYMBOL(drm_encoder_init); | 1161 | EXPORT_SYMBOL(drm_encoder_init); |
1162 | 1162 | ||
1163 | /** | 1163 | /** |
1164 | * drm_encoder_index - find the index of a registered encoder | ||
1165 | * @encoder: encoder to find index for | ||
1166 | * | ||
1167 | * Given a registered encoder, return the index of that encoder within a DRM | ||
1168 | * device's list of encoders. | ||
1169 | */ | ||
1170 | unsigned int drm_encoder_index(struct drm_encoder *encoder) | ||
1171 | { | ||
1172 | unsigned int index = 0; | ||
1173 | struct drm_encoder *tmp; | ||
1174 | |||
1175 | drm_for_each_encoder(tmp, encoder->dev) { | ||
1176 | if (tmp == encoder) | ||
1177 | return index; | ||
1178 | |||
1179 | index++; | ||
1180 | } | ||
1181 | |||
1182 | BUG(); | ||
1183 | } | ||
1184 | EXPORT_SYMBOL(drm_encoder_index); | ||
1185 | |||
1186 | /** | ||
1164 | * drm_encoder_cleanup - cleans up an initialised encoder | 1187 | * drm_encoder_cleanup - cleans up an initialised encoder |
1165 | * @encoder: encoder to cleanup | 1188 | * @encoder: encoder to cleanup |
1166 | * | 1189 | * |
@@ -5715,6 +5738,48 @@ int drm_format_vert_chroma_subsampling(uint32_t format) | |||
5715 | EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); | 5738 | EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); |
5716 | 5739 | ||
5717 | /** | 5740 | /** |
5741 | * drm_format_plane_width - width of the plane given the first plane | ||
5742 | * @width: width of the first plane | ||
5743 | * @format: pixel format | ||
5744 | * @plane: plane index | ||
5745 | * | ||
5746 | * Returns: | ||
5747 | * The width of @plane, given that the width of the first plane is @width. | ||
5748 | */ | ||
5749 | int drm_format_plane_width(int width, uint32_t format, int plane) | ||
5750 | { | ||
5751 | if (plane >= drm_format_num_planes(format)) | ||
5752 | return 0; | ||
5753 | |||
5754 | if (plane == 0) | ||
5755 | return width; | ||
5756 | |||
5757 | return width / drm_format_horz_chroma_subsampling(format); | ||
5758 | } | ||
5759 | EXPORT_SYMBOL(drm_format_plane_width); | ||
5760 | |||
5761 | /** | ||
5762 | * drm_format_plane_height - height of the plane given the first plane | ||
5763 | * @height: height of the first plane | ||
5764 | * @format: pixel format | ||
5765 | * @plane: plane index | ||
5766 | * | ||
5767 | * Returns: | ||
5768 | * The height of @plane, given that the height of the first plane is @height. | ||
5769 | */ | ||
5770 | int drm_format_plane_height(int height, uint32_t format, int plane) | ||
5771 | { | ||
5772 | if (plane >= drm_format_num_planes(format)) | ||
5773 | return 0; | ||
5774 | |||
5775 | if (plane == 0) | ||
5776 | return height; | ||
5777 | |||
5778 | return height / drm_format_vert_chroma_subsampling(format); | ||
5779 | } | ||
5780 | EXPORT_SYMBOL(drm_format_plane_height); | ||
5781 | |||
5782 | /** | ||
5718 | * drm_rotation_simplify() - Try to simplify the rotation | 5783 | * drm_rotation_simplify() - Try to simplify the rotation |
5719 | * @rotation: Rotation to be simplified | 5784 | * @rotation: Rotation to be simplified |
5720 | * @supported_rotations: Supported rotations | 5785 | * @supported_rotations: Supported rotations |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 9f8b894f4480..7539eea4ccbc 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
@@ -73,9 +73,6 @@ | |||
73 | * &drm_crtc_helper_funcs, struct &drm_encoder_helper_funcs and struct | 73 | * &drm_crtc_helper_funcs, struct &drm_encoder_helper_funcs and struct |
74 | * &drm_connector_helper_funcs. | 74 | * &drm_connector_helper_funcs. |
75 | */ | 75 | */ |
76 | MODULE_AUTHOR("David Airlie, Jesse Barnes"); | ||
77 | MODULE_DESCRIPTION("DRM KMS helper"); | ||
78 | MODULE_LICENSE("GPL and additional rights"); | ||
79 | 76 | ||
80 | /** | 77 | /** |
81 | * drm_helper_move_panel_connectors_to_head() - move panels to the front in the | 78 | * drm_helper_move_panel_connectors_to_head() - move panels to the front in the |
@@ -337,16 +334,21 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, | |||
337 | } | 334 | } |
338 | 335 | ||
339 | encoder_funcs = encoder->helper_private; | 336 | encoder_funcs = encoder->helper_private; |
340 | if (!(ret = encoder_funcs->mode_fixup(encoder, mode, | 337 | if (encoder_funcs->mode_fixup) { |
341 | adjusted_mode))) { | 338 | if (!(ret = encoder_funcs->mode_fixup(encoder, mode, |
342 | DRM_DEBUG_KMS("Encoder fixup failed\n"); | 339 | adjusted_mode))) { |
343 | goto done; | 340 | DRM_DEBUG_KMS("Encoder fixup failed\n"); |
341 | goto done; | ||
342 | } | ||
344 | } | 343 | } |
345 | } | 344 | } |
346 | 345 | ||
347 | if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { | 346 | if (crtc_funcs->mode_fixup) { |
348 | DRM_DEBUG_KMS("CRTC fixup failed\n"); | 347 | if (!(ret = crtc_funcs->mode_fixup(crtc, mode, |
349 | goto done; | 348 | adjusted_mode))) { |
349 | DRM_DEBUG_KMS("CRTC fixup failed\n"); | ||
350 | goto done; | ||
351 | } | ||
350 | } | 352 | } |
351 | DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); | 353 | DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); |
352 | 354 | ||
diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c new file mode 100644 index 000000000000..f73b38b33a8e --- /dev/null +++ b/drivers/gpu/drm/drm_dp_aux_dev.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* | ||
2 | * Copyright © 2015 Intel Corporation | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Rafael Antognolli <rafael.antognolli@intel.com> | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/device.h> | ||
29 | #include <linux/fs.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/uaccess.h> | ||
35 | #include <drm/drm_dp_helper.h> | ||
36 | #include <drm/drm_crtc.h> | ||
37 | #include <drm/drmP.h> | ||
38 | |||
39 | struct drm_dp_aux_dev { | ||
40 | unsigned index; | ||
41 | struct drm_dp_aux *aux; | ||
42 | struct device *dev; | ||
43 | struct kref refcount; | ||
44 | atomic_t usecount; | ||
45 | }; | ||
46 | |||
47 | #define DRM_AUX_MINORS 256 | ||
48 | #define AUX_MAX_OFFSET (1 << 20) | ||
49 | static DEFINE_IDR(aux_idr); | ||
50 | static DEFINE_MUTEX(aux_idr_mutex); | ||
51 | static struct class *drm_dp_aux_dev_class; | ||
52 | static int drm_dev_major = -1; | ||
53 | |||
54 | static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_minor(unsigned index) | ||
55 | { | ||
56 | struct drm_dp_aux_dev *aux_dev = NULL; | ||
57 | |||
58 | mutex_lock(&aux_idr_mutex); | ||
59 | aux_dev = idr_find(&aux_idr, index); | ||
60 | if (!kref_get_unless_zero(&aux_dev->refcount)) | ||
61 | aux_dev = NULL; | ||
62 | mutex_unlock(&aux_idr_mutex); | ||
63 | |||
64 | return aux_dev; | ||
65 | } | ||
66 | |||
67 | static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux) | ||
68 | { | ||
69 | struct drm_dp_aux_dev *aux_dev; | ||
70 | int index; | ||
71 | |||
72 | aux_dev = kzalloc(sizeof(*aux_dev), GFP_KERNEL); | ||
73 | if (!aux_dev) | ||
74 | return ERR_PTR(-ENOMEM); | ||
75 | aux_dev->aux = aux; | ||
76 | atomic_set(&aux_dev->usecount, 1); | ||
77 | kref_init(&aux_dev->refcount); | ||
78 | |||
79 | mutex_lock(&aux_idr_mutex); | ||
80 | index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, | ||
81 | GFP_KERNEL); | ||
82 | mutex_unlock(&aux_idr_mutex); | ||
83 | if (index < 0) { | ||
84 | kfree(aux_dev); | ||
85 | return ERR_PTR(index); | ||
86 | } | ||
87 | aux_dev->index = index; | ||
88 | |||
89 | return aux_dev; | ||
90 | } | ||
91 | |||
92 | static void release_drm_dp_aux_dev(struct kref *ref) | ||
93 | { | ||
94 | struct drm_dp_aux_dev *aux_dev = | ||
95 | container_of(ref, struct drm_dp_aux_dev, refcount); | ||
96 | |||
97 | kfree(aux_dev); | ||
98 | } | ||
99 | |||
100 | static ssize_t name_show(struct device *dev, | ||
101 | struct device_attribute *attr, char *buf) | ||
102 | { | ||
103 | ssize_t res; | ||
104 | struct drm_dp_aux_dev *aux_dev = | ||
105 | drm_dp_aux_dev_get_by_minor(MINOR(dev->devt)); | ||
106 | |||
107 | if (!aux_dev) | ||
108 | return -ENODEV; | ||
109 | |||
110 | res = sprintf(buf, "%s\n", aux_dev->aux->name); | ||
111 | kref_put(&aux_dev->refcount, release_drm_dp_aux_dev); | ||
112 | |||
113 | return res; | ||
114 | } | ||
115 | static DEVICE_ATTR_RO(name); | ||
116 | |||
117 | static struct attribute *drm_dp_aux_attrs[] = { | ||
118 | &dev_attr_name.attr, | ||
119 | NULL, | ||
120 | }; | ||
121 | ATTRIBUTE_GROUPS(drm_dp_aux); | ||
122 | |||
123 | static int auxdev_open(struct inode *inode, struct file *file) | ||
124 | { | ||
125 | unsigned int minor = iminor(inode); | ||
126 | struct drm_dp_aux_dev *aux_dev; | ||
127 | |||
128 | aux_dev = drm_dp_aux_dev_get_by_minor(minor); | ||
129 | if (!aux_dev) | ||
130 | return -ENODEV; | ||
131 | |||
132 | file->private_data = aux_dev; | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static loff_t auxdev_llseek(struct file *file, loff_t offset, int whence) | ||
137 | { | ||
138 | return fixed_size_llseek(file, offset, whence, AUX_MAX_OFFSET); | ||
139 | } | ||
140 | |||
141 | static ssize_t auxdev_read(struct file *file, char __user *buf, size_t count, | ||
142 | loff_t *offset) | ||
143 | { | ||
144 | size_t bytes_pending, num_bytes_processed = 0; | ||
145 | struct drm_dp_aux_dev *aux_dev = file->private_data; | ||
146 | ssize_t res = 0; | ||
147 | |||
148 | if (!atomic_inc_not_zero(&aux_dev->usecount)) | ||
149 | return -ENODEV; | ||
150 | |||
151 | bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - (*offset)); | ||
152 | |||
153 | if (!access_ok(VERIFY_WRITE, buf, bytes_pending)) { | ||
154 | res = -EFAULT; | ||
155 | goto out; | ||
156 | } | ||
157 | |||
158 | while (bytes_pending > 0) { | ||
159 | uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES]; | ||
160 | ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf)); | ||
161 | |||
162 | res = drm_dp_dpcd_read(aux_dev->aux, *offset, localbuf, todo); | ||
163 | if (res <= 0) { | ||
164 | res = num_bytes_processed ? num_bytes_processed : res; | ||
165 | goto out; | ||
166 | } | ||
167 | if (__copy_to_user(buf + num_bytes_processed, localbuf, res)) { | ||
168 | res = num_bytes_processed ? | ||
169 | num_bytes_processed : -EFAULT; | ||
170 | goto out; | ||
171 | } | ||
172 | bytes_pending -= res; | ||
173 | *offset += res; | ||
174 | num_bytes_processed += res; | ||
175 | res = num_bytes_processed; | ||
176 | } | ||
177 | |||
178 | out: | ||
179 | atomic_dec(&aux_dev->usecount); | ||
180 | wake_up_atomic_t(&aux_dev->usecount); | ||
181 | return res; | ||
182 | } | ||
183 | |||
184 | static ssize_t auxdev_write(struct file *file, const char __user *buf, | ||
185 | size_t count, loff_t *offset) | ||
186 | { | ||
187 | size_t bytes_pending, num_bytes_processed = 0; | ||
188 | struct drm_dp_aux_dev *aux_dev = file->private_data; | ||
189 | ssize_t res = 0; | ||
190 | |||
191 | if (!atomic_inc_not_zero(&aux_dev->usecount)) | ||
192 | return -ENODEV; | ||
193 | |||
194 | bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - *offset); | ||
195 | |||
196 | if (!access_ok(VERIFY_READ, buf, bytes_pending)) { | ||
197 | res = -EFAULT; | ||
198 | goto out; | ||
199 | } | ||
200 | |||
201 | while (bytes_pending > 0) { | ||
202 | uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES]; | ||
203 | ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf)); | ||
204 | |||
205 | if (__copy_from_user(localbuf, | ||
206 | buf + num_bytes_processed, todo)) { | ||
207 | res = num_bytes_processed ? | ||
208 | num_bytes_processed : -EFAULT; | ||
209 | goto out; | ||
210 | } | ||
211 | |||
212 | res = drm_dp_dpcd_write(aux_dev->aux, *offset, localbuf, todo); | ||
213 | if (res <= 0) { | ||
214 | res = num_bytes_processed ? num_bytes_processed : res; | ||
215 | goto out; | ||
216 | } | ||
217 | bytes_pending -= res; | ||
218 | *offset += res; | ||
219 | num_bytes_processed += res; | ||
220 | res = num_bytes_processed; | ||
221 | } | ||
222 | |||
223 | out: | ||
224 | atomic_dec(&aux_dev->usecount); | ||
225 | wake_up_atomic_t(&aux_dev->usecount); | ||
226 | return res; | ||
227 | } | ||
228 | |||
229 | static int auxdev_release(struct inode *inode, struct file *file) | ||
230 | { | ||
231 | struct drm_dp_aux_dev *aux_dev = file->private_data; | ||
232 | |||
233 | kref_put(&aux_dev->refcount, release_drm_dp_aux_dev); | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static const struct file_operations auxdev_fops = { | ||
238 | .owner = THIS_MODULE, | ||
239 | .llseek = auxdev_llseek, | ||
240 | .read = auxdev_read, | ||
241 | .write = auxdev_write, | ||
242 | .open = auxdev_open, | ||
243 | .release = auxdev_release, | ||
244 | }; | ||
245 | |||
246 | #define to_auxdev(d) container_of(d, struct drm_dp_aux_dev, aux) | ||
247 | |||
248 | static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_aux(struct drm_dp_aux *aux) | ||
249 | { | ||
250 | struct drm_dp_aux_dev *iter, *aux_dev = NULL; | ||
251 | int id; | ||
252 | |||
253 | /* don't increase kref count here because this function should only be | ||
254 | * used by drm_dp_aux_unregister_devnode. Thus, it will always have at | ||
255 | * least one reference - the one that drm_dp_aux_register_devnode | ||
256 | * created | ||
257 | */ | ||
258 | mutex_lock(&aux_idr_mutex); | ||
259 | idr_for_each_entry(&aux_idr, iter, id) { | ||
260 | if (iter->aux == aux) { | ||
261 | aux_dev = iter; | ||
262 | break; | ||
263 | } | ||
264 | } | ||
265 | mutex_unlock(&aux_idr_mutex); | ||
266 | return aux_dev; | ||
267 | } | ||
268 | |||
269 | static int auxdev_wait_atomic_t(atomic_t *p) | ||
270 | { | ||
271 | schedule(); | ||
272 | return 0; | ||
273 | } | ||
274 | /** | ||
275 | * drm_dp_aux_unregister_devnode() - unregister a devnode for this aux channel | ||
276 | * @aux: DisplayPort AUX channel | ||
277 | * | ||
278 | * Returns 0 on success or a negative error code on failure. | ||
279 | */ | ||
280 | void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) | ||
281 | { | ||
282 | struct drm_dp_aux_dev *aux_dev; | ||
283 | unsigned int minor; | ||
284 | |||
285 | aux_dev = drm_dp_aux_dev_get_by_aux(aux); | ||
286 | if (!aux_dev) /* attach must have failed */ | ||
287 | return; | ||
288 | |||
289 | mutex_lock(&aux_idr_mutex); | ||
290 | idr_remove(&aux_idr, aux_dev->index); | ||
291 | mutex_unlock(&aux_idr_mutex); | ||
292 | |||
293 | atomic_dec(&aux_dev->usecount); | ||
294 | wait_on_atomic_t(&aux_dev->usecount, auxdev_wait_atomic_t, | ||
295 | TASK_UNINTERRUPTIBLE); | ||
296 | |||
297 | minor = aux_dev->index; | ||
298 | if (aux_dev->dev) | ||
299 | device_destroy(drm_dp_aux_dev_class, | ||
300 | MKDEV(drm_dev_major, minor)); | ||
301 | |||
302 | DRM_DEBUG("drm_dp_aux_dev: aux [%s] unregistering\n", aux->name); | ||
303 | kref_put(&aux_dev->refcount, release_drm_dp_aux_dev); | ||
304 | } | ||
305 | EXPORT_SYMBOL(drm_dp_aux_unregister_devnode); | ||
306 | |||
307 | /** | ||
308 | * drm_dp_aux_register_devnode() - register a devnode for this aux channel | ||
309 | * @aux: DisplayPort AUX channel | ||
310 | * | ||
311 | * Returns 0 on success or a negative error code on failure. | ||
312 | */ | ||
313 | int drm_dp_aux_register_devnode(struct drm_dp_aux *aux) | ||
314 | { | ||
315 | struct drm_dp_aux_dev *aux_dev; | ||
316 | int res; | ||
317 | |||
318 | aux_dev = alloc_drm_dp_aux_dev(aux); | ||
319 | if (IS_ERR(aux_dev)) | ||
320 | return PTR_ERR(aux_dev); | ||
321 | |||
322 | aux_dev->dev = device_create(drm_dp_aux_dev_class, aux->dev, | ||
323 | MKDEV(drm_dev_major, aux_dev->index), NULL, | ||
324 | "drm_dp_aux%d", aux_dev->index); | ||
325 | if (IS_ERR(aux_dev->dev)) { | ||
326 | res = PTR_ERR(aux_dev->dev); | ||
327 | aux_dev->dev = NULL; | ||
328 | goto error; | ||
329 | } | ||
330 | |||
331 | DRM_DEBUG("drm_dp_aux_dev: aux [%s] registered as minor %d\n", | ||
332 | aux->name, aux_dev->index); | ||
333 | return 0; | ||
334 | error: | ||
335 | drm_dp_aux_unregister_devnode(aux); | ||
336 | return res; | ||
337 | } | ||
338 | EXPORT_SYMBOL(drm_dp_aux_register_devnode); | ||
339 | |||
340 | int drm_dp_aux_dev_init(void) | ||
341 | { | ||
342 | int res; | ||
343 | |||
344 | drm_dp_aux_dev_class = class_create(THIS_MODULE, "drm_dp_aux_dev"); | ||
345 | if (IS_ERR(drm_dp_aux_dev_class)) { | ||
346 | res = PTR_ERR(drm_dp_aux_dev_class); | ||
347 | goto out; | ||
348 | } | ||
349 | drm_dp_aux_dev_class->dev_groups = drm_dp_aux_groups; | ||
350 | |||
351 | res = register_chrdev(0, "aux", &auxdev_fops); | ||
352 | if (res < 0) | ||
353 | goto out; | ||
354 | drm_dev_major = res; | ||
355 | |||
356 | return 0; | ||
357 | out: | ||
358 | class_destroy(drm_dp_aux_dev_class); | ||
359 | return res; | ||
360 | } | ||
361 | EXPORT_SYMBOL(drm_dp_aux_dev_init); | ||
362 | |||
363 | void drm_dp_aux_dev_exit(void) | ||
364 | { | ||
365 | unregister_chrdev(drm_dev_major, "aux"); | ||
366 | class_destroy(drm_dp_aux_dev_class); | ||
367 | } | ||
368 | EXPORT_SYMBOL(drm_dp_aux_dev_exit); | ||
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 9535c5b60387..7d58f594cffe 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
30 | #include <drm/drm_dp_helper.h> | 30 | #include <drm/drm_dp_helper.h> |
31 | #include <drm/drm_dp_aux_dev.h> | ||
31 | #include <drm/drmP.h> | 32 | #include <drm/drmP.h> |
32 | 33 | ||
33 | /** | 34 | /** |
@@ -754,6 +755,8 @@ static const struct i2c_algorithm drm_dp_i2c_algo = { | |||
754 | */ | 755 | */ |
755 | int drm_dp_aux_register(struct drm_dp_aux *aux) | 756 | int drm_dp_aux_register(struct drm_dp_aux *aux) |
756 | { | 757 | { |
758 | int ret; | ||
759 | |||
757 | mutex_init(&aux->hw_mutex); | 760 | mutex_init(&aux->hw_mutex); |
758 | 761 | ||
759 | aux->ddc.algo = &drm_dp_i2c_algo; | 762 | aux->ddc.algo = &drm_dp_i2c_algo; |
@@ -768,7 +771,17 @@ int drm_dp_aux_register(struct drm_dp_aux *aux) | |||
768 | strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev), | 771 | strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev), |
769 | sizeof(aux->ddc.name)); | 772 | sizeof(aux->ddc.name)); |
770 | 773 | ||
771 | return i2c_add_adapter(&aux->ddc); | 774 | ret = drm_dp_aux_register_devnode(aux); |
775 | if (ret) | ||
776 | return ret; | ||
777 | |||
778 | ret = i2c_add_adapter(&aux->ddc); | ||
779 | if (ret) { | ||
780 | drm_dp_aux_unregister_devnode(aux); | ||
781 | return ret; | ||
782 | } | ||
783 | |||
784 | return 0; | ||
772 | } | 785 | } |
773 | EXPORT_SYMBOL(drm_dp_aux_register); | 786 | EXPORT_SYMBOL(drm_dp_aux_register); |
774 | 787 | ||
@@ -778,6 +791,7 @@ EXPORT_SYMBOL(drm_dp_aux_register); | |||
778 | */ | 791 | */ |
779 | void drm_dp_aux_unregister(struct drm_dp_aux *aux) | 792 | void drm_dp_aux_unregister(struct drm_dp_aux *aux) |
780 | { | 793 | { |
794 | drm_dp_aux_unregister_devnode(aux); | ||
781 | i2c_del_adapter(&aux->ddc); | 795 | i2c_del_adapter(&aux->ddc); |
782 | } | 796 | } |
783 | EXPORT_SYMBOL(drm_dp_aux_unregister); | 797 | EXPORT_SYMBOL(drm_dp_aux_unregister); |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 04cb4877fabd..fdb1eb014586 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/hdmi.h> | 32 | #include <linux/hdmi.h> |
33 | #include <linux/i2c.h> | 33 | #include <linux/i2c.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/vga_switcheroo.h> | ||
35 | #include <drm/drmP.h> | 36 | #include <drm/drmP.h> |
36 | #include <drm/drm_edid.h> | 37 | #include <drm/drm_edid.h> |
37 | #include <drm/drm_displayid.h> | 38 | #include <drm/drm_displayid.h> |
@@ -1395,6 +1396,31 @@ struct edid *drm_get_edid(struct drm_connector *connector, | |||
1395 | EXPORT_SYMBOL(drm_get_edid); | 1396 | EXPORT_SYMBOL(drm_get_edid); |
1396 | 1397 | ||
1397 | /** | 1398 | /** |
1399 | * drm_get_edid_switcheroo - get EDID data for a vga_switcheroo output | ||
1400 | * @connector: connector we're probing | ||
1401 | * @adapter: I2C adapter to use for DDC | ||
1402 | * | ||
1403 | * Wrapper around drm_get_edid() for laptops with dual GPUs using one set of | ||
1404 | * outputs. The wrapper adds the requisite vga_switcheroo calls to temporarily | ||
1405 | * switch DDC to the GPU which is retrieving EDID. | ||
1406 | * | ||
1407 | * Return: Pointer to valid EDID or %NULL if we couldn't find any. | ||
1408 | */ | ||
1409 | struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, | ||
1410 | struct i2c_adapter *adapter) | ||
1411 | { | ||
1412 | struct pci_dev *pdev = connector->dev->pdev; | ||
1413 | struct edid *edid; | ||
1414 | |||
1415 | vga_switcheroo_lock_ddc(pdev); | ||
1416 | edid = drm_get_edid(connector, adapter); | ||
1417 | vga_switcheroo_unlock_ddc(pdev); | ||
1418 | |||
1419 | return edid; | ||
1420 | } | ||
1421 | EXPORT_SYMBOL(drm_get_edid_switcheroo); | ||
1422 | |||
1423 | /** | ||
1398 | * drm_edid_duplicate - duplicate an EDID and the extensions | 1424 | * drm_edid_duplicate - duplicate an EDID and the extensions |
1399 | * @edid: EDID to duplicate | 1425 | * @edid: EDID to duplicate |
1400 | * | 1426 | * |
diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c index e8629076de32..4484785cd9ac 100644 --- a/drivers/gpu/drm/drm_encoder_slave.c +++ b/drivers/gpu/drm/drm_encoder_slave.c | |||
@@ -140,6 +140,9 @@ bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder, | |||
140 | const struct drm_display_mode *mode, | 140 | const struct drm_display_mode *mode, |
141 | struct drm_display_mode *adjusted_mode) | 141 | struct drm_display_mode *adjusted_mode) |
142 | { | 142 | { |
143 | if (!get_slave_funcs(encoder)->mode_fixup) | ||
144 | return true; | ||
145 | |||
143 | return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode); | 146 | return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode); |
144 | } | 147 | } |
145 | EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup); | 148 | EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup); |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 76a364e62081..855108e6e1bd 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -104,21 +104,17 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) | |||
104 | { | 104 | { |
105 | struct drm_device *dev = fb_helper->dev; | 105 | struct drm_device *dev = fb_helper->dev; |
106 | struct drm_connector *connector; | 106 | struct drm_connector *connector; |
107 | int i; | 107 | int i, ret; |
108 | 108 | ||
109 | if (!drm_fbdev_emulation) | 109 | if (!drm_fbdev_emulation) |
110 | return 0; | 110 | return 0; |
111 | 111 | ||
112 | mutex_lock(&dev->mode_config.mutex); | 112 | mutex_lock(&dev->mode_config.mutex); |
113 | drm_for_each_connector(connector, dev) { | 113 | drm_for_each_connector(connector, dev) { |
114 | struct drm_fb_helper_connector *fb_helper_connector; | 114 | ret = drm_fb_helper_add_one_connector(fb_helper, connector); |
115 | 115 | ||
116 | fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); | 116 | if (ret) |
117 | if (!fb_helper_connector) | ||
118 | goto fail; | 117 | goto fail; |
119 | |||
120 | fb_helper_connector->connector = connector; | ||
121 | fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector; | ||
122 | } | 118 | } |
123 | mutex_unlock(&dev->mode_config.mutex); | 119 | mutex_unlock(&dev->mode_config.mutex); |
124 | return 0; | 120 | return 0; |
@@ -130,7 +126,7 @@ fail: | |||
130 | fb_helper->connector_count = 0; | 126 | fb_helper->connector_count = 0; |
131 | mutex_unlock(&dev->mode_config.mutex); | 127 | mutex_unlock(&dev->mode_config.mutex); |
132 | 128 | ||
133 | return -ENOMEM; | 129 | return ret; |
134 | } | 130 | } |
135 | EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); | 131 | EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); |
136 | 132 | ||
@@ -1989,13 +1985,13 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) | |||
1989 | width = dev->mode_config.max_width; | 1985 | width = dev->mode_config.max_width; |
1990 | height = dev->mode_config.max_height; | 1986 | height = dev->mode_config.max_height; |
1991 | 1987 | ||
1992 | crtcs = kcalloc(dev->mode_config.num_connector, | 1988 | crtcs = kcalloc(fb_helper->connector_count, |
1993 | sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); | 1989 | sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL); |
1994 | modes = kcalloc(dev->mode_config.num_connector, | 1990 | modes = kcalloc(fb_helper->connector_count, |
1995 | sizeof(struct drm_display_mode *), GFP_KERNEL); | 1991 | sizeof(struct drm_display_mode *), GFP_KERNEL); |
1996 | offsets = kcalloc(dev->mode_config.num_connector, | 1992 | offsets = kcalloc(fb_helper->connector_count, |
1997 | sizeof(struct drm_fb_offset), GFP_KERNEL); | 1993 | sizeof(struct drm_fb_offset), GFP_KERNEL); |
1998 | enabled = kcalloc(dev->mode_config.num_connector, | 1994 | enabled = kcalloc(fb_helper->connector_count, |
1999 | sizeof(bool), GFP_KERNEL); | 1995 | sizeof(bool), GFP_KERNEL); |
2000 | if (!crtcs || !modes || !enabled || !offsets) { | 1996 | if (!crtcs || !modes || !enabled || !offsets) { |
2001 | DRM_ERROR("Memory allocation failed\n"); | 1997 | DRM_ERROR("Memory allocation failed\n"); |
@@ -2009,9 +2005,9 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) | |||
2009 | fb_helper->funcs->initial_config(fb_helper, crtcs, modes, | 2005 | fb_helper->funcs->initial_config(fb_helper, crtcs, modes, |
2010 | offsets, | 2006 | offsets, |
2011 | enabled, width, height))) { | 2007 | enabled, width, height))) { |
2012 | memset(modes, 0, dev->mode_config.num_connector*sizeof(modes[0])); | 2008 | memset(modes, 0, fb_helper->connector_count*sizeof(modes[0])); |
2013 | memset(crtcs, 0, dev->mode_config.num_connector*sizeof(crtcs[0])); | 2009 | memset(crtcs, 0, fb_helper->connector_count*sizeof(crtcs[0])); |
2014 | memset(offsets, 0, dev->mode_config.num_connector*sizeof(offsets[0])); | 2010 | memset(offsets, 0, fb_helper->connector_count*sizeof(offsets[0])); |
2015 | 2011 | ||
2016 | if (!drm_target_cloned(fb_helper, modes, offsets, | 2012 | if (!drm_target_cloned(fb_helper, modes, offsets, |
2017 | enabled, width, height) && | 2013 | enabled, width, height) && |
@@ -2196,9 +2192,9 @@ EXPORT_SYMBOL(drm_fb_helper_hotplug_event); | |||
2196 | * but the module doesn't depend on any fb console symbols. At least | 2192 | * but the module doesn't depend on any fb console symbols. At least |
2197 | * attempt to load fbcon to avoid leaving the system without a usable console. | 2193 | * attempt to load fbcon to avoid leaving the system without a usable console. |
2198 | */ | 2194 | */ |
2199 | #if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT) | 2195 | int __init drm_fb_helper_modinit(void) |
2200 | static int __init drm_fb_helper_modinit(void) | ||
2201 | { | 2196 | { |
2197 | #if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT) | ||
2202 | const char *name = "fbcon"; | 2198 | const char *name = "fbcon"; |
2203 | struct module *fbcon; | 2199 | struct module *fbcon; |
2204 | 2200 | ||
@@ -2208,8 +2204,7 @@ static int __init drm_fb_helper_modinit(void) | |||
2208 | 2204 | ||
2209 | if (!fbcon) | 2205 | if (!fbcon) |
2210 | request_module_nowait(name); | 2206 | request_module_nowait(name); |
2207 | #endif | ||
2211 | return 0; | 2208 | return 0; |
2212 | } | 2209 | } |
2213 | 2210 | EXPORT_SYMBOL(drm_fb_helper_modinit); | |
2214 | module_init(drm_fb_helper_modinit); | ||
2215 | #endif | ||
diff --git a/drivers/gpu/drm/drm_kms_helper_common.c b/drivers/gpu/drm/drm_kms_helper_common.c new file mode 100644 index 000000000000..3187c4bb01cb --- /dev/null +++ b/drivers/gpu/drm/drm_kms_helper_common.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Copyright © 2015 Intel Corporation | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Rafael Antognolli <rafael.antognolli@intel.com> | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <drm/drmP.h> | ||
29 | #include <drm/drm_fb_helper.h> | ||
30 | #include <drm/drm_dp_aux_dev.h> | ||
31 | |||
32 | MODULE_AUTHOR("David Airlie, Jesse Barnes"); | ||
33 | MODULE_DESCRIPTION("DRM KMS helper"); | ||
34 | MODULE_LICENSE("GPL and additional rights"); | ||
35 | |||
36 | static int __init drm_kms_helper_init(void) | ||
37 | { | ||
38 | int ret; | ||
39 | |||
40 | /* Call init functions from specific kms helpers here */ | ||
41 | ret = drm_fb_helper_modinit(); | ||
42 | if (ret < 0) | ||
43 | goto out; | ||
44 | |||
45 | ret = drm_dp_aux_dev_init(); | ||
46 | if (ret < 0) | ||
47 | goto out; | ||
48 | |||
49 | out: | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | static void __exit drm_kms_helper_exit(void) | ||
54 | { | ||
55 | /* Call exit functions from specific kms helpers here */ | ||
56 | drm_dp_aux_dev_exit(); | ||
57 | } | ||
58 | |||
59 | module_init(drm_kms_helper_init); | ||
60 | module_exit(drm_kms_helper_exit); | ||
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 20775c05235a..f7448a5e95a9 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
@@ -1371,8 +1371,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, | |||
1371 | } | 1371 | } |
1372 | done: | 1372 | done: |
1373 | if (i >= 0) { | 1373 | if (i >= 0) { |
1374 | printk(KERN_WARNING | 1374 | pr_warn("[drm] parse error at position %i in video mode '%s'\n", |
1375 | "parse error at position %i in video mode '%s'\n", | ||
1376 | i, name); | 1375 | i, name); |
1377 | mode->specified = false; | 1376 | mode->specified = false; |
1378 | return false; | 1377 | return false; |
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 27aa7183b20b..df6cdc76a16e 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c | |||
@@ -329,7 +329,7 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = { | |||
329 | * drm_gem_prime_export - helper library implementation of the export callback | 329 | * drm_gem_prime_export - helper library implementation of the export callback |
330 | * @dev: drm_device to export from | 330 | * @dev: drm_device to export from |
331 | * @obj: GEM object to export | 331 | * @obj: GEM object to export |
332 | * @flags: flags like DRM_CLOEXEC | 332 | * @flags: flags like DRM_CLOEXEC and DRM_RDWR |
333 | * | 333 | * |
334 | * This is the implementation of the gem_prime_export functions for GEM drivers | 334 | * This is the implementation of the gem_prime_export functions for GEM drivers |
335 | * using the PRIME helpers. | 335 | * using the PRIME helpers. |
@@ -628,7 +628,6 @@ int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, | |||
628 | struct drm_file *file_priv) | 628 | struct drm_file *file_priv) |
629 | { | 629 | { |
630 | struct drm_prime_handle *args = data; | 630 | struct drm_prime_handle *args = data; |
631 | uint32_t flags; | ||
632 | 631 | ||
633 | if (!drm_core_check_feature(dev, DRIVER_PRIME)) | 632 | if (!drm_core_check_feature(dev, DRIVER_PRIME)) |
634 | return -EINVAL; | 633 | return -EINVAL; |
@@ -637,14 +636,11 @@ int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, | |||
637 | return -ENOSYS; | 636 | return -ENOSYS; |
638 | 637 | ||
639 | /* check flags are valid */ | 638 | /* check flags are valid */ |
640 | if (args->flags & ~DRM_CLOEXEC) | 639 | if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR)) |
641 | return -EINVAL; | 640 | return -EINVAL; |
642 | 641 | ||
643 | /* we only want to pass DRM_CLOEXEC which is == O_CLOEXEC */ | ||
644 | flags = args->flags & DRM_CLOEXEC; | ||
645 | |||
646 | return dev->driver->prime_handle_to_fd(dev, file_priv, | 642 | return dev->driver->prime_handle_to_fd(dev, file_priv, |
647 | args->handle, flags, &args->fd); | 643 | args->handle, args->flags, &args->fd); |
648 | } | 644 | } |
649 | 645 | ||
650 | int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, | 646 | int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, |
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 673164b331c8..9fd12c621270 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c | |||
@@ -1155,13 +1155,6 @@ static int exynos_dp_create_connector(struct drm_encoder *encoder) | |||
1155 | return 0; | 1155 | return 0; |
1156 | } | 1156 | } |
1157 | 1157 | ||
1158 | static bool exynos_dp_mode_fixup(struct drm_encoder *encoder, | ||
1159 | const struct drm_display_mode *mode, | ||
1160 | struct drm_display_mode *adjusted_mode) | ||
1161 | { | ||
1162 | return true; | ||
1163 | } | ||
1164 | |||
1165 | static void exynos_dp_mode_set(struct drm_encoder *encoder, | 1158 | static void exynos_dp_mode_set(struct drm_encoder *encoder, |
1166 | struct drm_display_mode *mode, | 1159 | struct drm_display_mode *mode, |
1167 | struct drm_display_mode *adjusted_mode) | 1160 | struct drm_display_mode *adjusted_mode) |
@@ -1177,7 +1170,6 @@ static void exynos_dp_disable(struct drm_encoder *encoder) | |||
1177 | } | 1170 | } |
1178 | 1171 | ||
1179 | static const struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = { | 1172 | static const struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = { |
1180 | .mode_fixup = exynos_dp_mode_fixup, | ||
1181 | .mode_set = exynos_dp_mode_set, | 1173 | .mode_set = exynos_dp_mode_set, |
1182 | .enable = exynos_dp_enable, | 1174 | .enable = exynos_dp_enable, |
1183 | .disable = exynos_dp_disable, | 1175 | .disable = exynos_dp_disable, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index 05350ae0785b..75e570f45259 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c | |||
@@ -128,13 +128,6 @@ static int exynos_dpi_create_connector(struct drm_encoder *encoder) | |||
128 | return 0; | 128 | return 0; |
129 | } | 129 | } |
130 | 130 | ||
131 | static bool exynos_dpi_mode_fixup(struct drm_encoder *encoder, | ||
132 | const struct drm_display_mode *mode, | ||
133 | struct drm_display_mode *adjusted_mode) | ||
134 | { | ||
135 | return true; | ||
136 | } | ||
137 | |||
138 | static void exynos_dpi_mode_set(struct drm_encoder *encoder, | 131 | static void exynos_dpi_mode_set(struct drm_encoder *encoder, |
139 | struct drm_display_mode *mode, | 132 | struct drm_display_mode *mode, |
140 | struct drm_display_mode *adjusted_mode) | 133 | struct drm_display_mode *adjusted_mode) |
@@ -162,7 +155,6 @@ static void exynos_dpi_disable(struct drm_encoder *encoder) | |||
162 | } | 155 | } |
163 | 156 | ||
164 | static const struct drm_encoder_helper_funcs exynos_dpi_encoder_helper_funcs = { | 157 | static const struct drm_encoder_helper_funcs exynos_dpi_encoder_helper_funcs = { |
165 | .mode_fixup = exynos_dpi_mode_fixup, | ||
166 | .mode_set = exynos_dpi_mode_set, | 158 | .mode_set = exynos_dpi_mode_set, |
167 | .enable = exynos_dpi_enable, | 159 | .enable = exynos_dpi_enable, |
168 | .disable = exynos_dpi_disable, | 160 | .disable = exynos_dpi_disable, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index e977a81af2e6..736115c580fc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c | |||
@@ -1597,13 +1597,6 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder) | |||
1597 | return 0; | 1597 | return 0; |
1598 | } | 1598 | } |
1599 | 1599 | ||
1600 | static bool exynos_dsi_mode_fixup(struct drm_encoder *encoder, | ||
1601 | const struct drm_display_mode *mode, | ||
1602 | struct drm_display_mode *adjusted_mode) | ||
1603 | { | ||
1604 | return true; | ||
1605 | } | ||
1606 | |||
1607 | static void exynos_dsi_mode_set(struct drm_encoder *encoder, | 1600 | static void exynos_dsi_mode_set(struct drm_encoder *encoder, |
1608 | struct drm_display_mode *mode, | 1601 | struct drm_display_mode *mode, |
1609 | struct drm_display_mode *adjusted_mode) | 1602 | struct drm_display_mode *adjusted_mode) |
@@ -1623,7 +1616,6 @@ static void exynos_dsi_mode_set(struct drm_encoder *encoder, | |||
1623 | } | 1616 | } |
1624 | 1617 | ||
1625 | static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = { | 1618 | static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = { |
1626 | .mode_fixup = exynos_dsi_mode_fixup, | ||
1627 | .mode_set = exynos_dsi_mode_set, | 1619 | .mode_set = exynos_dsi_mode_set, |
1628 | .enable = exynos_dsi_enable, | 1620 | .enable = exynos_dsi_enable, |
1629 | .disable = exynos_dsi_disable, | 1621 | .disable = exynos_dsi_disable, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 62ac4e5fa51d..65108cbd79d4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c | |||
@@ -410,13 +410,6 @@ static int vidi_create_connector(struct drm_encoder *encoder) | |||
410 | return 0; | 410 | return 0; |
411 | } | 411 | } |
412 | 412 | ||
413 | static bool exynos_vidi_mode_fixup(struct drm_encoder *encoder, | ||
414 | const struct drm_display_mode *mode, | ||
415 | struct drm_display_mode *adjusted_mode) | ||
416 | { | ||
417 | return true; | ||
418 | } | ||
419 | |||
420 | static void exynos_vidi_mode_set(struct drm_encoder *encoder, | 413 | static void exynos_vidi_mode_set(struct drm_encoder *encoder, |
421 | struct drm_display_mode *mode, | 414 | struct drm_display_mode *mode, |
422 | struct drm_display_mode *adjusted_mode) | 415 | struct drm_display_mode *adjusted_mode) |
@@ -432,7 +425,6 @@ static void exynos_vidi_disable(struct drm_encoder *encoder) | |||
432 | } | 425 | } |
433 | 426 | ||
434 | static const struct drm_encoder_helper_funcs exynos_vidi_encoder_helper_funcs = { | 427 | static const struct drm_encoder_helper_funcs exynos_vidi_encoder_helper_funcs = { |
435 | .mode_fixup = exynos_vidi_mode_fixup, | ||
436 | .mode_set = exynos_vidi_mode_set, | 428 | .mode_set = exynos_vidi_mode_set, |
437 | .enable = exynos_vidi_enable, | 429 | .enable = exynos_vidi_enable, |
438 | .disable = exynos_vidi_disable, | 430 | .disable = exynos_vidi_disable, |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index d0717a85c7ec..b837e7a92196 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c | |||
@@ -217,7 +217,6 @@ static int cdv_intel_crt_set_property(struct drm_connector *connector, | |||
217 | 217 | ||
218 | static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = { | 218 | static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = { |
219 | .dpms = cdv_intel_crt_dpms, | 219 | .dpms = cdv_intel_crt_dpms, |
220 | .mode_fixup = gma_encoder_mode_fixup, | ||
221 | .prepare = gma_encoder_prepare, | 220 | .prepare = gma_encoder_prepare, |
222 | .commit = gma_encoder_commit, | 221 | .commit = gma_encoder_commit, |
223 | .mode_set = cdv_intel_crt_mode_set, | 222 | .mode_set = cdv_intel_crt_mode_set, |
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index ddf2d7700759..28f9d90988ff 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c | |||
@@ -255,7 +255,6 @@ static void cdv_hdmi_destroy(struct drm_connector *connector) | |||
255 | 255 | ||
256 | static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = { | 256 | static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = { |
257 | .dpms = cdv_hdmi_dpms, | 257 | .dpms = cdv_hdmi_dpms, |
258 | .mode_fixup = gma_encoder_mode_fixup, | ||
259 | .prepare = gma_encoder_prepare, | 258 | .prepare = gma_encoder_prepare, |
260 | .mode_set = cdv_hdmi_mode_set, | 259 | .mode_set = cdv_hdmi_mode_set, |
261 | .commit = gma_encoder_commit, | 260 | .commit = gma_encoder_commit, |
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index ff17af4cfc64..927082148d4d 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c | |||
@@ -478,13 +478,6 @@ int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | |||
478 | return 0; | 478 | return 0; |
479 | } | 479 | } |
480 | 480 | ||
481 | bool gma_encoder_mode_fixup(struct drm_encoder *encoder, | ||
482 | const struct drm_display_mode *mode, | ||
483 | struct drm_display_mode *adjusted_mode) | ||
484 | { | ||
485 | return true; | ||
486 | } | ||
487 | |||
488 | bool gma_crtc_mode_fixup(struct drm_crtc *crtc, | 481 | bool gma_crtc_mode_fixup(struct drm_crtc *crtc, |
489 | const struct drm_display_mode *mode, | 482 | const struct drm_display_mode *mode, |
490 | struct drm_display_mode *adjusted_mode) | 483 | struct drm_display_mode *adjusted_mode) |
diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h index ed569d8a6af3..78b9f986a6e5 100644 --- a/drivers/gpu/drm/gma500/gma_display.h +++ b/drivers/gpu/drm/gma500/gma_display.h | |||
@@ -90,9 +90,6 @@ extern void gma_crtc_restore(struct drm_crtc *crtc); | |||
90 | extern void gma_encoder_prepare(struct drm_encoder *encoder); | 90 | extern void gma_encoder_prepare(struct drm_encoder *encoder); |
91 | extern void gma_encoder_commit(struct drm_encoder *encoder); | 91 | extern void gma_encoder_commit(struct drm_encoder *encoder); |
92 | extern void gma_encoder_destroy(struct drm_encoder *encoder); | 92 | extern void gma_encoder_destroy(struct drm_encoder *encoder); |
93 | extern bool gma_encoder_mode_fixup(struct drm_encoder *encoder, | ||
94 | const struct drm_display_mode *mode, | ||
95 | struct drm_display_mode *adjusted_mode); | ||
96 | 93 | ||
97 | /* Common clock related functions */ | 94 | /* Common clock related functions */ |
98 | extern const struct gma_limit_t *gma_limit(struct drm_crtc *crtc, int refclk); | 95 | extern const struct gma_limit_t *gma_limit(struct drm_crtc *crtc, int refclk); |
diff --git a/drivers/gpu/drm/gma500/intel_gmbus.c b/drivers/gpu/drm/gma500/intel_gmbus.c index 566d330aaeea..e7e22187c539 100644 --- a/drivers/gpu/drm/gma500/intel_gmbus.c +++ b/drivers/gpu/drm/gma500/intel_gmbus.c | |||
@@ -436,7 +436,7 @@ int gma_intel_setup_gmbus(struct drm_device *dev) | |||
436 | return 0; | 436 | return 0; |
437 | 437 | ||
438 | err: | 438 | err: |
439 | while (--i) { | 439 | while (i--) { |
440 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; | 440 | struct intel_gmbus *bus = &dev_priv->gmbus[i]; |
441 | i2c_del_adapter(&bus->adapter); | 441 | i2c_del_adapter(&bus->adapter); |
442 | } | 442 | } |
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index 2d18499d6060..8b2eb32ee988 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c | |||
@@ -601,7 +601,6 @@ static void oaktrail_hdmi_destroy(struct drm_connector *connector) | |||
601 | 601 | ||
602 | static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = { | 602 | static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = { |
603 | .dpms = oaktrail_hdmi_dpms, | 603 | .dpms = oaktrail_hdmi_dpms, |
604 | .mode_fixup = gma_encoder_mode_fixup, | ||
605 | .prepare = gma_encoder_prepare, | 604 | .prepare = gma_encoder_prepare, |
606 | .mode_set = oaktrail_hdmi_mode_set, | 605 | .mode_set = oaktrail_hdmi_mode_set, |
607 | .commit = gma_encoder_commit, | 606 | .commit = gma_encoder_commit, |
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 90db5f4dcce5..0594c45f7164 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c | |||
@@ -253,6 +253,8 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder, | |||
253 | drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names); | 253 | drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names); |
254 | 254 | ||
255 | priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2); | 255 | priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2); |
256 | if (!priv->scale_property) | ||
257 | return -ENOMEM; | ||
256 | 258 | ||
257 | drm_object_attach_property(&connector->base, conf->tv_select_subconnector_property, | 259 | drm_object_attach_property(&connector->base, conf->tv_select_subconnector_property, |
258 | priv->select_subconnector); | 260 | priv->select_subconnector); |
diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c index c400428f6c8c..db0b03fb0ff1 100644 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ b/drivers/gpu/drm/i2c/sil164_drv.c | |||
@@ -252,14 +252,6 @@ sil164_encoder_restore(struct drm_encoder *encoder) | |||
252 | priv->saved_slave_state); | 252 | priv->saved_slave_state); |
253 | } | 253 | } |
254 | 254 | ||
255 | static bool | ||
256 | sil164_encoder_mode_fixup(struct drm_encoder *encoder, | ||
257 | const struct drm_display_mode *mode, | ||
258 | struct drm_display_mode *adjusted_mode) | ||
259 | { | ||
260 | return true; | ||
261 | } | ||
262 | |||
263 | static int | 255 | static int |
264 | sil164_encoder_mode_valid(struct drm_encoder *encoder, | 256 | sil164_encoder_mode_valid(struct drm_encoder *encoder, |
265 | struct drm_display_mode *mode) | 257 | struct drm_display_mode *mode) |
@@ -347,7 +339,6 @@ static const struct drm_encoder_slave_funcs sil164_encoder_funcs = { | |||
347 | .dpms = sil164_encoder_dpms, | 339 | .dpms = sil164_encoder_dpms, |
348 | .save = sil164_encoder_save, | 340 | .save = sil164_encoder_save, |
349 | .restore = sil164_encoder_restore, | 341 | .restore = sil164_encoder_restore, |
350 | .mode_fixup = sil164_encoder_mode_fixup, | ||
351 | .mode_valid = sil164_encoder_mode_valid, | 342 | .mode_valid = sil164_encoder_mode_valid, |
352 | .mode_set = sil164_encoder_mode_set, | 343 | .mode_set = sil164_encoder_mode_set, |
353 | .detect = sil164_encoder_detect, | 344 | .detect = sil164_encoder_detect, |
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 34e38749a817..b61282d89aa3 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c | |||
@@ -856,14 +856,6 @@ static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
856 | priv->dpms = mode; | 856 | priv->dpms = mode; |
857 | } | 857 | } |
858 | 858 | ||
859 | static bool | ||
860 | tda998x_encoder_mode_fixup(struct drm_encoder *encoder, | ||
861 | const struct drm_display_mode *mode, | ||
862 | struct drm_display_mode *adjusted_mode) | ||
863 | { | ||
864 | return true; | ||
865 | } | ||
866 | |||
867 | static int tda998x_connector_mode_valid(struct drm_connector *connector, | 859 | static int tda998x_connector_mode_valid(struct drm_connector *connector, |
868 | struct drm_display_mode *mode) | 860 | struct drm_display_mode *mode) |
869 | { | 861 | { |
@@ -1343,7 +1335,6 @@ static void tda998x_encoder_commit(struct drm_encoder *encoder) | |||
1343 | 1335 | ||
1344 | static const struct drm_encoder_helper_funcs tda998x_encoder_helper_funcs = { | 1336 | static const struct drm_encoder_helper_funcs tda998x_encoder_helper_funcs = { |
1345 | .dpms = tda998x_encoder_dpms, | 1337 | .dpms = tda998x_encoder_dpms, |
1346 | .mode_fixup = tda998x_encoder_mode_fixup, | ||
1347 | .prepare = tda998x_encoder_prepare, | 1338 | .prepare = tda998x_encoder_prepare, |
1348 | .commit = tda998x_encoder_commit, | 1339 | .commit = tda998x_encoder_commit, |
1349 | .mode_set = tda998x_encoder_mode_set, | 1340 | .mode_set = tda998x_encoder_mode_set, |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 11d8414edbbe..44912ecebc1a 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -35,9 +35,12 @@ | |||
35 | #include "i915_trace.h" | 35 | #include "i915_trace.h" |
36 | #include "intel_drv.h" | 36 | #include "intel_drv.h" |
37 | 37 | ||
38 | #include <linux/apple-gmux.h> | ||
38 | #include <linux/console.h> | 39 | #include <linux/console.h> |
39 | #include <linux/module.h> | 40 | #include <linux/module.h> |
40 | #include <linux/pm_runtime.h> | 41 | #include <linux/pm_runtime.h> |
42 | #include <linux/vgaarb.h> | ||
43 | #include <linux/vga_switcheroo.h> | ||
41 | #include <drm/drm_crtc_helper.h> | 44 | #include <drm/drm_crtc_helper.h> |
42 | 45 | ||
43 | static struct drm_driver driver; | 46 | static struct drm_driver driver; |
@@ -969,6 +972,15 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
969 | if (PCI_FUNC(pdev->devfn)) | 972 | if (PCI_FUNC(pdev->devfn)) |
970 | return -ENODEV; | 973 | return -ENODEV; |
971 | 974 | ||
975 | /* | ||
976 | * apple-gmux is needed on dual GPU MacBook Pro | ||
977 | * to probe the panel if we're the inactive GPU. | ||
978 | */ | ||
979 | if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) && | ||
980 | apple_gmux_present() && pdev != vga_default_device() && | ||
981 | !vga_switcheroo_handler_flags()) | ||
982 | return -EPROBE_DEFER; | ||
983 | |||
972 | return drm_get_pci_dev(pdev, ent, &driver); | 984 | return drm_get_pci_dev(pdev, ent, &driver); |
973 | } | 985 | } |
974 | 986 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index e9c2bfd85b52..1f3eef6fb345 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c | |||
@@ -193,10 +193,26 @@ static void i915_gem_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_n | |||
193 | 193 | ||
194 | static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) | 194 | static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) |
195 | { | 195 | { |
196 | return -EINVAL; | 196 | struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); |
197 | int ret; | ||
198 | |||
199 | if (obj->base.size < vma->vm_end - vma->vm_start) | ||
200 | return -EINVAL; | ||
201 | |||
202 | if (!obj->base.filp) | ||
203 | return -ENODEV; | ||
204 | |||
205 | ret = obj->base.filp->f_op->mmap(obj->base.filp, vma); | ||
206 | if (ret) | ||
207 | return ret; | ||
208 | |||
209 | fput(vma->vm_file); | ||
210 | vma->vm_file = get_file(obj->base.filp); | ||
211 | |||
212 | return 0; | ||
197 | } | 213 | } |
198 | 214 | ||
199 | static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, size_t start, size_t length, enum dma_data_direction direction) | 215 | static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction) |
200 | { | 216 | { |
201 | struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); | 217 | struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); |
202 | struct drm_device *dev = obj->base.dev; | 218 | struct drm_device *dev = obj->base.dev; |
@@ -212,6 +228,27 @@ static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, size_t start, size | |||
212 | return ret; | 228 | return ret; |
213 | } | 229 | } |
214 | 230 | ||
231 | static void i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction) | ||
232 | { | ||
233 | struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); | ||
234 | struct drm_device *dev = obj->base.dev; | ||
235 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
236 | bool was_interruptible; | ||
237 | int ret; | ||
238 | |||
239 | mutex_lock(&dev->struct_mutex); | ||
240 | was_interruptible = dev_priv->mm.interruptible; | ||
241 | dev_priv->mm.interruptible = false; | ||
242 | |||
243 | ret = i915_gem_object_set_to_gtt_domain(obj, false); | ||
244 | |||
245 | dev_priv->mm.interruptible = was_interruptible; | ||
246 | mutex_unlock(&dev->struct_mutex); | ||
247 | |||
248 | if (unlikely(ret)) | ||
249 | DRM_ERROR("unable to flush buffer following CPU access; rendering may be corrupt\n"); | ||
250 | } | ||
251 | |||
215 | static const struct dma_buf_ops i915_dmabuf_ops = { | 252 | static const struct dma_buf_ops i915_dmabuf_ops = { |
216 | .map_dma_buf = i915_gem_map_dma_buf, | 253 | .map_dma_buf = i915_gem_map_dma_buf, |
217 | .unmap_dma_buf = i915_gem_unmap_dma_buf, | 254 | .unmap_dma_buf = i915_gem_unmap_dma_buf, |
@@ -224,6 +261,7 @@ static const struct dma_buf_ops i915_dmabuf_ops = { | |||
224 | .vmap = i915_gem_dmabuf_vmap, | 261 | .vmap = i915_gem_dmabuf_vmap, |
225 | .vunmap = i915_gem_dmabuf_vunmap, | 262 | .vunmap = i915_gem_dmabuf_vunmap, |
226 | .begin_cpu_access = i915_gem_begin_cpu_access, | 263 | .begin_cpu_access = i915_gem_begin_cpu_access, |
264 | .end_cpu_access = i915_gem_end_cpu_access, | ||
227 | }; | 265 | }; |
228 | 266 | ||
229 | struct dma_buf *i915_gem_prime_export(struct drm_device *dev, | 267 | struct dma_buf *i915_gem_prime_export(struct drm_device *dev, |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7a5ed95f2cd9..e1e7cdee3bbd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -10521,7 +10521,6 @@ retry: | |||
10521 | } | 10521 | } |
10522 | 10522 | ||
10523 | connector_state->crtc = crtc; | 10523 | connector_state->crtc = crtc; |
10524 | connector_state->best_encoder = &intel_encoder->base; | ||
10525 | 10524 | ||
10526 | crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); | 10525 | crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); |
10527 | if (IS_ERR(crtc_state)) { | 10526 | if (IS_ERR(crtc_state)) { |
@@ -10617,7 +10616,6 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, | |||
10617 | if (IS_ERR(crtc_state)) | 10616 | if (IS_ERR(crtc_state)) |
10618 | goto fail; | 10617 | goto fail; |
10619 | 10618 | ||
10620 | connector_state->best_encoder = NULL; | ||
10621 | connector_state->crtc = NULL; | 10619 | connector_state->crtc = NULL; |
10622 | 10620 | ||
10623 | crtc_state->base.enable = crtc_state->base.active = false; | 10621 | crtc_state->base.enable = crtc_state->base.active = false; |
@@ -15593,6 +15591,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) | |||
15593 | crtc->base.state->active = crtc->active; | 15591 | crtc->base.state->active = crtc->active; |
15594 | crtc->base.enabled = crtc->active; | 15592 | crtc->base.enabled = crtc->active; |
15595 | crtc->base.state->connector_mask = 0; | 15593 | crtc->base.state->connector_mask = 0; |
15594 | crtc->base.state->encoder_mask = 0; | ||
15596 | 15595 | ||
15597 | /* Because we only establish the connector -> encoder -> | 15596 | /* Because we only establish the connector -> encoder -> |
15598 | * crtc links if something is active, this means the | 15597 | * crtc links if something is active, this means the |
@@ -15832,6 +15831,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) | |||
15832 | */ | 15831 | */ |
15833 | encoder->base.crtc->state->connector_mask |= | 15832 | encoder->base.crtc->state->connector_mask |= |
15834 | 1 << drm_connector_index(&connector->base); | 15833 | 1 << drm_connector_index(&connector->base); |
15834 | encoder->base.crtc->state->encoder_mask |= | ||
15835 | 1 << drm_encoder_index(&encoder->base); | ||
15835 | } | 15836 | } |
15836 | 15837 | ||
15837 | } else { | 15838 | } else { |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e2bea710614f..da704c6ee5cb 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1188,7 +1188,6 @@ intel_dp_aux_fini(struct intel_dp *intel_dp) | |||
1188 | static int | 1188 | static int |
1189 | intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) | 1189 | intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) |
1190 | { | 1190 | { |
1191 | struct drm_device *dev = intel_dp_to_dev(intel_dp); | ||
1192 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | 1191 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
1193 | enum port port = intel_dig_port->port; | 1192 | enum port port = intel_dig_port->port; |
1194 | int ret; | 1193 | int ret; |
@@ -1199,7 +1198,7 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) | |||
1199 | if (!intel_dp->aux.name) | 1198 | if (!intel_dp->aux.name) |
1200 | return -ENOMEM; | 1199 | return -ENOMEM; |
1201 | 1200 | ||
1202 | intel_dp->aux.dev = dev->dev; | 1201 | intel_dp->aux.dev = connector->base.kdev; |
1203 | intel_dp->aux.transfer = intel_dp_aux_transfer; | 1202 | intel_dp->aux.transfer = intel_dp_aux_transfer; |
1204 | 1203 | ||
1205 | DRM_DEBUG_KMS("registering %s bus for %s\n", | 1204 | DRM_DEBUG_KMS("registering %s bus for %s\n", |
@@ -1214,16 +1213,6 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector) | |||
1214 | return ret; | 1213 | return ret; |
1215 | } | 1214 | } |
1216 | 1215 | ||
1217 | ret = sysfs_create_link(&connector->base.kdev->kobj, | ||
1218 | &intel_dp->aux.ddc.dev.kobj, | ||
1219 | intel_dp->aux.ddc.dev.kobj.name); | ||
1220 | if (ret < 0) { | ||
1221 | DRM_ERROR("sysfs_create_link() for %s failed (%d)\n", | ||
1222 | intel_dp->aux.name, ret); | ||
1223 | intel_dp_aux_fini(intel_dp); | ||
1224 | return ret; | ||
1225 | } | ||
1226 | |||
1227 | return 0; | 1216 | return 0; |
1228 | } | 1217 | } |
1229 | 1218 | ||
@@ -1232,9 +1221,7 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector) | |||
1232 | { | 1221 | { |
1233 | struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base); | 1222 | struct intel_dp *intel_dp = intel_attached_dp(&intel_connector->base); |
1234 | 1223 | ||
1235 | if (!intel_connector->mst_port) | 1224 | intel_dp_aux_fini(intel_dp); |
1236 | sysfs_remove_link(&intel_connector->base.kdev->kobj, | ||
1237 | intel_dp->aux.ddc.dev.kobj.name); | ||
1238 | intel_connector_unregister(intel_connector); | 1225 | intel_connector_unregister(intel_connector); |
1239 | } | 1226 | } |
1240 | 1227 | ||
@@ -4868,7 +4855,6 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) | |||
4868 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); | 4855 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
4869 | struct intel_dp *intel_dp = &intel_dig_port->dp; | 4856 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
4870 | 4857 | ||
4871 | intel_dp_aux_fini(intel_dp); | ||
4872 | intel_dp_mst_encoder_cleanup(intel_dig_port); | 4858 | intel_dp_mst_encoder_cleanup(intel_dig_port); |
4873 | if (is_edp(intel_dp)) { | 4859 | if (is_edp(intel_dp)) { |
4874 | cancel_delayed_work_sync(&intel_dp->panel_vdd_work); | 4860 | cancel_delayed_work_sync(&intel_dp->panel_vdd_work); |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 0da0240caf81..811ddf7799f0 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/dmi.h> | 31 | #include <linux/dmi.h> |
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/vga_switcheroo.h> | ||
34 | #include <drm/drmP.h> | 35 | #include <drm/drmP.h> |
35 | #include <drm/drm_atomic_helper.h> | 36 | #include <drm/drm_atomic_helper.h> |
36 | #include <drm/drm_crtc.h> | 37 | #include <drm/drm_crtc.h> |
@@ -1080,7 +1081,12 @@ void intel_lvds_init(struct drm_device *dev) | |||
1080 | * preferred mode is the right one. | 1081 | * preferred mode is the right one. |
1081 | */ | 1082 | */ |
1082 | mutex_lock(&dev->mode_config.mutex); | 1083 | mutex_lock(&dev->mode_config.mutex); |
1083 | edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, pin)); | 1084 | if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) |
1085 | edid = drm_get_edid_switcheroo(connector, | ||
1086 | intel_gmbus_get_adapter(dev_priv, pin)); | ||
1087 | else | ||
1088 | edid = drm_get_edid(connector, | ||
1089 | intel_gmbus_get_adapter(dev_priv, pin)); | ||
1084 | if (edid) { | 1090 | if (edid) { |
1085 | if (drm_add_edid_modes(connector, edid)) { | 1091 | if (drm_add_edid_modes(connector, edid)) { |
1086 | drm_mode_connector_update_edid_property(connector, | 1092 | drm_mode_connector_update_edid_property(connector, |
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index 063825fecbe2..21d615827837 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c | |||
@@ -109,13 +109,6 @@ static void dw_hdmi_imx_encoder_disable(struct drm_encoder *encoder) | |||
109 | { | 109 | { |
110 | } | 110 | } |
111 | 111 | ||
112 | static bool dw_hdmi_imx_encoder_mode_fixup(struct drm_encoder *encoder, | ||
113 | const struct drm_display_mode *mode, | ||
114 | struct drm_display_mode *adj_mode) | ||
115 | { | ||
116 | return true; | ||
117 | } | ||
118 | |||
119 | static void dw_hdmi_imx_encoder_mode_set(struct drm_encoder *encoder, | 112 | static void dw_hdmi_imx_encoder_mode_set(struct drm_encoder *encoder, |
120 | struct drm_display_mode *mode, | 113 | struct drm_display_mode *mode, |
121 | struct drm_display_mode *adj_mode) | 114 | struct drm_display_mode *adj_mode) |
@@ -138,7 +131,6 @@ static void dw_hdmi_imx_encoder_prepare(struct drm_encoder *encoder) | |||
138 | } | 131 | } |
139 | 132 | ||
140 | static const struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = { | 133 | static const struct drm_encoder_helper_funcs dw_hdmi_imx_encoder_helper_funcs = { |
141 | .mode_fixup = dw_hdmi_imx_encoder_mode_fixup, | ||
142 | .mode_set = dw_hdmi_imx_encoder_mode_set, | 134 | .mode_set = dw_hdmi_imx_encoder_mode_set, |
143 | .prepare = dw_hdmi_imx_encoder_prepare, | 135 | .prepare = dw_hdmi_imx_encoder_prepare, |
144 | .commit = dw_hdmi_imx_encoder_commit, | 136 | .commit = dw_hdmi_imx_encoder_commit, |
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 22ac482231ed..024d6134b848 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c | |||
@@ -139,13 +139,6 @@ static void imx_ldb_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
139 | { | 139 | { |
140 | } | 140 | } |
141 | 141 | ||
142 | static bool imx_ldb_encoder_mode_fixup(struct drm_encoder *encoder, | ||
143 | const struct drm_display_mode *mode, | ||
144 | struct drm_display_mode *adjusted_mode) | ||
145 | { | ||
146 | return true; | ||
147 | } | ||
148 | |||
149 | static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno, | 142 | static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno, |
150 | unsigned long serial_clk, unsigned long di_clk) | 143 | unsigned long serial_clk, unsigned long di_clk) |
151 | { | 144 | { |
@@ -376,7 +369,6 @@ static const struct drm_encoder_funcs imx_ldb_encoder_funcs = { | |||
376 | 369 | ||
377 | static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = { | 370 | static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = { |
378 | .dpms = imx_ldb_encoder_dpms, | 371 | .dpms = imx_ldb_encoder_dpms, |
379 | .mode_fixup = imx_ldb_encoder_mode_fixup, | ||
380 | .prepare = imx_ldb_encoder_prepare, | 372 | .prepare = imx_ldb_encoder_prepare, |
381 | .commit = imx_ldb_encoder_commit, | 373 | .commit = imx_ldb_encoder_commit, |
382 | .mode_set = imx_ldb_encoder_mode_set, | 374 | .mode_set = imx_ldb_encoder_mode_set, |
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index 292349f0b132..ae7a9fb3b8a2 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c | |||
@@ -286,13 +286,6 @@ static void imx_tve_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
286 | dev_err(tve->dev, "failed to disable TVOUT: %d\n", ret); | 286 | dev_err(tve->dev, "failed to disable TVOUT: %d\n", ret); |
287 | } | 287 | } |
288 | 288 | ||
289 | static bool imx_tve_encoder_mode_fixup(struct drm_encoder *encoder, | ||
290 | const struct drm_display_mode *mode, | ||
291 | struct drm_display_mode *adjusted_mode) | ||
292 | { | ||
293 | return true; | ||
294 | } | ||
295 | |||
296 | static void imx_tve_encoder_prepare(struct drm_encoder *encoder) | 289 | static void imx_tve_encoder_prepare(struct drm_encoder *encoder) |
297 | { | 290 | { |
298 | struct imx_tve *tve = enc_to_tve(encoder); | 291 | struct imx_tve *tve = enc_to_tve(encoder); |
@@ -379,7 +372,6 @@ static const struct drm_encoder_funcs imx_tve_encoder_funcs = { | |||
379 | 372 | ||
380 | static const struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = { | 373 | static const struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = { |
381 | .dpms = imx_tve_encoder_dpms, | 374 | .dpms = imx_tve_encoder_dpms, |
382 | .mode_fixup = imx_tve_encoder_mode_fixup, | ||
383 | .prepare = imx_tve_encoder_prepare, | 375 | .prepare = imx_tve_encoder_prepare, |
384 | .mode_set = imx_tve_encoder_mode_set, | 376 | .mode_set = imx_tve_encoder_mode_set, |
385 | .commit = imx_tve_encoder_commit, | 377 | .commit = imx_tve_encoder_commit, |
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 0ffef172afb4..363e2c7741e2 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c | |||
@@ -112,13 +112,6 @@ static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
112 | drm_panel_enable(imxpd->panel); | 112 | drm_panel_enable(imxpd->panel); |
113 | } | 113 | } |
114 | 114 | ||
115 | static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder, | ||
116 | const struct drm_display_mode *mode, | ||
117 | struct drm_display_mode *adjusted_mode) | ||
118 | { | ||
119 | return true; | ||
120 | } | ||
121 | |||
122 | static void imx_pd_encoder_prepare(struct drm_encoder *encoder) | 115 | static void imx_pd_encoder_prepare(struct drm_encoder *encoder) |
123 | { | 116 | { |
124 | struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); | 117 | struct imx_parallel_display *imxpd = enc_to_imxpd(encoder); |
@@ -166,7 +159,6 @@ static const struct drm_encoder_funcs imx_pd_encoder_funcs = { | |||
166 | 159 | ||
167 | static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { | 160 | static const struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { |
168 | .dpms = imx_pd_encoder_dpms, | 161 | .dpms = imx_pd_encoder_dpms, |
169 | .mode_fixup = imx_pd_encoder_mode_fixup, | ||
170 | .prepare = imx_pd_encoder_prepare, | 162 | .prepare = imx_pd_encoder_prepare, |
171 | .commit = imx_pd_encoder_commit, | 163 | .commit = imx_pd_encoder_commit, |
172 | .mode_set = imx_pd_encoder_mode_set, | 164 | .mode_set = imx_pd_encoder_mode_set, |
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index dc13c4857e6f..af8b4c19cf15 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c | |||
@@ -1479,13 +1479,6 @@ void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
1479 | * These functions are analagous to those in the CRTC code, but are intended | 1479 | * These functions are analagous to those in the CRTC code, but are intended |
1480 | * to handle any encoder-specific limitations | 1480 | * to handle any encoder-specific limitations |
1481 | */ | 1481 | */ |
1482 | static bool mga_encoder_mode_fixup(struct drm_encoder *encoder, | ||
1483 | const struct drm_display_mode *mode, | ||
1484 | struct drm_display_mode *adjusted_mode) | ||
1485 | { | ||
1486 | return true; | ||
1487 | } | ||
1488 | |||
1489 | static void mga_encoder_mode_set(struct drm_encoder *encoder, | 1482 | static void mga_encoder_mode_set(struct drm_encoder *encoder, |
1490 | struct drm_display_mode *mode, | 1483 | struct drm_display_mode *mode, |
1491 | struct drm_display_mode *adjusted_mode) | 1484 | struct drm_display_mode *adjusted_mode) |
@@ -1515,7 +1508,6 @@ static void mga_encoder_destroy(struct drm_encoder *encoder) | |||
1515 | 1508 | ||
1516 | static const struct drm_encoder_helper_funcs mga_encoder_helper_funcs = { | 1509 | static const struct drm_encoder_helper_funcs mga_encoder_helper_funcs = { |
1517 | .dpms = mga_encoder_dpms, | 1510 | .dpms = mga_encoder_dpms, |
1518 | .mode_fixup = mga_encoder_mode_fixup, | ||
1519 | .mode_set = mga_encoder_mode_set, | 1511 | .mode_set = mga_encoder_mode_set, |
1520 | .prepare = mga_encoder_prepare, | 1512 | .prepare = mga_encoder_prepare, |
1521 | .commit = mga_encoder_commit, | 1513 | .commit = mga_encoder_commit, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dsi_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dsi_encoder.c index 2f57e9453b67..106f0e772595 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dsi_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dsi_encoder.c | |||
@@ -47,13 +47,6 @@ static const struct drm_encoder_funcs mdp4_dsi_encoder_funcs = { | |||
47 | .destroy = mdp4_dsi_encoder_destroy, | 47 | .destroy = mdp4_dsi_encoder_destroy, |
48 | }; | 48 | }; |
49 | 49 | ||
50 | static bool mdp4_dsi_encoder_mode_fixup(struct drm_encoder *encoder, | ||
51 | const struct drm_display_mode *mode, | ||
52 | struct drm_display_mode *adjusted_mode) | ||
53 | { | ||
54 | return true; | ||
55 | } | ||
56 | |||
57 | static void mdp4_dsi_encoder_mode_set(struct drm_encoder *encoder, | 50 | static void mdp4_dsi_encoder_mode_set(struct drm_encoder *encoder, |
58 | struct drm_display_mode *mode, | 51 | struct drm_display_mode *mode, |
59 | struct drm_display_mode *adjusted_mode) | 52 | struct drm_display_mode *adjusted_mode) |
@@ -163,7 +156,6 @@ static void mdp4_dsi_encoder_enable(struct drm_encoder *encoder) | |||
163 | } | 156 | } |
164 | 157 | ||
165 | static const struct drm_encoder_helper_funcs mdp4_dsi_encoder_helper_funcs = { | 158 | static const struct drm_encoder_helper_funcs mdp4_dsi_encoder_helper_funcs = { |
166 | .mode_fixup = mdp4_dsi_encoder_mode_fixup, | ||
167 | .mode_set = mdp4_dsi_encoder_mode_set, | 159 | .mode_set = mdp4_dsi_encoder_mode_set, |
168 | .disable = mdp4_dsi_encoder_disable, | 160 | .disable = mdp4_dsi_encoder_disable, |
169 | .enable = mdp4_dsi_encoder_enable, | 161 | .enable = mdp4_dsi_encoder_enable, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c index a21df54cb50f..35ad78a1dc1c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c | |||
@@ -94,13 +94,6 @@ static const struct drm_encoder_funcs mdp4_dtv_encoder_funcs = { | |||
94 | .destroy = mdp4_dtv_encoder_destroy, | 94 | .destroy = mdp4_dtv_encoder_destroy, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static bool mdp4_dtv_encoder_mode_fixup(struct drm_encoder *encoder, | ||
98 | const struct drm_display_mode *mode, | ||
99 | struct drm_display_mode *adjusted_mode) | ||
100 | { | ||
101 | return true; | ||
102 | } | ||
103 | |||
104 | static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder, | 97 | static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder, |
105 | struct drm_display_mode *mode, | 98 | struct drm_display_mode *mode, |
106 | struct drm_display_mode *adjusted_mode) | 99 | struct drm_display_mode *adjusted_mode) |
@@ -234,7 +227,6 @@ static void mdp4_dtv_encoder_enable(struct drm_encoder *encoder) | |||
234 | } | 227 | } |
235 | 228 | ||
236 | static const struct drm_encoder_helper_funcs mdp4_dtv_encoder_helper_funcs = { | 229 | static const struct drm_encoder_helper_funcs mdp4_dtv_encoder_helper_funcs = { |
237 | .mode_fixup = mdp4_dtv_encoder_mode_fixup, | ||
238 | .mode_set = mdp4_dtv_encoder_mode_set, | 230 | .mode_set = mdp4_dtv_encoder_mode_set, |
239 | .enable = mdp4_dtv_encoder_enable, | 231 | .enable = mdp4_dtv_encoder_enable, |
240 | .disable = mdp4_dtv_encoder_disable, | 232 | .disable = mdp4_dtv_encoder_disable, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c index cd63fedb67cc..bc3d8e719c6c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c | |||
@@ -260,13 +260,6 @@ static void setup_phy(struct drm_encoder *encoder) | |||
260 | mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0); | 260 | mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0); |
261 | } | 261 | } |
262 | 262 | ||
263 | static bool mdp4_lcdc_encoder_mode_fixup(struct drm_encoder *encoder, | ||
264 | const struct drm_display_mode *mode, | ||
265 | struct drm_display_mode *adjusted_mode) | ||
266 | { | ||
267 | return true; | ||
268 | } | ||
269 | |||
270 | static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder, | 263 | static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder, |
271 | struct drm_display_mode *mode, | 264 | struct drm_display_mode *mode, |
272 | struct drm_display_mode *adjusted_mode) | 265 | struct drm_display_mode *adjusted_mode) |
@@ -430,7 +423,6 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) | |||
430 | } | 423 | } |
431 | 424 | ||
432 | static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = { | 425 | static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = { |
433 | .mode_fixup = mdp4_lcdc_encoder_mode_fixup, | ||
434 | .mode_set = mdp4_lcdc_encoder_mode_set, | 426 | .mode_set = mdp4_lcdc_encoder_mode_set, |
435 | .disable = mdp4_lcdc_encoder_disable, | 427 | .disable = mdp4_lcdc_encoder_disable, |
436 | .enable = mdp4_lcdc_encoder_enable, | 428 | .enable = mdp4_lcdc_encoder_enable, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c index 1aa21dba663d..69094cb28103 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c | |||
@@ -188,13 +188,6 @@ static const struct drm_encoder_funcs mdp5_cmd_encoder_funcs = { | |||
188 | .destroy = mdp5_cmd_encoder_destroy, | 188 | .destroy = mdp5_cmd_encoder_destroy, |
189 | }; | 189 | }; |
190 | 190 | ||
191 | static bool mdp5_cmd_encoder_mode_fixup(struct drm_encoder *encoder, | ||
192 | const struct drm_display_mode *mode, | ||
193 | struct drm_display_mode *adjusted_mode) | ||
194 | { | ||
195 | return true; | ||
196 | } | ||
197 | |||
198 | static void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder, | 191 | static void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder, |
199 | struct drm_display_mode *mode, | 192 | struct drm_display_mode *mode, |
200 | struct drm_display_mode *adjusted_mode) | 193 | struct drm_display_mode *adjusted_mode) |
@@ -256,7 +249,6 @@ static void mdp5_cmd_encoder_enable(struct drm_encoder *encoder) | |||
256 | } | 249 | } |
257 | 250 | ||
258 | static const struct drm_encoder_helper_funcs mdp5_cmd_encoder_helper_funcs = { | 251 | static const struct drm_encoder_helper_funcs mdp5_cmd_encoder_helper_funcs = { |
259 | .mode_fixup = mdp5_cmd_encoder_mode_fixup, | ||
260 | .mode_set = mdp5_cmd_encoder_mode_set, | 252 | .mode_set = mdp5_cmd_encoder_mode_set, |
261 | .disable = mdp5_cmd_encoder_disable, | 253 | .disable = mdp5_cmd_encoder_disable, |
262 | .enable = mdp5_cmd_encoder_enable, | 254 | .enable = mdp5_cmd_encoder_enable, |
@@ -340,4 +332,3 @@ fail: | |||
340 | 332 | ||
341 | return ERR_PTR(ret); | 333 | return ERR_PTR(ret); |
342 | } | 334 | } |
343 | |||
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c index 0d737cad03a6..1d95f9fd9dc7 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | |||
@@ -112,13 +112,6 @@ static const struct drm_encoder_funcs mdp5_encoder_funcs = { | |||
112 | .destroy = mdp5_encoder_destroy, | 112 | .destroy = mdp5_encoder_destroy, |
113 | }; | 113 | }; |
114 | 114 | ||
115 | static bool mdp5_encoder_mode_fixup(struct drm_encoder *encoder, | ||
116 | const struct drm_display_mode *mode, | ||
117 | struct drm_display_mode *adjusted_mode) | ||
118 | { | ||
119 | return true; | ||
120 | } | ||
121 | |||
122 | static void mdp5_encoder_mode_set(struct drm_encoder *encoder, | 115 | static void mdp5_encoder_mode_set(struct drm_encoder *encoder, |
123 | struct drm_display_mode *mode, | 116 | struct drm_display_mode *mode, |
124 | struct drm_display_mode *adjusted_mode) | 117 | struct drm_display_mode *adjusted_mode) |
@@ -287,7 +280,6 @@ static void mdp5_encoder_enable(struct drm_encoder *encoder) | |||
287 | } | 280 | } |
288 | 281 | ||
289 | static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = { | 282 | static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = { |
290 | .mode_fixup = mdp5_encoder_mode_fixup, | ||
291 | .mode_set = mdp5_encoder_mode_set, | 283 | .mode_set = mdp5_encoder_mode_set, |
292 | .disable = mdp5_encoder_disable, | 284 | .disable = mdp5_encoder_disable, |
293 | .enable = mdp5_encoder_enable, | 285 | .enable = mdp5_encoder_enable, |
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index d95af6eba602..d9759bf3482e 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c | |||
@@ -62,12 +62,8 @@ static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) | |||
62 | struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par; | 62 | struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par; |
63 | struct msm_fbdev *fbdev = to_msm_fbdev(helper); | 63 | struct msm_fbdev *fbdev = to_msm_fbdev(helper); |
64 | struct drm_gem_object *drm_obj = fbdev->bo; | 64 | struct drm_gem_object *drm_obj = fbdev->bo; |
65 | struct drm_device *dev = helper->dev; | ||
66 | int ret = 0; | 65 | int ret = 0; |
67 | 66 | ||
68 | if (drm_device_is_unplugged(dev)) | ||
69 | return -ENODEV; | ||
70 | |||
71 | ret = drm_gem_mmap_obj(drm_obj, drm_obj->size, vma); | 67 | ret = drm_gem_mmap_obj(drm_obj, drm_obj->size, vma); |
72 | if (ret) { | 68 | if (ret) { |
73 | pr_err("%s:drm_gem_mmap_obj fail\n", __func__); | 69 | pr_err("%s:drm_gem_mmap_obj fail\n", __func__); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index d5e6938cc6bc..cdf522770cfa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
@@ -314,7 +314,7 @@ void nouveau_register_dsm_handler(void) | |||
314 | if (!r) | 314 | if (!r) |
315 | return; | 315 | return; |
316 | 316 | ||
317 | vga_switcheroo_register_handler(&nouveau_dsm_handler); | 317 | vga_switcheroo_register_handler(&nouveau_dsm_handler, 0); |
318 | } | 318 | } |
319 | 319 | ||
320 | /* Must be called for Optimus models before the card can be turned off */ | 320 | /* Must be called for Optimus models before the card can be turned off */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index fcebfae5d426..ae96ebc490fb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <acpi/button.h> | 27 | #include <acpi/button.h> |
28 | 28 | ||
29 | #include <linux/pm_runtime.h> | 29 | #include <linux/pm_runtime.h> |
30 | #include <linux/vga_switcheroo.h> | ||
30 | 31 | ||
31 | #include <drm/drmP.h> | 32 | #include <drm/drmP.h> |
32 | #include <drm/drm_edid.h> | 33 | #include <drm/drm_edid.h> |
@@ -153,6 +154,17 @@ nouveau_connector_ddc_detect(struct drm_connector *connector) | |||
153 | if (ret == 0) | 154 | if (ret == 0) |
154 | break; | 155 | break; |
155 | } else | 156 | } else |
157 | if ((vga_switcheroo_handler_flags() & | ||
158 | VGA_SWITCHEROO_CAN_SWITCH_DDC) && | ||
159 | nv_encoder->dcb->type == DCB_OUTPUT_LVDS && | ||
160 | nv_encoder->i2c) { | ||
161 | int ret; | ||
162 | vga_switcheroo_lock_ddc(dev->pdev); | ||
163 | ret = nvkm_probe_i2c(nv_encoder->i2c, 0x50); | ||
164 | vga_switcheroo_unlock_ddc(dev->pdev); | ||
165 | if (ret) | ||
166 | break; | ||
167 | } else | ||
156 | if (nv_encoder->i2c) { | 168 | if (nv_encoder->i2c) { |
157 | if (nvkm_probe_i2c(nv_encoder->i2c, 0x50)) | 169 | if (nvkm_probe_i2c(nv_encoder->i2c, 0x50)) |
158 | break; | 170 | break; |
@@ -265,7 +277,14 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
265 | 277 | ||
266 | nv_encoder = nouveau_connector_ddc_detect(connector); | 278 | nv_encoder = nouveau_connector_ddc_detect(connector); |
267 | if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { | 279 | if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { |
268 | nv_connector->edid = drm_get_edid(connector, i2c); | 280 | if ((vga_switcheroo_handler_flags() & |
281 | VGA_SWITCHEROO_CAN_SWITCH_DDC) && | ||
282 | nv_connector->type == DCB_CONNECTOR_LVDS) | ||
283 | nv_connector->edid = drm_get_edid_switcheroo(connector, | ||
284 | i2c); | ||
285 | else | ||
286 | nv_connector->edid = drm_get_edid(connector, i2c); | ||
287 | |||
269 | drm_mode_connector_update_edid_property(connector, | 288 | drm_mode_connector_update_edid_property(connector, |
270 | nv_connector->edid); | 289 | nv_connector->edid); |
271 | if (!nv_connector->edid) { | 290 | if (!nv_connector->edid) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 2f2f252e3fb6..bb8498c9b13e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -22,11 +22,13 @@ | |||
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/apple-gmux.h> | ||
25 | #include <linux/console.h> | 26 | #include <linux/console.h> |
26 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
29 | #include <linux/pm_runtime.h> | 30 | #include <linux/pm_runtime.h> |
31 | #include <linux/vgaarb.h> | ||
30 | #include <linux/vga_switcheroo.h> | 32 | #include <linux/vga_switcheroo.h> |
31 | 33 | ||
32 | #include "drmP.h" | 34 | #include "drmP.h" |
@@ -312,6 +314,15 @@ static int nouveau_drm_probe(struct pci_dev *pdev, | |||
312 | bool boot = false; | 314 | bool boot = false; |
313 | int ret; | 315 | int ret; |
314 | 316 | ||
317 | /* | ||
318 | * apple-gmux is needed on dual GPU MacBook Pro | ||
319 | * to probe the panel if we're the inactive GPU. | ||
320 | */ | ||
321 | if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) && | ||
322 | apple_gmux_present() && pdev != vga_default_device() && | ||
323 | !vga_switcheroo_handler_flags()) | ||
324 | return -EPROBE_DEFER; | ||
325 | |||
315 | /* remove conflicting drivers (vesafb, efifb etc) */ | 326 | /* remove conflicting drivers (vesafb, efifb etc) */ |
316 | aper = alloc_apertures(3); | 327 | aper = alloc_apertures(3); |
317 | if (!aper) | 328 | if (!aper) |
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index 27c297672076..aebae1c2dab2 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | |||
@@ -79,7 +79,7 @@ static void omap_gem_dmabuf_release(struct dma_buf *buffer) | |||
79 | 79 | ||
80 | 80 | ||
81 | static int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer, | 81 | static int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer, |
82 | size_t start, size_t len, enum dma_data_direction dir) | 82 | enum dma_data_direction dir) |
83 | { | 83 | { |
84 | struct drm_gem_object *obj = buffer->priv; | 84 | struct drm_gem_object *obj = buffer->priv; |
85 | struct page **pages; | 85 | struct page **pages; |
@@ -94,7 +94,7 @@ static int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer, | |||
94 | } | 94 | } |
95 | 95 | ||
96 | static void omap_gem_dmabuf_end_cpu_access(struct dma_buf *buffer, | 96 | static void omap_gem_dmabuf_end_cpu_access(struct dma_buf *buffer, |
97 | size_t start, size_t len, enum dma_data_direction dir) | 97 | enum dma_data_direction dir) |
98 | { | 98 | { |
99 | struct drm_gem_object *obj = buffer->priv; | 99 | struct drm_gem_object *obj = buffer->priv; |
100 | omap_gem_put_pages(obj); | 100 | omap_gem_put_pages(obj); |
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 86276519b2ef..43e5f503d1c5 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c | |||
@@ -734,14 +734,6 @@ static void qxl_enc_dpms(struct drm_encoder *encoder, int mode) | |||
734 | DRM_DEBUG("\n"); | 734 | DRM_DEBUG("\n"); |
735 | } | 735 | } |
736 | 736 | ||
737 | static bool qxl_enc_mode_fixup(struct drm_encoder *encoder, | ||
738 | const struct drm_display_mode *mode, | ||
739 | struct drm_display_mode *adjusted_mode) | ||
740 | { | ||
741 | DRM_DEBUG("\n"); | ||
742 | return true; | ||
743 | } | ||
744 | |||
745 | static void qxl_enc_prepare(struct drm_encoder *encoder) | 737 | static void qxl_enc_prepare(struct drm_encoder *encoder) |
746 | { | 738 | { |
747 | DRM_DEBUG("\n"); | 739 | DRM_DEBUG("\n"); |
@@ -864,7 +856,6 @@ static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector) | |||
864 | 856 | ||
865 | static const struct drm_encoder_helper_funcs qxl_enc_helper_funcs = { | 857 | static const struct drm_encoder_helper_funcs qxl_enc_helper_funcs = { |
866 | .dpms = qxl_enc_dpms, | 858 | .dpms = qxl_enc_dpms, |
867 | .mode_fixup = qxl_enc_mode_fixup, | ||
868 | .prepare = qxl_enc_prepare, | 859 | .prepare = qxl_enc_prepare, |
869 | .mode_set = qxl_enc_mode_set, | 860 | .mode_set = qxl_enc_mode_set, |
870 | .commit = qxl_enc_commit, | 861 | .commit = qxl_enc_commit, |
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 01b20e14a247..1603751b1164 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c | |||
@@ -2623,16 +2623,8 @@ radeon_atom_ext_dpms(struct drm_encoder *encoder, int mode) | |||
2623 | 2623 | ||
2624 | } | 2624 | } |
2625 | 2625 | ||
2626 | static bool radeon_atom_ext_mode_fixup(struct drm_encoder *encoder, | ||
2627 | const struct drm_display_mode *mode, | ||
2628 | struct drm_display_mode *adjusted_mode) | ||
2629 | { | ||
2630 | return true; | ||
2631 | } | ||
2632 | |||
2633 | static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = { | 2626 | static const struct drm_encoder_helper_funcs radeon_atom_ext_helper_funcs = { |
2634 | .dpms = radeon_atom_ext_dpms, | 2627 | .dpms = radeon_atom_ext_dpms, |
2635 | .mode_fixup = radeon_atom_ext_mode_fixup, | ||
2636 | .prepare = radeon_atom_ext_prepare, | 2628 | .prepare = radeon_atom_ext_prepare, |
2637 | .mode_set = radeon_atom_ext_mode_set, | 2629 | .mode_set = radeon_atom_ext_mode_set, |
2638 | .commit = radeon_atom_ext_commit, | 2630 | .commit = radeon_atom_ext_commit, |
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index c4b4f298a283..56482e35d43e 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c | |||
@@ -551,13 +551,14 @@ static bool radeon_atpx_detect(void) | |||
551 | void radeon_register_atpx_handler(void) | 551 | void radeon_register_atpx_handler(void) |
552 | { | 552 | { |
553 | bool r; | 553 | bool r; |
554 | enum vga_switcheroo_handler_flags_t handler_flags = 0; | ||
554 | 555 | ||
555 | /* detect if we have any ATPX + 2 VGA in the system */ | 556 | /* detect if we have any ATPX + 2 VGA in the system */ |
556 | r = radeon_atpx_detect(); | 557 | r = radeon_atpx_detect(); |
557 | if (!r) | 558 | if (!r) |
558 | return; | 559 | return; |
559 | 560 | ||
560 | vga_switcheroo_register_handler(&radeon_atpx_handler); | 561 | vga_switcheroo_register_handler(&radeon_atpx_handler, handler_flags); |
561 | } | 562 | } |
562 | 563 | ||
563 | /** | 564 | /** |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 340f3f549f29..cfcc099c537d 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "atom.h" | 34 | #include "atom.h" |
35 | 35 | ||
36 | #include <linux/pm_runtime.h> | 36 | #include <linux/pm_runtime.h> |
37 | #include <linux/vga_switcheroo.h> | ||
37 | 38 | ||
38 | static int radeon_dp_handle_hpd(struct drm_connector *connector) | 39 | static int radeon_dp_handle_hpd(struct drm_connector *connector) |
39 | { | 40 | { |
@@ -344,6 +345,11 @@ static void radeon_connector_get_edid(struct drm_connector *connector) | |||
344 | else if (radeon_connector->ddc_bus) | 345 | else if (radeon_connector->ddc_bus) |
345 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, | 346 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, |
346 | &radeon_connector->ddc_bus->adapter); | 347 | &radeon_connector->ddc_bus->adapter); |
348 | } else if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC && | ||
349 | connector->connector_type == DRM_MODE_CONNECTOR_LVDS && | ||
350 | radeon_connector->ddc_bus) { | ||
351 | radeon_connector->edid = drm_get_edid_switcheroo(&radeon_connector->base, | ||
352 | &radeon_connector->ddc_bus->adapter); | ||
347 | } else if (radeon_connector->ddc_bus) { | 353 | } else if (radeon_connector->ddc_bus) { |
348 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, | 354 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, |
349 | &radeon_connector->ddc_bus->adapter); | 355 | &radeon_connector->ddc_bus->adapter); |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index e266ffc520d2..cad25557650f 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -34,9 +34,11 @@ | |||
34 | #include "radeon_drv.h" | 34 | #include "radeon_drv.h" |
35 | 35 | ||
36 | #include <drm/drm_pciids.h> | 36 | #include <drm/drm_pciids.h> |
37 | #include <linux/apple-gmux.h> | ||
37 | #include <linux/console.h> | 38 | #include <linux/console.h> |
38 | #include <linux/module.h> | 39 | #include <linux/module.h> |
39 | #include <linux/pm_runtime.h> | 40 | #include <linux/pm_runtime.h> |
41 | #include <linux/vgaarb.h> | ||
40 | #include <linux/vga_switcheroo.h> | 42 | #include <linux/vga_switcheroo.h> |
41 | #include <drm/drm_gem.h> | 43 | #include <drm/drm_gem.h> |
42 | 44 | ||
@@ -319,6 +321,15 @@ static int radeon_pci_probe(struct pci_dev *pdev, | |||
319 | { | 321 | { |
320 | int ret; | 322 | int ret; |
321 | 323 | ||
324 | /* | ||
325 | * apple-gmux is needed on dual GPU MacBook Pro | ||
326 | * to probe the panel if we're the inactive GPU. | ||
327 | */ | ||
328 | if (IS_ENABLED(CONFIG_VGA_ARB) && IS_ENABLED(CONFIG_VGA_SWITCHEROO) && | ||
329 | apple_gmux_present() && pdev != vga_default_device() && | ||
330 | !vga_switcheroo_handler_flags()) | ||
331 | return -EPROBE_DEFER; | ||
332 | |||
322 | /* Get rid of things like offb */ | 333 | /* Get rid of things like offb */ |
323 | ret = radeon_kick_out_firmware_fb(pdev); | 334 | ret = radeon_kick_out_firmware_fb(pdev); |
324 | if (ret) | 335 | if (ret) |
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c index f8f8f29fb7c3..77662068bc11 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi.c | |||
@@ -875,13 +875,6 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) | |||
875 | clk_disable_unprepare(dsi->pclk); | 875 | clk_disable_unprepare(dsi->pclk); |
876 | } | 876 | } |
877 | 877 | ||
878 | static bool dw_mipi_dsi_encoder_mode_fixup(struct drm_encoder *encoder, | ||
879 | const struct drm_display_mode *mode, | ||
880 | struct drm_display_mode *adjusted_mode) | ||
881 | { | ||
882 | return true; | ||
883 | } | ||
884 | |||
885 | static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder) | 878 | static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder) |
886 | { | 879 | { |
887 | struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder); | 880 | struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder); |
@@ -931,7 +924,6 @@ static void dw_mipi_dsi_encoder_commit(struct drm_encoder *encoder) | |||
931 | 924 | ||
932 | static struct drm_encoder_helper_funcs | 925 | static struct drm_encoder_helper_funcs |
933 | dw_mipi_dsi_encoder_helper_funcs = { | 926 | dw_mipi_dsi_encoder_helper_funcs = { |
934 | .mode_fixup = dw_mipi_dsi_encoder_mode_fixup, | ||
935 | .commit = dw_mipi_dsi_encoder_commit, | 927 | .commit = dw_mipi_dsi_encoder_commit, |
936 | .mode_set = dw_mipi_dsi_encoder_mode_set, | 928 | .mode_set = dw_mipi_dsi_encoder_mode_set, |
937 | .disable = dw_mipi_dsi_encoder_disable, | 929 | .disable = dw_mipi_dsi_encoder_disable, |
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index f2afcf5438b8..24a3735b88fd 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c | |||
@@ -440,13 +440,6 @@ static void sti_tvout_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
440 | { | 440 | { |
441 | } | 441 | } |
442 | 442 | ||
443 | static bool sti_tvout_encoder_mode_fixup(struct drm_encoder *encoder, | ||
444 | const struct drm_display_mode *mode, | ||
445 | struct drm_display_mode *adjusted_mode) | ||
446 | { | ||
447 | return true; | ||
448 | } | ||
449 | |||
450 | static void sti_tvout_encoder_mode_set(struct drm_encoder *encoder, | 443 | static void sti_tvout_encoder_mode_set(struct drm_encoder *encoder, |
451 | struct drm_display_mode *mode, | 444 | struct drm_display_mode *mode, |
452 | struct drm_display_mode *adjusted_mode) | 445 | struct drm_display_mode *adjusted_mode) |
@@ -486,7 +479,6 @@ static void sti_dvo_encoder_disable(struct drm_encoder *encoder) | |||
486 | 479 | ||
487 | static const struct drm_encoder_helper_funcs sti_dvo_encoder_helper_funcs = { | 480 | static const struct drm_encoder_helper_funcs sti_dvo_encoder_helper_funcs = { |
488 | .dpms = sti_tvout_encoder_dpms, | 481 | .dpms = sti_tvout_encoder_dpms, |
489 | .mode_fixup = sti_tvout_encoder_mode_fixup, | ||
490 | .mode_set = sti_tvout_encoder_mode_set, | 482 | .mode_set = sti_tvout_encoder_mode_set, |
491 | .prepare = sti_tvout_encoder_prepare, | 483 | .prepare = sti_tvout_encoder_prepare, |
492 | .commit = sti_dvo_encoder_commit, | 484 | .commit = sti_dvo_encoder_commit, |
@@ -540,7 +532,6 @@ static void sti_hda_encoder_disable(struct drm_encoder *encoder) | |||
540 | 532 | ||
541 | static const struct drm_encoder_helper_funcs sti_hda_encoder_helper_funcs = { | 533 | static const struct drm_encoder_helper_funcs sti_hda_encoder_helper_funcs = { |
542 | .dpms = sti_tvout_encoder_dpms, | 534 | .dpms = sti_tvout_encoder_dpms, |
543 | .mode_fixup = sti_tvout_encoder_mode_fixup, | ||
544 | .mode_set = sti_tvout_encoder_mode_set, | 535 | .mode_set = sti_tvout_encoder_mode_set, |
545 | .prepare = sti_tvout_encoder_prepare, | 536 | .prepare = sti_tvout_encoder_prepare, |
546 | .commit = sti_hda_encoder_commit, | 537 | .commit = sti_hda_encoder_commit, |
@@ -589,7 +580,6 @@ static void sti_hdmi_encoder_disable(struct drm_encoder *encoder) | |||
589 | 580 | ||
590 | static const struct drm_encoder_helper_funcs sti_hdmi_encoder_helper_funcs = { | 581 | static const struct drm_encoder_helper_funcs sti_hdmi_encoder_helper_funcs = { |
591 | .dpms = sti_tvout_encoder_dpms, | 582 | .dpms = sti_tvout_encoder_dpms, |
592 | .mode_fixup = sti_tvout_encoder_mode_fixup, | ||
593 | .mode_set = sti_tvout_encoder_mode_set, | 583 | .mode_set = sti_tvout_encoder_mode_set, |
594 | .prepare = sti_tvout_encoder_prepare, | 584 | .prepare = sti_tvout_encoder_prepare, |
595 | .commit = sti_hdmi_encoder_commit, | 585 | .commit = sti_hdmi_encoder_commit, |
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 4dda6e2f464b..8dcf02a79b23 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c | |||
@@ -70,14 +70,6 @@ static void panel_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
70 | mode == DRM_MODE_DPMS_ON ? 1 : 0); | 70 | mode == DRM_MODE_DPMS_ON ? 1 : 0); |
71 | } | 71 | } |
72 | 72 | ||
73 | static bool panel_encoder_mode_fixup(struct drm_encoder *encoder, | ||
74 | const struct drm_display_mode *mode, | ||
75 | struct drm_display_mode *adjusted_mode) | ||
76 | { | ||
77 | /* nothing needed */ | ||
78 | return true; | ||
79 | } | ||
80 | |||
81 | static void panel_encoder_prepare(struct drm_encoder *encoder) | 73 | static void panel_encoder_prepare(struct drm_encoder *encoder) |
82 | { | 74 | { |
83 | struct panel_encoder *panel_encoder = to_panel_encoder(encoder); | 75 | struct panel_encoder *panel_encoder = to_panel_encoder(encoder); |
@@ -103,7 +95,6 @@ static const struct drm_encoder_funcs panel_encoder_funcs = { | |||
103 | 95 | ||
104 | static const struct drm_encoder_helper_funcs panel_encoder_helper_funcs = { | 96 | static const struct drm_encoder_helper_funcs panel_encoder_helper_funcs = { |
105 | .dpms = panel_encoder_dpms, | 97 | .dpms = panel_encoder_dpms, |
106 | .mode_fixup = panel_encoder_mode_fixup, | ||
107 | .prepare = panel_encoder_prepare, | 98 | .prepare = panel_encoder_prepare, |
108 | .commit = panel_encoder_commit, | 99 | .commit = panel_encoder_commit, |
109 | .mode_set = panel_encoder_mode_set, | 100 | .mode_set = panel_encoder_mode_set, |
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index 5052a8af7ecb..1c230172b402 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | |||
@@ -80,14 +80,6 @@ static void tfp410_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
80 | tfp410_encoder->dpms = mode; | 80 | tfp410_encoder->dpms = mode; |
81 | } | 81 | } |
82 | 82 | ||
83 | static bool tfp410_encoder_mode_fixup(struct drm_encoder *encoder, | ||
84 | const struct drm_display_mode *mode, | ||
85 | struct drm_display_mode *adjusted_mode) | ||
86 | { | ||
87 | /* nothing needed */ | ||
88 | return true; | ||
89 | } | ||
90 | |||
91 | static void tfp410_encoder_prepare(struct drm_encoder *encoder) | 83 | static void tfp410_encoder_prepare(struct drm_encoder *encoder) |
92 | { | 84 | { |
93 | tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 85 | tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
@@ -112,7 +104,6 @@ static const struct drm_encoder_funcs tfp410_encoder_funcs = { | |||
112 | 104 | ||
113 | static const struct drm_encoder_helper_funcs tfp410_encoder_helper_funcs = { | 105 | static const struct drm_encoder_helper_funcs tfp410_encoder_helper_funcs = { |
114 | .dpms = tfp410_encoder_dpms, | 106 | .dpms = tfp410_encoder_dpms, |
115 | .mode_fixup = tfp410_encoder_mode_fixup, | ||
116 | .prepare = tfp410_encoder_prepare, | 107 | .prepare = tfp410_encoder_prepare, |
117 | .commit = tfp410_encoder_commit, | 108 | .commit = tfp410_encoder_commit, |
118 | .mode_set = tfp410_encoder_mode_set, | 109 | .mode_set = tfp410_encoder_mode_set, |
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index d5728ec85254..772ec9e1f590 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c | |||
@@ -125,17 +125,5 @@ static struct usb_driver udl_driver = { | |||
125 | .disconnect = udl_usb_disconnect, | 125 | .disconnect = udl_usb_disconnect, |
126 | .id_table = id_table, | 126 | .id_table = id_table, |
127 | }; | 127 | }; |
128 | 128 | module_usb_driver(udl_driver); | |
129 | static int __init udl_init(void) | ||
130 | { | ||
131 | return usb_register(&udl_driver); | ||
132 | } | ||
133 | |||
134 | static void __exit udl_exit(void) | ||
135 | { | ||
136 | usb_deregister(&udl_driver); | ||
137 | } | ||
138 | |||
139 | module_init(udl_init); | ||
140 | module_exit(udl_exit); | ||
141 | MODULE_LICENSE("GPL"); | 129 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/gpu/drm/udl/udl_encoder.c b/drivers/gpu/drm/udl/udl_encoder.c index a181a647fcf9..59a4b34e87ed 100644 --- a/drivers/gpu/drm/udl/udl_encoder.c +++ b/drivers/gpu/drm/udl/udl_encoder.c | |||
@@ -26,13 +26,6 @@ static void udl_encoder_disable(struct drm_encoder *encoder) | |||
26 | { | 26 | { |
27 | } | 27 | } |
28 | 28 | ||
29 | static bool udl_mode_fixup(struct drm_encoder *encoder, | ||
30 | const struct drm_display_mode *mode, | ||
31 | struct drm_display_mode *adjusted_mode) | ||
32 | { | ||
33 | return true; | ||
34 | } | ||
35 | |||
36 | static void udl_encoder_prepare(struct drm_encoder *encoder) | 29 | static void udl_encoder_prepare(struct drm_encoder *encoder) |
37 | { | 30 | { |
38 | } | 31 | } |
@@ -54,7 +47,6 @@ udl_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
54 | 47 | ||
55 | static const struct drm_encoder_helper_funcs udl_helper_funcs = { | 48 | static const struct drm_encoder_helper_funcs udl_helper_funcs = { |
56 | .dpms = udl_encoder_dpms, | 49 | .dpms = udl_encoder_dpms, |
57 | .mode_fixup = udl_mode_fixup, | ||
58 | .prepare = udl_encoder_prepare, | 50 | .prepare = udl_encoder_prepare, |
59 | .mode_set = udl_encoder_mode_set, | 51 | .mode_set = udl_encoder_mode_set, |
60 | .commit = udl_encoder_commit, | 52 | .commit = udl_encoder_commit, |
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 200419d4d43c..c427499133d6 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c | |||
@@ -409,7 +409,6 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb, | |||
409 | 409 | ||
410 | if (ufb->obj->base.import_attach) { | 410 | if (ufb->obj->base.import_attach) { |
411 | ret = dma_buf_begin_cpu_access(ufb->obj->base.import_attach->dmabuf, | 411 | ret = dma_buf_begin_cpu_access(ufb->obj->base.import_attach->dmabuf, |
412 | 0, ufb->obj->base.size, | ||
413 | DMA_FROM_DEVICE); | 412 | DMA_FROM_DEVICE); |
414 | if (ret) | 413 | if (ret) |
415 | goto unlock; | 414 | goto unlock; |
@@ -425,7 +424,6 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb, | |||
425 | 424 | ||
426 | if (ufb->obj->base.import_attach) { | 425 | if (ufb->obj->base.import_attach) { |
427 | dma_buf_end_cpu_access(ufb->obj->base.import_attach->dmabuf, | 426 | dma_buf_end_cpu_access(ufb->obj->base.import_attach->dmabuf, |
428 | 0, ufb->obj->base.size, | ||
429 | DMA_FROM_DEVICE); | 427 | DMA_FROM_DEVICE); |
430 | } | 428 | } |
431 | 429 | ||
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index a165f03eaa79..429aa311685a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c | |||
@@ -282,13 +282,6 @@ static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { | |||
282 | .atomic_check = virtio_gpu_crtc_atomic_check, | 282 | .atomic_check = virtio_gpu_crtc_atomic_check, |
283 | }; | 283 | }; |
284 | 284 | ||
285 | static bool virtio_gpu_enc_mode_fixup(struct drm_encoder *encoder, | ||
286 | const struct drm_display_mode *mode, | ||
287 | struct drm_display_mode *adjusted_mode) | ||
288 | { | ||
289 | return true; | ||
290 | } | ||
291 | |||
292 | static void virtio_gpu_enc_mode_set(struct drm_encoder *encoder, | 285 | static void virtio_gpu_enc_mode_set(struct drm_encoder *encoder, |
293 | struct drm_display_mode *mode, | 286 | struct drm_display_mode *mode, |
294 | struct drm_display_mode *adjusted_mode) | 287 | struct drm_display_mode *adjusted_mode) |
@@ -362,7 +355,6 @@ virtio_gpu_best_encoder(struct drm_connector *connector) | |||
362 | } | 355 | } |
363 | 356 | ||
364 | static const struct drm_encoder_helper_funcs virtio_gpu_enc_helper_funcs = { | 357 | static const struct drm_encoder_helper_funcs virtio_gpu_enc_helper_funcs = { |
365 | .mode_fixup = virtio_gpu_enc_mode_fixup, | ||
366 | .mode_set = virtio_gpu_enc_mode_set, | 358 | .mode_set = virtio_gpu_enc_mode_set, |
367 | .enable = virtio_gpu_enc_enable, | 359 | .enable = virtio_gpu_enc_enable, |
368 | .disable = virtio_gpu_enc_disable, | 360 | .disable = virtio_gpu_enc_disable, |
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 665ab9fd0e01..cbd7c986d926 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c | |||
@@ -74,9 +74,17 @@ | |||
74 | * there can thus be up to three clients: Two vga clients (GPUs) and one audio | 74 | * there can thus be up to three clients: Two vga clients (GPUs) and one audio |
75 | * client (on the discrete GPU). The code is mostly prepared to support | 75 | * client (on the discrete GPU). The code is mostly prepared to support |
76 | * machines with more than two GPUs should they become available. | 76 | * machines with more than two GPUs should they become available. |
77 | * | ||
77 | * The GPU to which the outputs are currently switched is called the | 78 | * The GPU to which the outputs are currently switched is called the |
78 | * active client in vga_switcheroo parlance. The GPU not in use is the | 79 | * active client in vga_switcheroo parlance. The GPU not in use is the |
79 | * inactive client. | 80 | * inactive client. When the inactive client's DRM driver is loaded, |
81 | * it will be unable to probe the panel's EDID and hence depends on | ||
82 | * VBIOS to provide its display modes. If the VBIOS modes are bogus or | ||
83 | * if there is no VBIOS at all (which is common on the MacBook Pro), | ||
84 | * a client may alternatively request that the DDC lines are temporarily | ||
85 | * switched to it, provided that the handler supports this. Switching | ||
86 | * only the DDC lines and not the entire output avoids unnecessary | ||
87 | * flickering. | ||
80 | */ | 88 | */ |
81 | 89 | ||
82 | /** | 90 | /** |
@@ -126,6 +134,10 @@ static DEFINE_MUTEX(vgasr_mutex); | |||
126 | * (counting only vga clients, not audio clients) | 134 | * (counting only vga clients, not audio clients) |
127 | * @clients: list of registered clients | 135 | * @clients: list of registered clients |
128 | * @handler: registered handler | 136 | * @handler: registered handler |
137 | * @handler_flags: flags of registered handler | ||
138 | * @mux_hw_lock: protects mux state | ||
139 | * (in particular while DDC lines are temporarily switched) | ||
140 | * @old_ddc_owner: client to which DDC lines will be switched back on unlock | ||
129 | * | 141 | * |
130 | * vga_switcheroo private data. Currently only one vga_switcheroo instance | 142 | * vga_switcheroo private data. Currently only one vga_switcheroo instance |
131 | * per system is supported. | 143 | * per system is supported. |
@@ -142,6 +154,9 @@ struct vgasr_priv { | |||
142 | struct list_head clients; | 154 | struct list_head clients; |
143 | 155 | ||
144 | const struct vga_switcheroo_handler *handler; | 156 | const struct vga_switcheroo_handler *handler; |
157 | enum vga_switcheroo_handler_flags_t handler_flags; | ||
158 | struct mutex mux_hw_lock; | ||
159 | int old_ddc_owner; | ||
145 | }; | 160 | }; |
146 | 161 | ||
147 | #define ID_BIT_AUDIO 0x100 | 162 | #define ID_BIT_AUDIO 0x100 |
@@ -156,6 +171,7 @@ static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv); | |||
156 | /* only one switcheroo per system */ | 171 | /* only one switcheroo per system */ |
157 | static struct vgasr_priv vgasr_priv = { | 172 | static struct vgasr_priv vgasr_priv = { |
158 | .clients = LIST_HEAD_INIT(vgasr_priv.clients), | 173 | .clients = LIST_HEAD_INIT(vgasr_priv.clients), |
174 | .mux_hw_lock = __MUTEX_INITIALIZER(vgasr_priv.mux_hw_lock), | ||
159 | }; | 175 | }; |
160 | 176 | ||
161 | static bool vga_switcheroo_ready(void) | 177 | static bool vga_switcheroo_ready(void) |
@@ -190,13 +206,15 @@ static void vga_switcheroo_enable(void) | |||
190 | /** | 206 | /** |
191 | * vga_switcheroo_register_handler() - register handler | 207 | * vga_switcheroo_register_handler() - register handler |
192 | * @handler: handler callbacks | 208 | * @handler: handler callbacks |
209 | * @handler_flags: handler flags | ||
193 | * | 210 | * |
194 | * Register handler. Enable vga_switcheroo if two vga clients have already | 211 | * Register handler. Enable vga_switcheroo if two vga clients have already |
195 | * registered. | 212 | * registered. |
196 | * | 213 | * |
197 | * Return: 0 on success, -EINVAL if a handler was already registered. | 214 | * Return: 0 on success, -EINVAL if a handler was already registered. |
198 | */ | 215 | */ |
199 | int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler) | 216 | int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, |
217 | enum vga_switcheroo_handler_flags_t handler_flags) | ||
200 | { | 218 | { |
201 | mutex_lock(&vgasr_mutex); | 219 | mutex_lock(&vgasr_mutex); |
202 | if (vgasr_priv.handler) { | 220 | if (vgasr_priv.handler) { |
@@ -205,6 +223,7 @@ int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler | |||
205 | } | 223 | } |
206 | 224 | ||
207 | vgasr_priv.handler = handler; | 225 | vgasr_priv.handler = handler; |
226 | vgasr_priv.handler_flags = handler_flags; | ||
208 | if (vga_switcheroo_ready()) { | 227 | if (vga_switcheroo_ready()) { |
209 | pr_info("enabled\n"); | 228 | pr_info("enabled\n"); |
210 | vga_switcheroo_enable(); | 229 | vga_switcheroo_enable(); |
@@ -222,16 +241,33 @@ EXPORT_SYMBOL(vga_switcheroo_register_handler); | |||
222 | void vga_switcheroo_unregister_handler(void) | 241 | void vga_switcheroo_unregister_handler(void) |
223 | { | 242 | { |
224 | mutex_lock(&vgasr_mutex); | 243 | mutex_lock(&vgasr_mutex); |
244 | mutex_lock(&vgasr_priv.mux_hw_lock); | ||
245 | vgasr_priv.handler_flags = 0; | ||
225 | vgasr_priv.handler = NULL; | 246 | vgasr_priv.handler = NULL; |
226 | if (vgasr_priv.active) { | 247 | if (vgasr_priv.active) { |
227 | pr_info("disabled\n"); | 248 | pr_info("disabled\n"); |
228 | vga_switcheroo_debugfs_fini(&vgasr_priv); | 249 | vga_switcheroo_debugfs_fini(&vgasr_priv); |
229 | vgasr_priv.active = false; | 250 | vgasr_priv.active = false; |
230 | } | 251 | } |
252 | mutex_unlock(&vgasr_priv.mux_hw_lock); | ||
231 | mutex_unlock(&vgasr_mutex); | 253 | mutex_unlock(&vgasr_mutex); |
232 | } | 254 | } |
233 | EXPORT_SYMBOL(vga_switcheroo_unregister_handler); | 255 | EXPORT_SYMBOL(vga_switcheroo_unregister_handler); |
234 | 256 | ||
257 | /** | ||
258 | * vga_switcheroo_handler_flags() - obtain handler flags | ||
259 | * | ||
260 | * Helper for clients to obtain the handler flags bitmask. | ||
261 | * | ||
262 | * Return: Handler flags. A value of 0 means that no handler is registered | ||
263 | * or that the handler has no special capabilities. | ||
264 | */ | ||
265 | enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void) | ||
266 | { | ||
267 | return vgasr_priv.handler_flags; | ||
268 | } | ||
269 | EXPORT_SYMBOL(vga_switcheroo_handler_flags); | ||
270 | |||
235 | static int register_client(struct pci_dev *pdev, | 271 | static int register_client(struct pci_dev *pdev, |
236 | const struct vga_switcheroo_client_ops *ops, | 272 | const struct vga_switcheroo_client_ops *ops, |
237 | enum vga_switcheroo_client_id id, bool active, | 273 | enum vga_switcheroo_client_id id, bool active, |
@@ -413,6 +449,76 @@ void vga_switcheroo_client_fb_set(struct pci_dev *pdev, | |||
413 | EXPORT_SYMBOL(vga_switcheroo_client_fb_set); | 449 | EXPORT_SYMBOL(vga_switcheroo_client_fb_set); |
414 | 450 | ||
415 | /** | 451 | /** |
452 | * vga_switcheroo_lock_ddc() - temporarily switch DDC lines to a given client | ||
453 | * @pdev: client pci device | ||
454 | * | ||
455 | * Temporarily switch DDC lines to the client identified by @pdev | ||
456 | * (but leave the outputs otherwise switched to where they are). | ||
457 | * This allows the inactive client to probe EDID. The DDC lines must | ||
458 | * afterwards be switched back by calling vga_switcheroo_unlock_ddc(), | ||
459 | * even if this function returns an error. | ||
460 | * | ||
461 | * Return: Previous DDC owner on success or a negative int on error. | ||
462 | * Specifically, %-ENODEV if no handler has registered or if the handler | ||
463 | * does not support switching the DDC lines. Also, a negative value | ||
464 | * returned by the handler is propagated back to the caller. | ||
465 | * The return value has merely an informational purpose for any caller | ||
466 | * which might be interested in it. It is acceptable to ignore the return | ||
467 | * value and simply rely on the result of the subsequent EDID probe, | ||
468 | * which will be %NULL if DDC switching failed. | ||
469 | */ | ||
470 | int vga_switcheroo_lock_ddc(struct pci_dev *pdev) | ||
471 | { | ||
472 | enum vga_switcheroo_client_id id; | ||
473 | |||
474 | mutex_lock(&vgasr_priv.mux_hw_lock); | ||
475 | if (!vgasr_priv.handler || !vgasr_priv.handler->switch_ddc) { | ||
476 | vgasr_priv.old_ddc_owner = -ENODEV; | ||
477 | return -ENODEV; | ||
478 | } | ||
479 | |||
480 | id = vgasr_priv.handler->get_client_id(pdev); | ||
481 | vgasr_priv.old_ddc_owner = vgasr_priv.handler->switch_ddc(id); | ||
482 | return vgasr_priv.old_ddc_owner; | ||
483 | } | ||
484 | EXPORT_SYMBOL(vga_switcheroo_lock_ddc); | ||
485 | |||
486 | /** | ||
487 | * vga_switcheroo_unlock_ddc() - switch DDC lines back to previous owner | ||
488 | * @pdev: client pci device | ||
489 | * | ||
490 | * Switch DDC lines back to the previous owner after calling | ||
491 | * vga_switcheroo_lock_ddc(). This must be called even if | ||
492 | * vga_switcheroo_lock_ddc() returned an error. | ||
493 | * | ||
494 | * Return: Previous DDC owner on success (i.e. the client identifier of @pdev) | ||
495 | * or a negative int on error. | ||
496 | * Specifically, %-ENODEV if no handler has registered or if the handler | ||
497 | * does not support switching the DDC lines. Also, a negative value | ||
498 | * returned by the handler is propagated back to the caller. | ||
499 | * Finally, invoking this function without calling vga_switcheroo_lock_ddc() | ||
500 | * first is not allowed and will result in %-EINVAL. | ||
501 | */ | ||
502 | int vga_switcheroo_unlock_ddc(struct pci_dev *pdev) | ||
503 | { | ||
504 | enum vga_switcheroo_client_id id; | ||
505 | int ret = vgasr_priv.old_ddc_owner; | ||
506 | |||
507 | if (WARN_ON_ONCE(!mutex_is_locked(&vgasr_priv.mux_hw_lock))) | ||
508 | return -EINVAL; | ||
509 | |||
510 | if (vgasr_priv.old_ddc_owner >= 0) { | ||
511 | id = vgasr_priv.handler->get_client_id(pdev); | ||
512 | if (vgasr_priv.old_ddc_owner != id) | ||
513 | ret = vgasr_priv.handler->switch_ddc( | ||
514 | vgasr_priv.old_ddc_owner); | ||
515 | } | ||
516 | mutex_unlock(&vgasr_priv.mux_hw_lock); | ||
517 | return ret; | ||
518 | } | ||
519 | EXPORT_SYMBOL(vga_switcheroo_unlock_ddc); | ||
520 | |||
521 | /** | ||
416 | * DOC: Manual switching and manual power control | 522 | * DOC: Manual switching and manual power control |
417 | * | 523 | * |
418 | * In this mode of use, the file /sys/kernel/debug/vgaswitcheroo/switch | 524 | * In this mode of use, the file /sys/kernel/debug/vgaswitcheroo/switch |
@@ -549,7 +655,9 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) | |||
549 | console_unlock(); | 655 | console_unlock(); |
550 | } | 656 | } |
551 | 657 | ||
658 | mutex_lock(&vgasr_priv.mux_hw_lock); | ||
552 | ret = vgasr_priv.handler->switchto(new_client->id); | 659 | ret = vgasr_priv.handler->switchto(new_client->id); |
660 | mutex_unlock(&vgasr_priv.mux_hw_lock); | ||
553 | if (ret) | 661 | if (ret) |
554 | return ret; | 662 | return ret; |
555 | 663 | ||
@@ -664,7 +772,9 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, | |||
664 | vgasr_priv.delayed_switch_active = false; | 772 | vgasr_priv.delayed_switch_active = false; |
665 | 773 | ||
666 | if (just_mux) { | 774 | if (just_mux) { |
775 | mutex_lock(&vgasr_priv.mux_hw_lock); | ||
667 | ret = vgasr_priv.handler->switchto(client_id); | 776 | ret = vgasr_priv.handler->switchto(client_id); |
777 | mutex_unlock(&vgasr_priv.mux_hw_lock); | ||
668 | goto out; | 778 | goto out; |
669 | } | 779 | } |
670 | 780 | ||
@@ -876,8 +986,11 @@ static int vga_switcheroo_runtime_suspend(struct device *dev) | |||
876 | if (ret) | 986 | if (ret) |
877 | return ret; | 987 | return ret; |
878 | mutex_lock(&vgasr_mutex); | 988 | mutex_lock(&vgasr_mutex); |
879 | if (vgasr_priv.handler->switchto) | 989 | if (vgasr_priv.handler->switchto) { |
990 | mutex_lock(&vgasr_priv.mux_hw_lock); | ||
880 | vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD); | 991 | vgasr_priv.handler->switchto(VGA_SWITCHEROO_IGD); |
992 | mutex_unlock(&vgasr_priv.mux_hw_lock); | ||
993 | } | ||
881 | vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_OFF); | 994 | vga_switcheroo_power_switch(pdev, VGA_SWITCHEROO_OFF); |
882 | mutex_unlock(&vgasr_mutex); | 995 | mutex_unlock(&vgasr_mutex); |
883 | return 0; | 996 | return 0; |
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index f236250ac106..4034d2d4c507 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/acpi.h> | 19 | #include <linux/acpi.h> |
20 | #include <linux/pnp.h> | 20 | #include <linux/pnp.h> |
21 | #include <linux/apple_bl.h> | 21 | #include <linux/apple_bl.h> |
22 | #include <linux/apple-gmux.h> | ||
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
24 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
@@ -57,7 +58,9 @@ struct apple_gmux_data { | |||
57 | /* switcheroo data */ | 58 | /* switcheroo data */ |
58 | acpi_handle dhandle; | 59 | acpi_handle dhandle; |
59 | int gpe; | 60 | int gpe; |
60 | enum vga_switcheroo_client_id resume_client_id; | 61 | enum vga_switcheroo_client_id switch_state_display; |
62 | enum vga_switcheroo_client_id switch_state_ddc; | ||
63 | enum vga_switcheroo_client_id switch_state_external; | ||
61 | enum vga_switcheroo_state power_state; | 64 | enum vga_switcheroo_state power_state; |
62 | struct completion powerchange_done; | 65 | struct completion powerchange_done; |
63 | }; | 66 | }; |
@@ -368,19 +371,70 @@ static const struct backlight_ops gmux_bl_ops = { | |||
368 | * for the selected GPU. | 371 | * for the selected GPU. |
369 | */ | 372 | */ |
370 | 373 | ||
374 | static void gmux_read_switch_state(struct apple_gmux_data *gmux_data) | ||
375 | { | ||
376 | if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DDC) == 1) | ||
377 | gmux_data->switch_state_ddc = VGA_SWITCHEROO_IGD; | ||
378 | else | ||
379 | gmux_data->switch_state_ddc = VGA_SWITCHEROO_DIS; | ||
380 | |||
381 | if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) == 2) | ||
382 | gmux_data->switch_state_display = VGA_SWITCHEROO_IGD; | ||
383 | else | ||
384 | gmux_data->switch_state_display = VGA_SWITCHEROO_DIS; | ||
385 | |||
386 | if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL) == 2) | ||
387 | gmux_data->switch_state_external = VGA_SWITCHEROO_IGD; | ||
388 | else | ||
389 | gmux_data->switch_state_external = VGA_SWITCHEROO_DIS; | ||
390 | } | ||
391 | |||
392 | static void gmux_write_switch_state(struct apple_gmux_data *gmux_data) | ||
393 | { | ||
394 | if (gmux_data->switch_state_ddc == VGA_SWITCHEROO_IGD) | ||
395 | gmux_write8(gmux_data, GMUX_PORT_SWITCH_DDC, 1); | ||
396 | else | ||
397 | gmux_write8(gmux_data, GMUX_PORT_SWITCH_DDC, 2); | ||
398 | |||
399 | if (gmux_data->switch_state_display == VGA_SWITCHEROO_IGD) | ||
400 | gmux_write8(gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2); | ||
401 | else | ||
402 | gmux_write8(gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3); | ||
403 | |||
404 | if (gmux_data->switch_state_external == VGA_SWITCHEROO_IGD) | ||
405 | gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2); | ||
406 | else | ||
407 | gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); | ||
408 | } | ||
409 | |||
371 | static int gmux_switchto(enum vga_switcheroo_client_id id) | 410 | static int gmux_switchto(enum vga_switcheroo_client_id id) |
372 | { | 411 | { |
373 | if (id == VGA_SWITCHEROO_IGD) { | 412 | apple_gmux_data->switch_state_ddc = id; |
413 | apple_gmux_data->switch_state_display = id; | ||
414 | apple_gmux_data->switch_state_external = id; | ||
415 | |||
416 | gmux_write_switch_state(apple_gmux_data); | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int gmux_switch_ddc(enum vga_switcheroo_client_id id) | ||
422 | { | ||
423 | enum vga_switcheroo_client_id old_ddc_owner = | ||
424 | apple_gmux_data->switch_state_ddc; | ||
425 | |||
426 | if (id == old_ddc_owner) | ||
427 | return id; | ||
428 | |||
429 | pr_debug("Switching DDC from %d to %d\n", old_ddc_owner, id); | ||
430 | apple_gmux_data->switch_state_ddc = id; | ||
431 | |||
432 | if (id == VGA_SWITCHEROO_IGD) | ||
374 | gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1); | 433 | gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1); |
375 | gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2); | 434 | else |
376 | gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2); | ||
377 | } else { | ||
378 | gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2); | 435 | gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2); |
379 | gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3); | ||
380 | gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); | ||
381 | } | ||
382 | 436 | ||
383 | return 0; | 437 | return old_ddc_owner; |
384 | } | 438 | } |
385 | 439 | ||
386 | /** | 440 | /** |
@@ -440,17 +494,15 @@ static int gmux_get_client_id(struct pci_dev *pdev) | |||
440 | return VGA_SWITCHEROO_DIS; | 494 | return VGA_SWITCHEROO_DIS; |
441 | } | 495 | } |
442 | 496 | ||
443 | static enum vga_switcheroo_client_id | 497 | static const struct vga_switcheroo_handler gmux_handler_indexed = { |
444 | gmux_active_client(struct apple_gmux_data *gmux_data) | 498 | .switchto = gmux_switchto, |
445 | { | 499 | .power_state = gmux_set_power_state, |
446 | if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) == 2) | 500 | .get_client_id = gmux_get_client_id, |
447 | return VGA_SWITCHEROO_IGD; | 501 | }; |
448 | |||
449 | return VGA_SWITCHEROO_DIS; | ||
450 | } | ||
451 | 502 | ||
452 | static const struct vga_switcheroo_handler gmux_handler = { | 503 | static const struct vga_switcheroo_handler gmux_handler_classic = { |
453 | .switchto = gmux_switchto, | 504 | .switchto = gmux_switchto, |
505 | .switch_ddc = gmux_switch_ddc, | ||
454 | .power_state = gmux_set_power_state, | 506 | .power_state = gmux_set_power_state, |
455 | .get_client_id = gmux_get_client_id, | 507 | .get_client_id = gmux_get_client_id, |
456 | }; | 508 | }; |
@@ -513,7 +565,6 @@ static int gmux_suspend(struct device *dev) | |||
513 | struct pnp_dev *pnp = to_pnp_dev(dev); | 565 | struct pnp_dev *pnp = to_pnp_dev(dev); |
514 | struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); | 566 | struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); |
515 | 567 | ||
516 | gmux_data->resume_client_id = gmux_active_client(gmux_data); | ||
517 | gmux_disable_interrupts(gmux_data); | 568 | gmux_disable_interrupts(gmux_data); |
518 | return 0; | 569 | return 0; |
519 | } | 570 | } |
@@ -524,7 +575,7 @@ static int gmux_resume(struct device *dev) | |||
524 | struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); | 575 | struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); |
525 | 576 | ||
526 | gmux_enable_interrupts(gmux_data); | 577 | gmux_enable_interrupts(gmux_data); |
527 | gmux_switchto(gmux_data->resume_client_id); | 578 | gmux_write_switch_state(gmux_data); |
528 | if (gmux_data->power_state == VGA_SWITCHEROO_OFF) | 579 | if (gmux_data->power_state == VGA_SWITCHEROO_OFF) |
529 | gmux_set_discrete_state(gmux_data, gmux_data->power_state); | 580 | gmux_set_discrete_state(gmux_data, gmux_data->power_state); |
530 | return 0; | 581 | return 0; |
@@ -704,9 +755,23 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | |||
704 | apple_gmux_data = gmux_data; | 755 | apple_gmux_data = gmux_data; |
705 | init_completion(&gmux_data->powerchange_done); | 756 | init_completion(&gmux_data->powerchange_done); |
706 | gmux_enable_interrupts(gmux_data); | 757 | gmux_enable_interrupts(gmux_data); |
758 | gmux_read_switch_state(gmux_data); | ||
707 | 759 | ||
708 | if (vga_switcheroo_register_handler(&gmux_handler)) { | 760 | /* |
709 | ret = -ENODEV; | 761 | * Retina MacBook Pros cannot switch the panel's AUX separately |
762 | * and need eDP pre-calibration. They are distinguishable from | ||
763 | * pre-retinas by having an "indexed" gmux. | ||
764 | * | ||
765 | * Pre-retina MacBook Pros can switch the panel's DDC separately. | ||
766 | */ | ||
767 | if (gmux_data->indexed) | ||
768 | ret = vga_switcheroo_register_handler(&gmux_handler_indexed, | ||
769 | VGA_SWITCHEROO_NEEDS_EDP_CONFIG); | ||
770 | else | ||
771 | ret = vga_switcheroo_register_handler(&gmux_handler_classic, | ||
772 | VGA_SWITCHEROO_CAN_SWITCH_DDC); | ||
773 | if (ret) { | ||
774 | pr_err("Failed to register vga_switcheroo handler\n"); | ||
710 | goto err_register_handler; | 775 | goto err_register_handler; |
711 | } | 776 | } |
712 | 777 | ||
@@ -764,7 +829,7 @@ static void gmux_remove(struct pnp_dev *pnp) | |||
764 | } | 829 | } |
765 | 830 | ||
766 | static const struct pnp_device_id gmux_device_ids[] = { | 831 | static const struct pnp_device_id gmux_device_ids[] = { |
767 | {"APP000B", 0}, | 832 | {GMUX_ACPI_HID, 0}, |
768 | {"", 0} | 833 | {"", 0} |
769 | }; | 834 | }; |
770 | 835 | ||
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index e237e9f3312d..0754a37c9674 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c | |||
@@ -1057,8 +1057,7 @@ static void ion_dma_buf_kunmap(struct dma_buf *dmabuf, unsigned long offset, | |||
1057 | { | 1057 | { |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, | 1060 | static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, |
1061 | size_t len, | ||
1062 | enum dma_data_direction direction) | 1061 | enum dma_data_direction direction) |
1063 | { | 1062 | { |
1064 | struct ion_buffer *buffer = dmabuf->priv; | 1063 | struct ion_buffer *buffer = dmabuf->priv; |
@@ -1076,8 +1075,7 @@ static int ion_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, size_t start, | |||
1076 | return PTR_ERR_OR_ZERO(vaddr); | 1075 | return PTR_ERR_OR_ZERO(vaddr); |
1077 | } | 1076 | } |
1078 | 1077 | ||
1079 | static void ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, size_t start, | 1078 | static void ion_dma_buf_end_cpu_access(struct dma_buf *dmabuf, |
1080 | size_t len, | ||
1081 | enum dma_data_direction direction) | 1079 | enum dma_data_direction direction) |
1082 | { | 1080 | { |
1083 | struct ion_buffer *buffer = dmabuf->priv; | 1081 | struct ion_buffer *buffer = dmabuf->priv; |
diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c index b8dcf5a26cc4..da34bc12cd7c 100644 --- a/drivers/staging/android/ion/ion_test.c +++ b/drivers/staging/android/ion/ion_test.c | |||
@@ -109,7 +109,7 @@ static int ion_handle_test_kernel(struct dma_buf *dma_buf, void __user *ptr, | |||
109 | if (offset > dma_buf->size || size > dma_buf->size - offset) | 109 | if (offset > dma_buf->size || size > dma_buf->size - offset) |
110 | return -EINVAL; | 110 | return -EINVAL; |
111 | 111 | ||
112 | ret = dma_buf_begin_cpu_access(dma_buf, offset, size, dir); | 112 | ret = dma_buf_begin_cpu_access(dma_buf, dir); |
113 | if (ret) | 113 | if (ret) |
114 | return ret; | 114 | return ret; |
115 | 115 | ||
@@ -139,7 +139,7 @@ static int ion_handle_test_kernel(struct dma_buf *dma_buf, void __user *ptr, | |||
139 | copy_offset = 0; | 139 | copy_offset = 0; |
140 | } | 140 | } |
141 | err: | 141 | err: |
142 | dma_buf_end_cpu_access(dma_buf, offset, size, dir); | 142 | dma_buf_end_cpu_access(dma_buf, dir); |
143 | return ret; | 143 | return ret; |
144 | } | 144 | } |
145 | 145 | ||
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c65a212db77e..8c7fb3d0f9d0 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -307,6 +307,7 @@ struct drm_plane_helper_funcs; | |||
307 | * @connectors_changed: connectors to this crtc have been updated | 307 | * @connectors_changed: connectors to this crtc have been updated |
308 | * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes | 308 | * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes |
309 | * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors | 309 | * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors |
310 | * @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders | ||
310 | * @last_vblank_count: for helpers and drivers to capture the vblank of the | 311 | * @last_vblank_count: for helpers and drivers to capture the vblank of the |
311 | * update to ensure framebuffer cleanup isn't done too early | 312 | * update to ensure framebuffer cleanup isn't done too early |
312 | * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings | 313 | * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings |
@@ -341,6 +342,7 @@ struct drm_crtc_state { | |||
341 | u32 plane_mask; | 342 | u32 plane_mask; |
342 | 343 | ||
343 | u32 connector_mask; | 344 | u32 connector_mask; |
345 | u32 encoder_mask; | ||
344 | 346 | ||
345 | /* last_vblank_count: for vblank waits before cleanup */ | 347 | /* last_vblank_count: for vblank waits before cleanup */ |
346 | u32 last_vblank_count; | 348 | u32 last_vblank_count; |
@@ -2153,6 +2155,17 @@ struct drm_mode_config { | |||
2153 | list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \ | 2155 | list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \ |
2154 | for_each_if ((plane_mask) & (1 << drm_plane_index(plane))) | 2156 | for_each_if ((plane_mask) & (1 << drm_plane_index(plane))) |
2155 | 2157 | ||
2158 | /** | ||
2159 | * drm_for_each_encoder_mask - iterate over encoders specified by bitmask | ||
2160 | * @encoder: the loop cursor | ||
2161 | * @dev: the DRM device | ||
2162 | * @encoder_mask: bitmask of encoder indices | ||
2163 | * | ||
2164 | * Iterate over all encoders specified by bitmask. | ||
2165 | */ | ||
2166 | #define drm_for_each_encoder_mask(encoder, dev, encoder_mask) \ | ||
2167 | list_for_each_entry((encoder), &(dev)->mode_config.encoder_list, head) \ | ||
2168 | for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder))) | ||
2156 | 2169 | ||
2157 | #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) | 2170 | #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) |
2158 | #define obj_to_connector(x) container_of(x, struct drm_connector, base) | 2171 | #define obj_to_connector(x) container_of(x, struct drm_connector, base) |
@@ -2225,6 +2238,7 @@ int drm_encoder_init(struct drm_device *dev, | |||
2225 | struct drm_encoder *encoder, | 2238 | struct drm_encoder *encoder, |
2226 | const struct drm_encoder_funcs *funcs, | 2239 | const struct drm_encoder_funcs *funcs, |
2227 | int encoder_type, const char *name, ...); | 2240 | int encoder_type, const char *name, ...); |
2241 | extern unsigned int drm_encoder_index(struct drm_encoder *encoder); | ||
2228 | 2242 | ||
2229 | /** | 2243 | /** |
2230 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? | 2244 | * drm_encoder_crtc_ok - can a given crtc drive a given encoder? |
@@ -2282,6 +2296,8 @@ extern void drm_property_destroy_user_blobs(struct drm_device *dev, | |||
2282 | extern bool drm_probe_ddc(struct i2c_adapter *adapter); | 2296 | extern bool drm_probe_ddc(struct i2c_adapter *adapter); |
2283 | extern struct edid *drm_get_edid(struct drm_connector *connector, | 2297 | extern struct edid *drm_get_edid(struct drm_connector *connector, |
2284 | struct i2c_adapter *adapter); | 2298 | struct i2c_adapter *adapter); |
2299 | extern struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, | ||
2300 | struct i2c_adapter *adapter); | ||
2285 | extern struct edid *drm_edid_duplicate(const struct edid *edid); | 2301 | extern struct edid *drm_edid_duplicate(const struct edid *edid); |
2286 | extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); | 2302 | extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); |
2287 | extern void drm_mode_config_init(struct drm_device *dev); | 2303 | extern void drm_mode_config_init(struct drm_device *dev); |
@@ -2482,6 +2498,8 @@ extern int drm_format_num_planes(uint32_t format); | |||
2482 | extern int drm_format_plane_cpp(uint32_t format, int plane); | 2498 | extern int drm_format_plane_cpp(uint32_t format, int plane); |
2483 | extern int drm_format_horz_chroma_subsampling(uint32_t format); | 2499 | extern int drm_format_horz_chroma_subsampling(uint32_t format); |
2484 | extern int drm_format_vert_chroma_subsampling(uint32_t format); | 2500 | extern int drm_format_vert_chroma_subsampling(uint32_t format); |
2501 | extern int drm_format_plane_width(int width, uint32_t format, int plane); | ||
2502 | extern int drm_format_plane_height(int height, uint32_t format, int plane); | ||
2485 | extern const char *drm_get_format_name(uint32_t format); | 2503 | extern const char *drm_get_format_name(uint32_t format); |
2486 | extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, | 2504 | extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, |
2487 | unsigned int supported_rotations); | 2505 | unsigned int supported_rotations); |
diff --git a/include/drm/drm_dp_aux_dev.h b/include/drm/drm_dp_aux_dev.h new file mode 100644 index 000000000000..1b76d990d8ab --- /dev/null +++ b/include/drm/drm_dp_aux_dev.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright © 2015 Intel Corporation | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
21 | * IN THE SOFTWARE. | ||
22 | * | ||
23 | * Authors: | ||
24 | * Rafael Antognolli <rafael.antognolli@intel.com> | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #ifndef DRM_DP_AUX_DEV | ||
29 | #define DRM_DP_AUX_DEV | ||
30 | |||
31 | #include <drm/drm_dp_helper.h> | ||
32 | |||
33 | #ifdef CONFIG_DRM_DP_AUX_CHARDEV | ||
34 | |||
35 | int drm_dp_aux_dev_init(void); | ||
36 | void drm_dp_aux_dev_exit(void); | ||
37 | int drm_dp_aux_register_devnode(struct drm_dp_aux *aux); | ||
38 | void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux); | ||
39 | |||
40 | #else | ||
41 | |||
42 | static inline int drm_dp_aux_dev_init(void) | ||
43 | { | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static inline void drm_dp_aux_dev_exit(void) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux) | ||
52 | { | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | #endif | ||
61 | |||
62 | #endif | ||
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index d8a40dff0d1d..062723bdcabe 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h | |||
@@ -219,6 +219,7 @@ struct drm_fb_helper { | |||
219 | }; | 219 | }; |
220 | 220 | ||
221 | #ifdef CONFIG_DRM_FBDEV_EMULATION | 221 | #ifdef CONFIG_DRM_FBDEV_EMULATION |
222 | int drm_fb_helper_modinit(void); | ||
222 | void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, | 223 | void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, |
223 | const struct drm_fb_helper_funcs *funcs); | 224 | const struct drm_fb_helper_funcs *funcs); |
224 | int drm_fb_helper_init(struct drm_device *dev, | 225 | int drm_fb_helper_init(struct drm_device *dev, |
@@ -283,6 +284,11 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_ | |||
283 | int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, | 284 | int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, |
284 | struct drm_connector *connector); | 285 | struct drm_connector *connector); |
285 | #else | 286 | #else |
287 | static inline int drm_fb_helper_modinit(void) | ||
288 | { | ||
289 | return 0; | ||
290 | } | ||
291 | |||
286 | static inline void drm_fb_helper_prepare(struct drm_device *dev, | 292 | static inline void drm_fb_helper_prepare(struct drm_device *dev, |
287 | struct drm_fb_helper *helper, | 293 | struct drm_fb_helper *helper, |
288 | const struct drm_fb_helper_funcs *funcs) | 294 | const struct drm_fb_helper_funcs *funcs) |
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index a126a0d7aed4..b61c2d45192e 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h | |||
@@ -439,7 +439,7 @@ struct drm_encoder_helper_funcs { | |||
439 | * can be modified by this callback and does not need to match mode. | 439 | * can be modified by this callback and does not need to match mode. |
440 | * | 440 | * |
441 | * This function is used by both legacy CRTC helpers and atomic helpers. | 441 | * This function is used by both legacy CRTC helpers and atomic helpers. |
442 | * With atomic helpers it is optional. | 442 | * This hook is optional. |
443 | * | 443 | * |
444 | * NOTE: | 444 | * NOTE: |
445 | * | 445 | * |
diff --git a/include/linux/apple-gmux.h b/include/linux/apple-gmux.h new file mode 100644 index 000000000000..b2d32e01dfe4 --- /dev/null +++ b/include/linux/apple-gmux.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * apple-gmux.h - microcontroller built into dual GPU MacBook Pro & Mac Pro | ||
3 | * Copyright (C) 2015 Lukas Wunner <lukas@wunner.de> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License (version 2) as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | #ifndef LINUX_APPLE_GMUX_H | ||
19 | #define LINUX_APPLE_GMUX_H | ||
20 | |||
21 | #include <linux/acpi.h> | ||
22 | |||
23 | #define GMUX_ACPI_HID "APP000B" | ||
24 | |||
25 | #if IS_ENABLED(CONFIG_APPLE_GMUX) | ||
26 | |||
27 | /** | ||
28 | * apple_gmux_present() - detect if gmux is built into the machine | ||
29 | * | ||
30 | * Drivers may use this to activate quirks specific to dual GPU MacBook Pros | ||
31 | * and Mac Pros, e.g. for deferred probing, runtime pm and backlight. | ||
32 | * | ||
33 | * Return: %true if gmux is present and the kernel was configured | ||
34 | * with CONFIG_APPLE_GMUX, %false otherwise. | ||
35 | */ | ||
36 | static inline bool apple_gmux_present(void) | ||
37 | { | ||
38 | return acpi_dev_present(GMUX_ACPI_HID); | ||
39 | } | ||
40 | |||
41 | #else /* !CONFIG_APPLE_GMUX */ | ||
42 | |||
43 | static inline bool apple_gmux_present(void) | ||
44 | { | ||
45 | return false; | ||
46 | } | ||
47 | |||
48 | #endif /* !CONFIG_APPLE_GMUX */ | ||
49 | |||
50 | #endif /* LINUX_APPLE_GMUX_H */ | ||
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index f98bd7068d55..532108ea0c1c 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h | |||
@@ -54,7 +54,7 @@ struct dma_buf_attachment; | |||
54 | * @release: release this buffer; to be called after the last dma_buf_put. | 54 | * @release: release this buffer; to be called after the last dma_buf_put. |
55 | * @begin_cpu_access: [optional] called before cpu access to invalidate cpu | 55 | * @begin_cpu_access: [optional] called before cpu access to invalidate cpu |
56 | * caches and allocate backing storage (if not yet done) | 56 | * caches and allocate backing storage (if not yet done) |
57 | * respectively pin the objet into memory. | 57 | * respectively pin the object into memory. |
58 | * @end_cpu_access: [optional] called after cpu access to flush caches. | 58 | * @end_cpu_access: [optional] called after cpu access to flush caches. |
59 | * @kmap_atomic: maps a page from the buffer into kernel address | 59 | * @kmap_atomic: maps a page from the buffer into kernel address |
60 | * space, users may not block until the subsequent unmap call. | 60 | * space, users may not block until the subsequent unmap call. |
@@ -93,10 +93,8 @@ struct dma_buf_ops { | |||
93 | /* after final dma_buf_put() */ | 93 | /* after final dma_buf_put() */ |
94 | void (*release)(struct dma_buf *); | 94 | void (*release)(struct dma_buf *); |
95 | 95 | ||
96 | int (*begin_cpu_access)(struct dma_buf *, size_t, size_t, | 96 | int (*begin_cpu_access)(struct dma_buf *, enum dma_data_direction); |
97 | enum dma_data_direction); | 97 | void (*end_cpu_access)(struct dma_buf *, enum dma_data_direction); |
98 | void (*end_cpu_access)(struct dma_buf *, size_t, size_t, | ||
99 | enum dma_data_direction); | ||
100 | void *(*kmap_atomic)(struct dma_buf *, unsigned long); | 98 | void *(*kmap_atomic)(struct dma_buf *, unsigned long); |
101 | void (*kunmap_atomic)(struct dma_buf *, unsigned long, void *); | 99 | void (*kunmap_atomic)(struct dma_buf *, unsigned long, void *); |
102 | void *(*kmap)(struct dma_buf *, unsigned long); | 100 | void *(*kmap)(struct dma_buf *, unsigned long); |
@@ -224,9 +222,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *, | |||
224 | enum dma_data_direction); | 222 | enum dma_data_direction); |
225 | void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *, | 223 | void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *, |
226 | enum dma_data_direction); | 224 | enum dma_data_direction); |
227 | int dma_buf_begin_cpu_access(struct dma_buf *dma_buf, size_t start, size_t len, | 225 | int dma_buf_begin_cpu_access(struct dma_buf *dma_buf, |
228 | enum dma_data_direction dir); | 226 | enum dma_data_direction dir); |
229 | void dma_buf_end_cpu_access(struct dma_buf *dma_buf, size_t start, size_t len, | 227 | void dma_buf_end_cpu_access(struct dma_buf *dma_buf, |
230 | enum dma_data_direction dir); | 228 | enum dma_data_direction dir); |
231 | void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long); | 229 | void *dma_buf_kmap_atomic(struct dma_buf *, unsigned long); |
232 | void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *); | 230 | void dma_buf_kunmap_atomic(struct dma_buf *, unsigned long, void *); |
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h index 69e1d4a1f1b3..b39a5f3153bd 100644 --- a/include/linux/vga_switcheroo.h +++ b/include/linux/vga_switcheroo.h | |||
@@ -36,6 +36,26 @@ | |||
36 | struct pci_dev; | 36 | struct pci_dev; |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * enum vga_switcheroo_handler_flags_t - handler flags bitmask | ||
40 | * @VGA_SWITCHEROO_CAN_SWITCH_DDC: whether the handler is able to switch the | ||
41 | * DDC lines separately. This signals to clients that they should call | ||
42 | * drm_get_edid_switcheroo() to probe the EDID | ||
43 | * @VGA_SWITCHEROO_NEEDS_EDP_CONFIG: whether the handler is unable to switch | ||
44 | * the AUX channel separately. This signals to clients that the active | ||
45 | * GPU needs to train the link and communicate the link parameters to the | ||
46 | * inactive GPU (mediated by vga_switcheroo). The inactive GPU may then | ||
47 | * skip the AUX handshake and set up its output with these pre-calibrated | ||
48 | * values (DisplayPort specification v1.1a, section 2.5.3.3) | ||
49 | * | ||
50 | * Handler flags bitmask. Used by handlers to declare their capabilities upon | ||
51 | * registering with vga_switcheroo. | ||
52 | */ | ||
53 | enum vga_switcheroo_handler_flags_t { | ||
54 | VGA_SWITCHEROO_CAN_SWITCH_DDC = (1 << 0), | ||
55 | VGA_SWITCHEROO_NEEDS_EDP_CONFIG = (1 << 1), | ||
56 | }; | ||
57 | |||
58 | /** | ||
39 | * enum vga_switcheroo_state - client power state | 59 | * enum vga_switcheroo_state - client power state |
40 | * @VGA_SWITCHEROO_OFF: off | 60 | * @VGA_SWITCHEROO_OFF: off |
41 | * @VGA_SWITCHEROO_ON: on | 61 | * @VGA_SWITCHEROO_ON: on |
@@ -82,6 +102,9 @@ enum vga_switcheroo_client_id { | |||
82 | * Mandatory. For muxless machines this should be a no-op. Returning 0 | 102 | * Mandatory. For muxless machines this should be a no-op. Returning 0 |
83 | * denotes success, anything else failure (in which case the switch is | 103 | * denotes success, anything else failure (in which case the switch is |
84 | * aborted) | 104 | * aborted) |
105 | * @switch_ddc: switch DDC lines to given client. | ||
106 | * Optional. Should return the previous DDC owner on success or a | ||
107 | * negative int on failure | ||
85 | * @power_state: cut or reinstate power of given client. | 108 | * @power_state: cut or reinstate power of given client. |
86 | * Optional. The return value is ignored | 109 | * Optional. The return value is ignored |
87 | * @get_client_id: determine if given pci device is integrated or discrete GPU. | 110 | * @get_client_id: determine if given pci device is integrated or discrete GPU. |
@@ -93,6 +116,7 @@ enum vga_switcheroo_client_id { | |||
93 | struct vga_switcheroo_handler { | 116 | struct vga_switcheroo_handler { |
94 | int (*init)(void); | 117 | int (*init)(void); |
95 | int (*switchto)(enum vga_switcheroo_client_id id); | 118 | int (*switchto)(enum vga_switcheroo_client_id id); |
119 | int (*switch_ddc)(enum vga_switcheroo_client_id id); | ||
96 | int (*power_state)(enum vga_switcheroo_client_id id, | 120 | int (*power_state)(enum vga_switcheroo_client_id id, |
97 | enum vga_switcheroo_state state); | 121 | enum vga_switcheroo_state state); |
98 | enum vga_switcheroo_client_id (*get_client_id)(struct pci_dev *pdev); | 122 | enum vga_switcheroo_client_id (*get_client_id)(struct pci_dev *pdev); |
@@ -132,8 +156,12 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev, | |||
132 | void vga_switcheroo_client_fb_set(struct pci_dev *dev, | 156 | void vga_switcheroo_client_fb_set(struct pci_dev *dev, |
133 | struct fb_info *info); | 157 | struct fb_info *info); |
134 | 158 | ||
135 | int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler); | 159 | int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, |
160 | enum vga_switcheroo_handler_flags_t handler_flags); | ||
136 | void vga_switcheroo_unregister_handler(void); | 161 | void vga_switcheroo_unregister_handler(void); |
162 | enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void); | ||
163 | int vga_switcheroo_lock_ddc(struct pci_dev *pdev); | ||
164 | int vga_switcheroo_unlock_ddc(struct pci_dev *pdev); | ||
137 | 165 | ||
138 | int vga_switcheroo_process_delayed_switch(void); | 166 | int vga_switcheroo_process_delayed_switch(void); |
139 | 167 | ||
@@ -150,11 +178,15 @@ static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {} | |||
150 | static inline int vga_switcheroo_register_client(struct pci_dev *dev, | 178 | static inline int vga_switcheroo_register_client(struct pci_dev *dev, |
151 | const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { return 0; } | 179 | const struct vga_switcheroo_client_ops *ops, bool driver_power_control) { return 0; } |
152 | static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {} | 180 | static inline void vga_switcheroo_client_fb_set(struct pci_dev *dev, struct fb_info *info) {} |
153 | static inline int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler) { return 0; } | 181 | static inline int vga_switcheroo_register_handler(const struct vga_switcheroo_handler *handler, |
182 | enum vga_switcheroo_handler_flags_t handler_flags) { return 0; } | ||
154 | static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, | 183 | static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, |
155 | const struct vga_switcheroo_client_ops *ops, | 184 | const struct vga_switcheroo_client_ops *ops, |
156 | enum vga_switcheroo_client_id id) { return 0; } | 185 | enum vga_switcheroo_client_id id) { return 0; } |
157 | static inline void vga_switcheroo_unregister_handler(void) {} | 186 | static inline void vga_switcheroo_unregister_handler(void) {} |
187 | static inline enum vga_switcheroo_handler_flags_t vga_switcheroo_handler_flags(void) { return 0; } | ||
188 | static inline int vga_switcheroo_lock_ddc(struct pci_dev *pdev) { return -ENODEV; } | ||
189 | static inline int vga_switcheroo_unlock_ddc(struct pci_dev *pdev) { return -ENODEV; } | ||
158 | static inline int vga_switcheroo_process_delayed_switch(void) { return 0; } | 190 | static inline int vga_switcheroo_process_delayed_switch(void) { return 0; } |
159 | static inline enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; } | 191 | static inline enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; } |
160 | 192 | ||
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index b4e92eb12044..a0ebfe7c9a28 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h | |||
@@ -669,6 +669,7 @@ struct drm_set_client_cap { | |||
669 | __u64 value; | 669 | __u64 value; |
670 | }; | 670 | }; |
671 | 671 | ||
672 | #define DRM_RDWR O_RDWR | ||
672 | #define DRM_CLOEXEC O_CLOEXEC | 673 | #define DRM_CLOEXEC O_CLOEXEC |
673 | struct drm_prime_handle { | 674 | struct drm_prime_handle { |
674 | __u32 handle; | 675 | __u32 handle; |
diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h new file mode 100644 index 000000000000..fb0dedb7c121 --- /dev/null +++ b/include/uapi/linux/dma-buf.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Framework for buffer objects that can be shared across devices/subsystems. | ||
3 | * | ||
4 | * Copyright(C) 2015 Intel Ltd | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #ifndef _DMA_BUF_UAPI_H_ | ||
20 | #define _DMA_BUF_UAPI_H_ | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | |||
24 | /* begin/end dma-buf functions used for userspace mmap. */ | ||
25 | struct dma_buf_sync { | ||
26 | __u64 flags; | ||
27 | }; | ||
28 | |||
29 | #define DMA_BUF_SYNC_READ (1 << 0) | ||
30 | #define DMA_BUF_SYNC_WRITE (2 << 0) | ||
31 | #define DMA_BUF_SYNC_RW (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE) | ||
32 | #define DMA_BUF_SYNC_START (0 << 2) | ||
33 | #define DMA_BUF_SYNC_END (1 << 2) | ||
34 | #define DMA_BUF_SYNC_VALID_FLAGS_MASK \ | ||
35 | (DMA_BUF_SYNC_RW | DMA_BUF_SYNC_END) | ||
36 | |||
37 | #define DMA_BUF_BASE 'b' | ||
38 | #define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) | ||
39 | |||
40 | #endif | ||