root/drivers/gpu/drm/bochs/bochs_kms.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bochs_plane_update
  2. bochs_pipe_enable
  3. bochs_pipe_update
  4. bochs_pipe_prepare_fb
  5. bochs_pipe_cleanup_fb
  6. bochs_connector_get_modes
  7. bochs_connector_mode_valid
  8. bochs_connector_init
  9. bochs_gem_fb_create
  10. bochs_kms_init
  11. bochs_kms_fini

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  */
   4 
   5 #include <linux/moduleparam.h>
   6 
   7 #include <drm/drm_atomic_helper.h>
   8 #include <drm/drm_gem_framebuffer_helper.h>
   9 #include <drm/drm_probe_helper.h>
  10 #include <drm/drm_vblank.h>
  11 
  12 #include "bochs.h"
  13 
  14 static int defx = 1024;
  15 static int defy = 768;
  16 
  17 module_param(defx, int, 0444);
  18 module_param(defy, int, 0444);
  19 MODULE_PARM_DESC(defx, "default x resolution");
  20 MODULE_PARM_DESC(defy, "default y resolution");
  21 
  22 /* ---------------------------------------------------------------------- */
  23 
  24 static const uint32_t bochs_formats[] = {
  25         DRM_FORMAT_XRGB8888,
  26         DRM_FORMAT_BGRX8888,
  27 };
  28 
  29 static void bochs_plane_update(struct bochs_device *bochs,
  30                                struct drm_plane_state *state)
  31 {
  32         struct drm_gem_vram_object *gbo;
  33 
  34         if (!state->fb || !bochs->stride)
  35                 return;
  36 
  37         gbo = drm_gem_vram_of_gem(state->fb->obj[0]);
  38         bochs_hw_setbase(bochs,
  39                          state->crtc_x,
  40                          state->crtc_y,
  41                          state->fb->pitches[0],
  42                          state->fb->offsets[0] + gbo->bo.offset);
  43         bochs_hw_setformat(bochs, state->fb->format);
  44 }
  45 
  46 static void bochs_pipe_enable(struct drm_simple_display_pipe *pipe,
  47                               struct drm_crtc_state *crtc_state,
  48                               struct drm_plane_state *plane_state)
  49 {
  50         struct bochs_device *bochs = pipe->crtc.dev->dev_private;
  51 
  52         bochs_hw_setmode(bochs, &crtc_state->mode);
  53         bochs_plane_update(bochs, plane_state);
  54 }
  55 
  56 static void bochs_pipe_update(struct drm_simple_display_pipe *pipe,
  57                               struct drm_plane_state *old_state)
  58 {
  59         struct bochs_device *bochs = pipe->crtc.dev->dev_private;
  60         struct drm_crtc *crtc = &pipe->crtc;
  61 
  62         bochs_plane_update(bochs, pipe->plane.state);
  63 
  64         if (crtc->state->event) {
  65                 spin_lock_irq(&crtc->dev->event_lock);
  66                 drm_crtc_send_vblank_event(crtc, crtc->state->event);
  67                 crtc->state->event = NULL;
  68                 spin_unlock_irq(&crtc->dev->event_lock);
  69         }
  70 }
  71 
  72 static int bochs_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
  73                                  struct drm_plane_state *new_state)
  74 {
  75         struct drm_gem_vram_object *gbo;
  76 
  77         if (!new_state->fb)
  78                 return 0;
  79         gbo = drm_gem_vram_of_gem(new_state->fb->obj[0]);
  80         return drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
  81 }
  82 
  83 static void bochs_pipe_cleanup_fb(struct drm_simple_display_pipe *pipe,
  84                                   struct drm_plane_state *old_state)
  85 {
  86         struct drm_gem_vram_object *gbo;
  87 
  88         if (!old_state->fb)
  89                 return;
  90         gbo = drm_gem_vram_of_gem(old_state->fb->obj[0]);
  91         drm_gem_vram_unpin(gbo);
  92 }
  93 
  94 static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = {
  95         .enable     = bochs_pipe_enable,
  96         .update     = bochs_pipe_update,
  97         .prepare_fb = bochs_pipe_prepare_fb,
  98         .cleanup_fb = bochs_pipe_cleanup_fb,
  99 };
 100 
 101 static int bochs_connector_get_modes(struct drm_connector *connector)
 102 {
 103         struct bochs_device *bochs =
 104                 container_of(connector, struct bochs_device, connector);
 105         int count = 0;
 106 
 107         if (bochs->edid)
 108                 count = drm_add_edid_modes(connector, bochs->edid);
 109 
 110         if (!count) {
 111                 count = drm_add_modes_noedid(connector, 8192, 8192);
 112                 drm_set_preferred_mode(connector, defx, defy);
 113         }
 114         return count;
 115 }
 116 
 117 static enum drm_mode_status bochs_connector_mode_valid(struct drm_connector *connector,
 118                                       struct drm_display_mode *mode)
 119 {
 120         struct bochs_device *bochs =
 121                 container_of(connector, struct bochs_device, connector);
 122         unsigned long size = mode->hdisplay * mode->vdisplay * 4;
 123 
 124         /*
 125          * Make sure we can fit two framebuffers into video memory.
 126          * This allows up to 1600x1200 with 16 MB (default size).
 127          * If you want more try this:
 128          *     'qemu -vga std -global VGA.vgamem_mb=32 $otherargs'
 129          */
 130         if (size * 2 > bochs->fb_size)
 131                 return MODE_BAD;
 132 
 133         return MODE_OK;
 134 }
 135 
 136 static const struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
 137         .get_modes = bochs_connector_get_modes,
 138         .mode_valid = bochs_connector_mode_valid,
 139 };
 140 
 141 static const struct drm_connector_funcs bochs_connector_connector_funcs = {
 142         .dpms = drm_helper_connector_dpms,
 143         .fill_modes = drm_helper_probe_single_connector_modes,
 144         .destroy = drm_connector_cleanup,
 145         .reset = drm_atomic_helper_connector_reset,
 146         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 147         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 148 };
 149 
 150 static void bochs_connector_init(struct drm_device *dev)
 151 {
 152         struct bochs_device *bochs = dev->dev_private;
 153         struct drm_connector *connector = &bochs->connector;
 154 
 155         drm_connector_init(dev, connector, &bochs_connector_connector_funcs,
 156                            DRM_MODE_CONNECTOR_VIRTUAL);
 157         drm_connector_helper_add(connector,
 158                                  &bochs_connector_connector_helper_funcs);
 159         drm_connector_register(connector);
 160 
 161         bochs_hw_load_edid(bochs);
 162         if (bochs->edid) {
 163                 DRM_INFO("Found EDID data blob.\n");
 164                 drm_connector_attach_edid_property(connector);
 165                 drm_connector_update_edid_property(connector, bochs->edid);
 166         }
 167 }
 168 
 169 static struct drm_framebuffer *
 170 bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
 171                     const struct drm_mode_fb_cmd2 *mode_cmd)
 172 {
 173         if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
 174             mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
 175                 return ERR_PTR(-EINVAL);
 176 
 177         return drm_gem_fb_create(dev, file, mode_cmd);
 178 }
 179 
 180 const struct drm_mode_config_funcs bochs_mode_funcs = {
 181         .fb_create = bochs_gem_fb_create,
 182         .atomic_check = drm_atomic_helper_check,
 183         .atomic_commit = drm_atomic_helper_commit,
 184 };
 185 
 186 int bochs_kms_init(struct bochs_device *bochs)
 187 {
 188         drm_mode_config_init(bochs->dev);
 189 
 190         bochs->dev->mode_config.max_width = 8192;
 191         bochs->dev->mode_config.max_height = 8192;
 192 
 193         bochs->dev->mode_config.fb_base = bochs->fb_base;
 194         bochs->dev->mode_config.preferred_depth = 24;
 195         bochs->dev->mode_config.prefer_shadow = 0;
 196         bochs->dev->mode_config.prefer_shadow_fbdev = 1;
 197         bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
 198 
 199         bochs->dev->mode_config.funcs = &bochs_mode_funcs;
 200 
 201         bochs_connector_init(bochs->dev);
 202         drm_simple_display_pipe_init(bochs->dev,
 203                                      &bochs->pipe,
 204                                      &bochs_pipe_funcs,
 205                                      bochs_formats,
 206                                      ARRAY_SIZE(bochs_formats),
 207                                      NULL,
 208                                      &bochs->connector);
 209 
 210         drm_mode_config_reset(bochs->dev);
 211 
 212         return 0;
 213 }
 214 
 215 void bochs_kms_fini(struct bochs_device *bochs)
 216 {
 217         drm_atomic_helper_shutdown(bochs->dev);
 218         drm_mode_config_cleanup(bochs->dev);
 219 }

/* [<][>][^][v][top][bottom][index][help] */