Commit 5a394f19 authored by Dave Airlie's avatar Dave Airlie
Browse files

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: default avatarDave Airlie <airlied@redhat.com>

From: Philipp Zabel <p.zabel@pengutronix.de>
Link: https://patchwork.freedesktop.org/patch/msgid/ac4452eb3a989bf5d85b65fd30840a21f15ec301.camel@pengutronix.de
parents fa07634d 408a85e3
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -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);
}

+2 −1
Original line number Diff line number Diff line
@@ -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);
+14 −22
Original line number Diff line number Diff line
@@ -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);
}

+21 −27
Original line number Diff line number Diff line
@@ -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);
}

+10 −11
Original line number Diff line number Diff line
@@ -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);
}

Loading