1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/aperture.h> 4 #include <linux/ioport.h> 5 #include <linux/limits.h> 6 #include <linux/platform_device.h> 7 #include <linux/screen_info.h> 8 9 #include <drm/clients/drm_client_setup.h> 10 #include <drm/drm_atomic.h> 11 #include <drm/drm_atomic_state_helper.h> 12 #include <drm/drm_connector.h> 13 #include <drm/drm_damage_helper.h> 14 #include <drm/drm_device.h> 15 #include <drm/drm_drv.h> 16 #include <drm/drm_fbdev_shmem.h> 17 #include <drm/drm_framebuffer.h> 18 #include <drm/drm_gem_atomic_helper.h> 19 #include <drm/drm_gem_framebuffer_helper.h> 20 #include <drm/drm_gem_shmem_helper.h> 21 #include <drm/drm_managed.h> 22 #include <drm/drm_modeset_helper_vtables.h> 23 #include <drm/drm_probe_helper.h> 24 25 #include <video/pixel_format.h> 26 27 #include "drm_sysfb_helper.h" 28 29 #define DRIVER_NAME "vesadrm" 30 #define DRIVER_DESC "DRM driver for VESA platform devices" 31 #define DRIVER_MAJOR 1 32 #define DRIVER_MINOR 0 33 34 static int vesadrm_get_validated_int(struct drm_device *dev, const char *name, 35 u64 value, u32 max) 36 { 37 if (max > INT_MAX) 38 max = INT_MAX; 39 if (value > max) { 40 drm_err(dev, "%s of %llu exceeds maximum of %u\n", name, value, max); 41 return -EINVAL; 42 } 43 return value; 44 } 45 46 static int vesadrm_get_validated_int0(struct drm_device *dev, const char *name, 47 u64 value, u32 max) 48 { 49 if (!value) { 50 drm_err(dev, "%s of 0 not allowed\n", name); 51 return -EINVAL; 52 } 53 return vesadrm_get_validated_int(dev, name, value, max); 54 } 55 56 static s64 vesadrm_get_validated_size0(struct drm_device *dev, const char *name, 57 u64 value, u64 max) 58 { 59 if (!value) { 60 drm_err(dev, "vesadrm: %s of 0 not allowed\n", name); 61 return -EINVAL; 62 } else if (value > max) { 63 drm_err(dev, "vesadrm: %s of %llu exceeds maximum of %llu\n", name, value, max); 64 return -EINVAL; 65 } 66 return value; 67 } 68 69 static int vesadrm_get_width_si(struct drm_device *dev, const struct screen_info *si) 70 { 71 return vesadrm_get_validated_int0(dev, "width", si->lfb_width, U16_MAX); 72 } 73 74 static int vesadrm_get_height_si(struct drm_device *dev, const struct screen_info *si) 75 { 76 return vesadrm_get_validated_int0(dev, "height", si->lfb_height, U16_MAX); 77 } 78 79 static struct resource *vesadrm_get_memory_si(struct drm_device *dev, 80 const struct screen_info *si, 81 struct resource *res) 82 { 83 ssize_t num; 84 85 num = screen_info_resources(si, res, 1); 86 if (!num) { 87 drm_err(dev, "vesadrm: memory resource not found\n"); 88 return NULL; 89 } 90 91 return res; 92 } 93 94 static int vesadrm_get_stride_si(struct drm_device *dev, const struct screen_info *si, 95 const struct drm_format_info *format, 96 unsigned int width, unsigned int height, u64 size) 97 { 98 u64 lfb_linelength = si->lfb_linelength; 99 100 if (!lfb_linelength) 101 lfb_linelength = drm_format_info_min_pitch(format, 0, width); 102 103 return vesadrm_get_validated_int0(dev, "stride", lfb_linelength, div64_u64(size, height)); 104 } 105 106 static u64 vesadrm_get_visible_size_si(struct drm_device *dev, const struct screen_info *si, 107 unsigned int height, unsigned int stride, u64 size) 108 { 109 u64 vsize = PAGE_ALIGN(height * stride); 110 111 return vesadrm_get_validated_size0(dev, "visible size", vsize, size); 112 } 113 114 static const struct drm_format_info *vesadrm_get_format_si(struct drm_device *dev, 115 const struct screen_info *si) 116 { 117 static const struct { 118 struct pixel_format pixel; 119 u32 fourcc; 120 } vesa_formats[] = { 121 { PIXEL_FORMAT_XRGB1555, DRM_FORMAT_XRGB1555, }, 122 { PIXEL_FORMAT_RGB565, DRM_FORMAT_RGB565, }, 123 { PIXEL_FORMAT_RGB888, DRM_FORMAT_RGB888, }, 124 { PIXEL_FORMAT_XRGB8888, DRM_FORMAT_XRGB8888, }, 125 { PIXEL_FORMAT_XBGR8888, DRM_FORMAT_XBGR8888, }, 126 }; 127 const struct drm_format_info *format = NULL; 128 u32 bits_per_pixel; 129 size_t i; 130 131 bits_per_pixel = __screen_info_lfb_bits_per_pixel(si); 132 133 for (i = 0; i < ARRAY_SIZE(vesa_formats); ++i) { 134 const struct pixel_format *f = &vesa_formats[i].pixel; 135 136 if (bits_per_pixel == f->bits_per_pixel && 137 si->red_size == f->red.length && 138 si->red_pos == f->red.offset && 139 si->green_size == f->green.length && 140 si->green_pos == f->green.offset && 141 si->blue_size == f->blue.length && 142 si->blue_pos == f->blue.offset) { 143 format = drm_format_info(vesa_formats[i].fourcc); 144 break; 145 } 146 } 147 148 if (!format) 149 return ERR_PTR(-EINVAL); 150 if (format->is_color_indexed) 151 return ERR_PTR(-EINVAL); 152 153 return format; 154 } 155 156 /* 157 * VESA device 158 */ 159 160 struct vesadrm_device { 161 struct drm_sysfb_device sysfb; 162 163 /* modesetting */ 164 u32 formats[DRM_SYSFB_PLANE_NFORMATS(1)]; 165 struct drm_plane primary_plane; 166 struct drm_crtc crtc; 167 struct drm_encoder encoder; 168 struct drm_connector connector; 169 }; 170 171 /* 172 * Modesetting 173 */ 174 175 static const u64 vesadrm_primary_plane_format_modifiers[] = { 176 DRM_SYSFB_PLANE_FORMAT_MODIFIERS, 177 }; 178 179 static const struct drm_plane_helper_funcs vesadrm_primary_plane_helper_funcs = { 180 DRM_SYSFB_PLANE_HELPER_FUNCS, 181 }; 182 183 static const struct drm_plane_funcs vesadrm_primary_plane_funcs = { 184 DRM_SYSFB_PLANE_FUNCS, 185 .destroy = drm_plane_cleanup, 186 }; 187 188 static const struct drm_crtc_helper_funcs vesadrm_crtc_helper_funcs = { 189 DRM_SYSFB_CRTC_HELPER_FUNCS, 190 }; 191 192 static const struct drm_crtc_funcs vesadrm_crtc_funcs = { 193 DRM_SYSFB_CRTC_FUNCS, 194 .destroy = drm_crtc_cleanup, 195 }; 196 197 static const struct drm_encoder_funcs vesadrm_encoder_funcs = { 198 .destroy = drm_encoder_cleanup, 199 }; 200 201 static const struct drm_connector_helper_funcs vesadrm_connector_helper_funcs = { 202 DRM_SYSFB_CONNECTOR_HELPER_FUNCS, 203 }; 204 205 static const struct drm_connector_funcs vesadrm_connector_funcs = { 206 DRM_SYSFB_CONNECTOR_FUNCS, 207 .destroy = drm_connector_cleanup, 208 }; 209 210 static const struct drm_mode_config_funcs vesadrm_mode_config_funcs = { 211 DRM_SYSFB_MODE_CONFIG_FUNCS, 212 }; 213 214 /* 215 * Init / Cleanup 216 */ 217 218 static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, 219 struct platform_device *pdev) 220 { 221 const struct screen_info *si; 222 const struct drm_format_info *format; 223 int width, height, stride; 224 u64 vsize; 225 struct resource resbuf; 226 struct resource *res; 227 struct vesadrm_device *vesa; 228 struct drm_sysfb_device *sysfb; 229 struct drm_device *dev; 230 struct resource *mem = NULL; 231 void __iomem *screen_base; 232 struct drm_plane *primary_plane; 233 struct drm_crtc *crtc; 234 struct drm_encoder *encoder; 235 struct drm_connector *connector; 236 unsigned long max_width, max_height; 237 size_t nformats; 238 int ret; 239 240 si = dev_get_platdata(&pdev->dev); 241 if (!si) 242 return ERR_PTR(-ENODEV); 243 if (screen_info_video_type(si) != VIDEO_TYPE_VLFB) 244 return ERR_PTR(-ENODEV); 245 246 /* 247 * VESA DRM driver 248 */ 249 250 vesa = devm_drm_dev_alloc(&pdev->dev, drv, struct vesadrm_device, sysfb.dev); 251 if (IS_ERR(vesa)) 252 return ERR_CAST(vesa); 253 sysfb = &vesa->sysfb; 254 dev = &sysfb->dev; 255 platform_set_drvdata(pdev, dev); 256 257 /* 258 * Hardware settings 259 */ 260 261 format = vesadrm_get_format_si(dev, si); 262 if (IS_ERR(format)) 263 return ERR_CAST(format); 264 width = vesadrm_get_width_si(dev, si); 265 if (width < 0) 266 return ERR_PTR(width); 267 height = vesadrm_get_height_si(dev, si); 268 if (height < 0) 269 return ERR_PTR(height); 270 res = vesadrm_get_memory_si(dev, si, &resbuf); 271 if (!res) 272 return ERR_PTR(-EINVAL); 273 stride = vesadrm_get_stride_si(dev, si, format, width, height, resource_size(res)); 274 if (stride < 0) 275 return ERR_PTR(stride); 276 vsize = vesadrm_get_visible_size_si(dev, si, height, stride, resource_size(res)); 277 if (!vsize) 278 return ERR_PTR(-EINVAL); 279 280 drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d bytes\n", 281 &format->format, width, height, stride); 282 283 sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0); 284 sysfb->fb_format = format; 285 sysfb->fb_pitch = stride; 286 287 /* 288 * Memory management 289 */ 290 291 ret = devm_aperture_acquire_for_platform_device(pdev, res->start, vsize); 292 if (ret) { 293 drm_err(dev, "could not acquire memory range %pr: %d\n", res, ret); 294 return ERR_PTR(ret); 295 } 296 297 drm_dbg(dev, "using I/O memory framebuffer at %pr\n", res); 298 299 mem = devm_request_mem_region(&pdev->dev, res->start, vsize, drv->name); 300 if (!mem) { 301 /* 302 * We cannot make this fatal. Sometimes this comes from magic 303 * spaces our resource handlers simply don't know about. Use 304 * the I/O-memory resource as-is and try to map that instead. 305 */ 306 drm_warn(dev, "could not acquire memory region %pr\n", res); 307 mem = res; 308 } 309 310 screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem)); 311 if (!screen_base) 312 return ERR_PTR(-ENOMEM); 313 iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base); 314 315 /* 316 * Modesetting 317 */ 318 319 ret = drmm_mode_config_init(dev); 320 if (ret) 321 return ERR_PTR(ret); 322 323 max_width = max_t(unsigned long, width, DRM_SHADOW_PLANE_MAX_WIDTH); 324 max_height = max_t(unsigned long, height, DRM_SHADOW_PLANE_MAX_HEIGHT); 325 326 dev->mode_config.min_width = width; 327 dev->mode_config.max_width = max_width; 328 dev->mode_config.min_height = height; 329 dev->mode_config.max_height = max_height; 330 dev->mode_config.preferred_depth = format->depth; 331 dev->mode_config.funcs = &vesadrm_mode_config_funcs; 332 333 /* Primary plane */ 334 335 nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, 336 vesa->formats, ARRAY_SIZE(vesa->formats)); 337 338 primary_plane = &vesa->primary_plane; 339 ret = drm_universal_plane_init(dev, primary_plane, 0, &vesadrm_primary_plane_funcs, 340 vesa->formats, nformats, 341 vesadrm_primary_plane_format_modifiers, 342 DRM_PLANE_TYPE_PRIMARY, NULL); 343 if (ret) 344 return ERR_PTR(ret); 345 drm_plane_helper_add(primary_plane, &vesadrm_primary_plane_helper_funcs); 346 drm_plane_enable_fb_damage_clips(primary_plane); 347 348 /* CRTC */ 349 350 crtc = &vesa->crtc; 351 ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, 352 &vesadrm_crtc_funcs, NULL); 353 if (ret) 354 return ERR_PTR(ret); 355 drm_crtc_helper_add(crtc, &vesadrm_crtc_helper_funcs); 356 357 /* Encoder */ 358 359 encoder = &vesa->encoder; 360 ret = drm_encoder_init(dev, encoder, &vesadrm_encoder_funcs, 361 DRM_MODE_ENCODER_NONE, NULL); 362 if (ret) 363 return ERR_PTR(ret); 364 encoder->possible_crtcs = drm_crtc_mask(crtc); 365 366 /* Connector */ 367 368 connector = &vesa->connector; 369 ret = drm_connector_init(dev, connector, &vesadrm_connector_funcs, 370 DRM_MODE_CONNECTOR_Unknown); 371 if (ret) 372 return ERR_PTR(ret); 373 drm_connector_helper_add(connector, &vesadrm_connector_helper_funcs); 374 drm_connector_set_panel_orientation_with_quirk(connector, 375 DRM_MODE_PANEL_ORIENTATION_UNKNOWN, 376 width, height); 377 378 ret = drm_connector_attach_encoder(connector, encoder); 379 if (ret) 380 return ERR_PTR(ret); 381 382 drm_mode_config_reset(dev); 383 384 return vesa; 385 } 386 387 /* 388 * DRM driver 389 */ 390 391 DEFINE_DRM_GEM_FOPS(vesadrm_fops); 392 393 static struct drm_driver vesadrm_driver = { 394 DRM_GEM_SHMEM_DRIVER_OPS, 395 DRM_FBDEV_SHMEM_DRIVER_OPS, 396 .name = DRIVER_NAME, 397 .desc = DRIVER_DESC, 398 .major = DRIVER_MAJOR, 399 .minor = DRIVER_MINOR, 400 .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET, 401 .fops = &vesadrm_fops, 402 }; 403 404 /* 405 * Platform driver 406 */ 407 408 static int vesadrm_probe(struct platform_device *pdev) 409 { 410 struct vesadrm_device *vesa; 411 struct drm_sysfb_device *sysfb; 412 struct drm_device *dev; 413 int ret; 414 415 vesa = vesadrm_device_create(&vesadrm_driver, pdev); 416 if (IS_ERR(vesa)) 417 return PTR_ERR(vesa); 418 sysfb = &vesa->sysfb; 419 dev = &sysfb->dev; 420 421 ret = drm_dev_register(dev, 0); 422 if (ret) 423 return ret; 424 425 drm_client_setup(dev, sysfb->fb_format); 426 427 return 0; 428 } 429 430 static void vesadrm_remove(struct platform_device *pdev) 431 { 432 struct drm_device *dev = platform_get_drvdata(pdev); 433 434 drm_dev_unplug(dev); 435 } 436 437 static struct platform_driver vesadrm_platform_driver = { 438 .driver = { 439 .name = "vesa-framebuffer", 440 }, 441 .probe = vesadrm_probe, 442 .remove = vesadrm_remove, 443 }; 444 445 module_platform_driver(vesadrm_platform_driver); 446 447 MODULE_DESCRIPTION(DRIVER_DESC); 448 MODULE_LICENSE("GPL"); 449