diff --git a/Documentation/devicetree/bindings/display/panel/jdi,lpm102a188a.yaml b/Documentation/devicetree/bindings/display/panel/jdi,lpm102a188a.yaml new file mode 100644 index 000000000000..2f4d27a309a7 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/jdi,lpm102a188a.yaml @@ -0,0 +1,94 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/jdi,lpm102a188a.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: JDI LPM102A188A 2560x1800 10.2" DSI Panel + +maintainers: + - Diogo Ivo + +description: | + This panel requires a dual-channel DSI host to operate. It supports two modes: + - left-right: each channel drives the left or right half of the screen + - even-odd: each channel drives the even or odd lines of the screen + + Each of the DSI channels controls a separate DSI peripheral. The peripheral + driven by the first link (DSI-LINK1) is considered the primary peripheral + and controls the device. The 'link2' property contains a phandle to the + peripheral driven by the second link (DSI-LINK2). + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + const: jdi,lpm102a188a + + reg: true + enable-gpios: true + reset-gpios: true + power-supply: true + backlight: true + + ddi-supply: + description: The regulator that provides IOVCC (1.8V). + + link2: + $ref: /schemas/types.yaml#/definitions/phandle + description: | + phandle to the DSI peripheral on the secondary link. Note that the + presence of this property marks the containing node as DSI-LINK1. + +required: + - compatible + - reg + +if: + required: + - link2 +then: + required: + - power-supply + - ddi-supply + - enable-gpios + - reset-gpios + +additionalProperties: false + +examples: + - | + #include + #include + + dsia: dsi@54300000 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x54300000 0x0 0x00040000>; + + link2: panel@0 { + compatible = "jdi,lpm102a188a"; + reg = <0>; + }; + }; + + dsib: dsi@54400000{ + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x54400000 0x0 0x00040000>; + nvidia,ganged-mode = <&dsia>; + + link1: panel@0 { + compatible = "jdi,lpm102a188a"; + reg = <0>; + power-supply = <&pplcd_vdd>; + ddi-supply = <&pp1800_lcdio>; + enable-gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>; + link2 = <&link2>; + backlight = <&backlight>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index 25b4589d4a58..50143fe67471 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -238,6 +238,8 @@ properties: - logictechno,lttd800480070-l6wh-rt # Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel - mitsubishi,aa070mc01-ca1 + # Mitsubishi AA084XE01 8.4" XGA TFT LCD panel + - mitsubishi,aa084xe01 # Multi-Inno Technology Co.,Ltd MI0700S4T-6 7" 800x480 TFT Resistive Touch Module - multi-inno,mi0700s4t-6 # Multi-Inno Technology Co.,Ltd MI0800FT-9 8" 800x600 TFT Resistive Touch Module diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml index 8e8a40879140..ccf79e738fa1 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-mipi-dsi.yaml @@ -18,6 +18,7 @@ properties: - rockchip,rk3288-mipi-dsi - rockchip,rk3399-mipi-dsi - rockchip,rk3568-mipi-dsi + - rockchip,rv1126-mipi-dsi - const: snps,dw-mipi-dsi interrupts: @@ -77,6 +78,7 @@ allOf: enum: - rockchip,px30-mipi-dsi - rockchip,rk3568-mipi-dsi + - rockchip,rv1126-mipi-dsi then: properties: diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml index df61cb5f5c54..b339b7e708c6 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-vop.yaml @@ -31,6 +31,7 @@ properties: - rockchip,rk3368-vop - rockchip,rk3399-vop-big - rockchip,rk3399-vop-lit + - rockchip,rv1126-vop reg: minItems: 1 diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst index f92a32d095d9..0c153d79ccc4 100644 --- a/Documentation/driver-api/dma-buf.rst +++ b/Documentation/driver-api/dma-buf.rst @@ -5,14 +5,30 @@ The dma-buf subsystem provides the framework for sharing buffers for hardware (DMA) access across multiple device drivers and subsystems, and for synchronizing asynchronous hardware access. -This is used, for example, by drm "prime" multi-GPU support, but is of -course not limited to GPU use cases. +As an example, it is used extensively by the DRM subsystem to exchange +buffers between processes, contexts, library APIs within the same +process, and also to exchange buffers with other subsystems such as +V4L2. + +This document describes the way in which kernel subsystems can use and +interact with the three main primitives offered by dma-buf: + + - dma-buf, representing a sg_table and exposed to userspace as a file + descriptor to allow passing between processes, subsystems, devices, + etc; + - dma-fence, providing a mechanism to signal when an asynchronous + hardware operation has completed; and + - dma-resv, which manages a set of dma-fences for a particular dma-buf + allowing implicit (kernel-ordered) synchronization of work to + preserve the illusion of coherent access + + +Userspace API principles and use +-------------------------------- + +For more details on how to design your subsystem's API for dma-buf use, please +see Documentation/userspace-api/dma-buf-alloc-exchange.rst. -The three main components of this are: (1) dma-buf, representing a -sg_table and exposed to userspace as a file descriptor to allow passing -between devices, (2) fence, which provides a mechanism to signal when -one device has finished access, and (3) reservation, which manages the -shared or exclusive fence(s) associated with the buffer. Shared DMA Buffers ------------------ diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 65fb3036a580..eef5fd19bc92 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -486,3 +486,10 @@ and the CRTC index is its position in this array. .. kernel-doc:: include/uapi/drm/drm_mode.h :internal: + + +dma-buf interoperability +======================== + +Please see Documentation/userspace-api/dma-buf-alloc-exchange.rst for +information on how dma-buf is integrated and exposed within DRM. diff --git a/Documentation/gpu/rfc/xe.rst b/Documentation/gpu/rfc/xe.rst index 2516fe141db6..b67f8e6a1825 100644 --- a/Documentation/gpu/rfc/xe.rst +++ b/Documentation/gpu/rfc/xe.rst @@ -67,14 +67,8 @@ platforms. When the time comes for Xe, the protection will be lifted on Xe and kept in i915. -Xe driver will be protected with both STAGING Kconfig and force_probe. Changes in -the uAPI are expected while the driver is behind these protections. STAGING will -be removed when the driver uAPI gets to a mature state where we can guarantee the -‘no regression’ rule. Then force_probe will be lifted only for future platforms -that will be productized with Xe driver, but not with i915. - -Xe – Pre-Merge Goals -==================== +Xe – Pre-Merge Goals - Work-in-Progress +======================================= Drm_scheduler ------------- @@ -94,41 +88,6 @@ depend on any other patch touching drm_scheduler itself that was not yet merged through drm-misc. This, by itself, already includes the reach of an agreement for uniform 1 to 1 relationship implementation / usage across drivers. -GPU VA ------- -Two main goals of Xe are meeting together here: - -1) Have an uAPI that aligns with modern UMD needs. - -2) Early upstream engagement. - -RedHat engineers working on Nouveau proposed a new DRM feature to handle keeping -track of GPU virtual address mappings. This is still not merged upstream, but -this aligns very well with our goals and with our VM_BIND. The engagement with -upstream and the port of Xe towards GPUVA is already ongoing. - -As a key measurable result, Xe needs to be aligned with the GPU VA and working in -our tree. Missing Nouveau patches should *not* block Xe and any needed GPUVA -related patch should be independent and present on dri-devel or acked by -maintainers to go along with the first Xe pull request towards drm-next. - -DRM_VM_BIND ------------ -Nouveau, and Xe are all implementing ‘VM_BIND’ and new ‘Exec’ uAPIs in order to -fulfill the needs of the modern uAPI. Xe merge should *not* be blocked on the -development of a common new drm_infrastructure. However, the Xe team needs to -engage with the community to explore the options of a common API. - -As a key measurable result, the DRM_VM_BIND needs to be documented in this file -below, or this entire block deleted if the consensus is for independent drivers -vm_bind ioctls. - -Although having a common DRM level IOCTL for VM_BIND is not a requirement to get -Xe merged, it is mandatory to enforce the overall locking scheme for all major -structs and list (so vm and vma). So, a consensus is needed, and possibly some -common helpers. If helpers are needed, they should be also documented in this -document. - ASYNC VM_BIND ------------- Although having a common DRM level IOCTL for VM_BIND is not a requirement to get @@ -212,6 +171,14 @@ This item ties into the GPUVA, VM_BIND, and even long-running compute support. As a key measurable result, we need to have a community consensus documented in this document and the Xe driver prepared for the changes, if necessary. +Xe – uAPI high level overview +============================= + +...Warning: To be done in follow up patches after/when/where the main consensus in various items are individually reached. + +Xe – Pre-Merge Goals - Completed +================================ + Dev_coredump ------------ @@ -229,7 +196,37 @@ infrastructure with overall possible improvements, like multiple file support for better organization of the dumps, snapshot support, dmesg extra print, and whatever may make sense and help the overall infrastructure. -Xe – uAPI high level overview -============================= +DRM_VM_BIND +----------- +Nouveau, and Xe are all implementing ‘VM_BIND’ and new ‘Exec’ uAPIs in order to +fulfill the needs of the modern uAPI. Xe merge should *not* be blocked on the +development of a common new drm_infrastructure. However, the Xe team needs to +engage with the community to explore the options of a common API. -...Warning: To be done in follow up patches after/when/where the main consensus in various items are individually reached. +As a key measurable result, the DRM_VM_BIND needs to be documented in this file +below, or this entire block deleted if the consensus is for independent drivers +vm_bind ioctls. + +Although having a common DRM level IOCTL for VM_BIND is not a requirement to get +Xe merged, it is mandatory to enforce the overall locking scheme for all major +structs and list (so vm and vma). So, a consensus is needed, and possibly some +common helpers. If helpers are needed, they should be also documented in this +document. + +GPU VA +------ +Two main goals of Xe are meeting together here: + +1) Have an uAPI that aligns with modern UMD needs. + +2) Early upstream engagement. + +RedHat engineers working on Nouveau proposed a new DRM feature to handle keeping +track of GPU virtual address mappings. This is still not merged upstream, but +this aligns very well with our goals and with our VM_BIND. The engagement with +upstream and the port of Xe towards GPUVA is already ongoing. + +As a key measurable result, Xe needs to be aligned with the GPU VA and working in +our tree. Missing Nouveau patches should *not* block Xe and any needed GPUVA +related patch should be independent and present on dri-devel or acked by +maintainers to go along with the first Xe pull request towards drm-next. diff --git a/Documentation/userspace-api/dma-buf-alloc-exchange.rst b/Documentation/userspace-api/dma-buf-alloc-exchange.rst new file mode 100644 index 000000000000..fdff19fce13e --- /dev/null +++ b/Documentation/userspace-api/dma-buf-alloc-exchange.rst @@ -0,0 +1,389 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. Copyright 2021-2023 Collabora Ltd. + +======================== +Exchanging pixel buffers +======================== + +As originally designed, the Linux graphics subsystem had extremely limited +support for sharing pixel-buffer allocations between processes, devices, and +subsystems. Modern systems require extensive integration between all three +classes; this document details how applications and kernel subsystems should +approach this sharing for two-dimensional image data. + +It is written with reference to the DRM subsystem for GPU and display devices, +V4L2 for media devices, and also to Vulkan, EGL and Wayland, for userspace +support, however any other subsystems should also follow this design and advice. + + +Glossary of terms +================= + +.. glossary:: + + image: + Conceptually a two-dimensional array of pixels. The pixels may be stored + in one or more memory buffers. Has width and height in pixels, pixel + format and modifier (implicit or explicit). + + row: + A span along a single y-axis value, e.g. from co-ordinates (0,100) to + (200,100). + + scanline: + Synonym for row. + + column: + A span along a single x-axis value, e.g. from co-ordinates (100,0) to + (100,100). + + memory buffer: + A piece of memory for storing (parts of) pixel data. Has stride and size + in bytes and at least one handle in some API. May contain one or more + planes. + + plane: + A two-dimensional array of some or all of an image's color and alpha + channel values. + + pixel: + A picture element. Has a single color value which is defined by one or + more color channels values, e.g. R, G and B, or Y, Cb and Cr. May also + have an alpha value as an additional channel. + + pixel data: + Bytes or bits that represent some or all of the color/alpha channel values + of a pixel or an image. The data for one pixel may be spread over several + planes or memory buffers depending on format and modifier. + + color value: + A tuple of numbers, representing a color. Each element in the tuple is a + color channel value. + + color channel: + One of the dimensions in a color model. For example, RGB model has + channels R, G, and B. Alpha channel is sometimes counted as a color + channel as well. + + pixel format: + A description of how pixel data represents the pixel's color and alpha + values. + + modifier: + A description of how pixel data is laid out in memory buffers. + + alpha: + A value that denotes the color coverage in a pixel. Sometimes used for + translucency instead. + + stride: + A value that denotes the relationship between pixel-location co-ordinates + and byte-offset values. Typically used as the byte offset between two + pixels at the start of vertically-consecutive tiling blocks. For linear + layouts, the byte offset between two vertically-adjacent pixels. For + non-linear formats the stride must be computed in a consistent way, which + usually is done as-if the layout was linear. + + pitch: + Synonym for stride. + + +Formats and modifiers +===================== + +Each buffer must have an underlying format. This format describes the color +values provided for each pixel. Although each subsystem has its own format +descriptions (e.g. V4L2 and fbdev), the ``DRM_FORMAT_*`` tokens should be reused +wherever possible, as they are the standard descriptions used for interchange. +These tokens are described in the ``drm_fourcc.h`` file, which is a part of +DRM's uAPI. + +Each ``DRM_FORMAT_*`` token describes the translation between a pixel +co-ordinate in an image, and the color values for that pixel contained within +its memory buffers. The number and type of color channels are described: +whether they are RGB or YUV, integer or floating-point, the size of each channel +and their locations within the pixel memory, and the relationship between color +planes. + +For example, ``DRM_FORMAT_ARGB8888`` describes a format in which each pixel has +a single 32-bit value in memory. Alpha, red, green, and blue, color channels are +available at 8-bit precision per channel, ordered respectively from most to +least significant bits in little-endian storage. ``DRM_FORMAT_*`` is not +affected by either CPU or device endianness; the byte pattern in memory is +always as described in the format definition, which is usually little-endian. + +As a more complex example, ``DRM_FORMAT_NV12`` describes a format in which luma +and chroma YUV samples are stored in separate planes, where the chroma plane is +stored at half the resolution in both dimensions (i.e. one U/V chroma +sample is stored for each 2x2 pixel grouping). + +Format modifiers describe a translation mechanism between these per-pixel memory +samples, and the actual memory storage for the buffer. The most straightforward +modifier is ``DRM_FORMAT_MOD_LINEAR``, describing a scheme in which each plane +is laid out row-sequentially, from the top-left to the bottom-right corner. +This is considered the baseline interchange format, and most convenient for CPU +access. + +Modern hardware employs much more sophisticated access mechanisms, typically +making use of tiled access and possibly also compression. For example, the +``DRM_FORMAT_MOD_VIVANTE_TILED`` modifier describes memory storage where pixels +are stored in 4x4 blocks arranged in row-major ordering, i.e. the first tile in +a plane stores pixels (0,0) to (3,3) inclusive, and the second tile in a plane +stores pixels (4,0) to (7,3) inclusive. + +Some modifiers may modify the number of planes required for an image; for +example, the ``I915_FORMAT_MOD_Y_TILED_CCS`` modifier adds a second plane to RGB +formats in which it stores data about the status of every tile, notably +including whether the tile is fully populated with pixel data, or can be +expanded from a single solid color. + +These extended layouts are highly vendor-specific, and even specific to +particular generations or configurations of devices per-vendor. For this reason, +support of modifiers must be explicitly enumerated and negotiated by all users +in order to ensure a compatible and optimal pipeline, as discussed below. + + +Dimensions and size +=================== + +Each pixel buffer must be accompanied by logical pixel dimensions. This refers +to the number of unique samples which can be extracted from, or stored to, the +underlying memory storage. For example, even though a 1920x1080 +``DRM_FORMAT_NV12`` buffer has a luma plane containing 1920x1080 samples for the Y +component, and 960x540 samples for the U and V components, the overall buffer is +still described as having dimensions of 1920x1080. + +The in-memory storage of a buffer is not guaranteed to begin immediately at the +base address of the underlying memory, nor is it guaranteed that the memory +storage is tightly clipped to either dimension. + +Each plane must therefore be described with an ``offset`` in bytes, which will be +added to the base address of the memory storage before performing any per-pixel +calculations. This may be used to combine multiple planes into a single memory +buffer; for example, ``DRM_FORMAT_NV12`` may be stored in a single memory buffer +where the luma plane's storage begins immediately at the start of the buffer +with an offset of 0, and the chroma plane's storage follows within the same buffer +beginning from the byte offset for that plane. + +Each plane must also have a ``stride`` in bytes, expressing the offset in memory +between two contiguous row. For example, a ``DRM_FORMAT_MOD_LINEAR`` buffer +with dimensions of 1000x1000 may have been allocated as if it were 1024x1000, in +order to allow for aligned access patterns. In this case, the buffer will still +be described with a width of 1000, however the stride will be ``1024 * bpp``, +indicating that there are 24 pixels at the positive extreme of the x axis whose +values are not significant. + +Buffers may also be padded further in the y dimension, simply by allocating a +larger area than would ordinarily be required. For example, many media decoders +are not able to natively output buffers of height 1080, but instead require an +effective height of 1088 pixels. In this case, the buffer continues to be +described as having a height of 1080, with the memory allocation for each buffer +being increased to account for the extra padding. + + +Enumeration +=========== + +Every user of pixel buffers must be able to enumerate a set of supported formats +and modifiers, described together. Within KMS, this is achieved with the +``IN_FORMATS`` property on each DRM plane, listing the supported DRM formats, and +the modifiers supported for each format. In userspace, this is supported through +the `EGL_EXT_image_dma_buf_import_modifiers`_ extension entrypoints for EGL, the +`VK_EXT_image_drm_format_modifier`_ extension for Vulkan, and the +`zwp_linux_dmabuf_v1`_ extension for Wayland. + +Each of these interfaces allows users to query a set of supported +format+modifier combinations. + + +Negotiation +=========== + +It is the responsibility of userspace to negotiate an acceptable format+modifier +combination for its usage. This is performed through a simple intersection of +lists. For example, if a user wants to use Vulkan to render an image to be +displayed on a KMS plane, it must: + + - query KMS for the ``IN_FORMATS`` property for the given plane + - query Vulkan for the supported formats for its physical device, making sure + to pass the ``VkImageUsageFlagBits`` and ``VkImageCreateFlagBits`` + corresponding to the intended rendering use + - intersect these formats to determine the most appropriate one + - for this format, intersect the lists of supported modifiers for both KMS and + Vulkan, to obtain a final list of acceptable modifiers for that format + +This intersection must be performed for all usages. For example, if the user +also wishes to encode the image to a video stream, it must query the media API +it intends to use for encoding for the set of modifiers it supports, and +additionally intersect against this list. + +If the intersection of all lists is an empty list, it is not possible to share +buffers in this way, and an alternate strategy must be considered (e.g. using +CPU access routines to copy data between the different uses, with the +corresponding performance cost). + +The resulting modifier list is unsorted; the order is not significant. + + +Allocation +========== + +Once userspace has determined an appropriate format, and corresponding list of +acceptable modifiers, it must allocate the buffer. As there is no universal +buffer-allocation interface available at either kernel or userspace level, the +client makes an arbitrary choice of allocation interface such as Vulkan, GBM, or +a media API. + +Each allocation request must take, at a minimum: the pixel format, a list of +acceptable modifiers, and the buffer's width and height. Each API may extend +this set of properties in different ways, such as allowing allocation in more +than two dimensions, intended usage patterns, etc. + +The component which allocates the buffer will make an arbitrary choice of what +it considers the 'best' modifier within the acceptable list for the requested +allocation, any padding required, and further properties of the underlying +memory buffers such as whether they are stored in system or device-specific +memory, whether or not they are physically contiguous, and their cache mode. +These properties of the memory buffer are not visible to userspace, however the +``dma-heaps`` API is an effort to address this. + +After allocation, the client must query the allocator to determine the actual +modifier selected for the buffer, as well as the per-plane offset and stride. +Allocators are not permitted to vary the format in use, to select a modifier not +provided within the acceptable list, nor to vary the pixel dimensions other than +the padding expressed through offset, stride, and size. + +Communicating additional constraints, such as alignment of stride or offset, +placement within a particular memory area, etc, is out of scope of dma-buf, +and is not solved by format and modifier tokens. + + +Import +====== + +To use a buffer within a different context, device, or subsystem, the user +passes these parameters (format, modifier, width, height, and per-plane offset +and stride) to an importing API. + +Each memory buffer is referred to by a buffer handle, which may be unique or +duplicated within an image. For example, a ``DRM_FORMAT_NV12`` buffer may have +the luma and chroma buffers combined into a single memory buffer by use of the +per-plane offset parameters, or they may be completely separate allocations in +memory. For this reason, each import and allocation API must provide a separate +handle for each plane. + +Each kernel subsystem has its own types and interfaces for buffer management. +DRM uses GEM buffer objects (BOs), V4L2 has its own references, etc. These types +are not portable between contexts, processes, devices, or subsystems. + +To address this, ``dma-buf`` handles are used as the universal interchange for +buffers. Subsystem-specific operations are used to export native buffer handles +to a ``dma-buf`` file descriptor, and to import those file descriptors into a +native buffer handle. dma-buf file descriptors can be transferred between +contexts, processes, devices, and subsystems. + +For example, a Wayland media player may use V4L2 to decode a video frame into a +``DRM_FORMAT_NV12`` buffer. This will result in two memory planes (luma and +chroma) being dequeued by the user from V4L2. These planes are then exported to +one dma-buf file descriptor per plane, these descriptors are then sent along +with the metadata (format, modifier, width, height, per-plane offset and stride) +to the Wayland server. The Wayland server will then import these file +descriptors as an EGLImage for use through EGL/OpenGL (ES), a VkImage for use +through Vulkan, or a KMS framebuffer object; each of these import operations +will take the same metadata and convert the dma-buf file descriptors into their +native buffer handles. + +Having a non-empty intersection of supported modifiers does not guarantee that +import will succeed into all consumers; they may have constraints beyond those +implied by modifiers which must be satisfied. + + +Implicit modifiers +================== + +The concept of modifiers post-dates all of the subsystems mentioned above. As +such, it has been retrofitted into all of these APIs, and in order to ensure +backwards compatibility, support is needed for drivers and userspace which do +not (yet) support modifiers. + +As an example, GBM is used to allocate buffers to be shared between EGL for +rendering and KMS for display. It has two entrypoints for allocating buffers: +``gbm_bo_create`` which only takes the format, width, height, and a usage token, +and ``gbm_bo_create_with_modifiers`` which extends this with a list of modifiers. + +In the latter case, the allocation is as discussed above, being provided with a +list of acceptable modifiers that the implementation can choose from (or fail if +it is not possible to allocate within those constraints). In the former case +where modifiers are not provided, the GBM implementation must make its own +choice as to what is likely to be the 'best' layout. Such a choice is entirely +implementation-specific: some will internally use tiled layouts which are not +CPU-accessible if the implementation decides that is a good idea through +whatever heuristic. It is the implementation's responsibility to ensure that +this choice is appropriate. + +To support this case where the layout is not known because there is no awareness +of modifiers, a special ``DRM_FORMAT_MOD_INVALID`` token has been defined. This +pseudo-modifier declares that the layout is not known, and that the driver +should use its own logic to determine what the underlying layout may be. + +.. note:: + + ``DRM_FORMAT_MOD_INVALID`` is a non-zero value. The modifier value zero is + ``DRM_FORMAT_MOD_LINEAR``, which is an explicit guarantee that the image + has the linear layout. Care and attention should be taken to ensure that + zero as a default value is not mixed up with either no modifier or the linear + modifier. Also note that in some APIs the invalid modifier value is specified + with an out-of-band flag, like in ``DRM_IOCTL_MODE_ADDFB2``. + +There are four cases where this token may be used: + - during enumeration, an interface may return ``DRM_FORMAT_MOD_INVALID``, either + as the sole member of a modifier list to declare that explicit modifiers are + not supported, or as part of a larger list to declare that implicit modifiers + may be used + - during allocation, a user may supply ``DRM_FORMAT_MOD_INVALID``, either as the + sole member of a modifier list (equivalent to not supplying a modifier list + at all) to declare that explicit modifiers are not supported and must not be + used, or as part of a larger list to declare that an allocation using implicit + modifiers is acceptable + - in a post-allocation query, an implementation may return + ``DRM_FORMAT_MOD_INVALID`` as the modifier of the allocated buffer to declare + that the underlying layout is implementation-defined and that an explicit + modifier description is not available; per the above rules, this may only be + returned when the user has included ``DRM_FORMAT_MOD_INVALID`` as part of the + list of acceptable modifiers, or not provided a list + - when importing a buffer, the user may supply ``DRM_FORMAT_MOD_INVALID`` as the + buffer modifier (or not supply a modifier) to indicate that the modifier is + unknown for whatever reason; this is only acceptable when the buffer has + not been allocated with an explicit modifier + +It follows from this that for any single buffer, the complete chain of operations +formed by the producer and all the consumers must be either fully implicit or fully +explicit. For example, if a user wishes to allocate a buffer for use between +GPU, display, and media, but the media API does not support modifiers, then the +user **must not** allocate the buffer with explicit modifiers and attempt to +import the buffer into the media API with no modifier, but either perform the +allocation using implicit modifiers, or allocate the buffer for media use +separately and copy between the two buffers. + +As one exception to the above, allocations may be 'upgraded' from implicit +to explicit modifiers. For example, if the buffer is allocated with +``gbm_bo_create`` (taking no modifiers), the user may then query the modifier with +``gbm_bo_get_modifier`` and then use this modifier as an explicit modifier token +if a valid modifier is returned. + +When allocating buffers for exchange between different users and modifiers are +not available, implementations are strongly encouraged to use +``DRM_FORMAT_MOD_LINEAR`` for their allocation, as this is the universal baseline +for exchange. However, it is not guaranteed that this will result in the correct +interpretation of buffer content, as implicit modifier operation may still be +subject to driver-specific heuristics. + +Any new users - userspace programs and protocols, kernel subsystems, etc - +wishing to exchange buffers must offer interoperability through dma-buf file +descriptors for memory planes, DRM format tokens to describe the format, DRM +format modifiers to describe the layout in memory, at least width and height for +dimensions, and at least offset and stride for each memory plane. + +.. _zwp_linux_dmabuf_v1: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/main/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml +.. _VK_EXT_image_drm_format_modifier: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_image_drm_format_modifier.html +.. _EGL_EXT_image_dma_buf_import_modifiers: https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import_modifiers.txt diff --git a/Documentation/userspace-api/index.rst b/Documentation/userspace-api/index.rst index 72a65db0c498..031df47a7c19 100644 --- a/Documentation/userspace-api/index.rst +++ b/Documentation/userspace-api/index.rst @@ -22,6 +22,7 @@ place where this information is gathered. unshare spec_ctrl accelerators/ocxl + dma-buf-alloc-exchange ebpf/index ELF ioctl/index diff --git a/MAINTAINERS b/MAINTAINERS index bf0f54c24f81..5ea898ffd8de 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1626,10 +1626,9 @@ F: drivers/gpu/drm/arm/display/include/ F: drivers/gpu/drm/arm/display/komeda/ ARM MALI PANFROST DRM DRIVER +M: Boris Brezillon M: Rob Herring -M: Tomeu Vizoso R: Steven Price -R: Alyssa Rosenzweig L: dri-devel@lists.freedesktop.org S: Supported T: git git://anongit.freedesktop.org/drm/drm-misc @@ -6132,6 +6131,7 @@ L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers) S: Maintained T: git git://anongit.freedesktop.org/drm/drm-misc F: Documentation/driver-api/dma-buf.rst +F: Documentation/userspace-api/dma-buf-alloc-exchange.rst F: drivers/dma-buf/ F: include/linux/*fence.h F: include/linux/dma-buf.h @@ -7138,6 +7138,7 @@ F: include/drm/gpu_scheduler.h DRM PANEL DRIVERS M: Neil Armstrong +R: Jessica Zhang R: Sam Ravnborg L: dri-devel@lists.freedesktop.org S: Maintained diff --git a/drivers/accel/drm_accel.c b/drivers/accel/drm_accel.c index 4a9baf02439e..94b4ac12cf24 100644 --- a/drivers/accel/drm_accel.c +++ b/drivers/accel/drm_accel.c @@ -79,29 +79,30 @@ static const struct drm_info_list accel_debugfs_list[] = { #define ACCEL_DEBUGFS_ENTRIES ARRAY_SIZE(accel_debugfs_list) /** - * accel_debugfs_init() - Initialize debugfs for accel minor - * @minor: Pointer to the drm_minor instance. - * @minor_id: The minor's id + * accel_debugfs_init() - Initialize debugfs for device + * @dev: Pointer to the device instance. * - * This function initializes the drm minor's debugfs members and creates - * a root directory for the minor in debugfs. It also creates common files - * for accelerators and calls the driver's debugfs init callback. + * This function creates a root directory for the device in debugfs. */ -void accel_debugfs_init(struct drm_minor *minor, int minor_id) +void accel_debugfs_init(struct drm_device *dev) { - struct drm_device *dev = minor->dev; - char name[64]; + drm_debugfs_dev_init(dev, accel_debugfs_root); +} - INIT_LIST_HEAD(&minor->debugfs_list); - mutex_init(&minor->debugfs_lock); - sprintf(name, "%d", minor_id); - minor->debugfs_root = debugfs_create_dir(name, accel_debugfs_root); +/** + * accel_debugfs_register() - Register debugfs for device + * @dev: Pointer to the device instance. + * + * Creates common files for accelerators. + */ +void accel_debugfs_register(struct drm_device *dev) +{ + struct drm_minor *minor = dev->accel; + + minor->debugfs_root = dev->debugfs_root; drm_debugfs_create_files(accel_debugfs_list, ACCEL_DEBUGFS_ENTRIES, - minor->debugfs_root, minor); - - if (dev->driver->debugfs_init) - dev->driver->debugfs_init(minor); + dev->debugfs_root, minor); } /** diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index ba79f397c9e8..fa0680ba9340 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -518,78 +518,52 @@ static int ivpu_dev_init(struct ivpu_device *vdev) lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key); ret = ivpu_pci_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize PCI device: %d\n", ret); + if (ret) goto err_xa_destroy; - } ret = ivpu_irq_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize IRQs: %d\n", ret); + if (ret) goto err_xa_destroy; - } /* Init basic HW info based on buttress registers which are accessible before power up */ ret = ivpu_hw_info_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize HW info: %d\n", ret); + if (ret) goto err_xa_destroy; - } /* Power up early so the rest of init code can access VPU registers */ ret = ivpu_hw_power_up(vdev); - if (ret) { - ivpu_err(vdev, "Failed to power up HW: %d\n", ret); + if (ret) goto err_xa_destroy; - } ret = ivpu_mmu_global_context_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize global MMU context: %d\n", ret); + if (ret) goto err_power_down; - } ret = ivpu_mmu_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize MMU device: %d\n", ret); + if (ret) + goto err_mmu_gctx_fini; + + ret = ivpu_mmu_reserved_context_init(vdev); + if (ret) goto err_mmu_gctx_fini; - } ret = ivpu_fw_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize firmware: %d\n", ret); - goto err_mmu_gctx_fini; - } + if (ret) + goto err_mmu_rctx_fini; ret = ivpu_ipc_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize IPC: %d\n", ret); + if (ret) goto err_fw_fini; - } - ret = ivpu_pm_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize PM: %d\n", ret); - goto err_ipc_fini; - } + ivpu_pm_init(vdev); ret = ivpu_job_done_thread_init(vdev); - if (ret) { - ivpu_err(vdev, "Failed to initialize job done thread: %d\n", ret); + if (ret) goto err_ipc_fini; - } - - ret = ivpu_fw_load(vdev); - if (ret) { - ivpu_err(vdev, "Failed to load firmware: %d\n", ret); - goto err_job_done_thread_fini; - } ret = ivpu_boot(vdev); - if (ret) { - ivpu_err(vdev, "Failed to boot: %d\n", ret); + if (ret) goto err_job_done_thread_fini; - } ivpu_pm_enable(vdev); @@ -601,6 +575,8 @@ err_ipc_fini: ivpu_ipc_fini(vdev); err_fw_fini: ivpu_fw_fini(vdev); +err_mmu_rctx_fini: + ivpu_mmu_reserved_context_fini(vdev); err_mmu_gctx_fini: ivpu_mmu_global_context_fini(vdev); err_power_down: @@ -624,6 +600,7 @@ static void ivpu_dev_fini(struct ivpu_device *vdev) ivpu_ipc_fini(vdev); ivpu_fw_fini(vdev); + ivpu_mmu_reserved_context_fini(vdev); ivpu_mmu_global_context_fini(vdev); drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa)); @@ -651,10 +628,8 @@ static int ivpu_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, vdev); ret = ivpu_dev_init(vdev); - if (ret) { - dev_err(&pdev->dev, "Failed to initialize VPU device: %d\n", ret); + if (ret) return ret; - } ret = drm_dev_register(&vdev->drm, 0); if (ret) { diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 9e8c075fe9ef..12a63f8a73e8 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -28,12 +28,13 @@ #define IVPU_HW_37XX 37 #define IVPU_HW_40XX 40 -#define IVPU_GLOBAL_CONTEXT_MMU_SSID 0 -/* SSID 1 is used by the VPU to represent invalid context */ -#define IVPU_USER_CONTEXT_MIN_SSID 2 -#define IVPU_USER_CONTEXT_MAX_SSID (IVPU_USER_CONTEXT_MIN_SSID + 63) +#define IVPU_GLOBAL_CONTEXT_MMU_SSID 0 +/* SSID 1 is used by the VPU to represent reserved context */ +#define IVPU_RESERVED_CONTEXT_MMU_SSID 1 +#define IVPU_USER_CONTEXT_MIN_SSID 2 +#define IVPU_USER_CONTEXT_MAX_SSID (IVPU_USER_CONTEXT_MIN_SSID + 63) -#define IVPU_NUM_ENGINES 2 +#define IVPU_NUM_ENGINES 2 #define IVPU_PLATFORM_SILICON 0 #define IVPU_PLATFORM_SIMICS 2 @@ -75,6 +76,11 @@ #define IVPU_WA(wa_name) (vdev->wa.wa_name) +#define IVPU_PRINT_WA(wa_name) do { \ + if (IVPU_WA(wa_name)) \ + ivpu_dbg(vdev, MISC, "Using WA: " #wa_name "\n"); \ +} while (0) + struct ivpu_wa_table { bool punit_disabled; bool clear_runtime_mem; @@ -104,6 +110,7 @@ struct ivpu_device { struct ivpu_pm_info *pm; struct ivpu_mmu_context gctx; + struct ivpu_mmu_context rctx; struct xarray context_xa; struct xa_limit context_xa_limit; @@ -117,6 +124,7 @@ struct ivpu_device { int jsm; int tdr; int reschedule_suspend; + int autosuspend; } timeout; }; diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c index 9827ea4d7b83..d57e103aae1c 100644 --- a/drivers/accel/ivpu/ivpu_fw.c +++ b/drivers/accel/ivpu/ivpu_fw.c @@ -301,6 +301,8 @@ int ivpu_fw_init(struct ivpu_device *vdev) if (ret) goto err_fw_release; + ivpu_fw_load(vdev); + return 0; err_fw_release: @@ -314,7 +316,7 @@ void ivpu_fw_fini(struct ivpu_device *vdev) ivpu_fw_release(vdev); } -int ivpu_fw_load(struct ivpu_device *vdev) +void ivpu_fw_load(struct ivpu_device *vdev) { struct ivpu_fw_info *fw = vdev->fw; u64 image_end_offset = fw->image_load_offset + fw->image_size; @@ -331,8 +333,6 @@ int ivpu_fw_load(struct ivpu_device *vdev) } wmb(); /* Flush WC buffers after writing fw->mem */ - - return 0; } static void ivpu_fw_boot_params_print(struct ivpu_device *vdev, struct vpu_boot_params *boot_params) diff --git a/drivers/accel/ivpu/ivpu_fw.h b/drivers/accel/ivpu/ivpu_fw.h index 8567fdf925fe..10ae2847f0ef 100644 --- a/drivers/accel/ivpu/ivpu_fw.h +++ b/drivers/accel/ivpu/ivpu_fw.h @@ -31,7 +31,7 @@ struct ivpu_fw_info { int ivpu_fw_init(struct ivpu_device *vdev); void ivpu_fw_fini(struct ivpu_device *vdev); -int ivpu_fw_load(struct ivpu_device *vdev); +void ivpu_fw_load(struct ivpu_device *vdev); void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params *bp); static inline bool ivpu_fw_is_cold_boot(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c index 9eae1c241bc0..edd4d860f135 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c @@ -104,6 +104,11 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) if (ivpu_device_id(vdev) == PCI_DEVICE_ID_MTL && ivpu_revision(vdev) < 4) vdev->wa.interrupt_clear_with_0 = true; + + IVPU_PRINT_WA(punit_disabled); + IVPU_PRINT_WA(clear_runtime_mem); + IVPU_PRINT_WA(d3hot_after_power_off); + IVPU_PRINT_WA(interrupt_clear_with_0); } static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) @@ -113,11 +118,13 @@ static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) vdev->timeout.jsm = 50000; vdev->timeout.tdr = 2000000; vdev->timeout.reschedule_suspend = 1000; + vdev->timeout.autosuspend = -1; } else { vdev->timeout.boot = 1000; vdev->timeout.jsm = 500; vdev->timeout.tdr = 2000; vdev->timeout.reschedule_suspend = 10; + vdev->timeout.autosuspend = 10; } } @@ -345,10 +352,10 @@ static int ivpu_boot_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val) { - u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN); + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN); - if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) + if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, exp_val, val)) return -EIO; return 0; @@ -356,10 +363,10 @@ static int ivpu_boot_top_noc_qrenqn_check(struct ivpu_device *vdev, u32 exp_val) static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_val) { - u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QACCEPTN); + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QACCEPTN); - if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) + if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QACCEPTN, HOSTIF_L2CACHE, exp_val, val)) return -EIO; return 0; @@ -367,10 +374,10 @@ static int ivpu_boot_top_noc_qacceptn_check(struct ivpu_device *vdev, u32 exp_va static int ivpu_boot_top_noc_qdeny_check(struct ivpu_device *vdev, u32 exp_val) { - u32 val = REGV_RD32(MTL_VPU_TOP_NOC_QDENY); + u32 val = REGV_RD32(VPU_37XX_TOP_NOC_QDENY); - if (!REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || - !REG_TEST_FLD_NUM(MTL_VPU_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) + if (!REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, CPU_CTRL, exp_val, val) || + !REG_TEST_FLD_NUM(VPU_37XX_TOP_NOC_QDENY, HOSTIF_L2CACHE, exp_val, val)) return -EIO; return 0; @@ -423,15 +430,15 @@ static int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable int ret; u32 val; - val = REGV_RD32(MTL_VPU_TOP_NOC_QREQN); + val = REGV_RD32(VPU_37XX_TOP_NOC_QREQN); if (enable) { - val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val); - val = REG_SET_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); + val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val); + val = REG_SET_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); } else { - val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, CPU_CTRL, val); - val = REG_CLR_FLD(MTL_VPU_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); + val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, CPU_CTRL, val); + val = REG_CLR_FLD(VPU_37XX_TOP_NOC_QREQN, HOSTIF_L2CACHE, val); } - REGV_WR32(MTL_VPU_TOP_NOC_QREQN, val); + REGV_WR32(VPU_37XX_TOP_NOC_QREQN, val); ret = ivpu_boot_top_noc_qacceptn_check(vdev, enable ? 0x1 : 0x0); if (ret) { @@ -563,17 +570,17 @@ static void ivpu_boot_soc_cpu_boot(struct ivpu_device *vdev) { u32 val; - val = REGV_RD32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC); - val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val); + val = REGV_RD32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC); + val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTRUN0, val); - val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val); - REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); + val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RSTVEC, val); + REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); - val = REG_SET_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); - REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); + val = REG_SET_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); + REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); - val = REG_CLR_FLD(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); - REGV_WR32(MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); + val = REG_CLR_FLD(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, IRQI_RESUME0, val); + REGV_WR32(VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC, val); val = vdev->fw->entry_point >> 9; REGV_WR32(VPU_37XX_HOST_SS_LOADING_ADDRESS_LO, val); @@ -777,17 +784,17 @@ static void ivpu_hw_37xx_wdt_disable(struct ivpu_device *vdev) u32 val; /* Enable writing and set non-zero WDT value */ - REGV_WR32(MTL_VPU_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); - REGV_WR32(MTL_VPU_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE); + REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); + REGV_WR32(VPU_37XX_CPU_SS_TIM_WATCHDOG, TIM_WATCHDOG_RESET_VALUE); /* Enable writing and disable watchdog timer */ - REGV_WR32(MTL_VPU_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); - REGV_WR32(MTL_VPU_CPU_SS_TIM_WDOG_EN, 0); + REGV_WR32(VPU_37XX_CPU_SS_TIM_SAFE, TIM_SAFE_ENABLE); + REGV_WR32(VPU_37XX_CPU_SS_TIM_WDOG_EN, 0); /* Now clear the timeout interrupt */ - val = REGV_RD32(MTL_VPU_CPU_SS_TIM_GEN_CONFIG); - val = REG_CLR_FLD(MTL_VPU_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val); - REGV_WR32(MTL_VPU_CPU_SS_TIM_GEN_CONFIG, val); + val = REGV_RD32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG); + val = REG_CLR_FLD(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, WDOG_TO_INT_CLR, val); + REGV_WR32(VPU_37XX_CPU_SS_TIM_GEN_CONFIG, val); } static u32 ivpu_hw_37xx_pll_to_freq(u32 ratio, u32 config) @@ -834,10 +841,10 @@ static u32 ivpu_hw_37xx_reg_telemetry_enable_get(struct ivpu_device *vdev) static void ivpu_hw_37xx_reg_db_set(struct ivpu_device *vdev, u32 db_id) { - u32 reg_stride = MTL_VPU_CPU_SS_DOORBELL_1 - MTL_VPU_CPU_SS_DOORBELL_0; - u32 val = REG_FLD(MTL_VPU_CPU_SS_DOORBELL_0, SET); + u32 reg_stride = VPU_37XX_CPU_SS_DOORBELL_1 - VPU_37XX_CPU_SS_DOORBELL_0; + u32 val = REG_FLD(VPU_37XX_CPU_SS_DOORBELL_0, SET); - REGV_WR32I(MTL_VPU_CPU_SS_DOORBELL_0, reg_stride, db_id, val); + REGV_WR32I(VPU_37XX_CPU_SS_DOORBELL_0, reg_stride, db_id, val); } static u32 ivpu_hw_37xx_reg_ipc_rx_addr_get(struct ivpu_device *vdev) @@ -854,7 +861,7 @@ static u32 ivpu_hw_37xx_reg_ipc_rx_count_get(struct ivpu_device *vdev) static void ivpu_hw_37xx_reg_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr) { - REGV_WR32(MTL_VPU_CPU_SS_TIM_IPC_FIFO, vpu_addr); + REGV_WR32(VPU_37XX_CPU_SS_TIM_IPC_FIFO, vpu_addr); } static void ivpu_hw_37xx_irq_clear(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h index 6e4e915948f9..4083beb5e9db 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx_reg.h +++ b/drivers/accel/ivpu/ivpu_hw_37xx_reg.h @@ -3,70 +3,70 @@ * Copyright (C) 2020-2023 Intel Corporation */ -#ifndef __IVPU_HW_MTL_REG_H__ -#define __IVPU_HW_MTL_REG_H__ +#ifndef __IVPU_HW_37XX_REG_H__ +#define __IVPU_HW_37XX_REG_H__ #include -#define VPU_37XX_BUTTRESS_INTERRUPT_TYPE 0x00000000u +#define VPU_37XX_BUTTRESS_INTERRUPT_TYPE 0x00000000u -#define VPU_37XX_BUTTRESS_INTERRUPT_STAT 0x00000004u -#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0) +#define VPU_37XX_BUTTRESS_INTERRUPT_STAT 0x00000004u +#define VPU_37XX_BUTTRESS_INTERRUPT_STAT_FREQ_CHANGE_MASK BIT_MASK(0) #define VPU_37XX_BUTTRESS_INTERRUPT_STAT_ATS_ERR_MASK BIT_MASK(1) #define VPU_37XX_BUTTRESS_INTERRUPT_STAT_UFI_ERR_MASK BIT_MASK(2) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0 0x00000008u -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16) +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0 0x00000008u +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MIN_RATIO_MASK GENMASK(15, 0) +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD0_MAX_RATIO_MASK GENMASK(31, 16) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1 0x0000000cu -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16) +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1 0x0000000cu +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_TARGET_RATIO_MASK GENMASK(15, 0) +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD1_EPP_MASK GENMASK(31, 16) -#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2 0x00000010u +#define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2 0x00000010u #define VPU_37XX_BUTTRESS_WP_REQ_PAYLOAD2_CONFIG_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_WP_REQ_CMD 0x00000014u +#define VPU_37XX_BUTTRESS_WP_REQ_CMD 0x00000014u #define VPU_37XX_BUTTRESS_WP_REQ_CMD_SEND_MASK BIT_MASK(0) #define VPU_37XX_BUTTRESS_WP_DOWNLOAD 0x00000018u #define VPU_37XX_BUTTRESS_WP_DOWNLOAD_TARGET_RATIO_MASK GENMASK(15, 0) #define VPU_37XX_BUTTRESS_CURRENT_PLL 0x0000001cu -#define VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK GENMASK(15, 0) +#define VPU_37XX_BUTTRESS_CURRENT_PLL_RATIO_MASK GENMASK(15, 0) -#define VPU_37XX_BUTTRESS_PLL_ENABLE 0x00000020u +#define VPU_37XX_BUTTRESS_PLL_ENABLE 0x00000020u -#define VPU_37XX_BUTTRESS_FMIN_FUSE 0x00000024u -#define VPU_37XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0) -#define VPU_37XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8) +#define VPU_37XX_BUTTRESS_FMIN_FUSE 0x00000024u +#define VPU_37XX_BUTTRESS_FMIN_FUSE_MIN_RATIO_MASK GENMASK(7, 0) +#define VPU_37XX_BUTTRESS_FMIN_FUSE_PN_RATIO_MASK GENMASK(15, 8) -#define VPU_37XX_BUTTRESS_FMAX_FUSE 0x00000028u -#define VPU_37XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0) +#define VPU_37XX_BUTTRESS_FMAX_FUSE 0x00000028u +#define VPU_37XX_BUTTRESS_FMAX_FUSE_MAX_RATIO_MASK GENMASK(7, 0) -#define VPU_37XX_BUTTRESS_TILE_FUSE 0x0000002cu +#define VPU_37XX_BUTTRESS_TILE_FUSE 0x0000002cu #define VPU_37XX_BUTTRESS_TILE_FUSE_VALID_MASK BIT_MASK(0) -#define VPU_37XX_BUTTRESS_TILE_FUSE_SKU_MASK GENMASK(3, 2) +#define VPU_37XX_BUTTRESS_TILE_FUSE_SKU_MASK GENMASK(3, 2) -#define VPU_37XX_BUTTRESS_LOCAL_INT_MASK 0x00000030u -#define VPU_37XX_BUTTRESS_GLOBAL_INT_MASK 0x00000034u +#define VPU_37XX_BUTTRESS_LOCAL_INT_MASK 0x00000030u +#define VPU_37XX_BUTTRESS_GLOBAL_INT_MASK 0x00000034u -#define VPU_37XX_BUTTRESS_PLL_STATUS 0x00000040u +#define VPU_37XX_BUTTRESS_PLL_STATUS 0x00000040u #define VPU_37XX_BUTTRESS_PLL_STATUS_LOCK_MASK BIT_MASK(1) -#define VPU_37XX_BUTTRESS_VPU_STATUS 0x00000044u +#define VPU_37XX_BUTTRESS_VPU_STATUS 0x00000044u #define VPU_37XX_BUTTRESS_VPU_STATUS_READY_MASK BIT_MASK(0) #define VPU_37XX_BUTTRESS_VPU_STATUS_IDLE_MASK BIT_MASK(1) -#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL 0x00000060u -#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0) -#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_I3_MASK BIT_MASK(2) +#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL 0x00000060u +#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_INPROGRESS_MASK BIT_MASK(0) +#define VPU_37XX_BUTTRESS_VPU_D0I3_CONTROL_I3_MASK BIT_MASK(2) #define VPU_37XX_BUTTRESS_VPU_IP_RESET 0x00000050u -#define VPU_37XX_BUTTRESS_VPU_IP_RESET_TRIGGER_MASK BIT_MASK(0) +#define VPU_37XX_BUTTRESS_VPU_IP_RESET_TRIGGER_MASK BIT_MASK(0) #define VPU_37XX_BUTTRESS_VPU_TELEMETRY_OFFSET 0x00000080u -#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_SIZE 0x00000084u +#define VPU_37XX_BUTTRESS_VPU_TELEMETRY_SIZE 0x00000084u #define VPU_37XX_BUTTRESS_VPU_TELEMETRY_ENABLE 0x00000088u #define VPU_37XX_BUTTRESS_ATS_ERR_LOG_0 0x000000a0u @@ -74,9 +74,9 @@ #define VPU_37XX_BUTTRESS_ATS_ERR_CLEAR 0x000000a8u #define VPU_37XX_BUTTRESS_UFI_ERR_LOG 0x000000b0u -#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_CQ_ID_MASK GENMASK(11, 0) -#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_AXI_ID_MASK GENMASK(19, 12) -#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_OPCODE_MASK GENMASK(24, 20) +#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_CQ_ID_MASK GENMASK(11, 0) +#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_AXI_ID_MASK GENMASK(19, 12) +#define VPU_37XX_BUTTRESS_UFI_ERR_LOG_OPCODE_MASK GENMASK(24, 20) #define VPU_37XX_BUTTRESS_UFI_ERR_CLEAR 0x000000b4u @@ -113,17 +113,17 @@ #define VPU_37XX_HOST_SS_NOC_QDENY 0x0000015cu #define VPU_37XX_HOST_SS_NOC_QDENY_TOP_SOCMMIO_MASK BIT_MASK(0) -#define MTL_VPU_TOP_NOC_QREQN 0x00000160u -#define MTL_VPU_TOP_NOC_QREQN_CPU_CTRL_MASK BIT_MASK(0) -#define MTL_VPU_TOP_NOC_QREQN_HOSTIF_L2CACHE_MASK BIT_MASK(1) +#define VPU_37XX_TOP_NOC_QREQN 0x00000160u +#define VPU_37XX_TOP_NOC_QREQN_CPU_CTRL_MASK BIT_MASK(0) +#define VPU_37XX_TOP_NOC_QREQN_HOSTIF_L2CACHE_MASK BIT_MASK(1) -#define MTL_VPU_TOP_NOC_QACCEPTN 0x00000164u -#define MTL_VPU_TOP_NOC_QACCEPTN_CPU_CTRL_MASK BIT_MASK(0) -#define MTL_VPU_TOP_NOC_QACCEPTN_HOSTIF_L2CACHE_MASK BIT_MASK(1) +#define VPU_37XX_TOP_NOC_QACCEPTN 0x00000164u +#define VPU_37XX_TOP_NOC_QACCEPTN_CPU_CTRL_MASK BIT_MASK(0) +#define VPU_37XX_TOP_NOC_QACCEPTN_HOSTIF_L2CACHE_MASK BIT_MASK(1) -#define MTL_VPU_TOP_NOC_QDENY 0x00000168u -#define MTL_VPU_TOP_NOC_QDENY_CPU_CTRL_MASK BIT_MASK(0) -#define MTL_VPU_TOP_NOC_QDENY_HOSTIF_L2CACHE_MASK BIT_MASK(1) +#define VPU_37XX_TOP_NOC_QDENY 0x00000168u +#define VPU_37XX_TOP_NOC_QDENY_CPU_CTRL_MASK BIT_MASK(0) +#define VPU_37XX_TOP_NOC_QDENY_HOSTIF_L2CACHE_MASK BIT_MASK(1) #define VPU_37XX_HOST_SS_FW_SOC_IRQ_EN 0x00000170u #define VPU_37XX_HOST_SS_FW_SOC_IRQ_EN_CSS_ROM_CMX_MASK BIT_MASK(0) @@ -140,9 +140,9 @@ #define VPU_37XX_HOST_SS_ICB_STATUS_0_TIMER_2_INT_MASK BIT_MASK(2) #define VPU_37XX_HOST_SS_ICB_STATUS_0_TIMER_3_INT_MASK BIT_MASK(3) #define VPU_37XX_HOST_SS_ICB_STATUS_0_HOST_IPC_FIFO_INT_MASK BIT_MASK(4) -#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_0_INT_MASK BIT_MASK(5) -#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_1_INT_MASK BIT_MASK(6) -#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_2_INT_MASK BIT_MASK(7) +#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_0_INT_MASK BIT_MASK(5) +#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_1_INT_MASK BIT_MASK(6) +#define VPU_37XX_HOST_SS_ICB_STATUS_0_MMU_IRQ_2_INT_MASK BIT_MASK(7) #define VPU_37XX_HOST_SS_ICB_STATUS_0_NOC_FIREWALL_INT_MASK BIT_MASK(8) #define VPU_37XX_HOST_SS_ICB_STATUS_0_CPU_INT_REDIRECT_0_INT_MASK BIT_MASK(30) #define VPU_37XX_HOST_SS_ICB_STATUS_0_CPU_INT_REDIRECT_1_INT_MASK BIT_MASK(31) @@ -164,14 +164,14 @@ #define VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT_FILL_LEVEL_MASK GENMASK(23, 16) #define VPU_37XX_HOST_SS_TIM_IPC_FIFO_STAT_RSVD0_MASK GENMASK(31, 24) -#define VPU_37XX_HOST_SS_AON_PWR_ISO_EN0 0x00030020u +#define VPU_37XX_HOST_SS_AON_PWR_ISO_EN0 0x00030020u #define VPU_37XX_HOST_SS_AON_PWR_ISO_EN0_MSS_CPU_MASK BIT_MASK(3) #define VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0 0x00030024u -#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0_MSS_CPU_MASK BIT_MASK(3) +#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_EN0_MSS_CPU_MASK BIT_MASK(3) #define VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0 0x00030028u -#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0_MSS_CPU_MASK BIT_MASK(3) +#define VPU_37XX_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0_MSS_CPU_MASK BIT_MASK(3) #define VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0 0x0003002cu #define VPU_37XX_HOST_SS_AON_PWR_ISLAND_STATUS0_MSS_CPU_MASK BIT_MASK(3) @@ -187,47 +187,14 @@ #define VPU_37XX_HOST_SS_LOADING_ADDRESS_LO_IOSF_RS_ID_MASK GENMASK(2, 1) #define VPU_37XX_HOST_SS_LOADING_ADDRESS_LO_IMAGE_LOCATION_MASK GENMASK(31, 3) -#define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR 0x00082020u +#define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR 0x00082020u #define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR_FINAL_PLL_FREQ_MASK GENMASK(15, 0) #define VPU_37XX_HOST_SS_WORKPOINT_CONFIG_MIRROR_CONFIG_ID_MASK GENMASK(31, 16) -#define VPU_37XX_HOST_MMU_IDR0 0x00200000u -#define VPU_37XX_HOST_MMU_IDR1 0x00200004u -#define VPU_37XX_HOST_MMU_IDR3 0x0020000cu -#define VPU_37XX_HOST_MMU_IDR5 0x00200014u -#define VPU_37XX_HOST_MMU_CR0 0x00200020u -#define VPU_37XX_HOST_MMU_CR0ACK 0x00200024u -#define VPU_37XX_HOST_MMU_CR1 0x00200028u -#define VPU_37XX_HOST_MMU_CR2 0x0020002cu -#define VPU_37XX_HOST_MMU_IRQ_CTRL 0x00200050u -#define VPU_37XX_HOST_MMU_IRQ_CTRLACK 0x00200054u - -#define VPU_37XX_HOST_MMU_GERROR 0x00200060u -#define VPU_37XX_HOST_MMU_GERROR_CMDQ_MASK BIT_MASK(0) -#define VPU_37XX_HOST_MMU_GERROR_EVTQ_ABT_MASK BIT_MASK(2) -#define VPU_37XX_HOST_MMU_GERROR_PRIQ_ABT_MASK BIT_MASK(3) -#define VPU_37XX_HOST_MMU_GERROR_MSI_CMDQ_ABT_MASK BIT_MASK(4) -#define VPU_37XX_HOST_MMU_GERROR_MSI_EVTQ_ABT_MASK BIT_MASK(5) -#define VPU_37XX_HOST_MMU_GERROR_MSI_PRIQ_ABT_MASK BIT_MASK(6) -#define VPU_37XX_HOST_MMU_GERROR_MSI_ABT_MASK BIT_MASK(7) - -#define VPU_37XX_HOST_MMU_GERRORN 0x00200064u - -#define VPU_37XX_HOST_MMU_STRTAB_BASE 0x00200080u -#define VPU_37XX_HOST_MMU_STRTAB_BASE_CFG 0x00200088u -#define VPU_37XX_HOST_MMU_CMDQ_BASE 0x00200090u -#define VPU_37XX_HOST_MMU_CMDQ_PROD 0x00200098u -#define VPU_37XX_HOST_MMU_CMDQ_CONS 0x0020009cu -#define VPU_37XX_HOST_MMU_EVTQ_BASE 0x002000a0u -#define VPU_37XX_HOST_MMU_EVTQ_PROD 0x002000a8u -#define VPU_37XX_HOST_MMU_EVTQ_CONS 0x002000acu -#define VPU_37XX_HOST_MMU_EVTQ_PROD_SEC (0x002000a8u + SZ_64K) -#define VPU_37XX_HOST_MMU_EVTQ_CONS_SEC (0x002000acu + SZ_64K) - #define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES 0x00360000u #define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_CACHE_OVERRIDE_EN_MASK BIT_MASK(0) -#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_AWCACHE_OVERRIDE_MASK BIT_MASK(1) -#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_ARCACHE_OVERRIDE_MASK BIT_MASK(2) +#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_AWCACHE_OVERRIDE_MASK BIT_MASK(1) +#define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_ARCACHE_OVERRIDE_MASK BIT_MASK(2) #define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_NOSNOOP_OVERRIDE_EN_MASK BIT_MASK(3) #define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_AW_NOSNOOP_OVERRIDE_MASK BIT_MASK(4) #define VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES_AR_NOSNOOP_OVERRIDE_MASK BIT_MASK(5) @@ -246,36 +213,36 @@ #define VPU_37XX_HOST_IF_TBU_MMUSSIDV_TBU4_AWMMUSSIDV_MASK BIT_MASK(8) #define VPU_37XX_HOST_IF_TBU_MMUSSIDV_TBU4_ARMMUSSIDV_MASK BIT_MASK(9) -#define MTL_VPU_CPU_SS_DSU_LEON_RT_BASE 0x04000000u -#define MTL_VPU_CPU_SS_DSU_LEON_RT_DSU_CTRL 0x04000000u -#define MTL_VPU_CPU_SS_DSU_LEON_RT_PC_REG 0x04400010u -#define MTL_VPU_CPU_SS_DSU_LEON_RT_NPC_REG 0x04400014u -#define MTL_VPU_CPU_SS_DSU_LEON_RT_DSU_TRAP_REG 0x04400020u +#define VPU_37XX_CPU_SS_DSU_LEON_RT_BASE 0x04000000u +#define VPU_37XX_CPU_SS_DSU_LEON_RT_DSU_CTRL 0x04000000u +#define VPU_37XX_CPU_SS_DSU_LEON_RT_PC_REG 0x04400010u +#define VPU_37XX_CPU_SS_DSU_LEON_RT_NPC_REG 0x04400014u +#define VPU_37XX_CPU_SS_DSU_LEON_RT_DSU_TRAP_REG 0x04400020u -#define MTL_VPU_CPU_SS_MSSCPU_CPR_CLK_SET 0x06010004u -#define MTL_VPU_CPU_SS_MSSCPU_CPR_CLK_SET_CPU_DSU_MASK BIT_MASK(1) +#define VPU_37XX_CPU_SS_MSSCPU_CPR_CLK_SET 0x06010004u +#define VPU_37XX_CPU_SS_MSSCPU_CPR_CLK_SET_CPU_DSU_MASK BIT_MASK(1) -#define MTL_VPU_CPU_SS_MSSCPU_CPR_RST_CLR 0x06010018u -#define MTL_VPU_CPU_SS_MSSCPU_CPR_RST_CLR_CPU_DSU_MASK BIT_MASK(1) +#define VPU_37XX_CPU_SS_MSSCPU_CPR_RST_CLR 0x06010018u +#define VPU_37XX_CPU_SS_MSSCPU_CPR_RST_CLR_CPU_DSU_MASK BIT_MASK(1) -#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC 0x06010040u -#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN0_MASK BIT_MASK(0) -#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME0_MASK BIT_MASK(1) -#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN1_MASK BIT_MASK(2) -#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME1_MASK BIT_MASK(3) -#define MTL_VPU_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTVEC_MASK GENMASK(31, 4) +#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC 0x06010040u +#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN0_MASK BIT_MASK(0) +#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME0_MASK BIT_MASK(1) +#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTRUN1_MASK BIT_MASK(2) +#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RESUME1_MASK BIT_MASK(3) +#define VPU_37XX_CPU_SS_MSSCPU_CPR_LEON_RT_VEC_IRQI_RSTVEC_MASK GENMASK(31, 4) -#define MTL_VPU_CPU_SS_TIM_WATCHDOG 0x0602009cu -#define MTL_VPU_CPU_SS_TIM_WDOG_EN 0x060200a4u -#define MTL_VPU_CPU_SS_TIM_SAFE 0x060200a8u -#define MTL_VPU_CPU_SS_TIM_IPC_FIFO 0x060200f0u +#define VPU_37XX_CPU_SS_TIM_WATCHDOG 0x0602009cu +#define VPU_37XX_CPU_SS_TIM_WDOG_EN 0x060200a4u +#define VPU_37XX_CPU_SS_TIM_SAFE 0x060200a8u +#define VPU_37XX_CPU_SS_TIM_IPC_FIFO 0x060200f0u -#define MTL_VPU_CPU_SS_TIM_GEN_CONFIG 0x06021008u -#define MTL_VPU_CPU_SS_TIM_GEN_CONFIG_WDOG_TO_INT_CLR_MASK BIT_MASK(9) +#define VPU_37XX_CPU_SS_TIM_GEN_CONFIG 0x06021008u +#define VPU_37XX_CPU_SS_TIM_GEN_CONFIG_WDOG_TO_INT_CLR_MASK BIT_MASK(9) -#define MTL_VPU_CPU_SS_DOORBELL_0 0x06300000u -#define MTL_VPU_CPU_SS_DOORBELL_0_SET_MASK BIT_MASK(0) +#define VPU_37XX_CPU_SS_DOORBELL_0 0x06300000u +#define VPU_37XX_CPU_SS_DOORBELL_0_SET_MASK BIT_MASK(0) -#define MTL_VPU_CPU_SS_DOORBELL_1 0x06301000u +#define VPU_37XX_CPU_SS_DOORBELL_1 0x06301000u -#endif /* __IVPU_HW_MTL_REG_H__ */ +#endif /* __IVPU_HW_37XX_REG_H__ */ diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c index 34626d66fa10..1c2528549635 100644 --- a/drivers/accel/ivpu/ivpu_hw_40xx.c +++ b/drivers/accel/ivpu/ivpu_hw_40xx.c @@ -126,6 +126,10 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) if (ivpu_hw_gen(vdev) == IVPU_HW_40XX) vdev->wa.disable_clock_relinquish = true; + + IVPU_PRINT_WA(punit_disabled); + IVPU_PRINT_WA(clear_runtime_mem); + IVPU_PRINT_WA(disable_clock_relinquish); } static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) @@ -135,16 +139,19 @@ static void ivpu_hw_timeouts_init(struct ivpu_device *vdev) vdev->timeout.jsm = 50000; vdev->timeout.tdr = 2000000; vdev->timeout.reschedule_suspend = 1000; + vdev->timeout.autosuspend = -1; } else if (ivpu_is_simics(vdev)) { vdev->timeout.boot = 50; vdev->timeout.jsm = 500; vdev->timeout.tdr = 10000; vdev->timeout.reschedule_suspend = 10; + vdev->timeout.autosuspend = -1; } else { vdev->timeout.boot = 1000; vdev->timeout.jsm = 500; vdev->timeout.tdr = 2000; vdev->timeout.reschedule_suspend = 10; + vdev->timeout.autosuspend = 10; } } diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c index fa0af59e39ab..6b2e9dbb284a 100644 --- a/drivers/accel/ivpu/ivpu_ipc.c +++ b/drivers/accel/ivpu/ivpu_ipc.c @@ -426,15 +426,20 @@ int ivpu_ipc_irq_handler(struct ivpu_device *vdev) int ivpu_ipc_init(struct ivpu_device *vdev) { struct ivpu_ipc_info *ipc = vdev->ipc; - int ret = -ENOMEM; + int ret; ipc->mem_tx = ivpu_bo_alloc_internal(vdev, 0, SZ_16K, DRM_IVPU_BO_WC); - if (!ipc->mem_tx) - return ret; + if (!ipc->mem_tx) { + ivpu_err(vdev, "Failed to allocate mem_tx\n"); + return -ENOMEM; + } ipc->mem_rx = ivpu_bo_alloc_internal(vdev, 0, SZ_16K, DRM_IVPU_BO_WC); - if (!ipc->mem_rx) + if (!ipc->mem_rx) { + ivpu_err(vdev, "Failed to allocate mem_rx\n"); + ret = -ENOMEM; goto err_free_tx; + } ipc->mm_tx = devm_gen_pool_create(vdev->drm.dev, __ffs(IVPU_IPC_ALIGNMENT), -1, "TX_IPC_JSM"); diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index baefaf7bb3cb..473e1fc686a7 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -7,12 +7,45 @@ #include #include "ivpu_drv.h" -#include "ivpu_hw_37xx_reg.h" #include "ivpu_hw_reg_io.h" #include "ivpu_mmu.h" #include "ivpu_mmu_context.h" #include "ivpu_pm.h" +#define IVPU_MMU_REG_IDR0 0x00200000u +#define IVPU_MMU_REG_IDR1 0x00200004u +#define IVPU_MMU_REG_IDR3 0x0020000cu +#define IVPU_MMU_REG_IDR5 0x00200014u +#define IVPU_MMU_REG_CR0 0x00200020u +#define IVPU_MMU_REG_CR0ACK 0x00200024u +#define IVPU_MMU_REG_CR1 0x00200028u +#define IVPU_MMU_REG_CR2 0x0020002cu +#define IVPU_MMU_REG_IRQ_CTRL 0x00200050u +#define IVPU_MMU_REG_IRQ_CTRLACK 0x00200054u + +#define IVPU_MMU_REG_GERROR 0x00200060u +#define IVPU_MMU_REG_GERROR_CMDQ_MASK BIT_MASK(0) +#define IVPU_MMU_REG_GERROR_EVTQ_ABT_MASK BIT_MASK(2) +#define IVPU_MMU_REG_GERROR_PRIQ_ABT_MASK BIT_MASK(3) +#define IVPU_MMU_REG_GERROR_MSI_CMDQ_ABT_MASK BIT_MASK(4) +#define IVPU_MMU_REG_GERROR_MSI_EVTQ_ABT_MASK BIT_MASK(5) +#define IVPU_MMU_REG_GERROR_MSI_PRIQ_ABT_MASK BIT_MASK(6) +#define IVPU_MMU_REG_GERROR_MSI_ABT_MASK BIT_MASK(7) + +#define IVPU_MMU_REG_GERRORN 0x00200064u + +#define IVPU_MMU_REG_STRTAB_BASE 0x00200080u +#define IVPU_MMU_REG_STRTAB_BASE_CFG 0x00200088u +#define IVPU_MMU_REG_CMDQ_BASE 0x00200090u +#define IVPU_MMU_REG_CMDQ_PROD 0x00200098u +#define IVPU_MMU_REG_CMDQ_CONS 0x0020009cu +#define IVPU_MMU_REG_EVTQ_BASE 0x002000a0u +#define IVPU_MMU_REG_EVTQ_PROD 0x002000a8u +#define IVPU_MMU_REG_EVTQ_CONS 0x002000acu +#define IVPU_MMU_REG_EVTQ_PROD_SEC (0x002000a8u + SZ_64K) +#define IVPU_MMU_REG_EVTQ_CONS_SEC (0x002000acu + SZ_64K) +#define IVPU_MMU_REG_CMDQ_CONS_ERR_MASK GENMASK(30, 24) + #define IVPU_MMU_IDR0_REF 0x080f3e0f #define IVPU_MMU_IDR0_REF_SIMICS 0x080f3e1f #define IVPU_MMU_IDR1_REF 0x0e739d18 @@ -186,13 +219,13 @@ #define IVPU_MMU_REG_TIMEOUT_US (10 * USEC_PER_MSEC) #define IVPU_MMU_QUEUE_TIMEOUT_US (100 * USEC_PER_MSEC) -#define IVPU_MMU_GERROR_ERR_MASK ((REG_FLD(VPU_37XX_HOST_MMU_GERROR, CMDQ)) | \ - (REG_FLD(VPU_37XX_HOST_MMU_GERROR, EVTQ_ABT)) | \ - (REG_FLD(VPU_37XX_HOST_MMU_GERROR, PRIQ_ABT)) | \ - (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_CMDQ_ABT)) | \ - (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_EVTQ_ABT)) | \ - (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_PRIQ_ABT)) | \ - (REG_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_ABT))) +#define IVPU_MMU_GERROR_ERR_MASK ((REG_FLD(IVPU_MMU_REG_GERROR, CMDQ)) | \ + (REG_FLD(IVPU_MMU_REG_GERROR, EVTQ_ABT)) | \ + (REG_FLD(IVPU_MMU_REG_GERROR, PRIQ_ABT)) | \ + (REG_FLD(IVPU_MMU_REG_GERROR, MSI_CMDQ_ABT)) | \ + (REG_FLD(IVPU_MMU_REG_GERROR, MSI_EVTQ_ABT)) | \ + (REG_FLD(IVPU_MMU_REG_GERROR, MSI_PRIQ_ABT)) | \ + (REG_FLD(IVPU_MMU_REG_GERROR, MSI_ABT))) static char *ivpu_mmu_event_to_str(u32 cmd) { @@ -250,15 +283,15 @@ static void ivpu_mmu_config_check(struct ivpu_device *vdev) else val_ref = IVPU_MMU_IDR0_REF; - val = REGV_RD32(VPU_37XX_HOST_MMU_IDR0); + val = REGV_RD32(IVPU_MMU_REG_IDR0); if (val != val_ref) ivpu_dbg(vdev, MMU, "IDR0 0x%x != IDR0_REF 0x%x\n", val, val_ref); - val = REGV_RD32(VPU_37XX_HOST_MMU_IDR1); + val = REGV_RD32(IVPU_MMU_REG_IDR1); if (val != IVPU_MMU_IDR1_REF) ivpu_dbg(vdev, MMU, "IDR1 0x%x != IDR1_REF 0x%x\n", val, IVPU_MMU_IDR1_REF); - val = REGV_RD32(VPU_37XX_HOST_MMU_IDR3); + val = REGV_RD32(IVPU_MMU_REG_IDR3); if (val != IVPU_MMU_IDR3_REF) ivpu_dbg(vdev, MMU, "IDR3 0x%x != IDR3_REF 0x%x\n", val, IVPU_MMU_IDR3_REF); @@ -269,7 +302,7 @@ static void ivpu_mmu_config_check(struct ivpu_device *vdev) else val_ref = IVPU_MMU_IDR5_REF; - val = REGV_RD32(VPU_37XX_HOST_MMU_IDR5); + val = REGV_RD32(IVPU_MMU_REG_IDR5); if (val != val_ref) ivpu_dbg(vdev, MMU, "IDR5 0x%x != IDR5_REF 0x%x\n", val, val_ref); } @@ -396,18 +429,18 @@ static int ivpu_mmu_irqs_setup(struct ivpu_device *vdev) u32 irq_ctrl = IVPU_MMU_IRQ_EVTQ_EN | IVPU_MMU_IRQ_GERROR_EN; int ret; - ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_IRQ_CTRL, 0); + ret = ivpu_mmu_reg_write(vdev, IVPU_MMU_REG_IRQ_CTRL, 0); if (ret) return ret; - return ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_IRQ_CTRL, irq_ctrl); + return ivpu_mmu_reg_write(vdev, IVPU_MMU_REG_IRQ_CTRL, irq_ctrl); } static int ivpu_mmu_cmdq_wait_for_cons(struct ivpu_device *vdev) { struct ivpu_mmu_queue *cmdq = &vdev->mmu->cmdq; - return REGV_POLL(VPU_37XX_HOST_MMU_CMDQ_CONS, cmdq->cons, (cmdq->prod == cmdq->cons), + return REGV_POLL(IVPU_MMU_REG_CMDQ_CONS, cmdq->cons, (cmdq->prod == cmdq->cons), IVPU_MMU_QUEUE_TIMEOUT_US); } @@ -447,7 +480,7 @@ static int ivpu_mmu_cmdq_sync(struct ivpu_device *vdev) return ret; clflush_cache_range(q->base, IVPU_MMU_CMDQ_SIZE); - REGV_WR32(VPU_37XX_HOST_MMU_CMDQ_PROD, q->prod); + REGV_WR32(IVPU_MMU_REG_CMDQ_PROD, q->prod); ret = ivpu_mmu_cmdq_wait_for_cons(vdev); if (ret) @@ -495,7 +528,7 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) mmu->evtq.prod = 0; mmu->evtq.cons = 0; - ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, 0); + ret = ivpu_mmu_reg_write(vdev, IVPU_MMU_REG_CR0, 0); if (ret) return ret; @@ -505,17 +538,17 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) FIELD_PREP(IVPU_MMU_CR1_QUEUE_SH, IVPU_MMU_SH_ISH) | FIELD_PREP(IVPU_MMU_CR1_QUEUE_OC, IVPU_MMU_CACHE_WB) | FIELD_PREP(IVPU_MMU_CR1_QUEUE_IC, IVPU_MMU_CACHE_WB); - REGV_WR32(VPU_37XX_HOST_MMU_CR1, val); + REGV_WR32(IVPU_MMU_REG_CR1, val); - REGV_WR64(VPU_37XX_HOST_MMU_STRTAB_BASE, mmu->strtab.dma_q); - REGV_WR32(VPU_37XX_HOST_MMU_STRTAB_BASE_CFG, mmu->strtab.base_cfg); + REGV_WR64(IVPU_MMU_REG_STRTAB_BASE, mmu->strtab.dma_q); + REGV_WR32(IVPU_MMU_REG_STRTAB_BASE_CFG, mmu->strtab.base_cfg); - REGV_WR64(VPU_37XX_HOST_MMU_CMDQ_BASE, mmu->cmdq.dma_q); - REGV_WR32(VPU_37XX_HOST_MMU_CMDQ_PROD, 0); - REGV_WR32(VPU_37XX_HOST_MMU_CMDQ_CONS, 0); + REGV_WR64(IVPU_MMU_REG_CMDQ_BASE, mmu->cmdq.dma_q); + REGV_WR32(IVPU_MMU_REG_CMDQ_PROD, 0); + REGV_WR32(IVPU_MMU_REG_CMDQ_CONS, 0); val = IVPU_MMU_CR0_CMDQEN; - ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val); + ret = ivpu_mmu_reg_write(vdev, IVPU_MMU_REG_CR0, val); if (ret) return ret; @@ -531,17 +564,17 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) if (ret) return ret; - REGV_WR64(VPU_37XX_HOST_MMU_EVTQ_BASE, mmu->evtq.dma_q); - REGV_WR32(VPU_37XX_HOST_MMU_EVTQ_PROD_SEC, 0); - REGV_WR32(VPU_37XX_HOST_MMU_EVTQ_CONS_SEC, 0); + REGV_WR64(IVPU_MMU_REG_EVTQ_BASE, mmu->evtq.dma_q); + REGV_WR32(IVPU_MMU_REG_EVTQ_PROD_SEC, 0); + REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, 0); val |= IVPU_MMU_CR0_EVTQEN; - ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val); + ret = ivpu_mmu_reg_write(vdev, IVPU_MMU_REG_CR0, val); if (ret) return ret; val |= IVPU_MMU_CR0_ATSCHK; - ret = ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val); + ret = ivpu_mmu_reg_write(vdev, IVPU_MMU_REG_CR0, val); if (ret) return ret; @@ -550,7 +583,7 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) return ret; val |= IVPU_MMU_CR0_SMMUEN; - return ivpu_mmu_reg_write(vdev, VPU_37XX_HOST_MMU_CR0, val); + return ivpu_mmu_reg_write(vdev, IVPU_MMU_REG_CR0, val); } static void ivpu_mmu_strtab_link_cd(struct ivpu_device *vdev, u32 sid) @@ -801,14 +834,14 @@ static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev) u32 idx = IVPU_MMU_Q_IDX(evtq->cons); u32 *evt = evtq->base + (idx * IVPU_MMU_EVTQ_CMD_SIZE); - evtq->prod = REGV_RD32(VPU_37XX_HOST_MMU_EVTQ_PROD_SEC); + evtq->prod = REGV_RD32(IVPU_MMU_REG_EVTQ_PROD_SEC); if (!CIRC_CNT(IVPU_MMU_Q_IDX(evtq->prod), IVPU_MMU_Q_IDX(evtq->cons), IVPU_MMU_Q_COUNT)) return NULL; clflush_cache_range(evt, IVPU_MMU_EVTQ_CMD_SIZE); evtq->cons = (evtq->cons + 1) & IVPU_MMU_Q_WRAP_MASK; - REGV_WR32(VPU_37XX_HOST_MMU_EVTQ_CONS_SEC, evtq->cons); + REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, evtq->cons); return evt; } @@ -841,35 +874,35 @@ void ivpu_mmu_irq_gerr_handler(struct ivpu_device *vdev) ivpu_dbg(vdev, IRQ, "MMU error\n"); - gerror_val = REGV_RD32(VPU_37XX_HOST_MMU_GERROR); - gerrorn_val = REGV_RD32(VPU_37XX_HOST_MMU_GERRORN); + gerror_val = REGV_RD32(IVPU_MMU_REG_GERROR); + gerrorn_val = REGV_RD32(IVPU_MMU_REG_GERRORN); active = gerror_val ^ gerrorn_val; if (!(active & IVPU_MMU_GERROR_ERR_MASK)) return; - if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_ABT, active)) + if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, MSI_ABT, active)) ivpu_warn_ratelimited(vdev, "MMU MSI ABT write aborted\n"); - if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_PRIQ_ABT, active)) + if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, MSI_PRIQ_ABT, active)) ivpu_warn_ratelimited(vdev, "MMU PRIQ MSI ABT write aborted\n"); - if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_EVTQ_ABT, active)) + if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, MSI_EVTQ_ABT, active)) ivpu_warn_ratelimited(vdev, "MMU EVTQ MSI ABT write aborted\n"); - if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, MSI_CMDQ_ABT, active)) + if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, MSI_CMDQ_ABT, active)) ivpu_warn_ratelimited(vdev, "MMU CMDQ MSI ABT write aborted\n"); - if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, PRIQ_ABT, active)) + if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, PRIQ_ABT, active)) ivpu_err_ratelimited(vdev, "MMU PRIQ write aborted\n"); - if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, EVTQ_ABT, active)) + if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, EVTQ_ABT, active)) ivpu_err_ratelimited(vdev, "MMU EVTQ write aborted\n"); - if (REG_TEST_FLD(VPU_37XX_HOST_MMU_GERROR, CMDQ, active)) + if (REG_TEST_FLD(IVPU_MMU_REG_GERROR, CMDQ, active)) ivpu_err_ratelimited(vdev, "MMU CMDQ write aborted\n"); - REGV_WR32(VPU_37XX_HOST_MMU_GERRORN, gerror_val); + REGV_WR32(IVPU_MMU_REG_GERRORN, gerror_val); } int ivpu_mmu_set_pgtable(struct ivpu_device *vdev, int ssid, struct ivpu_mmu_pgtable *pgtable) diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c index 1d2e554e2c4a..0c8c65351919 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.c +++ b/drivers/accel/ivpu/ivpu_mmu_context.c @@ -427,8 +427,10 @@ ivpu_mmu_context_init(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u3 INIT_LIST_HEAD(&ctx->bo_list); ret = ivpu_mmu_pgtable_init(vdev, &ctx->pgtable); - if (ret) + if (ret) { + ivpu_err(vdev, "Failed to initialize pgtable for ctx %u: %d\n", context_id, ret); return ret; + } if (!context_id) { start = vdev->hw->ranges.global.start; @@ -467,6 +469,16 @@ void ivpu_mmu_global_context_fini(struct ivpu_device *vdev) return ivpu_mmu_context_fini(vdev, &vdev->gctx); } +int ivpu_mmu_reserved_context_init(struct ivpu_device *vdev) +{ + return ivpu_mmu_user_context_init(vdev, &vdev->rctx, IVPU_RESERVED_CONTEXT_MMU_SSID); +} + +void ivpu_mmu_reserved_context_fini(struct ivpu_device *vdev) +{ + return ivpu_mmu_user_context_fini(vdev, &vdev->rctx); +} + void ivpu_mmu_user_context_mark_invalid(struct ivpu_device *vdev, u32 ssid) { struct ivpu_file_priv *file_priv; @@ -488,13 +500,13 @@ int ivpu_mmu_user_context_init(struct ivpu_device *vdev, struct ivpu_mmu_context ret = ivpu_mmu_context_init(vdev, ctx, ctx_id); if (ret) { - ivpu_err(vdev, "Failed to initialize context: %d\n", ret); + ivpu_err(vdev, "Failed to initialize context %u: %d\n", ctx_id, ret); return ret; } ret = ivpu_mmu_set_pgtable(vdev, ctx_id, &ctx->pgtable); if (ret) { - ivpu_err(vdev, "Failed to set page table: %d\n", ret); + ivpu_err(vdev, "Failed to set page table for context %u: %d\n", ctx_id, ret); goto err_context_fini; } diff --git a/drivers/accel/ivpu/ivpu_mmu_context.h b/drivers/accel/ivpu/ivpu_mmu_context.h index 961a0d6a6c7f..f15d8c630d8a 100644 --- a/drivers/accel/ivpu/ivpu_mmu_context.h +++ b/drivers/accel/ivpu/ivpu_mmu_context.h @@ -32,6 +32,8 @@ struct ivpu_mmu_context { int ivpu_mmu_global_context_init(struct ivpu_device *vdev); void ivpu_mmu_global_context_fini(struct ivpu_device *vdev); +int ivpu_mmu_reserved_context_init(struct ivpu_device *vdev); +void ivpu_mmu_reserved_context_fini(struct ivpu_device *vdev); int ivpu_mmu_user_context_init(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u32 ctx_id); void ivpu_mmu_user_context_fini(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx); diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index e6f27daf5560..28a0d1111e12 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -282,10 +282,11 @@ void ivpu_pm_reset_done_cb(struct pci_dev *pdev) pm_runtime_put_autosuspend(vdev->drm.dev); } -int ivpu_pm_init(struct ivpu_device *vdev) +void ivpu_pm_init(struct ivpu_device *vdev) { struct device *dev = vdev->drm.dev; struct ivpu_pm_info *pm = vdev->pm; + int delay; pm->vdev = vdev; pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT; @@ -293,16 +294,15 @@ int ivpu_pm_init(struct ivpu_device *vdev) atomic_set(&pm->in_reset, 0); INIT_WORK(&pm->recovery_work, ivpu_pm_recovery_work); - pm_runtime_use_autosuspend(dev); - if (ivpu_disable_recovery) - pm_runtime_set_autosuspend_delay(dev, -1); - else if (ivpu_is_silicon(vdev)) - pm_runtime_set_autosuspend_delay(dev, 100); + delay = -1; else - pm_runtime_set_autosuspend_delay(dev, 60000); + delay = vdev->timeout.autosuspend; - return 0; + pm_runtime_use_autosuspend(dev); + pm_runtime_set_autosuspend_delay(dev, delay); + + ivpu_dbg(vdev, PM, "Autosuspend delay = %d\n", delay); } void ivpu_pm_cancel_recovery(struct ivpu_device *vdev) diff --git a/drivers/accel/ivpu/ivpu_pm.h b/drivers/accel/ivpu/ivpu_pm.h index fd4eada1290f..f41c30a14a40 100644 --- a/drivers/accel/ivpu/ivpu_pm.h +++ b/drivers/accel/ivpu/ivpu_pm.h @@ -19,7 +19,7 @@ struct ivpu_pm_info { u32 suspend_reschedule_counter; }; -int ivpu_pm_init(struct ivpu_device *vdev); +void ivpu_pm_init(struct ivpu_device *vdev); void ivpu_pm_enable(struct ivpu_device *vdev); void ivpu_pm_disable(struct ivpu_device *vdev); void ivpu_pm_cancel_recovery(struct ivpu_device *vdev); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 4b230933b28e..cbef4ff28cd8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -219,7 +219,7 @@ static void dm_helpers_construct_old_payload( /* Set correct time_slots/PBN of old payload. * other fields (delete & dsc_enabled) in * struct drm_dp_mst_atomic_payload are don't care fields - * while calling drm_dp_remove_payload() + * while calling drm_dp_remove_payload_part2() */ for (i = 0; i < current_link_table.stream_count; i++) { dc_alloc = @@ -263,13 +263,12 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( mst_mgr = &aconnector->mst_root->mst_mgr; mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); - - /* It's OK for this to fail */ new_payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port); if (enable) { target_payload = new_payload; + /* It's OK for this to fail */ drm_dp_add_payload_part1(mst_mgr, mst_state, new_payload); } else { /* construct old payload by VCPI*/ @@ -277,7 +276,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table( new_payload, &old_payload); target_payload = &old_payload; - drm_dp_remove_payload(mst_mgr, mst_state, &old_payload, new_payload); + drm_dp_remove_payload_part1(mst_mgr, mst_state, new_payload); } /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or @@ -344,7 +343,7 @@ bool dm_helpers_dp_mst_send_payload_allocation( struct amdgpu_dm_connector *aconnector; struct drm_dp_mst_topology_state *mst_state; struct drm_dp_mst_topology_mgr *mst_mgr; - struct drm_dp_mst_atomic_payload *payload; + struct drm_dp_mst_atomic_payload *new_payload, *old_payload; enum mst_progress_status set_flag = MST_ALLOCATE_NEW_PAYLOAD; enum mst_progress_status clr_flag = MST_CLEAR_ALLOCATED_PAYLOAD; int ret = 0; @@ -357,15 +356,20 @@ bool dm_helpers_dp_mst_send_payload_allocation( mst_mgr = &aconnector->mst_root->mst_mgr; mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state); - payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port); + new_payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port); if (!enable) { set_flag = MST_CLEAR_ALLOCATED_PAYLOAD; clr_flag = MST_ALLOCATE_NEW_PAYLOAD; } - if (enable) - ret = drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, payload); + if (enable) { + ret = drm_dp_add_payload_part2(mst_mgr, mst_state->base.state, new_payload); + } else { + dm_helpers_construct_old_payload(stream->link, mst_state->pbn_div, + new_payload, old_payload); + drm_dp_remove_payload_part2(mst_mgr, mst_state, old_payload, new_payload); + } if (ret) { amdgpu_dm_set_mst_status(&aconnector->mst_status, diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c index 4618687a8f4d..f3e744172673 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c @@ -1223,7 +1223,7 @@ int komeda_build_display_data_flow(struct komeda_crtc *kcrtc, return 0; } -static void +static int komeda_pipeline_unbound_components(struct komeda_pipeline *pipe, struct komeda_pipeline_state *new) { @@ -1243,8 +1243,12 @@ komeda_pipeline_unbound_components(struct komeda_pipeline *pipe, c = komeda_pipeline_get_component(pipe, id); c_st = komeda_component_get_state_and_set_user(c, drm_st, NULL, new->crtc); + if (PTR_ERR(c_st) == -EDEADLK) + return -EDEADLK; WARN_ON(IS_ERR(c_st)); } + + return 0; } /* release unclaimed pipeline resource */ @@ -1266,9 +1270,8 @@ int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe, if (WARN_ON(IS_ERR_OR_NULL(st))) return -EINVAL; - komeda_pipeline_unbound_components(pipe, st); + return komeda_pipeline_unbound_components(pipe, st); - return 0; } /* Since standalone disabled components must be disabled separately and in the diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 44a660a4bdbf..ba82a1142adf 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -181,6 +181,7 @@ config DRM_NWL_MIPI_DSI select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL_BRIDGE + select GENERIC_PHY select GENERIC_PHY_MIPI_DPHY select MFD_SYSCON select MULTIPLEXER @@ -227,6 +228,7 @@ config DRM_SAMSUNG_DSIM select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL_BRIDGE + select GENERIC_PHY select GENERIC_PHY_MIPI_DPHY help The Samsung MIPI DSIM bridge controller driver. diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c index 800555aef97f..ad8241758896 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c @@ -1231,9 +1231,7 @@ static int anx78xx_i2c_probe(struct i2c_client *client) mutex_init(&anx78xx->lock); -#if IS_ENABLED(CONFIG_OF) anx78xx->bridge.of_node = client->dev.of_node; -#endif anx78xx->client = client; i2c_set_clientdata(client, anx78xx); @@ -1367,12 +1365,6 @@ static void anx78xx_i2c_remove(struct i2c_client *client) kfree(anx78xx->edid); } -static const struct i2c_device_id anx78xx_id[] = { - { "anx7814", 0 }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(i2c, anx78xx_id); - static const struct of_device_id anx78xx_match_table[] = { { .compatible = "analogix,anx7808", .data = anx7808_i2c_addresses }, { .compatible = "analogix,anx7812", .data = anx781x_i2c_addresses }, @@ -1389,7 +1381,6 @@ static struct i2c_driver anx78xx_driver = { }, .probe = anx78xx_i2c_probe, .remove = anx78xx_i2c_remove, - .id_table = anx78xx_id, }; module_i2c_driver(anx78xx_driver); diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig index ec35215a2003..cced81633ddc 100644 --- a/drivers/gpu/drm/bridge/cadence/Kconfig +++ b/drivers/gpu/drm/bridge/cadence/Kconfig @@ -4,6 +4,7 @@ config DRM_CDNS_DSI select DRM_KMS_HELPER select DRM_MIPI_DSI select DRM_PANEL_BRIDGE + select GENERIC_PHY select GENERIC_PHY_MIPI_DPHY depends on OF help diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index 466641c77fe9..3c9b42c9d2ee 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -1447,10 +1447,14 @@ static int it66121_audio_get_eld(struct device *dev, void *data, struct it66121_ctx *ctx = dev_get_drvdata(dev); mutex_lock(&ctx->lock); - - memcpy(buf, ctx->connector->eld, - min(sizeof(ctx->connector->eld), len)); - + if (!ctx->connector) { + /* Pass en empty ELD if connector not available */ + dev_dbg(dev, "No connector present, passing empty EDID data"); + memset(buf, 0, len); + } else { + memcpy(buf, ctx->connector->eld, + min(sizeof(ctx->connector->eld), len)); + } mutex_unlock(&ctx->lock); return 0; @@ -1501,7 +1505,6 @@ static const char * const it66121_supplies[] = { static int it66121_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 }; struct device_node *ep; int ret; @@ -1523,7 +1526,7 @@ static int it66121_probe(struct i2c_client *client) ctx->dev = dev; ctx->client = client; - ctx->info = (const struct it66121_chip_info *) id->driver_data; + ctx->info = i2c_get_match_data(client); of_property_read_u32(ep, "bus-width", &ctx->bus_width); of_node_put(ep); @@ -1609,13 +1612,6 @@ static void it66121_remove(struct i2c_client *client) mutex_destroy(&ctx->lock); } -static const struct of_device_id it66121_dt_match[] = { - { .compatible = "ite,it66121" }, - { .compatible = "ite,it6610" }, - { } -}; -MODULE_DEVICE_TABLE(of, it66121_dt_match); - static const struct it66121_chip_info it66121_chip_info = { .id = ID_IT66121, .vid = 0x4954, @@ -1628,6 +1624,13 @@ static const struct it66121_chip_info it6610_chip_info = { .pid = 0x0611, }; +static const struct of_device_id it66121_dt_match[] = { + { .compatible = "ite,it66121", &it66121_chip_info }, + { .compatible = "ite,it6610", &it6610_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(of, it66121_dt_match); + static const struct i2c_device_id it66121_id[] = { { "it66121", (kernel_ulong_t) &it66121_chip_info }, { "it6610", (kernel_ulong_t) &it6610_chip_info }, diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c index 4eaea67fb71c..03532efb893b 100644 --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c @@ -45,7 +45,6 @@ struct lt8912 { u8 data_lanes; bool is_power_on; - bool is_attached; }; static int lt8912_write_init_config(struct lt8912 *lt) @@ -559,6 +558,13 @@ static int lt8912_bridge_attach(struct drm_bridge *bridge, struct lt8912 *lt = bridge_to_lt8912(bridge); int ret; + ret = drm_bridge_attach(bridge->encoder, lt->hdmi_port, bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret < 0) { + dev_err(lt->dev, "Failed to attach next bridge (%d)\n", ret); + return ret; + } + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { ret = lt8912_bridge_connector_init(bridge); if (ret) { @@ -575,8 +581,6 @@ static int lt8912_bridge_attach(struct drm_bridge *bridge, if (ret) goto error; - lt->is_attached = true; - return 0; error: @@ -588,15 +592,10 @@ static void lt8912_bridge_detach(struct drm_bridge *bridge) { struct lt8912 *lt = bridge_to_lt8912(bridge); - if (lt->is_attached) { - lt8912_hard_power_off(lt); + lt8912_hard_power_off(lt); - if (lt->hdmi_port->ops & DRM_BRIDGE_OP_HPD) - drm_bridge_hpd_disable(lt->hdmi_port); - - drm_connector_unregister(<->connector); - drm_connector_cleanup(<->connector); - } + if (lt->connector.dev && lt->hdmi_port->ops & DRM_BRIDGE_OP_HPD) + drm_bridge_hpd_disable(lt->hdmi_port); } static enum drm_connector_status @@ -750,7 +749,6 @@ static void lt8912_remove(struct i2c_client *client) { struct lt8912 *lt = i2c_get_clientdata(client); - lt8912_bridge_detach(<->bridge); drm_bridge_remove(<->bridge); lt8912_free_i2c(lt); lt8912_put_dt(lt); diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c index 8c5668dca0c4..991732c4b629 100644 --- a/drivers/gpu/drm/bridge/lvds-codec.c +++ b/drivers/gpu/drm/bridge/lvds-codec.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -71,12 +72,6 @@ static void lvds_codec_disable(struct drm_bridge *bridge) "Failed to disable regulator \"vcc\": %d\n", ret); } -static const struct drm_bridge_funcs funcs = { - .attach = lvds_codec_attach, - .enable = lvds_codec_enable, - .disable = lvds_codec_disable, -}; - #define MAX_INPUT_SEL_FORMATS 1 static u32 * lvds_codec_atomic_get_input_bus_fmts(struct drm_bridge *bridge, @@ -102,7 +97,7 @@ lvds_codec_atomic_get_input_bus_fmts(struct drm_bridge *bridge, return input_fmts; } -static const struct drm_bridge_funcs funcs_decoder = { +static const struct drm_bridge_funcs funcs = { .attach = lvds_codec_attach, .enable = lvds_codec_enable, .disable = lvds_codec_disable, @@ -184,8 +179,9 @@ static int lvds_codec_probe(struct platform_device *pdev) return ret; } else { lvds_codec->bus_format = ret; - lvds_codec->bridge.funcs = &funcs_decoder; } + } else { + lvds_codec->bus_format = MEDIA_BUS_FMT_RGB888_1X24; } /* diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 9316384b4474..e00d2e94c751 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -4,6 +4,8 @@ * Copyright (C) 2017 Broadcom */ +#include + #include #include #include @@ -19,6 +21,7 @@ struct panel_bridge { struct drm_bridge bridge; struct drm_connector connector; struct drm_panel *panel; + struct device_link *link; u32 connector_type; }; @@ -60,6 +63,8 @@ static int panel_bridge_attach(struct drm_bridge *bridge, { struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); struct drm_connector *connector = &panel_bridge->connector; + struct drm_panel *panel = panel_bridge->panel; + struct drm_device *drm_dev = bridge->dev; int ret; if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) @@ -70,6 +75,14 @@ static int panel_bridge_attach(struct drm_bridge *bridge, return -ENODEV; } + panel_bridge->link = device_link_add(drm_dev->dev, panel->dev, + DL_FLAG_STATELESS); + if (!panel_bridge->link) { + DRM_ERROR("Failed to add device link between %s and %s\n", + dev_name(drm_dev->dev), dev_name(panel->dev)); + return -EINVAL; + } + drm_connector_helper_add(connector, &panel_bridge_connector_helper_funcs); @@ -78,6 +91,7 @@ static int panel_bridge_attach(struct drm_bridge *bridge, panel_bridge->connector_type); if (ret) { DRM_ERROR("Failed to initialize connector\n"); + device_link_del(panel_bridge->link); return ret; } @@ -100,6 +114,8 @@ static void panel_bridge_detach(struct drm_bridge *bridge) struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); struct drm_connector *connector = &panel_bridge->connector; + device_link_del(panel_bridge->link); + /* * Cleanup the connector if we know it was initialized. * @@ -302,9 +318,7 @@ struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel, panel_bridge->panel = panel; panel_bridge->bridge.funcs = &panel_bridge_bridge_funcs; -#ifdef CONFIG_OF panel_bridge->bridge.of_node = panel->dev->of_node; -#endif panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES; panel_bridge->bridge.type = connector_type; diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index cf777bdb25d2..19bdb32dbc9a 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -385,7 +385,7 @@ static const unsigned int imx8mm_dsim_reg_values[] = { [RESET_TYPE] = DSIM_SWRST, [PLL_TIMER] = 500, [STOP_STATE_CNT] = 0xf, - [PHYCTRL_ULPS_EXIT] = 0, + [PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0xaf), [PHYCTRL_VREG_LP] = 0, [PHYCTRL_SLEW_UP] = 0, [PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x06), @@ -413,6 +413,7 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = { .m_min = 41, .m_max = 125, .min_freq = 500, + .has_broken_fifoctrl_emptyhdr = 1, }; static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = { @@ -429,6 +430,7 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = { .m_min = 41, .m_max = 125, .min_freq = 500, + .has_broken_fifoctrl_emptyhdr = 1, }; static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = { @@ -1010,8 +1012,20 @@ static int samsung_dsim_wait_for_hdr_fifo(struct samsung_dsim *dsi) do { u32 reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG); - if (reg & DSIM_SFR_HEADER_EMPTY) - return 0; + if (!dsi->driver_data->has_broken_fifoctrl_emptyhdr) { + if (reg & DSIM_SFR_HEADER_EMPTY) + return 0; + } else { + if (!(reg & DSIM_SFR_HEADER_FULL)) { + /* + * Wait a little bit, so the pending data can + * actually leave the FIFO to avoid overflow. + */ + if (!cond_resched()) + usleep_range(950, 1050); + return 0; + } + } if (!cond_resched()) usleep_range(950, 1050); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 6c1d79474505..52d91a0df85e 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -3541,9 +3541,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, | DRM_BRIDGE_OP_HPD; hdmi->bridge.interlace_allowed = true; hdmi->bridge.ddc = hdmi->ddc; -#ifdef CONFIG_OF hdmi->bridge.of_node = pdev->dev.of_node; -#endif memset(&pdevinfo, 0, sizeof(pdevinfo)); pdevinfo.parent = dev; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 04d4a1a10698..a8dd2a2e7c7b 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -1182,9 +1182,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, dsi->bridge.driver_private = dsi; dsi->bridge.funcs = &dw_mipi_dsi_bridge_funcs; -#ifdef CONFIG_OF dsi->bridge.of_node = pdev->dev.of_node; -#endif return dsi; } diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index ed96cfcfa304..e04f87ff755a 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -3255,15 +3255,15 @@ out_get_port: } EXPORT_SYMBOL(drm_dp_send_query_stream_enc_status); -static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_atomic_payload *payload) +static int drm_dp_create_payload_at_dfp(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_atomic_payload *payload) { return drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot, payload->time_slots); } -static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_atomic_payload *payload) +static int drm_dp_create_payload_to_remote(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_atomic_payload *payload) { int ret; struct drm_dp_mst_port *port = drm_dp_mst_topology_get_port_validated(mgr, payload->port); @@ -3276,17 +3276,20 @@ static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr, return ret; } -static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_topology_state *mst_state, - struct drm_dp_mst_atomic_payload *payload) +static void drm_dp_destroy_payload_at_remote_and_dfp(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_atomic_payload *payload) { drm_dbg_kms(mgr->dev, "\n"); /* it's okay for these to fail */ - drm_dp_payload_send_msg(mgr, payload->port, payload->vcpi, 0); - drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot, 0); + if (payload->payload_allocation_status == DRM_DP_MST_PAYLOAD_ALLOCATION_REMOTE) { + drm_dp_payload_send_msg(mgr, payload->port, payload->vcpi, 0); + payload->payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_DFP; + } - return 0; + if (payload->payload_allocation_status == DRM_DP_MST_PAYLOAD_ALLOCATION_DFP) + drm_dp_dpcd_write_payload(mgr, payload->vcpi, payload->vc_start_slot, 0); } /** @@ -3296,81 +3299,105 @@ static int drm_dp_destroy_payload_step1(struct drm_dp_mst_topology_mgr *mgr, * @payload: The payload to write * * Determines the starting time slot for the given payload, and programs the VCPI for this payload - * into hardware. After calling this, the driver should generate ACT and payload packets. + * into the DPCD of DPRX. After calling this, the driver should generate ACT and payload packets. * - * Returns: 0 on success, error code on failure. In the event that this fails, - * @payload.vc_start_slot will also be set to -1. + * Returns: 0 on success, error code on failure. */ int drm_dp_add_payload_part1(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_topology_state *mst_state, struct drm_dp_mst_atomic_payload *payload) { struct drm_dp_mst_port *port; - int ret; - - port = drm_dp_mst_topology_get_port_validated(mgr, payload->port); - if (!port) { - drm_dbg_kms(mgr->dev, - "VCPI %d for port %p not in topology, not creating a payload\n", - payload->vcpi, payload->port); - payload->vc_start_slot = -1; - return 0; - } + int ret = 0; + bool allocate = true; + /* Update mst mgr info */ if (mgr->payload_count == 0) mgr->next_start_slot = mst_state->start_slot; payload->vc_start_slot = mgr->next_start_slot; - ret = drm_dp_create_payload_step1(mgr, payload); - drm_dp_mst_topology_put_port(port); - if (ret < 0) { - drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n", - payload->port, ret); - payload->vc_start_slot = -1; - return ret; - } - mgr->payload_count++; mgr->next_start_slot += payload->time_slots; - return 0; + /* Allocate payload to immediate downstream facing port */ + port = drm_dp_mst_topology_get_port_validated(mgr, payload->port); + if (!port) { + drm_dbg_kms(mgr->dev, + "VCPI %d for port %p not in topology, not creating a payload to remote\n", + payload->vcpi, payload->port); + allocate = false; + } + + if (allocate) { + ret = drm_dp_create_payload_at_dfp(mgr, payload); + if (ret < 0) + drm_warn(mgr->dev, "Failed to create MST payload for port %p: %d\n", + payload->port, ret); + + } + + payload->payload_allocation_status = + (!allocate || ret < 0) ? DRM_DP_MST_PAYLOAD_ALLOCATION_LOCAL : + DRM_DP_MST_PAYLOAD_ALLOCATION_DFP; + + drm_dp_mst_topology_put_port(port); + + return ret; } EXPORT_SYMBOL(drm_dp_add_payload_part1); /** - * drm_dp_remove_payload() - Remove an MST payload + * drm_dp_remove_payload_part1() - Remove an MST payload along the virtual channel * @mgr: Manager to use. * @mst_state: The MST atomic state - * @old_payload: The payload with its old state - * @new_payload: The payload to write + * @payload: The payload to remove * - * Removes a payload from an MST topology if it was successfully assigned a start slot. Also updates - * the starting time slots of all other payloads which would have been shifted towards the start of - * the VC table as a result. After calling this, the driver should generate ACT and payload packets. + * Removes a payload along the virtual channel if it was successfully allocated. + * After calling this, the driver should set HW to generate ACT and then switch to new + * payload allocation state. */ -void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_topology_state *mst_state, - const struct drm_dp_mst_atomic_payload *old_payload, - struct drm_dp_mst_atomic_payload *new_payload) +void drm_dp_remove_payload_part1(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_atomic_payload *payload) { - struct drm_dp_mst_atomic_payload *pos; + /* Remove remote payload allocation */ bool send_remove = false; - /* We failed to make the payload, so nothing to do */ - if (new_payload->vc_start_slot == -1) - return; - mutex_lock(&mgr->lock); - send_remove = drm_dp_mst_port_downstream_of_branch(new_payload->port, mgr->mst_primary); + send_remove = drm_dp_mst_port_downstream_of_branch(payload->port, mgr->mst_primary); mutex_unlock(&mgr->lock); if (send_remove) - drm_dp_destroy_payload_step1(mgr, mst_state, new_payload); + drm_dp_destroy_payload_at_remote_and_dfp(mgr, mst_state, payload); else drm_dbg_kms(mgr->dev, "Payload for VCPI %d not in topology, not sending remove\n", - new_payload->vcpi); + payload->vcpi); + payload->payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_LOCAL; +} +EXPORT_SYMBOL(drm_dp_remove_payload_part1); + +/** + * drm_dp_remove_payload_part2() - Remove an MST payload locally + * @mgr: Manager to use. + * @mst_state: The MST atomic state + * @old_payload: The payload with its old state + * @new_payload: The payload with its latest state + * + * Updates the starting time slots of all other payloads which would have been shifted towards + * the start of the payload ID table as a result of removing a payload. Driver should call this + * function whenever it removes a payload in its HW. It's independent to the result of payload + * allocation/deallocation at branch devices along the virtual channel. + */ +void drm_dp_remove_payload_part2(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_topology_state *mst_state, + const struct drm_dp_mst_atomic_payload *old_payload, + struct drm_dp_mst_atomic_payload *new_payload) +{ + struct drm_dp_mst_atomic_payload *pos; + + /* Remove local payload allocation */ list_for_each_entry(pos, &mst_state->payloads, next) { if (pos != new_payload && pos->vc_start_slot > new_payload->vc_start_slot) pos->vc_start_slot -= old_payload->time_slots; @@ -3382,9 +3409,10 @@ void drm_dp_remove_payload(struct drm_dp_mst_topology_mgr *mgr, if (new_payload->delete) drm_dp_mst_put_port_malloc(new_payload->port); -} -EXPORT_SYMBOL(drm_dp_remove_payload); + new_payload->payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_NONE; +} +EXPORT_SYMBOL(drm_dp_remove_payload_part2); /** * drm_dp_add_payload_part2() - Execute payload update part 2 * @mgr: Manager to use. @@ -3403,21 +3431,19 @@ int drm_dp_add_payload_part2(struct drm_dp_mst_topology_mgr *mgr, int ret = 0; /* Skip failed payloads */ - if (payload->vc_start_slot == -1) { - drm_dbg_kms(mgr->dev, "Part 1 of payload creation for %s failed, skipping part 2\n", + if (payload->payload_allocation_status != DRM_DP_MST_PAYLOAD_ALLOCATION_DFP) { + drm_dbg_kms(state->dev, "Part 1 of payload creation for %s failed, skipping part 2\n", payload->port->connector->name); return -EIO; } - ret = drm_dp_create_payload_step2(mgr, payload); - if (ret < 0) { - if (!payload->delete) - drm_err(mgr->dev, "Step 2 of creating MST payload for %p failed: %d\n", - payload->port, ret); - else - drm_dbg_kms(mgr->dev, "Step 2 of removing MST payload for %p failed: %d\n", - payload->port, ret); - } + /* Allocate payload to remote end */ + ret = drm_dp_create_payload_to_remote(mgr, payload); + if (ret < 0) + drm_err(mgr->dev, "Step 2 of creating MST payload for %p failed: %d\n", + payload->port, ret); + else + payload->payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_REMOTE; return ret; } @@ -4328,6 +4354,7 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, drm_dp_mst_get_port_malloc(port); payload->port = port; payload->vc_start_slot = -1; + payload->payload_allocation_status = DRM_DP_MST_PAYLOAD_ALLOCATION_NONE; list_add(&payload->next, &topology_state->payloads); } payload->time_slots = req_slots; @@ -4497,7 +4524,7 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state) } /* Now that previous state is committed, it's safe to copy over the start slot - * assignments + * and allocation status assignments */ list_for_each_entry(old_payload, &old_mst_state->payloads, next) { if (old_payload->delete) @@ -4506,6 +4533,8 @@ void drm_dp_mst_atomic_wait_for_dependencies(struct drm_atomic_state *state) new_payload = drm_atomic_get_mst_payload_state(new_mst_state, old_payload->port); new_payload->vc_start_slot = old_payload->vc_start_slot; + new_payload->payload_allocation_status = + old_payload->payload_allocation_status; } } } @@ -4822,6 +4851,13 @@ void drm_dp_mst_dump_topology(struct seq_file *m, struct drm_dp_mst_atomic_payload *payload; int i, ret; + static const char *const status[] = { + "None", + "Local", + "DFP", + "Remote", + }; + mutex_lock(&mgr->lock); if (mgr->mst_primary) drm_dp_mst_dump_mstb(m, mgr->mst_primary); @@ -4838,7 +4874,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m, seq_printf(m, "payload_mask: %x, max_payloads: %d, start_slot: %u, pbn_div: %d\n", state->payload_mask, mgr->max_payloads, state->start_slot, state->pbn_div); - seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc | sink name |\n"); + seq_printf(m, "\n| idx | port | vcpi | slots | pbn | dsc | status | sink name |\n"); for (i = 0; i < mgr->max_payloads; i++) { list_for_each_entry(payload, &state->payloads, next) { char name[14]; @@ -4847,7 +4883,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m, continue; fetch_monitor_name(mgr, payload->port, name, sizeof(name)); - seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %19s\n", + seq_printf(m, " %5d %6d %6d %02d - %02d %5d %5s %8s %19s\n", i, payload->port->port_num, payload->vcpi, @@ -4855,6 +4891,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m, payload->vc_start_slot + payload->time_slots - 1, payload->pbn, payload->dsc_enabled ? "Y" : "N", + status[payload->payload_allocation_status], (*name != 0) ? name : "Unknown"); } } diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index c277b198fa3f..f1a503aafe5a 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1841,9 +1841,9 @@ static const struct drm_debugfs_info drm_atomic_debugfs_list[] = { {"state", drm_state_info, 0}, }; -void drm_atomic_debugfs_init(struct drm_minor *minor) +void drm_atomic_debugfs_init(struct drm_device *dev) { - drm_debugfs_add_files(minor->dev, drm_atomic_debugfs_list, + drm_debugfs_add_files(dev, drm_atomic_debugfs_list, ARRAY_SIZE(drm_atomic_debugfs_list)); } #endif diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 39e68e45bb12..30d66bee0ec6 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -1384,9 +1384,9 @@ static const struct drm_debugfs_info drm_bridge_debugfs_list[] = { { "bridge_chains", drm_bridge_chains_info, 0 }, }; -void drm_bridge_debugfs_init(struct drm_minor *minor) +void drm_bridge_debugfs_init(struct drm_device *dev) { - drm_debugfs_add_files(minor->dev, drm_bridge_debugfs_list, + drm_debugfs_add_files(dev, drm_bridge_debugfs_list, ARRAY_SIZE(drm_bridge_debugfs_list)); } #endif diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index 037e36f2049c..2762572f286e 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -535,9 +535,9 @@ static const struct drm_debugfs_info drm_client_debugfs_list[] = { { "internal_clients", drm_client_debugfs_internal_clients, 0 }, }; -void drm_client_debugfs_init(struct drm_minor *minor) +void drm_client_debugfs_init(struct drm_device *dev) { - drm_debugfs_add_files(minor->dev, drm_client_debugfs_list, + drm_debugfs_add_files(dev, drm_client_debugfs_list, ARRAY_SIZE(drm_client_debugfs_list)); } #endif diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 501a10edd0e1..8556c3b3ff88 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -232,7 +232,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, /* drm_atomic.c */ #ifdef CONFIG_DEBUG_FS struct drm_minor; -void drm_atomic_debugfs_init(struct drm_minor *minor); +void drm_atomic_debugfs_init(struct drm_device *dev); #endif int __drm_atomic_helper_disable_plane(struct drm_plane *plane, diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 2de43ff3ce0a..34c7d1a580e3 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -150,6 +150,9 @@ static int drm_debugfs_open(struct inode *inode, struct file *file) { struct drm_info_node *node = inode->i_private; + if (!device_is_registered(node->minor->kdev)) + return -ENODEV; + return single_open(file, node->info_ent->show, node); } @@ -157,6 +160,10 @@ static int drm_debugfs_entry_open(struct inode *inode, struct file *file) { struct drm_debugfs_entry *entry = inode->i_private; struct drm_debugfs_info *node = &entry->file; + struct drm_minor *minor = entry->dev->primary ?: entry->dev->accel; + + if (!device_is_registered(minor->kdev)) + return -ENODEV; return single_open(file, node->show, entry); } @@ -227,7 +234,7 @@ EXPORT_SYMBOL(drm_debugfs_gpuva_info); * * Create a given set of debugfs files represented by an array of * &struct drm_info_list in the given root directory. These files will be removed - * automatically on drm_debugfs_cleanup(). + * automatically on drm_debugfs_dev_fini(). */ void drm_debugfs_create_files(const struct drm_info_list *files, int count, struct dentry *root, struct drm_minor *minor) @@ -242,7 +249,7 @@ void drm_debugfs_create_files(const struct drm_info_list *files, int count, if (features && !drm_core_check_all_features(dev, features)) continue; - tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); + tmp = drmm_kzalloc(dev, sizeof(*tmp), GFP_KERNEL); if (tmp == NULL) continue; @@ -251,111 +258,89 @@ void drm_debugfs_create_files(const struct drm_info_list *files, int count, 0444, root, tmp, &drm_debugfs_fops); tmp->info_ent = &files[i]; - - mutex_lock(&minor->debugfs_lock); - list_add(&tmp->list, &minor->debugfs_list); - mutex_unlock(&minor->debugfs_lock); } } EXPORT_SYMBOL(drm_debugfs_create_files); -int drm_debugfs_init(struct drm_minor *minor, int minor_id, - struct dentry *root) -{ - struct drm_device *dev = minor->dev; - struct drm_debugfs_entry *entry, *tmp; - char name[64]; - - INIT_LIST_HEAD(&minor->debugfs_list); - mutex_init(&minor->debugfs_lock); - sprintf(name, "%d", minor_id); - minor->debugfs_root = debugfs_create_dir(name, root); - - drm_debugfs_add_files(minor->dev, drm_debugfs_list, DRM_DEBUGFS_ENTRIES); - - if (drm_drv_uses_atomic_modeset(dev)) { - drm_atomic_debugfs_init(minor); - drm_bridge_debugfs_init(minor); - } - - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - drm_framebuffer_debugfs_init(minor); - - drm_client_debugfs_init(minor); - } - - if (dev->driver->debugfs_init) - dev->driver->debugfs_init(minor); - - list_for_each_entry_safe(entry, tmp, &dev->debugfs_list, list) { - debugfs_create_file(entry->file.name, 0444, - minor->debugfs_root, entry, &drm_debugfs_entry_fops); - list_del(&entry->list); - } - - return 0; -} - -void drm_debugfs_late_register(struct drm_device *dev) -{ - struct drm_minor *minor = dev->primary; - struct drm_debugfs_entry *entry, *tmp; - - if (!minor) - return; - - list_for_each_entry_safe(entry, tmp, &dev->debugfs_list, list) { - debugfs_create_file(entry->file.name, 0444, - minor->debugfs_root, entry, &drm_debugfs_entry_fops); - list_del(&entry->list); - } -} - int drm_debugfs_remove_files(const struct drm_info_list *files, int count, - struct drm_minor *minor) + struct dentry *root, struct drm_minor *minor) { - struct list_head *pos, *q; - struct drm_info_node *tmp; int i; - mutex_lock(&minor->debugfs_lock); for (i = 0; i < count; i++) { - list_for_each_safe(pos, q, &minor->debugfs_list) { - tmp = list_entry(pos, struct drm_info_node, list); - if (tmp->info_ent == &files[i]) { - debugfs_remove(tmp->dent); - list_del(pos); - kfree(tmp); - } - } + struct dentry *dent = debugfs_lookup(files[i].name, root); + + if (!dent) + continue; + + drmm_kfree(minor->dev, d_inode(dent)->i_private); + debugfs_remove(dent); } - mutex_unlock(&minor->debugfs_lock); return 0; } EXPORT_SYMBOL(drm_debugfs_remove_files); -static void drm_debugfs_remove_all_files(struct drm_minor *minor) +/** + * drm_debugfs_dev_init - create debugfs directory for the device + * @dev: the device which we want to create the directory for + * @root: the parent directory depending on the device type + * + * Creates the debugfs directory for the device under the given root directory. + */ +void drm_debugfs_dev_init(struct drm_device *dev, struct dentry *root) { - struct drm_info_node *node, *tmp; - - mutex_lock(&minor->debugfs_lock); - list_for_each_entry_safe(node, tmp, &minor->debugfs_list, list) { - debugfs_remove(node->dent); - list_del(&node->list); - kfree(node); - } - mutex_unlock(&minor->debugfs_lock); + dev->debugfs_root = debugfs_create_dir(dev->unique, root); } -void drm_debugfs_cleanup(struct drm_minor *minor) +/** + * drm_debugfs_dev_fini - cleanup debugfs directory + * @dev: the device to cleanup the debugfs stuff + * + * Remove the debugfs directory, might be called multiple times. + */ +void drm_debugfs_dev_fini(struct drm_device *dev) { - if (!minor->debugfs_root) - return; + debugfs_remove_recursive(dev->debugfs_root); + dev->debugfs_root = NULL; +} - drm_debugfs_remove_all_files(minor); +void drm_debugfs_dev_register(struct drm_device *dev) +{ + drm_debugfs_add_files(dev, drm_debugfs_list, DRM_DEBUGFS_ENTRIES); - debugfs_remove_recursive(minor->debugfs_root); - minor->debugfs_root = NULL; + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + drm_framebuffer_debugfs_init(dev); + drm_client_debugfs_init(dev); + } + if (drm_drv_uses_atomic_modeset(dev)) { + drm_atomic_debugfs_init(dev); + drm_bridge_debugfs_init(dev); + } +} + +int drm_debugfs_register(struct drm_minor *minor, int minor_id, + struct dentry *root) +{ + struct drm_device *dev = minor->dev; + char name[64]; + + sprintf(name, "%d", minor_id); + minor->debugfs_symlink = debugfs_create_symlink(name, root, + dev->unique); + + /* TODO: Only for compatibility with drivers */ + minor->debugfs_root = dev->debugfs_root; + + if (dev->driver->debugfs_init && dev->render != minor) + dev->driver->debugfs_init(minor); + + return 0; +} + +void drm_debugfs_unregister(struct drm_minor *minor) +{ + debugfs_remove(minor->debugfs_symlink); + minor->debugfs_symlink = NULL; } /** @@ -381,9 +366,8 @@ void drm_debugfs_add_file(struct drm_device *dev, const char *name, entry->file.data = data; entry->dev = dev; - mutex_lock(&dev->debugfs_mutex); - list_add(&entry->list, &dev->debugfs_list); - mutex_unlock(&dev->debugfs_mutex); + debugfs_create_file(name, 0444, dev->debugfs_root, entry, + &drm_debugfs_entry_fops); } EXPORT_SYMBOL(drm_debugfs_add_file); @@ -540,13 +524,13 @@ static const struct file_operations drm_connector_fops = { void drm_debugfs_connector_add(struct drm_connector *connector) { - struct drm_minor *minor = connector->dev->primary; + struct drm_device *dev = connector->dev; struct dentry *root; - if (!minor->debugfs_root) + if (!dev->debugfs_root) return; - root = debugfs_create_dir(connector->name, minor->debugfs_root); + root = debugfs_create_dir(connector->name, dev->debugfs_root); connector->debugfs_entry = root; /* force */ @@ -581,7 +565,7 @@ void drm_debugfs_connector_remove(struct drm_connector *connector) void drm_debugfs_crtc_add(struct drm_crtc *crtc) { - struct drm_minor *minor = crtc->dev->primary; + struct drm_device *dev = crtc->dev; struct dentry *root; char *name; @@ -589,7 +573,7 @@ void drm_debugfs_crtc_add(struct drm_crtc *crtc) if (!name) return; - root = debugfs_create_dir(name, minor->debugfs_root); + root = debugfs_create_dir(name, dev->debugfs_root); kfree(name); crtc->debugfs_entry = root; diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 3eda026ffac6..535f16e7882e 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -172,10 +172,9 @@ static int drm_minor_register(struct drm_device *dev, enum drm_minor_type type) if (!minor) return 0; - if (minor->type == DRM_MINOR_ACCEL) { - accel_debugfs_init(minor, minor->index); - } else { - ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root); + if (minor->type != DRM_MINOR_ACCEL) { + ret = drm_debugfs_register(minor, minor->index, + drm_debugfs_root); if (ret) { DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n"); goto err_debugfs; @@ -199,7 +198,7 @@ static int drm_minor_register(struct drm_device *dev, enum drm_minor_type type) return 0; err_debugfs: - drm_debugfs_cleanup(minor); + drm_debugfs_unregister(minor); return ret; } @@ -223,7 +222,7 @@ static void drm_minor_unregister(struct drm_device *dev, enum drm_minor_type typ device_del(minor->kdev); dev_set_drvdata(minor->kdev, NULL); /* safety belt */ - drm_debugfs_cleanup(minor); + drm_debugfs_unregister(minor); } /* @@ -598,7 +597,6 @@ static void drm_dev_init_release(struct drm_device *dev, void *res) mutex_destroy(&dev->clientlist_mutex); mutex_destroy(&dev->filelist_mutex); mutex_destroy(&dev->struct_mutex); - mutex_destroy(&dev->debugfs_mutex); drm_legacy_destroy_members(dev); } @@ -639,14 +637,12 @@ static int drm_dev_init(struct drm_device *dev, INIT_LIST_HEAD(&dev->filelist_internal); INIT_LIST_HEAD(&dev->clientlist); INIT_LIST_HEAD(&dev->vblank_event_list); - INIT_LIST_HEAD(&dev->debugfs_list); spin_lock_init(&dev->event_lock); mutex_init(&dev->struct_mutex); mutex_init(&dev->filelist_mutex); mutex_init(&dev->clientlist_mutex); mutex_init(&dev->master_mutex); - mutex_init(&dev->debugfs_mutex); ret = drmm_add_action_or_reset(dev, drm_dev_init_release, NULL); if (ret) @@ -697,6 +693,11 @@ static int drm_dev_init(struct drm_device *dev, goto err; } + if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL)) + accel_debugfs_init(dev); + else + drm_debugfs_dev_init(dev, drm_debugfs_root); + return 0; err: @@ -786,6 +787,9 @@ static void drm_dev_release(struct kref *ref) { struct drm_device *dev = container_of(ref, struct drm_device, ref); + /* Just in case register/unregister was never called */ + drm_debugfs_dev_fini(dev); + if (dev->driver->release) dev->driver->release(dev); @@ -916,6 +920,11 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (drm_dev_needs_global_mutex(dev)) mutex_lock(&drm_global_mutex); + if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL)) + accel_debugfs_register(dev); + else + drm_debugfs_dev_register(dev); + ret = drm_minor_register(dev, DRM_MINOR_RENDER); if (ret) goto err_minors; @@ -1001,6 +1010,7 @@ void drm_dev_unregister(struct drm_device *dev) drm_minor_unregister(dev, DRM_MINOR_ACCEL); drm_minor_unregister(dev, DRM_MINOR_PRIMARY); drm_minor_unregister(dev, DRM_MINOR_RENDER); + drm_debugfs_dev_fini(dev); } EXPORT_SYMBOL(drm_dev_unregister); diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index aff3746dedfb..ba51deb6d042 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -1222,9 +1222,9 @@ static const struct drm_debugfs_info drm_framebuffer_debugfs_list[] = { { "framebuffer", drm_framebuffer_info, 0 }, }; -void drm_framebuffer_debugfs_init(struct drm_minor *minor) +void drm_framebuffer_debugfs_init(struct drm_device *dev) { - drm_debugfs_add_files(minor->dev, drm_framebuffer_debugfs_list, + drm_debugfs_add_files(dev, drm_framebuffer_debugfs_list, ARRAY_SIZE(drm_framebuffer_debugfs_list)); } #endif diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index ba12acd55139..ab9a472f4a47 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -180,27 +180,32 @@ void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map); /* drm_debugfs.c drm_debugfs_crc.c */ #if defined(CONFIG_DEBUG_FS) -int drm_debugfs_init(struct drm_minor *minor, int minor_id, - struct dentry *root); -void drm_debugfs_cleanup(struct drm_minor *minor); -void drm_debugfs_late_register(struct drm_device *dev); +void drm_debugfs_dev_fini(struct drm_device *dev); +void drm_debugfs_dev_register(struct drm_device *dev); +int drm_debugfs_register(struct drm_minor *minor, int minor_id, + struct dentry *root); +void drm_debugfs_unregister(struct drm_minor *minor); void drm_debugfs_connector_add(struct drm_connector *connector); void drm_debugfs_connector_remove(struct drm_connector *connector); void drm_debugfs_crtc_add(struct drm_crtc *crtc); void drm_debugfs_crtc_remove(struct drm_crtc *crtc); void drm_debugfs_crtc_crc_add(struct drm_crtc *crtc); #else -static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, - struct dentry *root) +static inline void drm_debugfs_dev_fini(struct drm_device *dev) +{ +} + +static inline void drm_debugfs_dev_register(struct drm_device *dev) +{ +} + +static inline int drm_debugfs_register(struct drm_minor *minor, int minor_id, + struct dentry *root) { return 0; } -static inline void drm_debugfs_cleanup(struct drm_minor *minor) -{ -} - -static inline void drm_debugfs_late_register(struct drm_device *dev) +static inline void drm_debugfs_unregister(struct drm_minor *minor) { } @@ -259,4 +264,4 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, /* drm_framebuffer.c */ void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent, const struct drm_framebuffer *fb); -void drm_framebuffer_debugfs_init(struct drm_minor *minor); +void drm_framebuffer_debugfs_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 87eb591fe9b5..8525ef851540 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -54,8 +54,6 @@ int drm_modeset_register_all(struct drm_device *dev) if (ret) goto err_connector; - drm_debugfs_late_register(dev); - return 0; err_connector: diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h index c8b611a2f6c6..1188a8d61caf 100644 --- a/drivers/gpu/drm/gma500/gma_display.h +++ b/drivers/gpu/drm/gma500/gma_display.h @@ -81,7 +81,6 @@ extern void gma_encoder_destroy(struct drm_encoder *encoder); /* Common clock related functions */ extern const struct gma_limit_t *gma_limit(struct drm_crtc *crtc, int refclk); -extern void gma_clock(int refclk, struct gma_clock_t *clock); extern bool gma_pll_is_valid(struct drm_crtc *crtc, const struct gma_limit_t *limit, struct gma_clock_t *clock); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index f7f709df99b4..c5edfa4aa4cc 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -161,14 +161,6 @@ #define PSB_NUM_VBLANKS 2 - -#define PSB_2D_SIZE (256*1024*1024) -#define PSB_MAX_RELOC_PAGES 1024 - -#define PSB_LOW_REG_OFFS 0x0204 -#define PSB_HIGH_REG_OFFS 0x0600 - -#define PSB_NUM_VBLANKS 2 #define PSB_WATCHDOG_DELAY (HZ * 2) #define PSB_LID_DELAY (HZ / 10) @@ -424,6 +416,7 @@ struct drm_psb_private { uint32_t pipestat[PSB_NUM_PIPE]; spinlock_t irqmask_lock; + bool irq_enabled; /* Power */ bool pm_initialized; diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 0bb85494e3da..c111e933e1ed 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -186,19 +186,13 @@ extern bool psb_intel_ddc_probe(struct i2c_adapter *adapter); extern void psb_intel_crtc_init(struct drm_device *dev, int pipe, struct psb_intel_mode_device *mode_dev); -extern void psb_intel_crt_init(struct drm_device *dev); extern bool psb_intel_sdvo_init(struct drm_device *dev, int output_device); -extern void psb_intel_dvo_init(struct drm_device *dev); -extern void psb_intel_tv_init(struct drm_device *dev); extern void psb_intel_lvds_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level); extern void oaktrail_lvds_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); -extern void oaktrail_wait_for_INTR_PKT_SENT(struct drm_device *dev); struct gma_i2c_chan *oaktrail_lvds_i2c_init(struct drm_device *dev); -extern void mid_dsi_init(struct drm_device *dev, - struct psb_intel_mode_device *mode_dev, int dsi_num); extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector); extern void gma_connector_attach_encoder(struct gma_connector *connector, @@ -214,11 +208,6 @@ extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, struct drm_crtc *crtc); extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); -extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, - int sdvoB); -extern int intelfb_probe(struct drm_device *dev); -extern int intelfb_remove(struct drm_device *dev, - struct drm_framebuffer *fb); extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); @@ -242,9 +231,6 @@ extern void cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); -extern void psb_intel_attach_force_audio_property(struct drm_connector *connector); -extern void psb_intel_attach_broadcast_rgb_property(struct drm_connector *connector); - extern int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val); extern int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val); extern void cdv_sb_reset(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 343c51250207..7bbb79b0497d 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -327,6 +327,8 @@ int gma_irq_install(struct drm_device *dev) gma_irq_postinstall(dev); + dev_priv->irq_enabled = true; + return 0; } @@ -337,6 +339,9 @@ void gma_irq_uninstall(struct drm_device *dev) unsigned long irqflags; unsigned int i; + if (!dev_priv->irq_enabled) + return; + spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); if (dev_priv->ops->hotplug_enable) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index e3f176a093d2..5f73cdabe7a1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -557,12 +557,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, struct intel_dp *intel_dp = &dig_port->dp; struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - struct drm_dp_mst_topology_state *old_mst_state = - drm_atomic_get_old_mst_topology_state(&state->base, &intel_dp->mst_mgr); struct drm_dp_mst_topology_state *new_mst_state = drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr); - const struct drm_dp_mst_atomic_payload *old_payload = - drm_atomic_get_mst_payload_state(old_mst_state, connector->port); struct drm_dp_mst_atomic_payload *new_payload = drm_atomic_get_mst_payload_state(new_mst_state, connector->port); struct drm_i915_private *i915 = to_i915(connector->base.dev); @@ -572,8 +568,7 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, intel_hdcp_disable(intel_mst->connector); - drm_dp_remove_payload(&intel_dp->mst_mgr, new_mst_state, - old_payload, new_payload); + drm_dp_remove_payload_part1(&intel_dp->mst_mgr, new_mst_state, new_payload); intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); } @@ -588,6 +583,14 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, struct intel_dp *intel_dp = &dig_port->dp; struct intel_connector *connector = to_intel_connector(old_conn_state->connector); + struct drm_dp_mst_topology_state *old_mst_state = + drm_atomic_get_old_mst_topology_state(&state->base, &intel_dp->mst_mgr); + struct drm_dp_mst_topology_state *new_mst_state = + drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr); + const struct drm_dp_mst_atomic_payload *old_payload = + drm_atomic_get_mst_payload_state(old_mst_state, connector->port); + struct drm_dp_mst_atomic_payload *new_payload = + drm_atomic_get_mst_payload_state(new_mst_state, connector->port); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); bool last_mst_stream; @@ -608,6 +611,9 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, wait_for_act_sent(encoder, old_crtc_state); + drm_dp_remove_payload_part2(&intel_dp->mst_mgr, new_mst_state, + old_payload, new_payload); + intel_ddi_disable_transcoder_func(old_crtc_state); if (DISPLAY_VER(dev_priv) >= 9) diff --git a/drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c b/drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c index a2277a0d6d06..0006ea52b83c 100644 --- a/drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c @@ -255,19 +255,17 @@ static int dw_hdmi_imx_probe(struct platform_device *pdev) return ret; } -static int dw_hdmi_imx_remove(struct platform_device *pdev) +static void dw_hdmi_imx_remove(struct platform_device *pdev) { struct imx_hdmi *hdmi = platform_get_drvdata(pdev); component_del(&pdev->dev, &dw_hdmi_imx_ops); dw_hdmi_remove(hdmi->hdmi); - - return 0; } static struct platform_driver dw_hdmi_imx_platform_driver = { .probe = dw_hdmi_imx_probe, - .remove = dw_hdmi_imx_remove, + .remove_new = dw_hdmi_imx_remove, .driver = { .name = "dwhdmi-imx", .of_match_table = dw_hdmi_imx_dt_ids, diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c index 4a866ac60fff..352fa31ab4ed 100644 --- a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c +++ b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c @@ -292,10 +292,9 @@ static int imx_drm_platform_probe(struct platform_device *pdev) return ret; } -static int imx_drm_platform_remove(struct platform_device *pdev) +static void imx_drm_platform_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &imx_drm_ops); - return 0; } #ifdef CONFIG_PM_SLEEP @@ -324,7 +323,7 @@ MODULE_DEVICE_TABLE(of, imx_drm_dt_ids); static struct platform_driver imx_drm_pdrv = { .probe = imx_drm_platform_probe, - .remove = imx_drm_platform_remove, + .remove_new = imx_drm_platform_remove, .driver = { .name = "imx-drm", .pm = &imx_drm_pm_ops, diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c index c45fc8f4744d..989eca32d325 100644 --- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c +++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c @@ -737,7 +737,7 @@ free_child: return ret; } -static int imx_ldb_remove(struct platform_device *pdev) +static void imx_ldb_remove(struct platform_device *pdev) { struct imx_ldb *imx_ldb = platform_get_drvdata(pdev); int i; @@ -750,12 +750,11 @@ static int imx_ldb_remove(struct platform_device *pdev) } component_del(&pdev->dev, &imx_ldb_ops); - return 0; } static struct platform_driver imx_ldb_driver = { .probe = imx_ldb_probe, - .remove = imx_ldb_remove, + .remove_new = imx_ldb_remove, .driver = { .of_match_table = imx_ldb_dt_ids, .name = DRIVER_NAME, diff --git a/drivers/gpu/drm/imx/ipuv3/imx-tve.c b/drivers/gpu/drm/imx/ipuv3/imx-tve.c index d6832f506322..b49bddb85535 100644 --- a/drivers/gpu/drm/imx/ipuv3/imx-tve.c +++ b/drivers/gpu/drm/imx/ipuv3/imx-tve.c @@ -645,10 +645,9 @@ static int imx_tve_probe(struct platform_device *pdev) return component_add(dev, &imx_tve_ops); } -static int imx_tve_remove(struct platform_device *pdev) +static void imx_tve_remove(struct platform_device *pdev) { component_del(&pdev->dev, &imx_tve_ops); - return 0; } static const struct of_device_id imx_tve_dt_ids[] = { @@ -659,7 +658,7 @@ MODULE_DEVICE_TABLE(of, imx_tve_dt_ids); static struct platform_driver imx_tve_driver = { .probe = imx_tve_probe, - .remove = imx_tve_remove, + .remove_new = imx_tve_remove, .driver = { .of_match_table = imx_tve_dt_ids, .name = "imx-tve", diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c index 89585b31b985..ef29c9a61a46 100644 --- a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c @@ -441,10 +441,9 @@ static int ipu_drm_probe(struct platform_device *pdev) return component_add(dev, &ipu_crtc_ops); } -static int ipu_drm_remove(struct platform_device *pdev) +static void ipu_drm_remove(struct platform_device *pdev) { component_del(&pdev->dev, &ipu_crtc_ops); - return 0; } struct platform_driver ipu_drm_driver = { @@ -452,5 +451,5 @@ struct platform_driver ipu_drm_driver = { .name = "imx-ipuv3-crtc", }, .probe = ipu_drm_probe, - .remove = ipu_drm_remove, + .remove_new = ipu_drm_remove, }; diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c index 0fa0b590830b..70349739dd89 100644 --- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c +++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c @@ -353,11 +353,9 @@ static int imx_pd_probe(struct platform_device *pdev) return component_add(dev, &imx_pd_ops); } -static int imx_pd_remove(struct platform_device *pdev) +static void imx_pd_remove(struct platform_device *pdev) { component_del(&pdev->dev, &imx_pd_ops); - - return 0; } static const struct of_device_id imx_pd_dt_ids[] = { @@ -368,7 +366,7 @@ MODULE_DEVICE_TABLE(of, imx_pd_dt_ids); static struct platform_driver imx_pd_driver = { .probe = imx_pd_probe, - .remove = imx_pd_remove, + .remove_new = imx_pd_remove, .driver = { .of_match_table = imx_pd_dt_ids, .name = "imx-parallel-display", diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 8dbd4847d3a6..c2547d48d6aa 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -1449,7 +1449,7 @@ static int ingenic_drm_probe(struct platform_device *pdev) return component_master_add_with_match(dev, &ingenic_master_ops, match); } -static int ingenic_drm_remove(struct platform_device *pdev) +static void ingenic_drm_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1457,8 +1457,6 @@ static int ingenic_drm_remove(struct platform_device *pdev) ingenic_drm_unbind(dev); else component_master_del(dev, &ingenic_master_ops); - - return 0; } static int ingenic_drm_suspend(struct device *dev) @@ -1611,7 +1609,7 @@ static struct platform_driver ingenic_drm_driver = { .of_match_table = of_match_ptr(ingenic_drm_of_match), }, .probe = ingenic_drm_probe, - .remove = ingenic_drm_remove, + .remove_new = ingenic_drm_remove, }; static int ingenic_drm_init(void) diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index 6d236547f611..5bd9072352b5 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -922,10 +922,9 @@ static int ingenic_ipu_probe(struct platform_device *pdev) return component_add(&pdev->dev, &ingenic_ipu_ops); } -static int ingenic_ipu_remove(struct platform_device *pdev) +static void ingenic_ipu_remove(struct platform_device *pdev) { component_del(&pdev->dev, &ingenic_ipu_ops); - return 0; } static const u32 jz4725b_ipu_formats[] = { @@ -992,7 +991,7 @@ static struct platform_driver ingenic_ipu_driver = { .of_match_table = ingenic_ipu_of_match, }, .probe = ingenic_ipu_probe, - .remove = ingenic_ipu_remove, + .remove_new = ingenic_ipu_remove, }; struct platform_driver *ingenic_ipu_driver_ptr = &ingenic_ipu_driver; diff --git a/drivers/gpu/drm/loongson/lsdc_pixpll.c b/drivers/gpu/drm/loongson/lsdc_pixpll.c index 04c15b4697e2..2609a2256da4 100644 --- a/drivers/gpu/drm/loongson/lsdc_pixpll.c +++ b/drivers/gpu/drm/loongson/lsdc_pixpll.c @@ -120,12 +120,14 @@ static int lsdc_pixel_pll_setup(struct lsdc_pixpll * const this) struct lsdc_pixpll_parms *pparms; this->mmio = ioremap(this->reg_base, this->reg_size); - if (IS_ERR_OR_NULL(this->mmio)) + if (!this->mmio) return -ENOMEM; pparms = kzalloc(sizeof(*pparms), GFP_KERNEL); - if (IS_ERR_OR_NULL(pparms)) + if (!pparms) { + iounmap(this->mmio); return -ENOMEM; + } pparms->ref_clock = LSDC_PLL_REF_CLK_KHZ; diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 575e7c56219f..fa527935ffd4 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -751,10 +751,9 @@ static int adreno_probe(struct platform_device *pdev) return 0; } -static int adreno_remove(struct platform_device *pdev) +static void adreno_remove(struct platform_device *pdev) { component_del(&pdev->dev, &a3xx_ops); - return 0; } static void adreno_shutdown(struct platform_device *pdev) @@ -869,7 +868,7 @@ static const struct dev_pm_ops adreno_pm_ops = { static struct platform_driver adreno_driver = { .probe = adreno_probe, - .remove = adreno_remove, + .remove_new = adreno_remove, .shutdown = adreno_shutdown, .driver = { .name = "adreno", diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index aa6ba2cf4b84..82381d12414d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1302,11 +1302,9 @@ static int dpu_dev_probe(struct platform_device *pdev) return msm_drv_probe(&pdev->dev, dpu_kms_init); } -static int dpu_dev_remove(struct platform_device *pdev) +static void dpu_dev_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &msm_drm_ops); - - return 0; } static int __maybe_unused dpu_runtime_suspend(struct device *dev) @@ -1382,7 +1380,7 @@ MODULE_DEVICE_TABLE(of, dpu_dt_match); static struct platform_driver dpu_driver = { .probe = dpu_dev_probe, - .remove = dpu_dev_remove, + .remove_new = dpu_dev_remove, .shutdown = msm_drv_shutdown, .driver = { .name = "msm_dpu", diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index 700df4040e9a..e5012fa6771f 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -560,11 +560,9 @@ static int mdp4_probe(struct platform_device *pdev) return msm_drv_probe(&pdev->dev, mdp4_kms_init); } -static int mdp4_remove(struct platform_device *pdev) +static void mdp4_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &msm_drm_ops); - - return 0; } static const struct of_device_id mdp4_dt_match[] = { @@ -575,7 +573,7 @@ MODULE_DEVICE_TABLE(of, mdp4_dt_match); static struct platform_driver mdp4_platform_driver = { .probe = mdp4_probe, - .remove = mdp4_remove, + .remove_new = mdp4_remove, .shutdown = msm_drv_shutdown, .driver = { .name = "mdp4", diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index 92bf9d949d09..8a7b44376bc6 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -942,11 +942,10 @@ static int mdp5_dev_probe(struct platform_device *pdev) return msm_drv_probe(&pdev->dev, mdp5_kms_init); } -static int mdp5_dev_remove(struct platform_device *pdev) +static void mdp5_dev_remove(struct platform_device *pdev) { DBG(""); component_master_del(&pdev->dev, &msm_drm_ops); - return 0; } static __maybe_unused int mdp5_runtime_suspend(struct device *dev) @@ -987,7 +986,7 @@ MODULE_DEVICE_TABLE(of, mdp5_dt_match); static struct platform_driver mdp5_driver = { .probe = mdp5_dev_probe, - .remove = mdp5_dev_remove, + .remove_new = mdp5_dev_remove, .shutdown = msm_drv_shutdown, .driver = { .name = "msm_mdp", diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 76f13954015b..01784e9e7127 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1296,7 +1296,7 @@ static int dp_display_probe(struct platform_device *pdev) return rc; } -static int dp_display_remove(struct platform_device *pdev) +static void dp_display_remove(struct platform_device *pdev) { struct dp_display_private *dp = dev_get_dp_display_private(&pdev->dev); @@ -1304,8 +1304,6 @@ static int dp_display_remove(struct platform_device *pdev) dp_display_deinit_sub_modules(dp); platform_set_drvdata(pdev, NULL); - - return 0; } static int dp_pm_resume(struct device *dev) @@ -1415,7 +1413,7 @@ static const struct dev_pm_ops dp_pm_ops = { static struct platform_driver dp_display_driver = { .probe = dp_display_probe, - .remove = dp_display_remove, + .remove_new = dp_display_remove, .driver = { .name = "msm-dp-display", .of_match_table = dp_dt_match, diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index baab79ab6e74..7a8208cd6649 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -161,14 +161,12 @@ static int dsi_dev_probe(struct platform_device *pdev) return 0; } -static int dsi_dev_remove(struct platform_device *pdev) +static void dsi_dev_remove(struct platform_device *pdev) { struct msm_dsi *msm_dsi = platform_get_drvdata(pdev); DBG(""); dsi_destroy(msm_dsi); - - return 0; } static const struct of_device_id dt_match[] = { @@ -187,7 +185,7 @@ static const struct dev_pm_ops dsi_pm_ops = { static struct platform_driver dsi_driver = { .probe = dsi_dev_probe, - .remove = dsi_dev_remove, + .remove_new = dsi_dev_remove, .driver = { .name = "msm_dsi", .of_match_table = dt_match, diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 60509fb39710..b6bcb9f675fe 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -551,15 +551,13 @@ err_put_phy: return ret; } -static int msm_hdmi_dev_remove(struct platform_device *pdev) +static void msm_hdmi_dev_remove(struct platform_device *pdev) { struct hdmi *hdmi = dev_get_drvdata(&pdev->dev); component_del(&pdev->dev, &msm_hdmi_ops); msm_hdmi_put_phy(hdmi); - - return 0; } static const struct of_device_id msm_hdmi_dt_match[] = { @@ -574,7 +572,7 @@ static const struct of_device_id msm_hdmi_dt_match[] = { static struct platform_driver msm_hdmi_driver = { .probe = msm_hdmi_dev_probe, - .remove = msm_hdmi_dev_remove, + .remove_new = msm_hdmi_dev_remove, .driver = { .name = "hdmi_msm", .of_match_table = msm_hdmi_dt_match, diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c index 3e00fb8190b2..88a3423b7f24 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c @@ -177,11 +177,9 @@ static int msm_hdmi_phy_probe(struct platform_device *pdev) return 0; } -static int msm_hdmi_phy_remove(struct platform_device *pdev) +static void msm_hdmi_phy_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static const struct of_device_id msm_hdmi_phy_dt_match[] = { @@ -200,7 +198,7 @@ static const struct of_device_id msm_hdmi_phy_dt_match[] = { static struct platform_driver msm_hdmi_phy_platform_driver = { .probe = msm_hdmi_phy_probe, - .remove = msm_hdmi_phy_remove, + .remove_new = msm_hdmi_phy_remove, .driver = { .name = "msm_hdmi_phy", .of_match_table = msm_hdmi_phy_dt_match, diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 4bd028fa7500..a428951ee539 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1278,11 +1278,9 @@ static int msm_pdev_probe(struct platform_device *pdev) return msm_drv_probe(&pdev->dev, NULL); } -static int msm_pdev_remove(struct platform_device *pdev) +static void msm_pdev_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &msm_drm_ops); - - return 0; } void msm_drv_shutdown(struct platform_device *pdev) @@ -1303,7 +1301,7 @@ void msm_drv_shutdown(struct platform_device *pdev) static struct platform_driver msm_platform_driver = { .probe = msm_pdev_probe, - .remove = msm_pdev_remove, + .remove_new = msm_pdev_remove, .shutdown = msm_drv_shutdown, .driver = { .name = "msm", diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c index 2e87dd6cb17b..a429b704059e 100644 --- a/drivers/gpu/drm/msm/msm_mdss.c +++ b/drivers/gpu/drm/msm/msm_mdss.c @@ -497,15 +497,13 @@ static int mdss_probe(struct platform_device *pdev) return 0; } -static int mdss_remove(struct platform_device *pdev) +static void mdss_remove(struct platform_device *pdev) { struct msm_mdss *mdss = platform_get_drvdata(pdev); of_platform_depopulate(&pdev->dev); msm_mdss_destroy(mdss); - - return 0; } static const struct msm_mdss_data msm8998_data = { @@ -629,7 +627,7 @@ MODULE_DEVICE_TABLE(of, mdss_dt_match); static struct platform_driver mdss_platform_driver = { .probe = mdss_probe, - .remove = mdss_remove, + .remove_new = mdss_remove, .driver = { .name = "msm-mdss", .of_match_table = mdss_dt_match, diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 4e7c9c353c51..bba01fa0780c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -882,21 +882,26 @@ struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder) static void nv50_msto_cleanup(struct drm_atomic_state *state, - struct drm_dp_mst_topology_state *mst_state, + struct drm_dp_mst_topology_state *new_mst_state, struct drm_dp_mst_topology_mgr *mgr, struct nv50_msto *msto) { struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev); - struct drm_dp_mst_atomic_payload *payload = - drm_atomic_get_mst_payload_state(mst_state, msto->mstc->port); + struct drm_dp_mst_atomic_payload *new_payload = + drm_atomic_get_mst_payload_state(new_mst_state, msto->mstc->port); + struct drm_dp_mst_topology_state *old_mst_state = + drm_atomic_get_old_mst_topology_state(state, mgr); + const struct drm_dp_mst_atomic_payload *old_payload = + drm_atomic_get_mst_payload_state(old_mst_state, msto->mstc->port); NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name); if (msto->disabled) { msto->mstc = NULL; msto->disabled = false; + drm_dp_remove_payload_part2(mgr, new_mst_state, old_payload, new_payload); } else if (msto->enabled) { - drm_dp_add_payload_part2(mgr, state, payload); + drm_dp_add_payload_part2(mgr, state, new_payload); msto->enabled = false; } } @@ -910,19 +915,15 @@ nv50_msto_prepare(struct drm_atomic_state *state, struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev); struct nv50_mstc *mstc = msto->mstc; struct nv50_mstm *mstm = mstc->mstm; - struct drm_dp_mst_topology_state *old_mst_state; - struct drm_dp_mst_atomic_payload *payload, *old_payload; + struct drm_dp_mst_atomic_payload *payload; NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name); - old_mst_state = drm_atomic_get_old_mst_topology_state(state, mgr); - payload = drm_atomic_get_mst_payload_state(mst_state, mstc->port); - old_payload = drm_atomic_get_mst_payload_state(old_mst_state, mstc->port); // TODO: Figure out if we want to do a better job of handling VCPI allocation failures here? if (msto->disabled) { - drm_dp_remove_payload(mgr, mst_state, old_payload, payload); + drm_dp_remove_payload_part1(mgr, mst_state, payload); nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0); } else { diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 1fe17ff95f5e..3666a7403e47 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -189,21 +189,12 @@ u_free(void *addr) static inline void * u_memcpya(uint64_t user, unsigned int nmemb, unsigned int size) { - void *mem; - void __user *userptr = (void __force __user *)(uintptr_t)user; + void __user *userptr = u64_to_user_ptr(user); + size_t bytes; - size *= nmemb; - - mem = kvmalloc(size, GFP_KERNEL); - if (!mem) - return ERR_PTR(-ENOMEM); - - if (copy_from_user(mem, userptr, size)) { - u_free(mem); - return ERR_PTR(-EFAULT); - } - - return mem; + if (unlikely(check_mul_overflow(nmemb, size, &bytes))) + return NULL; + return vmemdup_user(userptr, bytes); } #include diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 869e535faefa..2d6d96ee3547 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -244,6 +244,17 @@ config DRM_PANEL_JDI_LT070ME05000 The panel has a 1200(RGB)×1920 (WUXGA) resolution and uses 24 bit per pixel. +config DRM_PANEL_JDI_LPM102A188A + tristate "JDI LPM102A188A DSI panel" + depends on OF && GPIOLIB + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for JDI LPM102A188A DSI + command mode panel as found in Google Pixel C devices. + The panel has a 2560×1800 resolution. It provides a MIPI DSI interface + to the host. + config DRM_PANEL_JDI_R63452 tristate "JDI R63452 Full HD DSI panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 433e93d57949..157c77ff157f 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_DRM_PANEL_INNOLUX_EJ030NA) += panel-innolux-ej030na.o obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o obj-$(CONFIG_DRM_PANEL_JADARD_JD9365DA_H3) += panel-jadard-jd9365da-h3.o obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o +obj-$(CONFIG_DRM_PANEL_JDI_LPM102A188A) += panel-jdi-lpm102a188a.o obj-$(CONFIG_DRM_PANEL_JDI_R63452) += panel-jdi-fhd-r63452.o obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o diff --git a/drivers/gpu/drm/panel/panel-jdi-lpm102a188a.c b/drivers/gpu/drm/panel/panel-jdi-lpm102a188a.c new file mode 100644 index 000000000000..5b5082efb282 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-jdi-lpm102a188a.c @@ -0,0 +1,551 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2014 Google, Inc. + * + * Copyright (C) 2022 Diogo Ivo + * + * Adapted from the downstream Pixel C driver written by Sean Paul + */ + +#include +#include +#include +#include +#include +#include + +#include