LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_simple_kms_helper.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 79 0.0 %
Date: 2022-04-01 14:17:54 Functions: 0 13 0.0 %
Branches: 0 50 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * Copyright (C) 2016 Noralf Trønnes
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <linux/module.h>
       7                 :            : #include <linux/slab.h>
       8                 :            : 
       9                 :            : #include <drm/drm_atomic.h>
      10                 :            : #include <drm/drm_atomic_helper.h>
      11                 :            : #include <drm/drm_bridge.h>
      12                 :            : #include <drm/drm_plane_helper.h>
      13                 :            : #include <drm/drm_probe_helper.h>
      14                 :            : #include <drm/drm_simple_kms_helper.h>
      15                 :            : 
      16                 :            : /**
      17                 :            :  * DOC: overview
      18                 :            :  *
      19                 :            :  * This helper library provides helpers for drivers for simple display
      20                 :            :  * hardware.
      21                 :            :  *
      22                 :            :  * drm_simple_display_pipe_init() initializes a simple display pipeline
      23                 :            :  * which has only one full-screen scanout buffer feeding one output. The
      24                 :            :  * pipeline is represented by &struct drm_simple_display_pipe and binds
      25                 :            :  * together &drm_plane, &drm_crtc and &drm_encoder structures into one fixed
      26                 :            :  * entity. Some flexibility for code reuse is provided through a separately
      27                 :            :  * allocated &drm_connector object and supporting optional &drm_bridge
      28                 :            :  * encoder drivers.
      29                 :            :  */
      30                 :            : 
      31                 :            : static const struct drm_encoder_funcs drm_simple_kms_encoder_funcs = {
      32                 :            :         .destroy = drm_encoder_cleanup,
      33                 :            : };
      34                 :            : 
      35                 :            : static enum drm_mode_status
      36                 :          0 : drm_simple_kms_crtc_mode_valid(struct drm_crtc *crtc,
      37                 :            :                                const struct drm_display_mode *mode)
      38                 :            : {
      39                 :          0 :         struct drm_simple_display_pipe *pipe;
      40                 :            : 
      41                 :          0 :         pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
      42   [ #  #  #  # ]:          0 :         if (!pipe->funcs || !pipe->funcs->mode_valid)
      43                 :            :                 /* Anything goes */
      44                 :            :                 return MODE_OK;
      45                 :            : 
      46                 :          0 :         return pipe->funcs->mode_valid(pipe, mode);
      47                 :            : }
      48                 :            : 
      49                 :          0 : static int drm_simple_kms_crtc_check(struct drm_crtc *crtc,
      50                 :            :                                      struct drm_crtc_state *state)
      51                 :            : {
      52                 :          0 :         bool has_primary = state->plane_mask &
      53         [ #  # ]:          0 :                            drm_plane_mask(crtc->primary);
      54                 :            : 
      55                 :            :         /* We always want to have an active plane with an active CRTC */
      56         [ #  # ]:          0 :         if (has_primary != state->enable)
      57                 :            :                 return -EINVAL;
      58                 :            : 
      59                 :          0 :         return drm_atomic_add_affected_planes(state->state, crtc);
      60                 :            : }
      61                 :            : 
      62                 :          0 : static void drm_simple_kms_crtc_enable(struct drm_crtc *crtc,
      63                 :            :                                        struct drm_crtc_state *old_state)
      64                 :            : {
      65                 :          0 :         struct drm_plane *plane;
      66                 :          0 :         struct drm_simple_display_pipe *pipe;
      67                 :            : 
      68                 :          0 :         pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
      69   [ #  #  #  # ]:          0 :         if (!pipe->funcs || !pipe->funcs->enable)
      70                 :            :                 return;
      71                 :            : 
      72                 :          0 :         plane = &pipe->plane;
      73                 :          0 :         pipe->funcs->enable(pipe, crtc->state, plane->state);
      74                 :            : }
      75                 :            : 
      76                 :          0 : static void drm_simple_kms_crtc_disable(struct drm_crtc *crtc,
      77                 :            :                                         struct drm_crtc_state *old_state)
      78                 :            : {
      79                 :          0 :         struct drm_simple_display_pipe *pipe;
      80                 :            : 
      81                 :          0 :         pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
      82   [ #  #  #  # ]:          0 :         if (!pipe->funcs || !pipe->funcs->disable)
      83                 :            :                 return;
      84                 :            : 
      85                 :          0 :         pipe->funcs->disable(pipe);
      86                 :            : }
      87                 :            : 
      88                 :            : static const struct drm_crtc_helper_funcs drm_simple_kms_crtc_helper_funcs = {
      89                 :            :         .mode_valid = drm_simple_kms_crtc_mode_valid,
      90                 :            :         .atomic_check = drm_simple_kms_crtc_check,
      91                 :            :         .atomic_enable = drm_simple_kms_crtc_enable,
      92                 :            :         .atomic_disable = drm_simple_kms_crtc_disable,
      93                 :            : };
      94                 :            : 
      95                 :          0 : static int drm_simple_kms_crtc_enable_vblank(struct drm_crtc *crtc)
      96                 :            : {
      97                 :          0 :         struct drm_simple_display_pipe *pipe;
      98                 :            : 
      99                 :          0 :         pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
     100   [ #  #  #  # ]:          0 :         if (!pipe->funcs || !pipe->funcs->enable_vblank)
     101                 :            :                 return 0;
     102                 :            : 
     103                 :          0 :         return pipe->funcs->enable_vblank(pipe);
     104                 :            : }
     105                 :            : 
     106                 :          0 : static void drm_simple_kms_crtc_disable_vblank(struct drm_crtc *crtc)
     107                 :            : {
     108                 :          0 :         struct drm_simple_display_pipe *pipe;
     109                 :            : 
     110                 :          0 :         pipe = container_of(crtc, struct drm_simple_display_pipe, crtc);
     111   [ #  #  #  # ]:          0 :         if (!pipe->funcs || !pipe->funcs->disable_vblank)
     112                 :            :                 return;
     113                 :            : 
     114                 :          0 :         pipe->funcs->disable_vblank(pipe);
     115                 :            : }
     116                 :            : 
     117                 :            : static const struct drm_crtc_funcs drm_simple_kms_crtc_funcs = {
     118                 :            :         .reset = drm_atomic_helper_crtc_reset,
     119                 :            :         .destroy = drm_crtc_cleanup,
     120                 :            :         .set_config = drm_atomic_helper_set_config,
     121                 :            :         .page_flip = drm_atomic_helper_page_flip,
     122                 :            :         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
     123                 :            :         .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
     124                 :            :         .enable_vblank = drm_simple_kms_crtc_enable_vblank,
     125                 :            :         .disable_vblank = drm_simple_kms_crtc_disable_vblank,
     126                 :            : };
     127                 :            : 
     128                 :          0 : static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
     129                 :            :                                         struct drm_plane_state *plane_state)
     130                 :            : {
     131                 :          0 :         struct drm_simple_display_pipe *pipe;
     132                 :          0 :         struct drm_crtc_state *crtc_state;
     133                 :          0 :         int ret;
     134                 :            : 
     135                 :          0 :         pipe = container_of(plane, struct drm_simple_display_pipe, plane);
     136                 :          0 :         crtc_state = drm_atomic_get_new_crtc_state(plane_state->state,
     137                 :            :                                                    &pipe->crtc);
     138                 :            : 
     139                 :          0 :         ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
     140                 :            :                                                   DRM_PLANE_HELPER_NO_SCALING,
     141                 :            :                                                   DRM_PLANE_HELPER_NO_SCALING,
     142                 :            :                                                   false, true);
     143         [ #  # ]:          0 :         if (ret)
     144                 :            :                 return ret;
     145                 :            : 
     146         [ #  # ]:          0 :         if (!plane_state->visible)
     147                 :            :                 return 0;
     148                 :            : 
     149   [ #  #  #  # ]:          0 :         if (!pipe->funcs || !pipe->funcs->check)
     150                 :            :                 return 0;
     151                 :            : 
     152                 :          0 :         return pipe->funcs->check(pipe, plane_state, crtc_state);
     153                 :            : }
     154                 :            : 
     155                 :          0 : static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane,
     156                 :            :                                         struct drm_plane_state *old_pstate)
     157                 :            : {
     158                 :          0 :         struct drm_simple_display_pipe *pipe;
     159                 :            : 
     160                 :          0 :         pipe = container_of(plane, struct drm_simple_display_pipe, plane);
     161   [ #  #  #  # ]:          0 :         if (!pipe->funcs || !pipe->funcs->update)
     162                 :            :                 return;
     163                 :            : 
     164                 :          0 :         pipe->funcs->update(pipe, old_pstate);
     165                 :            : }
     166                 :            : 
     167                 :          0 : static int drm_simple_kms_plane_prepare_fb(struct drm_plane *plane,
     168                 :            :                                            struct drm_plane_state *state)
     169                 :            : {
     170                 :          0 :         struct drm_simple_display_pipe *pipe;
     171                 :            : 
     172                 :          0 :         pipe = container_of(plane, struct drm_simple_display_pipe, plane);
     173   [ #  #  #  # ]:          0 :         if (!pipe->funcs || !pipe->funcs->prepare_fb)
     174                 :            :                 return 0;
     175                 :            : 
     176                 :          0 :         return pipe->funcs->prepare_fb(pipe, state);
     177                 :            : }
     178                 :            : 
     179                 :          0 : static void drm_simple_kms_plane_cleanup_fb(struct drm_plane *plane,
     180                 :            :                                             struct drm_plane_state *state)
     181                 :            : {
     182                 :          0 :         struct drm_simple_display_pipe *pipe;
     183                 :            : 
     184                 :          0 :         pipe = container_of(plane, struct drm_simple_display_pipe, plane);
     185   [ #  #  #  # ]:          0 :         if (!pipe->funcs || !pipe->funcs->cleanup_fb)
     186                 :            :                 return;
     187                 :            : 
     188                 :          0 :         pipe->funcs->cleanup_fb(pipe, state);
     189                 :            : }
     190                 :            : 
     191                 :          0 : static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
     192                 :            :                                                 uint32_t format,
     193                 :            :                                                 uint64_t modifier)
     194                 :            : {
     195                 :          0 :         return modifier == DRM_FORMAT_MOD_LINEAR;
     196                 :            : }
     197                 :            : 
     198                 :            : static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
     199                 :            :         .prepare_fb = drm_simple_kms_plane_prepare_fb,
     200                 :            :         .cleanup_fb = drm_simple_kms_plane_cleanup_fb,
     201                 :            :         .atomic_check = drm_simple_kms_plane_atomic_check,
     202                 :            :         .atomic_update = drm_simple_kms_plane_atomic_update,
     203                 :            : };
     204                 :            : 
     205                 :            : static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
     206                 :            :         .update_plane           = drm_atomic_helper_update_plane,
     207                 :            :         .disable_plane          = drm_atomic_helper_disable_plane,
     208                 :            :         .destroy                = drm_plane_cleanup,
     209                 :            :         .reset                  = drm_atomic_helper_plane_reset,
     210                 :            :         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
     211                 :            :         .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
     212                 :            :         .format_mod_supported   = drm_simple_kms_format_mod_supported,
     213                 :            : };
     214                 :            : 
     215                 :            : /**
     216                 :            :  * drm_simple_display_pipe_attach_bridge - Attach a bridge to the display pipe
     217                 :            :  * @pipe: simple display pipe object
     218                 :            :  * @bridge: bridge to attach
     219                 :            :  *
     220                 :            :  * Makes it possible to still use the drm_simple_display_pipe helpers when
     221                 :            :  * a DRM bridge has to be used.
     222                 :            :  *
     223                 :            :  * Note that you probably want to initialize the pipe by passing a NULL
     224                 :            :  * connector to drm_simple_display_pipe_init().
     225                 :            :  *
     226                 :            :  * Returns:
     227                 :            :  * Zero on success, negative error code on failure.
     228                 :            :  */
     229                 :          0 : int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
     230                 :            :                                           struct drm_bridge *bridge)
     231                 :            : {
     232                 :          0 :         return drm_bridge_attach(&pipe->encoder, bridge, NULL);
     233                 :            : }
     234                 :            : EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
     235                 :            : 
     236                 :            : /**
     237                 :            :  * drm_simple_display_pipe_init - Initialize a simple display pipeline
     238                 :            :  * @dev: DRM device
     239                 :            :  * @pipe: simple display pipe object to initialize
     240                 :            :  * @funcs: callbacks for the display pipe (optional)
     241                 :            :  * @formats: array of supported formats (DRM_FORMAT\_\*)
     242                 :            :  * @format_count: number of elements in @formats
     243                 :            :  * @format_modifiers: array of formats modifiers
     244                 :            :  * @connector: connector to attach and register (optional)
     245                 :            :  *
     246                 :            :  * Sets up a display pipeline which consist of a really simple
     247                 :            :  * plane-crtc-encoder pipe.
     248                 :            :  *
     249                 :            :  * If a connector is supplied, the pipe will be coupled with the provided
     250                 :            :  * connector. You may supply a NULL connector when using drm bridges, that
     251                 :            :  * handle connectors themselves (see drm_simple_display_pipe_attach_bridge()).
     252                 :            :  *
     253                 :            :  * Teardown of a simple display pipe is all handled automatically by the drm
     254                 :            :  * core through calling drm_mode_config_cleanup(). Drivers afterwards need to
     255                 :            :  * release the memory for the structure themselves.
     256                 :            :  *
     257                 :            :  * Returns:
     258                 :            :  * Zero on success, negative error code on failure.
     259                 :            :  */
     260                 :          0 : int drm_simple_display_pipe_init(struct drm_device *dev,
     261                 :            :                         struct drm_simple_display_pipe *pipe,
     262                 :            :                         const struct drm_simple_display_pipe_funcs *funcs,
     263                 :            :                         const uint32_t *formats, unsigned int format_count,
     264                 :            :                         const uint64_t *format_modifiers,
     265                 :            :                         struct drm_connector *connector)
     266                 :            : {
     267                 :          0 :         struct drm_encoder *encoder = &pipe->encoder;
     268                 :          0 :         struct drm_plane *plane = &pipe->plane;
     269                 :          0 :         struct drm_crtc *crtc = &pipe->crtc;
     270                 :          0 :         int ret;
     271                 :            : 
     272                 :          0 :         pipe->connector = connector;
     273                 :          0 :         pipe->funcs = funcs;
     274                 :            : 
     275                 :          0 :         drm_plane_helper_add(plane, &drm_simple_kms_plane_helper_funcs);
     276                 :          0 :         ret = drm_universal_plane_init(dev, plane, 0,
     277                 :            :                                        &drm_simple_kms_plane_funcs,
     278                 :            :                                        formats, format_count,
     279                 :            :                                        format_modifiers,
     280                 :            :                                        DRM_PLANE_TYPE_PRIMARY, NULL);
     281         [ #  # ]:          0 :         if (ret)
     282                 :            :                 return ret;
     283                 :            : 
     284                 :          0 :         drm_crtc_helper_add(crtc, &drm_simple_kms_crtc_helper_funcs);
     285                 :          0 :         ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
     286                 :            :                                         &drm_simple_kms_crtc_funcs, NULL);
     287         [ #  # ]:          0 :         if (ret)
     288                 :            :                 return ret;
     289                 :            : 
     290                 :          0 :         encoder->possible_crtcs = drm_crtc_mask(crtc);
     291                 :          0 :         ret = drm_encoder_init(dev, encoder, &drm_simple_kms_encoder_funcs,
     292                 :            :                                DRM_MODE_ENCODER_NONE, NULL);
     293         [ #  # ]:          0 :         if (ret || !connector)
     294                 :            :                 return ret;
     295                 :            : 
     296                 :          0 :         return drm_connector_attach_encoder(connector, encoder);
     297                 :            : }
     298                 :            : EXPORT_SYMBOL(drm_simple_display_pipe_init);
     299                 :            : 
     300                 :            : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14