summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/imx
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2020-07-23 08:21:32 +0300
committerDave Airlie <airlied@redhat.com>2020-07-23 08:21:45 +0300
commit5a394f19a2878e476d5f0ca64a3c874608c38dd3 (patch)
tree04cb94cc1e7e14d4b8844efe3ffcb42b8fc80980 /drivers/gpu/drm/imx
parentfa07634d9c6757fa859e228b6b1e23017d1d7279 (diff)
parent408a85e31e3e5127c91e082c3544082ef1ba48d3 (diff)
downloadlinux-5a394f19a2878e476d5f0ca64a3c874608c38dd3.tar.xz
Merge tag 'imx-drm-next-2020-07-20' of git://git.pengutronix.de/pza/linux into drm-next
drm/imx: error path fixes and cleanups - Fix use after free issue in component bind error path by keeping memory allocated as long as the driver is bound. This will be replaced with drm managed memory in the next round. - Fix bus_flags overriding logic in parallel-display. - Disable regulator in imx-tve bind error path. - Drop unnecessary best_encoder callback. - Remove an unused enum in imx-ldb. - Bail out early on missing panel or bridge in parallel-display to speed up -EPROBE_DEFER path. - Disable both LDB channels in split mode. - Restore RGB32, BGR32 format support. - Fix tiled image conversion in case of out of order interrupts. - Remove a superfluous error message in imx-tve. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Philipp Zabel <p.zabel@pengutronix.de> Link: https://patchwork.freedesktop.org/patch/msgid/ac4452eb3a989bf5d85b65fd30840a21f15ec301.camel@pengutronix.de
Diffstat (limited to 'drivers/gpu/drm/imx')
-rw-r--r--drivers/gpu/drm/imx/dw_hdmi-imx.c15
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c3
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c36
-rw-r--r--drivers/gpu/drm/imx/imx-tve.c48
-rw-r--r--drivers/gpu/drm/imx/ipuv3-crtc.c21
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c38
6 files changed, 74 insertions, 87 deletions
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index 2dc93fa6ecb6..71d84c7a5378 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -211,9 +211,8 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
if (!pdev->dev.of_node)
return -ENODEV;
- hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
- if (!hdmi)
- return -ENOMEM;
+ hdmi = dev_get_drvdata(dev);
+ memset(hdmi, 0, sizeof(*hdmi));
match = of_match_node(dw_hdmi_imx_dt_ids, pdev->dev.of_node);
plat_data = match->data;
@@ -237,8 +236,6 @@ static int dw_hdmi_imx_bind(struct device *dev, struct device *master,
drm_encoder_helper_add(encoder, &dw_hdmi_imx_encoder_helper_funcs);
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
- platform_set_drvdata(pdev, hdmi);
-
hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
/*
@@ -268,6 +265,14 @@ static const struct component_ops dw_hdmi_imx_ops = {
static int dw_hdmi_imx_probe(struct platform_device *pdev)
{
+ struct imx_hdmi *hdmi;
+
+ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, hdmi);
+
return component_add(&pdev->dev, &dw_hdmi_imx_ops);
}
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 36037b2e6564..7d00c49fd5a5 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -265,9 +265,10 @@ static void imx_drm_unbind(struct device *dev)
drm_kms_helper_poll_fini(drm);
+ component_unbind_all(drm->dev, drm);
+
drm_mode_config_cleanup(drm);
- component_unbind_all(drm->dev, drm);
dev_set_drvdata(dev, NULL);
drm_dev_put(drm);
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 66ea68e8da87..8791d60be92e 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -156,14 +156,6 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
return num_modes;
}
-static struct drm_encoder *imx_ldb_connector_best_encoder(
- struct drm_connector *connector)
-{
- struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
-
- return &imx_ldb_ch->encoder;
-}
-
static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno,
unsigned long serial_clk, unsigned long di_clk)
{
@@ -304,18 +296,19 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
{
struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
struct imx_ldb *ldb = imx_ldb_ch->ldb;
+ int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
int mux, ret;
drm_panel_disable(imx_ldb_ch->panel);
- if (imx_ldb_ch == &ldb->channel[0])
+ if (imx_ldb_ch == &ldb->channel[0] || dual)
ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
- else if (imx_ldb_ch == &ldb->channel[1])
+ if (imx_ldb_ch == &ldb->channel[1] || dual)
ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
- if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
+ if (dual) {
clk_disable_unprepare(ldb->clk[0]);
clk_disable_unprepare(ldb->clk[1]);
}
@@ -391,7 +384,6 @@ static const struct drm_connector_funcs imx_ldb_connector_funcs = {
static const struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = {
.get_modes = imx_ldb_connector_get_modes,
- .best_encoder = imx_ldb_connector_best_encoder,
};
static const struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
@@ -473,11 +465,6 @@ static int imx_ldb_register(struct drm_device *drm,
return 0;
}
-enum {
- LVDS_BIT_MAP_SPWG,
- LVDS_BIT_MAP_JEIDA
-};
-
struct imx_ldb_bit_mapping {
u32 bus_format;
u32 datawidth;
@@ -590,9 +577,8 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
int ret;
int i;
- imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
- if (!imx_ldb)
- return -ENOMEM;
+ imx_ldb = dev_get_drvdata(dev);
+ memset(imx_ldb, 0, sizeof(*imx_ldb));
imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
if (IS_ERR(imx_ldb->regmap)) {
@@ -700,8 +686,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
}
}
- dev_set_drvdata(dev, imx_ldb);
-
return 0;
free_child:
@@ -733,6 +717,14 @@ static const struct component_ops imx_ldb_ops = {
static int imx_ldb_probe(struct platform_device *pdev)
{
+ struct imx_ldb *imx_ldb;
+
+ imx_ldb = devm_kzalloc(&pdev->dev, sizeof(*imx_ldb), GFP_KERNEL);
+ if (!imx_ldb)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, imx_ldb);
+
return component_add(&pdev->dev, &imx_ldb_ops);
}
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index ee63782c77e9..813bb6156a68 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -260,14 +260,6 @@ static int imx_tve_connector_mode_valid(struct drm_connector *connector,
return MODE_BAD;
}
-static struct drm_encoder *imx_tve_connector_best_encoder(
- struct drm_connector *connector)
-{
- struct imx_tve *tve = con_to_tve(connector);
-
- return &tve->encoder;
-}
-
static void imx_tve_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *orig_mode,
struct drm_display_mode *mode)
@@ -345,7 +337,6 @@ static const struct drm_connector_funcs imx_tve_connector_funcs = {
static const struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = {
.get_modes = imx_tve_connector_get_modes,
- .best_encoder = imx_tve_connector_best_encoder,
.mode_valid = imx_tve_connector_mode_valid,
};
@@ -490,6 +481,13 @@ static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve)
return 0;
}
+static void imx_tve_disable_regulator(void *data)
+{
+ struct imx_tve *tve = data;
+
+ regulator_disable(tve->dac_reg);
+}
+
static bool imx_tve_readable_reg(struct device *dev, unsigned int reg)
{
return (reg % 4 == 0) && (reg <= 0xdc);
@@ -542,9 +540,8 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
int irq;
int ret;
- tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL);
- if (!tve)
- return -ENOMEM;
+ tve = dev_get_drvdata(dev);
+ memset(tve, 0, sizeof(*tve));
tve->dev = dev;
spin_lock_init(&tve->lock);
@@ -594,10 +591,8 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "failed to get irq\n");
+ if (irq < 0)
return irq;
- }
ret = devm_request_threaded_irq(dev, irq, NULL,
imx_tve_irq_handler, IRQF_ONESHOT,
@@ -614,6 +609,9 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
ret = regulator_enable(tve->dac_reg);
if (ret)
return ret;
+ ret = devm_add_action_or_reset(dev, imx_tve_disable_regulator, tve);
+ if (ret)
+ return ret;
}
tve->clk = devm_clk_get(dev, "tve");
@@ -655,27 +653,23 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
if (ret)
return ret;
- dev_set_drvdata(dev, tve);
-
return 0;
}
-static void imx_tve_unbind(struct device *dev, struct device *master,
- void *data)
-{
- struct imx_tve *tve = dev_get_drvdata(dev);
-
- if (!IS_ERR(tve->dac_reg))
- regulator_disable(tve->dac_reg);
-}
-
static const struct component_ops imx_tve_ops = {
.bind = imx_tve_bind,
- .unbind = imx_tve_unbind,
};
static int imx_tve_probe(struct platform_device *pdev)
{
+ struct imx_tve *tve;
+
+ tve = devm_kzalloc(&pdev->dev, sizeof(*tve), GFP_KERNEL);
+ if (!tve)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, tve);
+
return component_add(&pdev->dev, &imx_tve_ops);
}
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index 02c2f848f2d1..d412fc265395 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -433,21 +433,13 @@ static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
struct ipu_client_platformdata *pdata = dev->platform_data;
struct drm_device *drm = data;
struct ipu_crtc *ipu_crtc;
- int ret;
- ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
- if (!ipu_crtc)
- return -ENOMEM;
+ ipu_crtc = dev_get_drvdata(dev);
+ memset(ipu_crtc, 0, sizeof(*ipu_crtc));
ipu_crtc->dev = dev;
- ret = ipu_crtc_init(ipu_crtc, pdata, drm);
- if (ret)
- return ret;
-
- dev_set_drvdata(dev, ipu_crtc);
-
- return 0;
+ return ipu_crtc_init(ipu_crtc, pdata, drm);
}
static void ipu_drm_unbind(struct device *dev, struct device *master,
@@ -469,6 +461,7 @@ static const struct component_ops ipu_crtc_ops = {
static int ipu_drm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct ipu_crtc *ipu_crtc;
int ret;
if (!dev->platform_data)
@@ -478,6 +471,12 @@ static int ipu_drm_probe(struct platform_device *pdev)
if (ret)
return ret;
+ ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
+ if (!ipu_crtc)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, ipu_crtc);
+
return component_add(dev, &ipu_crtc_ops);
}
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index ac916c84a631..a831b5bd1613 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -88,14 +88,6 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
return num_modes;
}
-static struct drm_encoder *imx_pd_connector_best_encoder(
- struct drm_connector *connector)
-{
- struct imx_parallel_display *imxpd = con_to_imxpd(connector);
-
- return &imxpd->encoder;
-}
-
static void imx_pd_bridge_enable(struct drm_bridge *bridge)
{
struct imx_parallel_display *imxpd = bridge_to_imxpd(bridge);
@@ -217,7 +209,7 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
if (next_bridge_state)
bus_flags = next_bridge_state->input_bus_cfg.flags;
- else if (!imxpd->bus_format && di->num_bus_formats)
+ else if (di->num_bus_formats)
bus_flags = di->bus_flags;
else
bus_flags = imxpd->bus_flags;
@@ -254,7 +246,6 @@ static const struct drm_connector_funcs imx_pd_connector_funcs = {
static const struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = {
.get_modes = imx_pd_connector_get_modes,
- .best_encoder = imx_pd_connector_best_encoder,
};
static const struct drm_bridge_funcs imx_pd_bridge_funcs = {
@@ -326,9 +317,14 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
u32 bus_format = 0;
const char *fmt;
- imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL);
- if (!imxpd)
- return -ENOMEM;
+ imxpd = dev_get_drvdata(dev);
+ memset(imxpd, 0, sizeof(*imxpd));
+
+ /* port@1 is the output port */
+ ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel,
+ &imxpd->next_bridge);
+ if (ret && ret != -ENODEV)
+ return ret;
edidp = of_get_property(np, "edid", &imxpd->edid_len);
if (edidp)
@@ -347,20 +343,12 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
}
imxpd->bus_format = bus_format;
- /* port@1 is the output port */
- ret = drm_of_find_panel_or_bridge(np, 1, 0, &imxpd->panel,
- &imxpd->next_bridge);
- if (ret && ret != -ENODEV)
- return ret;
-
imxpd->dev = dev;
ret = imx_pd_register(drm, imxpd);
if (ret)
return ret;
- dev_set_drvdata(dev, imxpd);
-
return 0;
}
@@ -382,6 +370,14 @@ static const struct component_ops imx_pd_ops = {
static int imx_pd_probe(struct platform_device *pdev)
{
+ struct imx_parallel_display *imxpd;
+
+ imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
+ if (!imxpd)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, imxpd);
+
return component_add(&pdev->dev, &imx_pd_ops);
}