summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/ingenic/ingenic-drm-drv.c')
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm-drv.c112
1 files changed, 71 insertions, 41 deletions
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index ab0515d2c420..d3213fbf22be 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -14,25 +14,25 @@
#include <linux/media-bus-format.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/regmap.h>
+#include <drm/clients/drm_client_setup.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
#include <drm/drm_color_mgmt.h>
#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_encoder.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_dma.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -229,7 +229,7 @@ static int ingenic_drm_update_pixclk(struct notifier_block *nb,
}
static void ingenic_drm_bridge_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+ struct drm_atomic_state *state)
{
struct ingenic_drm *priv = drm_device_get_priv(bridge->dev);
@@ -247,8 +247,8 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc,
struct ingenic_drm_private_state *priv_state;
unsigned int next_id;
- priv_state = ingenic_drm_get_priv_state(priv, state);
- if (WARN_ON(IS_ERR(priv_state)))
+ priv_state = ingenic_drm_get_new_priv_state(priv, state);
+ if (WARN_ON(!priv_state))
return;
/* Set addresses of our DMA descriptor chains */
@@ -260,7 +260,7 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc,
}
static void ingenic_drm_bridge_atomic_disable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+ struct drm_atomic_state *state)
{
struct ingenic_drm *priv = drm_device_get_priv(bridge->dev);
unsigned int var;
@@ -340,6 +340,7 @@ static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc,
crtc);
struct ingenic_drm *priv = drm_crtc_get_priv(crtc);
struct drm_plane_state *f1_state, *f0_state, *ipu_state = NULL;
+ struct ingenic_drm_private_state *priv_state;
if (crtc_state->gamma_lut &&
drm_color_lut_size(crtc_state->gamma_lut) != ARRAY_SIZE(priv->dma_hwdescs->palette)) {
@@ -347,6 +348,11 @@ static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc,
return -EINVAL;
}
+ /* We will need the state in atomic_enable, so let's make sure it's part of the state */
+ priv_state = ingenic_drm_get_priv_state(priv, state);
+ if (IS_ERR(priv_state))
+ return PTR_ERR(priv_state);
+
if (drm_atomic_crtc_needs_modeset(crtc_state) && priv->soc_info->has_osd) {
f1_state = drm_atomic_get_plane_state(crtc_state->state,
&priv->f1);
@@ -471,8 +477,7 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane,
if (priv->soc_info->plane_f0_not_working && plane == &priv->f0)
return -EINVAL;
- crtc_state = drm_atomic_get_existing_crtc_state(state,
- crtc);
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
if (WARN_ON(!crtc_state))
return -EINVAL;
@@ -791,11 +796,12 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
}
static int ingenic_drm_bridge_attach(struct drm_bridge *bridge,
+ struct drm_encoder *encoder,
enum drm_bridge_attach_flags flags)
{
- struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder);
+ struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(encoder);
- return drm_bridge_attach(bridge->encoder, ib->next_bridge,
+ return drm_bridge_attach(encoder, ib->next_bridge,
&ib->bridge, flags);
}
@@ -900,14 +906,15 @@ static void ingenic_drm_disable_vblank(struct drm_crtc *crtc)
static struct drm_framebuffer *
ingenic_drm_gem_fb_create(struct drm_device *drm, struct drm_file *file,
+ const struct drm_format_info *info,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct ingenic_drm *priv = drm_device_get_priv(drm);
if (priv->soc_info->map_noncoherent)
- return drm_gem_fb_create_with_dirty(drm, file, mode_cmd);
+ return drm_gem_fb_create_with_dirty(drm, file, info, mode_cmd);
- return drm_gem_fb_create(drm, file, mode_cmd);
+ return drm_gem_fb_create(drm, file, info, mode_cmd);
}
static struct drm_gem_object *
@@ -953,7 +960,6 @@ static const struct drm_driver ingenic_drm_driver_data = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
.name = "ingenic-drm",
.desc = "DRM module for Ingenic SoCs",
- .date = "20200716",
.major = 1,
.minor = 1,
.patchlevel = 0,
@@ -961,6 +967,7 @@ static const struct drm_driver ingenic_drm_driver_data = {
.fops = &ingenic_drm_fops,
.gem_create_object = ingenic_drm_gem_create_object,
DRM_GEM_DMA_DRIVER_OPS,
+ DRM_FBDEV_DMA_DRIVER_OPS,
};
static const struct drm_plane_funcs ingenic_drm_primary_plane_funcs = {
@@ -1018,7 +1025,6 @@ static const struct drm_bridge_funcs ingenic_drm_bridge_funcs = {
static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
.fb_create = ingenic_drm_gem_fb_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
@@ -1132,7 +1138,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
ret = drmm_mode_config_init(drm);
if (ret)
- return ret;
+ goto err_drvdata;
drm->mode_config.min_width = 0;
drm->mode_config.min_height = 0;
@@ -1144,7 +1150,8 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(base)) {
dev_err(dev, "Failed to get memory resource\n");
- return PTR_ERR(base);
+ ret = PTR_ERR(base);
+ goto err_drvdata;
}
regmap_config = ingenic_drm_regmap_config;
@@ -1153,33 +1160,40 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
&regmap_config);
if (IS_ERR(priv->map)) {
dev_err(dev, "Failed to create regmap\n");
- return PTR_ERR(priv->map);
+ ret = PTR_ERR(priv->map);
+ goto err_drvdata;
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return irq;
+ if (irq < 0) {
+ ret = irq;
+ goto err_drvdata;
+ }
if (soc_info->needs_dev_clk) {
priv->lcd_clk = devm_clk_get(dev, "lcd");
if (IS_ERR(priv->lcd_clk)) {
dev_err(dev, "Failed to get lcd clock\n");
- return PTR_ERR(priv->lcd_clk);
+ ret = PTR_ERR(priv->lcd_clk);
+ goto err_drvdata;
}
}
priv->pix_clk = devm_clk_get(dev, "lcd_pclk");
if (IS_ERR(priv->pix_clk)) {
dev_err(dev, "Failed to get pixel clock\n");
- return PTR_ERR(priv->pix_clk);
+ ret = PTR_ERR(priv->pix_clk);
+ goto err_drvdata;
}
priv->dma_hwdescs = dmam_alloc_coherent(dev,
sizeof(*priv->dma_hwdescs),
&priv->dma_hwdescs_phys,
GFP_KERNEL);
- if (!priv->dma_hwdescs)
- return -ENOMEM;
+ if (!priv->dma_hwdescs) {
+ ret = -ENOMEM;
+ goto err_drvdata;
+ }
/* Configure DMA hwdesc for foreground0 plane */
ingenic_drm_configure_hwdesc_plane(priv, 0);
@@ -1201,7 +1215,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
if (ret) {
dev_err(dev, "Failed to register plane: %i\n", ret);
- return ret;
+ goto err_drvdata;
}
if (soc_info->map_noncoherent)
@@ -1213,7 +1227,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
NULL, &ingenic_drm_crtc_funcs, NULL);
if (ret) {
dev_err(dev, "Failed to init CRTC: %i\n", ret);
- return ret;
+ goto err_drvdata;
}
drm_crtc_enable_color_mgmt(&priv->crtc, 0, false,
@@ -1232,7 +1246,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
if (ret) {
dev_err(dev, "Failed to register overlay plane: %i\n",
ret);
- return ret;
+ goto err_drvdata;
}
if (soc_info->map_noncoherent)
@@ -1243,17 +1257,18 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to bind components: %i\n", ret);
- return ret;
+ goto err_drvdata;
}
ret = devm_add_action_or_reset(dev, ingenic_drm_unbind_all, priv);
if (ret)
- return ret;
+ goto err_drvdata;
priv->ipu_plane = drm_plane_from_index(drm, 2);
if (!priv->ipu_plane) {
dev_err(dev, "Failed to retrieve IPU plane\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_drvdata;
}
}
}
@@ -1265,7 +1280,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
break; /* we're done */
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get bridge handle\n");
- return ret;
+ goto err_drvdata;
}
if (panel)
@@ -1277,7 +1292,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
if (IS_ERR(ib)) {
ret = PTR_ERR(ib);
dev_err(dev, "Failed to init encoder: %d\n", ret);
- return ret;
+ goto err_drvdata;
}
encoder = &ib->encoder;
@@ -1292,13 +1307,14 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret) {
dev_err(dev, "Unable to attach bridge\n");
- return ret;
+ goto err_drvdata;
}
connector = drm_bridge_connector_init(drm, encoder);
if (IS_ERR(connector)) {
dev_err(dev, "Unable to init connector\n");
- return PTR_ERR(connector);
+ ret = PTR_ERR(connector);
+ goto err_drvdata;
}
drm_connector_attach_encoder(connector, encoder);
@@ -1315,13 +1331,13 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
ret = devm_request_irq(dev, irq, ingenic_drm_irq_handler, 0, drm->driver->name, drm);
if (ret) {
dev_err(dev, "Unable to install IRQ handler\n");
- return ret;
+ goto err_drvdata;
}
ret = drm_vblank_init(drm, 1);
if (ret) {
dev_err(dev, "Failed calling drm_vblank_init()\n");
- return ret;
+ goto err_drvdata;
}
drm_mode_config_reset(drm);
@@ -1329,7 +1345,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
ret = clk_prepare_enable(priv->pix_clk);
if (ret) {
dev_err(dev, "Unable to start pixel clock\n");
- return ret;
+ goto err_drvdata;
}
if (priv->lcd_clk) {
@@ -1391,7 +1407,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components)
goto err_clk_notifier_unregister;
}
- drm_fbdev_generic_setup(drm, 32);
+ drm_client_setup(drm, NULL);
return 0;
@@ -1404,6 +1420,8 @@ err_devclk_disable:
clk_disable_unprepare(priv->lcd_clk);
err_pixclk_disable:
clk_disable_unprepare(priv->pix_clk);
+err_drvdata:
+ platform_set_drvdata(pdev, NULL);
return ret;
}
@@ -1424,6 +1442,7 @@ static void ingenic_drm_unbind(struct device *dev)
drm_dev_unregister(&priv->drm);
drm_atomic_helper_shutdown(&priv->drm);
+ dev_set_drvdata(dev, NULL);
}
static const struct component_master_ops ingenic_master_ops = {
@@ -1451,7 +1470,7 @@ static int ingenic_drm_probe(struct platform_device *pdev)
return component_master_add_with_match(dev, &ingenic_master_ops, match);
}
-static int ingenic_drm_remove(struct platform_device *pdev)
+static void ingenic_drm_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1459,8 +1478,14 @@ static int ingenic_drm_remove(struct platform_device *pdev)
ingenic_drm_unbind(dev);
else
component_master_del(dev, &ingenic_master_ops);
+}
- return 0;
+static void ingenic_drm_shutdown(struct platform_device *pdev)
+{
+ struct ingenic_drm *priv = platform_get_drvdata(pdev);
+
+ if (priv)
+ drm_atomic_helper_shutdown(&priv->drm);
}
static int ingenic_drm_suspend(struct device *dev)
@@ -1614,6 +1639,7 @@ static struct platform_driver ingenic_drm_driver = {
},
.probe = ingenic_drm_probe,
.remove = ingenic_drm_remove,
+ .shutdown = ingenic_drm_shutdown,
};
static int ingenic_drm_init(void)
@@ -1629,7 +1655,11 @@ static int ingenic_drm_init(void)
return err;
}
- return platform_driver_register(&ingenic_drm_driver);
+ err = platform_driver_register(&ingenic_drm_driver);
+ if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && err)
+ platform_driver_unregister(ingenic_ipu_driver_ptr);
+
+ return err;
}
module_init(ingenic_drm_init);