diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index d3485f742acc2074487d402e3b257338e1e0037b..61b792f2248e9624965b36f9514e5e74163b35d6 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -66,7 +66,7 @@ static int __maybe_unused hibmc_pm_suspend(struct device *dev) return drm_mode_config_helper_suspend(drm_dev); } -static int __maybe_unused hibmc_pm_resume(struct device *dev) +static int __maybe_unused hibmc_pm_resume(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); @@ -229,6 +229,21 @@ static int hibmc_hw_map(struct hibmc_drm_private *priv) return 0; } +static void hibmc_hw_unmap(struct hibmc_drm_private *priv) +{ + struct drm_device *dev = priv->dev; + + if (priv->fb_map) { + devm_iounmap(dev->dev, priv->fb_map); + priv->fb_map = NULL; + } + + if (priv->mmio) { + devm_iounmap(dev->dev, priv->mmio); + priv->mmio = NULL; + } +} + static int hibmc_hw_init(struct hibmc_drm_private *priv) { int ret; @@ -254,6 +269,7 @@ static int hibmc_unload(struct drm_device *dev) pci_disable_msi(dev->pdev); hibmc_kms_fini(priv); hibmc_mm_fini(priv); + hibmc_hw_unmap(priv); dev->dev_private = NULL; return 0; } @@ -368,6 +384,13 @@ static void hibmc_pci_remove(struct pci_dev *pdev) drm_dev_unregister(dev); hibmc_unload(dev); + pci_disable_device(pdev); + drm_dev_put(dev); +} + +static void hibmc_pci_shutdown(struct pci_dev *pdev) +{ + hibmc_pci_remove(pdev); } static struct pci_device_id hibmc_pci_table[] = { @@ -380,7 +403,8 @@ static struct pci_driver hibmc_pci_driver = { .id_table = hibmc_pci_table, .probe = hibmc_pci_probe, .remove = hibmc_pci_remove, - .driver.pm = &hibmc_pm_ops, + .shutdown = hibmc_pci_shutdown, + .driver.pm = &hibmc_pm_ops, }; module_pci_driver(hibmc_pci_driver); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index 61edae1837b2e3185cd0a244846970adf4097eaf..fb761853289c9e03c18d5141beeb6f537346a0c3 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -18,6 +18,26 @@ #include "hibmc_drm_drv.h" #include "hibmc_drm_regs.h" +#define HIBMC_STANDARD_VREFRESH 60 + +struct hibmc_resolution { + int width; + int height; +}; + +static const struct hibmc_resolution hibmc_mode_tables[] = { + {800, 600}, + {1024, 768}, + {1152, 864}, + {1280, 768}, + {1280, 720}, + {1280, 960}, + {1280, 1024}, + {1600, 1200}, + {1920, 1080}, + {1920, 1200}, +}; + static int hibmc_connector_get_modes(struct drm_connector *connector) { int count; @@ -42,10 +62,30 @@ static int hibmc_connector_get_modes(struct drm_connector *connector) return count; } -static enum drm_mode_status hibmc_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) +static int hibmc_valid_mode(int width, int height) { - return MODE_OK; + int i; + + for (i = 0; i < ARRAY_SIZE(hibmc_mode_tables); i++) { + if ((hibmc_mode_tables[i].width == width) && + (hibmc_mode_tables[i].height == height)) { + return MODE_OK; + } + } + + return MODE_NOMODE; +} + +static enum drm_mode_status hibmc_connector_mode_valid( + struct drm_connector *connector, struct drm_display_mode *mode) +{ + int vrefresh = drm_mode_vrefresh(mode); + + if ((vrefresh < HIBMC_STANDARD_VREFRESH - 1) || + (vrefresh > HIBMC_STANDARD_VREFRESH + 1)) + return MODE_NOMODE; + + return hibmc_valid_mode(mode->hdisplay, mode->vdisplay); } static void hibmc_connector_destroy(struct drm_connector *connector)