summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c')
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c447
1 files changed, 277 insertions, 170 deletions
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 034a91112098..dd70894c8f38 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2014 Traphandler
* Copyright (C) 2014 Free Electrons
@@ -5,25 +6,28 @@
*
* Author: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
* Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
+#include <linux/mfd/atmel-hlcdc.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+
+#include <drm/clients/drm_client_setup.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_dma.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_dma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_module.h>
+#include <drm/drm_print.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
#include "atmel_hlcdc_dc.h"
@@ -57,6 +61,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9n12 = {
.conflicting_output_formats = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers),
.layers = atmel_hlcdc_at91sam9n12_layers,
+ .ops = &atmel_hlcdc_ops,
};
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = {
@@ -150,6 +155,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9x5 = {
.conflicting_output_formats = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers),
.layers = atmel_hlcdc_at91sam9x5_layers,
+ .ops = &atmel_hlcdc_ops,
};
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = {
@@ -268,6 +274,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d3 = {
.conflicting_output_formats = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers),
.layers = atmel_hlcdc_sama5d3_layers,
+ .ops = &atmel_hlcdc_ops,
};
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = {
@@ -363,7 +370,202 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d4 = {
.max_hpw = 0x3ff,
.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers),
.layers = atmel_hlcdc_sama5d4_layers,
+ .ops = &atmel_hlcdc_ops,
+};
+
+static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sam9x60_layers[] = {
+ {
+ .name = "base",
+ .formats = &atmel_hlcdc_plane_rgb_formats,
+ .regs_offset = 0x60,
+ .id = 0,
+ .type = ATMEL_HLCDC_BASE_LAYER,
+ .cfgs_offset = 0x2c,
+ .layout = {
+ .xstride = { 2 },
+ .default_color = 3,
+ .general_config = 4,
+ .disc_pos = 5,
+ .disc_size = 6,
+ },
+ .clut_offset = 0x600,
+ },
+ {
+ .name = "overlay1",
+ .formats = &atmel_hlcdc_plane_rgb_formats,
+ .regs_offset = 0x160,
+ .id = 1,
+ .type = ATMEL_HLCDC_OVERLAY_LAYER,
+ .cfgs_offset = 0x2c,
+ .layout = {
+ .pos = 2,
+ .size = 3,
+ .xstride = { 4 },
+ .pstride = { 5 },
+ .default_color = 6,
+ .chroma_key = 7,
+ .chroma_key_mask = 8,
+ .general_config = 9,
+ },
+ .clut_offset = 0xa00,
+ },
+ {
+ .name = "overlay2",
+ .formats = &atmel_hlcdc_plane_rgb_formats,
+ .regs_offset = 0x260,
+ .id = 2,
+ .type = ATMEL_HLCDC_OVERLAY_LAYER,
+ .cfgs_offset = 0x2c,
+ .layout = {
+ .pos = 2,
+ .size = 3,
+ .xstride = { 4 },
+ .pstride = { 5 },
+ .default_color = 6,
+ .chroma_key = 7,
+ .chroma_key_mask = 8,
+ .general_config = 9,
+ },
+ .clut_offset = 0xe00,
+ },
+ {
+ .name = "high-end-overlay",
+ .formats = &atmel_hlcdc_plane_rgb_and_yuv_formats,
+ .regs_offset = 0x360,
+ .id = 3,
+ .type = ATMEL_HLCDC_OVERLAY_LAYER,
+ .cfgs_offset = 0x4c,
+ .layout = {
+ .pos = 2,
+ .size = 3,
+ .memsize = 4,
+ .xstride = { 5, 7 },
+ .pstride = { 6, 8 },
+ .default_color = 9,
+ .chroma_key = 10,
+ .chroma_key_mask = 11,
+ .general_config = 12,
+ .scaler_config = 13,
+ .phicoeffs = {
+ .x = 17,
+ .y = 33,
+ },
+ .csc = 14,
+ },
+ .clut_offset = 0x1200,
+ },
+};
+
+static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sam9x60 = {
+ .min_width = 0,
+ .min_height = 0,
+ .max_width = 2048,
+ .max_height = 2048,
+ .max_spw = 0xff,
+ .max_vpw = 0xff,
+ .max_hpw = 0x3ff,
+ .fixed_clksrc = true,
+ .nlayers = ARRAY_SIZE(atmel_hlcdc_sam9x60_layers),
+ .layers = atmel_hlcdc_sam9x60_layers,
+ .ops = &atmel_hlcdc_ops,
+};
+
+static const struct atmel_hlcdc_layer_desc atmel_xlcdc_sam9x75_layers[] = {
+ {
+ .name = "base",
+ .formats = &atmel_hlcdc_plane_rgb_formats,
+ .regs_offset = 0x60,
+ .id = 0,
+ .type = ATMEL_HLCDC_BASE_LAYER,
+ .cfgs_offset = 0x1c,
+ .layout = {
+ .xstride = { 2 },
+ .default_color = 3,
+ .general_config = 4,
+ .disc_pos = 5,
+ .disc_size = 6,
+ },
+ .clut_offset = 0x700,
+ },
+ {
+ .name = "overlay1",
+ .formats = &atmel_hlcdc_plane_rgb_formats,
+ .regs_offset = 0x160,
+ .id = 1,
+ .type = ATMEL_HLCDC_OVERLAY_LAYER,
+ .cfgs_offset = 0x1c,
+ .layout = {
+ .pos = 2,
+ .size = 3,
+ .xstride = { 4 },
+ .pstride = { 5 },
+ .default_color = 6,
+ .chroma_key = 7,
+ .chroma_key_mask = 8,
+ .general_config = 9,
+ },
+ .clut_offset = 0xb00,
+ },
+ {
+ .name = "overlay2",
+ .formats = &atmel_hlcdc_plane_rgb_formats,
+ .regs_offset = 0x260,
+ .id = 2,
+ .type = ATMEL_HLCDC_OVERLAY_LAYER,
+ .cfgs_offset = 0x1c,
+ .layout = {
+ .pos = 2,
+ .size = 3,
+ .xstride = { 4 },
+ .pstride = { 5 },
+ .default_color = 6,
+ .chroma_key = 7,
+ .chroma_key_mask = 8,
+ .general_config = 9,
+ },
+ .clut_offset = 0xf00,
+ },
+ {
+ .name = "high-end-overlay",
+ .formats = &atmel_hlcdc_plane_rgb_and_yuv_formats,
+ .regs_offset = 0x360,
+ .id = 3,
+ .type = ATMEL_HLCDC_OVERLAY_LAYER,
+ .cfgs_offset = 0x30,
+ .layout = {
+ .pos = 2,
+ .size = 3,
+ .memsize = 4,
+ .xstride = { 5, 7 },
+ .pstride = { 6, 8 },
+ .default_color = 9,
+ .chroma_key = 10,
+ .chroma_key_mask = 11,
+ .general_config = 12,
+ .csc = 16,
+ .scaler_config = 23,
+ .vxs_config = 30,
+ .hxs_config = 31,
+ },
+ .clut_offset = 0x1300,
+ },
};
+
+static const struct atmel_hlcdc_dc_desc atmel_xlcdc_dc_sam9x75 = {
+ .min_width = 0,
+ .min_height = 0,
+ .max_width = 2048,
+ .max_height = 2048,
+ .max_spw = 0x3ff,
+ .max_vpw = 0x3ff,
+ .max_hpw = 0x3ff,
+ .fixed_clksrc = true,
+ .is_xlcdc = true,
+ .nlayers = ARRAY_SIZE(atmel_xlcdc_sam9x75_layers),
+ .layers = atmel_xlcdc_sam9x75_layers,
+ .ops = &atmel_xlcdc_ops,
+};
+
static const struct of_device_id atmel_hlcdc_of_match[] = {
{
.compatible = "atmel,at91sam9n12-hlcdc",
@@ -385,6 +587,14 @@ static const struct of_device_id atmel_hlcdc_of_match[] = {
.compatible = "atmel,sama5d4-hlcdc",
.data = &atmel_hlcdc_dc_sama5d4,
},
+ {
+ .compatible = "microchip,sam9x60-hlcdc",
+ .data = &atmel_hlcdc_dc_sam9x60,
+ },
+ {
+ .compatible = "microchip,sam9x75-xlcdc",
+ .data = &atmel_xlcdc_dc_sam9x75,
+ },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, atmel_hlcdc_of_match);
@@ -455,109 +665,55 @@ static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static struct drm_framebuffer *atmel_hlcdc_fb_create(struct drm_device *dev,
- struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd)
-{
- return drm_gem_fb_create(dev, file_priv, mode_cmd);
-}
-
-struct atmel_hlcdc_dc_commit {
- struct work_struct work;
- struct drm_device *dev;
- struct drm_atomic_state *state;
-};
-
-static void
-atmel_hlcdc_dc_atomic_complete(struct atmel_hlcdc_dc_commit *commit)
+static void atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev)
{
- struct drm_device *dev = commit->dev;
struct atmel_hlcdc_dc *dc = dev->dev_private;
- struct drm_atomic_state *old_state = commit->state;
-
- /* Apply the atomic update. */
- drm_atomic_helper_commit_modeset_disables(dev, old_state);
- drm_atomic_helper_commit_planes(dev, old_state, 0);
- drm_atomic_helper_commit_modeset_enables(dev, old_state);
-
- drm_atomic_helper_wait_for_vblanks(dev, old_state);
-
- drm_atomic_helper_cleanup_planes(dev, old_state);
-
- drm_atomic_state_put(old_state);
+ unsigned int cfg = 0;
+ int i;
- /* Complete the commit, wake up any waiter. */
- spin_lock(&dc->commit.wait.lock);
- dc->commit.pending = false;
- wake_up_all_locked(&dc->commit.wait);
- spin_unlock(&dc->commit.wait.lock);
+ /* Enable interrupts on activated layers */
+ for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
+ if (dc->layers[i])
+ cfg |= ATMEL_HLCDC_LAYER_STATUS(i);
+ }
- kfree(commit);
+ regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, cfg);
}
-static void atmel_hlcdc_dc_atomic_work(struct work_struct *work)
+static void atmel_hlcdc_dc_irq_disable(struct drm_device *dev)
{
- struct atmel_hlcdc_dc_commit *commit =
- container_of(work, struct atmel_hlcdc_dc_commit, work);
+ struct atmel_hlcdc_dc *dc = dev->dev_private;
+ unsigned int isr;
- atmel_hlcdc_dc_atomic_complete(commit);
+ regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IDR, 0xffffffff);
+ regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr);
}
-static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
- struct drm_atomic_state *state,
- bool async)
+static int atmel_hlcdc_dc_irq_install(struct drm_device *dev, unsigned int irq)
{
- struct atmel_hlcdc_dc *dc = dev->dev_private;
- struct atmel_hlcdc_dc_commit *commit;
int ret;
- ret = drm_atomic_helper_prepare_planes(dev, state);
- if (ret)
- return ret;
-
- /* Allocate the commit object. */
- commit = kzalloc(sizeof(*commit), GFP_KERNEL);
- if (!commit) {
- ret = -ENOMEM;
- goto error;
- }
-
- INIT_WORK(&commit->work, atmel_hlcdc_dc_atomic_work);
- commit->dev = dev;
- commit->state = state;
-
- spin_lock(&dc->commit.wait.lock);
- ret = wait_event_interruptible_locked(dc->commit.wait,
- !dc->commit.pending);
- if (ret == 0)
- dc->commit.pending = true;
- spin_unlock(&dc->commit.wait.lock);
+ atmel_hlcdc_dc_irq_disable(dev);
+ ret = devm_request_irq(dev->dev, irq, atmel_hlcdc_dc_irq_handler, 0,
+ dev->driver->name, dev);
if (ret)
- goto err_free;
-
- /* We have our own synchronization through the commit lock. */
- BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
+ return ret;
- /* Swap state succeeded, this is the point of no return. */
- drm_atomic_state_get(state);
- if (async)
- queue_work(dc->wq, &commit->work);
- else
- atmel_hlcdc_dc_atomic_complete(commit);
+ atmel_hlcdc_dc_irq_postinstall(dev);
return 0;
+}
-err_free:
- kfree(commit);
-error:
- drm_atomic_helper_cleanup_planes(dev, state);
- return ret;
+static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
+{
+ atmel_hlcdc_dc_irq_disable(dev);
}
static const struct drm_mode_config_funcs mode_config_funcs = {
- .fb_create = atmel_hlcdc_fb_create,
+ .fb_create = drm_gem_fb_create,
.atomic_check = drm_atomic_helper_check,
- .atomic_commit = atmel_hlcdc_dc_atomic_commit,
+ .atomic_commit = drm_atomic_helper_commit,
};
static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
@@ -569,19 +725,19 @@ static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
ret = atmel_hlcdc_create_outputs(dev);
if (ret) {
- dev_err(dev->dev, "failed to create HLCDC outputs: %d\n", ret);
+ drm_err(dev, "failed to create HLCDC outputs: %d\n", ret);
return ret;
}
ret = atmel_hlcdc_create_planes(dev);
if (ret) {
- dev_err(dev->dev, "failed to create planes: %d\n", ret);
+ drm_err(dev, "failed to create planes: %d\n", ret);
return ret;
}
ret = atmel_hlcdc_crtc_create(dev);
if (ret) {
- dev_err(dev->dev, "failed to create crtc\n");
+ drm_err(dev, "failed to create crtc\n");
return ret;
}
@@ -590,6 +746,7 @@ static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
dev->mode_config.max_width = dc->desc->max_width;
dev->mode_config.max_height = dc->desc->max_height;
dev->mode_config.funcs = &mode_config_funcs;
+ dev->mode_config.async_page_flip = true;
return 0;
}
@@ -616,42 +773,37 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
if (!dc)
return -ENOMEM;
- dc->wq = alloc_ordered_workqueue("atmel-hlcdc-dc", 0);
- if (!dc->wq)
- return -ENOMEM;
-
- init_waitqueue_head(&dc->commit.wait);
dc->desc = match->data;
dc->hlcdc = dev_get_drvdata(dev->dev->parent);
dev->dev_private = dc;
ret = clk_prepare_enable(dc->hlcdc->periph_clk);
if (ret) {
- dev_err(dev->dev, "failed to enable periph_clk\n");
- goto err_destroy_wq;
+ drm_err(dev, "failed to enable periph_clk\n");
+ return ret;
}
pm_runtime_enable(dev->dev);
ret = drm_vblank_init(dev, 1);
if (ret < 0) {
- dev_err(dev->dev, "failed to initialize vblank\n");
+ drm_err(dev, "failed to initialize vblank\n");
goto err_periph_clk_disable;
}
ret = atmel_hlcdc_dc_modeset_init(dev);
if (ret < 0) {
- dev_err(dev->dev, "failed to initialize mode setting\n");
+ drm_err(dev, "failed to initialize mode setting\n");
goto err_periph_clk_disable;
}
drm_mode_config_reset(dev);
pm_runtime_get_sync(dev->dev);
- ret = drm_irq_install(dev, dc->hlcdc->irq);
+ ret = atmel_hlcdc_dc_irq_install(dev, dc->hlcdc->irq);
pm_runtime_put_sync(dev->dev);
if (ret < 0) {
- dev_err(dev->dev, "failed to install IRQ handler\n");
+ drm_err(dev, "failed to install IRQ handler\n");
goto err_periph_clk_disable;
}
@@ -665,9 +817,6 @@ err_periph_clk_disable:
pm_runtime_disable(dev->dev);
clk_disable_unprepare(dc->hlcdc->periph_clk);
-err_destroy_wq:
- destroy_workqueue(dc->wq);
-
return ret;
}
@@ -675,74 +824,29 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
{
struct atmel_hlcdc_dc *dc = dev->dev_private;
- flush_workqueue(dc->wq);
drm_kms_helper_poll_fini(dev);
drm_atomic_helper_shutdown(dev);
drm_mode_config_cleanup(dev);
pm_runtime_get_sync(dev->dev);
- drm_irq_uninstall(dev);
+ atmel_hlcdc_dc_irq_uninstall(dev);
pm_runtime_put_sync(dev->dev);
dev->dev_private = NULL;
pm_runtime_disable(dev->dev);
clk_disable_unprepare(dc->hlcdc->periph_clk);
- destroy_workqueue(dc->wq);
}
-static int atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev)
-{
- struct atmel_hlcdc_dc *dc = dev->dev_private;
- unsigned int cfg = 0;
- int i;
+DEFINE_DRM_GEM_DMA_FOPS(fops);
- /* Enable interrupts on activated layers */
- for (i = 0; i < ATMEL_HLCDC_MAX_LAYERS; i++) {
- if (dc->layers[i])
- cfg |= ATMEL_HLCDC_LAYER_STATUS(i);
- }
-
- regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, cfg);
-
- return 0;
-}
-
-static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
-{
- struct atmel_hlcdc_dc *dc = dev->dev_private;
- unsigned int isr;
-
- regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IDR, 0xffffffff);
- regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr);
-}
-
-DEFINE_DRM_GEM_CMA_FOPS(fops);
-
-static struct drm_driver atmel_hlcdc_dc_driver = {
- .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM |
- DRIVER_MODESET | DRIVER_PRIME |
- DRIVER_ATOMIC,
- .irq_handler = atmel_hlcdc_dc_irq_handler,
- .irq_preinstall = atmel_hlcdc_dc_irq_uninstall,
- .irq_postinstall = atmel_hlcdc_dc_irq_postinstall,
- .irq_uninstall = atmel_hlcdc_dc_irq_uninstall,
- .gem_free_object_unlocked = drm_gem_cma_free_object,
- .gem_vm_ops = &drm_gem_cma_vm_ops,
- .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
- .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
- .gem_prime_import = drm_gem_prime_import,
- .gem_prime_export = drm_gem_prime_export,
- .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
- .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
- .gem_prime_vmap = drm_gem_cma_prime_vmap,
- .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
- .gem_prime_mmap = drm_gem_cma_prime_mmap,
- .dumb_create = drm_gem_cma_dumb_create,
+static const struct drm_driver atmel_hlcdc_dc_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+ DRM_GEM_DMA_DRIVER_OPS,
+ DRM_FBDEV_DMA_DRIVER_OPS,
.fops = &fops,
.name = "atmel-hlcdc",
.desc = "Atmel HLCD Controller DRM",
- .date = "20141504",
.major = 1,
.minor = 0,
};
@@ -764,7 +868,7 @@ static int atmel_hlcdc_dc_drm_probe(struct platform_device *pdev)
if (ret)
goto err_unload;
- drm_fbdev_generic_setup(ddev, 24);
+ drm_client_setup_with_fourcc(ddev, DRM_FORMAT_RGB888);
return 0;
@@ -777,18 +881,20 @@ err_put:
return ret;
}
-static int atmel_hlcdc_dc_drm_remove(struct platform_device *pdev)
+static void atmel_hlcdc_dc_drm_remove(struct platform_device *pdev)
{
struct drm_device *ddev = platform_get_drvdata(pdev);
drm_dev_unregister(ddev);
atmel_hlcdc_dc_unload(ddev);
drm_dev_put(ddev);
+}
- return 0;
+static void atmel_hlcdc_dc_drm_shutdown(struct platform_device *pdev)
+{
+ drm_atomic_helper_shutdown(platform_get_drvdata(pdev));
}
-#ifdef CONFIG_PM_SLEEP
static int atmel_hlcdc_dc_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
@@ -819,10 +925,10 @@ static int atmel_hlcdc_dc_drm_resume(struct device *dev)
return drm_atomic_helper_resume(drm_dev, dc->suspend.state);
}
-#endif
-static SIMPLE_DEV_PM_OPS(atmel_hlcdc_dc_drm_pm_ops,
- atmel_hlcdc_dc_drm_suspend, atmel_hlcdc_dc_drm_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(atmel_hlcdc_dc_drm_pm_ops,
+ atmel_hlcdc_dc_drm_suspend,
+ atmel_hlcdc_dc_drm_resume);
static const struct of_device_id atmel_hlcdc_dc_of_match[] = {
{ .compatible = "atmel,hlcdc-display-controller" },
@@ -831,14 +937,15 @@ static const struct of_device_id atmel_hlcdc_dc_of_match[] = {
static struct platform_driver atmel_hlcdc_dc_platform_driver = {
.probe = atmel_hlcdc_dc_drm_probe,
- .remove = atmel_hlcdc_dc_drm_remove,
+ .remove = atmel_hlcdc_dc_drm_remove,
+ .shutdown = atmel_hlcdc_dc_drm_shutdown,
.driver = {
.name = "atmel-hlcdc-display-controller",
- .pm = &atmel_hlcdc_dc_drm_pm_ops,
+ .pm = pm_sleep_ptr(&atmel_hlcdc_dc_drm_pm_ops),
.of_match_table = atmel_hlcdc_dc_of_match,
},
};
-module_platform_driver(atmel_hlcdc_dc_platform_driver);
+drm_module_platform_driver(atmel_hlcdc_dc_platform_driver);
MODULE_AUTHOR("Jean-Jacques Hiblot <jjhiblot@traphandler.com>");
MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");