| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Geode LX framebuffer driver. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2007 Advanced Micro Devices, Inc. |
|---|
| 5 | 6 | * Built from gxfb (which is Copyright (C) 2006 Arcom Control Systems Ltd.) |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 8 | | - * under the terms of the GNU General Public License as published by the |
|---|
| 9 | | - * Free Software Foundation; either version 2 of the License, or (at your |
|---|
| 10 | | - * option) any later version. |
|---|
| 11 | 7 | */ |
|---|
| 12 | 8 | |
|---|
| 13 | 9 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 22 | 18 | #include <linux/init.h> |
|---|
| 23 | 19 | #include <linux/pci.h> |
|---|
| 24 | 20 | #include <linux/uaccess.h> |
|---|
| 21 | + |
|---|
| 22 | +#include <asm/olpc.h> |
|---|
| 25 | 23 | |
|---|
| 26 | 24 | #include "lxfb.h" |
|---|
| 27 | 25 | |
|---|
| .. | .. |
|---|
| 216 | 214 | 0, FB_VMODE_NONINTERLACED, 0 }, |
|---|
| 217 | 215 | }; |
|---|
| 218 | 216 | |
|---|
| 219 | | -#ifdef CONFIG_OLPC |
|---|
| 220 | | -#include <asm/olpc.h> |
|---|
| 221 | | - |
|---|
| 222 | 217 | static struct fb_videomode olpc_dcon_modedb[] = { |
|---|
| 223 | 218 | /* The only mode the DCON has is 1200x900 */ |
|---|
| 224 | 219 | { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3, |
|---|
| .. | .. |
|---|
| 237 | 232 | } |
|---|
| 238 | 233 | } |
|---|
| 239 | 234 | |
|---|
| 240 | | -#else |
|---|
| 241 | | -static void get_modedb(struct fb_videomode **modedb, unsigned int *size) |
|---|
| 242 | | -{ |
|---|
| 243 | | - *modedb = (struct fb_videomode *) geode_modedb; |
|---|
| 244 | | - *size = ARRAY_SIZE(geode_modedb); |
|---|
| 245 | | -} |
|---|
| 246 | | -#endif |
|---|
| 247 | | - |
|---|
| 248 | 235 | static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
|---|
| 249 | 236 | { |
|---|
| 237 | + if (!var->pixclock) |
|---|
| 238 | + return -EINVAL; |
|---|
| 239 | + |
|---|
| 250 | 240 | if (var->xres > 1920 || var->yres > 1440) |
|---|
| 251 | 241 | return -EINVAL; |
|---|
| 252 | 242 | |
|---|
| .. | .. |
|---|
| 399 | 389 | return 0; |
|---|
| 400 | 390 | } |
|---|
| 401 | 391 | |
|---|
| 402 | | -static struct fb_ops lxfb_ops = { |
|---|
| 392 | +static const struct fb_ops lxfb_ops = { |
|---|
| 403 | 393 | .owner = THIS_MODULE, |
|---|
| 404 | 394 | .fb_check_var = lxfb_check_var, |
|---|
| 405 | 395 | .fb_set_par = lxfb_set_par, |
|---|
| .. | .. |
|---|
| 456 | 446 | return info; |
|---|
| 457 | 447 | } |
|---|
| 458 | 448 | |
|---|
| 459 | | -#ifdef CONFIG_PM |
|---|
| 460 | | -static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state) |
|---|
| 449 | +static int __maybe_unused lxfb_suspend(struct device *dev) |
|---|
| 461 | 450 | { |
|---|
| 462 | | - struct fb_info *info = pci_get_drvdata(pdev); |
|---|
| 451 | + struct fb_info *info = dev_get_drvdata(dev); |
|---|
| 463 | 452 | |
|---|
| 464 | | - if (state.event == PM_EVENT_SUSPEND) { |
|---|
| 465 | | - console_lock(); |
|---|
| 466 | | - lx_powerdown(info); |
|---|
| 467 | | - fb_set_suspend(info, 1); |
|---|
| 468 | | - console_unlock(); |
|---|
| 469 | | - } |
|---|
| 453 | + console_lock(); |
|---|
| 454 | + lx_powerdown(info); |
|---|
| 455 | + fb_set_suspend(info, 1); |
|---|
| 456 | + console_unlock(); |
|---|
| 470 | 457 | |
|---|
| 471 | 458 | /* there's no point in setting PCI states; we emulate PCI, so |
|---|
| 472 | 459 | * we don't end up getting power savings anyways */ |
|---|
| .. | .. |
|---|
| 474 | 461 | return 0; |
|---|
| 475 | 462 | } |
|---|
| 476 | 463 | |
|---|
| 477 | | -static int lxfb_resume(struct pci_dev *pdev) |
|---|
| 464 | +static int __maybe_unused lxfb_resume(struct device *dev) |
|---|
| 478 | 465 | { |
|---|
| 479 | | - struct fb_info *info = pci_get_drvdata(pdev); |
|---|
| 466 | + struct fb_info *info = dev_get_drvdata(dev); |
|---|
| 480 | 467 | int ret; |
|---|
| 481 | 468 | |
|---|
| 482 | 469 | console_lock(); |
|---|
| .. | .. |
|---|
| 490 | 477 | console_unlock(); |
|---|
| 491 | 478 | return 0; |
|---|
| 492 | 479 | } |
|---|
| 493 | | -#else |
|---|
| 494 | | -#define lxfb_suspend NULL |
|---|
| 495 | | -#define lxfb_resume NULL |
|---|
| 496 | | -#endif |
|---|
| 497 | 480 | |
|---|
| 498 | 481 | static int lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
|---|
| 499 | 482 | { |
|---|
| .. | .. |
|---|
| 613 | 596 | |
|---|
| 614 | 597 | MODULE_DEVICE_TABLE(pci, lxfb_id_table); |
|---|
| 615 | 598 | |
|---|
| 599 | +static const struct dev_pm_ops lxfb_pm_ops = { |
|---|
| 600 | +#ifdef CONFIG_PM_SLEEP |
|---|
| 601 | + .suspend = lxfb_suspend, |
|---|
| 602 | + .resume = lxfb_resume, |
|---|
| 603 | + .freeze = NULL, |
|---|
| 604 | + .thaw = lxfb_resume, |
|---|
| 605 | + .poweroff = NULL, |
|---|
| 606 | + .restore = lxfb_resume, |
|---|
| 607 | +#endif |
|---|
| 608 | +}; |
|---|
| 609 | + |
|---|
| 616 | 610 | static struct pci_driver lxfb_driver = { |
|---|
| 617 | 611 | .name = "lxfb", |
|---|
| 618 | 612 | .id_table = lxfb_id_table, |
|---|
| 619 | 613 | .probe = lxfb_probe, |
|---|
| 620 | 614 | .remove = lxfb_remove, |
|---|
| 621 | | - .suspend = lxfb_suspend, |
|---|
| 622 | | - .resume = lxfb_resume, |
|---|
| 615 | + .driver.pm = &lxfb_pm_ops, |
|---|
| 623 | 616 | }; |
|---|
| 624 | 617 | |
|---|
| 625 | 618 | #ifndef MODULE |
|---|