1 // SPDX-License-Identifier: GPL-2.0-or-later
5 #include <linux/moduleparam.h>
7 #include <drm/drm_atomic_helper.h>
8 #include <drm/drm_gem_framebuffer_helper.h>
9 #include <drm/drm_probe_helper.h>
13 static int defx = 1024;
14 static int defy = 768;
16 module_param(defx, int, 0444);
17 module_param(defy, int, 0444);
18 MODULE_PARM_DESC(defx, "default x resolution");
19 MODULE_PARM_DESC(defy, "default y resolution");
21 /* ---------------------------------------------------------------------- */
23 static const uint32_t bochs_formats[] = {
28 static void bochs_plane_update(struct bochs_device *bochs,
29 struct drm_plane_state *state)
31 struct drm_gem_vram_object *gbo;
33 if (!state->fb || !bochs->stride)
36 gbo = drm_gem_vram_of_gem(state->fb->obj[0]);
37 bochs_hw_setbase(bochs,
40 state->fb->pitches[0],
41 state->fb->offsets[0] + gbo->bo.offset);
42 bochs_hw_setformat(bochs, state->fb->format);
45 static void bochs_pipe_enable(struct drm_simple_display_pipe *pipe,
46 struct drm_crtc_state *crtc_state,
47 struct drm_plane_state *plane_state)
49 struct bochs_device *bochs = pipe->crtc.dev->dev_private;
51 bochs_hw_setmode(bochs, &crtc_state->mode);
52 bochs_plane_update(bochs, plane_state);
55 static void bochs_pipe_update(struct drm_simple_display_pipe *pipe,
56 struct drm_plane_state *old_state)
58 struct bochs_device *bochs = pipe->crtc.dev->dev_private;
60 bochs_plane_update(bochs, pipe->plane.state);
63 static const struct drm_simple_display_pipe_funcs bochs_pipe_funcs = {
64 .enable = bochs_pipe_enable,
65 .update = bochs_pipe_update,
66 .prepare_fb = drm_gem_vram_simple_display_pipe_prepare_fb,
67 .cleanup_fb = drm_gem_vram_simple_display_pipe_cleanup_fb,
70 static int bochs_connector_get_modes(struct drm_connector *connector)
72 struct bochs_device *bochs =
73 container_of(connector, struct bochs_device, connector);
77 count = drm_add_edid_modes(connector, bochs->edid);
80 count = drm_add_modes_noedid(connector, 8192, 8192);
81 drm_set_preferred_mode(connector, defx, defy);
86 static const struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
87 .get_modes = bochs_connector_get_modes,
90 static const struct drm_connector_funcs bochs_connector_connector_funcs = {
91 .fill_modes = drm_helper_probe_single_connector_modes,
92 .destroy = drm_connector_cleanup,
93 .reset = drm_atomic_helper_connector_reset,
94 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
95 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
98 static void bochs_connector_init(struct drm_device *dev)
100 struct bochs_device *bochs = dev->dev_private;
101 struct drm_connector *connector = &bochs->connector;
103 drm_connector_init(dev, connector, &bochs_connector_connector_funcs,
104 DRM_MODE_CONNECTOR_VIRTUAL);
105 drm_connector_helper_add(connector,
106 &bochs_connector_connector_helper_funcs);
108 bochs_hw_load_edid(bochs);
110 DRM_INFO("Found EDID data blob.\n");
111 drm_connector_attach_edid_property(connector);
112 drm_connector_update_edid_property(connector, bochs->edid);
116 static struct drm_framebuffer *
117 bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
118 const struct drm_mode_fb_cmd2 *mode_cmd)
120 if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
121 mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
122 return ERR_PTR(-EINVAL);
124 return drm_gem_fb_create(dev, file, mode_cmd);
127 const struct drm_mode_config_funcs bochs_mode_funcs = {
128 .fb_create = bochs_gem_fb_create,
129 .mode_valid = drm_vram_helper_mode_valid,
130 .atomic_check = drm_atomic_helper_check,
131 .atomic_commit = drm_atomic_helper_commit,
134 int bochs_kms_init(struct bochs_device *bochs)
138 ret = drmm_mode_config_init(bochs->dev);
142 bochs->dev->mode_config.max_width = 8192;
143 bochs->dev->mode_config.max_height = 8192;
145 bochs->dev->mode_config.fb_base = bochs->fb_base;
146 bochs->dev->mode_config.preferred_depth = 24;
147 bochs->dev->mode_config.prefer_shadow = 0;
148 bochs->dev->mode_config.prefer_shadow_fbdev = 1;
149 bochs->dev->mode_config.fbdev_use_iomem = true;
150 bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
152 bochs->dev->mode_config.funcs = &bochs_mode_funcs;
154 bochs_connector_init(bochs->dev);
155 drm_simple_display_pipe_init(bochs->dev,
159 ARRAY_SIZE(bochs_formats),
163 drm_mode_config_reset(bochs->dev);