Commit e4b2eb13 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2017-11-30' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

drm-misc-fixes for -rc2

- big pile of bridge driver (mostly tc358767), all handled by Archit
  and Andrez
- rockchip dsi fix
- atomic helper regression fix for spurious -EBUSY (Maarten)
- fix deferred fbdev fallout (Maarten)

* tag 'drm-misc-fixes-2017-11-30' of git://anongit.freedesktop.org/drm/drm-misc:
  drm/bridge: tc358767: fix 1-lane behavior
  drm/bridge: tc358767: fix AUXDATAn registers access
  drm/bridge: tc358767: fix timing calculations
  drm/bridge: tc358767: fix DP0_MISC register set
  drm/bridge: tc358767: filter out too high modes
  drm/bridge: tc358767: do no fail on hi-res displays
  drm/bridge: Fix lvds-encoder since the panel_bridge rework.
  drm/bridge: synopsys/dw-hdmi: Enable cec clock
  drm/bridge: adv7511/33: Fix adv7511_cec_init() failure handling
  drm/fb_helper: Disable all crtc's when initial setup fails.
  drm/atomic: make drm_atomic_helper_wait_for_vblanks more agressive
  drm/rockchip: dw-mipi-dsi: fix possible un-balanced runtime PM enable
parents 43f462f1 4dbd6c03
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -372,9 +372,18 @@ struct adv7511 {
};

#ifdef CONFIG_DRM_I2C_ADV7511_CEC
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
		     unsigned int offset);
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511);
void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
#else
static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
{
	unsigned int offset = adv7511->type == ADV7533 ?
						ADV7533_REG_CEC_OFFSET : 0;

	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
		     ADV7511_CEC_CTRL_POWER_DOWN);
	return 0;
}
#endif

#ifdef CONFIG_DRM_I2C_ADV7533
+22 −10
Original line number Diff line number Diff line
@@ -300,18 +300,21 @@ static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
	return 0;
}

int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
		     unsigned int offset)
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
{
	unsigned int offset = adv7511->type == ADV7533 ?
						ADV7533_REG_CEC_OFFSET : 0;
	int ret = adv7511_cec_parse_dt(dev, adv7511);

	if (ret)
		return ret;
		goto err_cec_parse_dt;

	adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
		adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
	if (IS_ERR(adv7511->cec_adap))
		return PTR_ERR(adv7511->cec_adap);
	if (IS_ERR(adv7511->cec_adap)) {
		ret = PTR_ERR(adv7511->cec_adap);
		goto err_cec_alloc;
	}

	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
	/* cec soft reset */
@@ -329,9 +332,18 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
		     ((adv7511->cec_clk_freq / 750000) - 1) << 2);

	ret = cec_register_adapter(adv7511->cec_adap, dev);
	if (ret) {
	if (ret)
		goto err_cec_register;
	return 0;

err_cec_register:
	cec_delete_adapter(adv7511->cec_adap);
	adv7511->cec_adap = NULL;
	}
	return ret;
err_cec_alloc:
	dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
		 ret);
err_cec_parse_dt:
	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
		     ADV7511_CEC_CTRL_POWER_DOWN);
	return ret == -EPROBE_DEFER ? ret : 0;
}
+4 −13
Original line number Diff line number Diff line
@@ -1084,7 +1084,6 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
	struct device *dev = &i2c->dev;
	unsigned int main_i2c_addr = i2c->addr << 1;
	unsigned int edid_i2c_addr = main_i2c_addr + 4;
	unsigned int offset;
	unsigned int val;
	int ret;

@@ -1192,24 +1191,16 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
	if (adv7511->type == ADV7511)
		adv7511_set_link_config(adv7511, &link_config);

	ret = adv7511_cec_init(dev, adv7511);
	if (ret)
		goto err_unregister_cec;

	adv7511->bridge.funcs = &adv7511_bridge_funcs;
	adv7511->bridge.of_node = dev->of_node;

	drm_bridge_add(&adv7511->bridge);

	adv7511_audio_init(dev, adv7511);

	offset = adv7511->type == ADV7533 ? ADV7533_REG_CEC_OFFSET : 0;

#ifdef CONFIG_DRM_I2C_ADV7511_CEC
	ret = adv7511_cec_init(dev, adv7511, offset);
	if (ret)
		goto err_unregister_cec;
#else
	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
		     ADV7511_CEC_CTRL_POWER_DOWN);
#endif

	return 0;

err_unregister_cec:
+41 −7
Original line number Diff line number Diff line
@@ -13,13 +13,37 @@

#include <linux/of_graph.h>

struct lvds_encoder {
	struct drm_bridge bridge;
	struct drm_bridge *panel_bridge;
};

static int lvds_encoder_attach(struct drm_bridge *bridge)
{
	struct lvds_encoder *lvds_encoder = container_of(bridge,
							 struct lvds_encoder,
							 bridge);

	return drm_bridge_attach(bridge->encoder, lvds_encoder->panel_bridge,
				 bridge);
}

static struct drm_bridge_funcs funcs = {
	.attach = lvds_encoder_attach,
};

static int lvds_encoder_probe(struct platform_device *pdev)
{
	struct device_node *port;
	struct device_node *endpoint;
	struct device_node *panel_node;
	struct drm_panel *panel;
	struct drm_bridge *bridge;
	struct lvds_encoder *lvds_encoder;

	lvds_encoder = devm_kzalloc(&pdev->dev, sizeof(*lvds_encoder),
				    GFP_KERNEL);
	if (!lvds_encoder)
		return -ENOMEM;

	/* Locate the panel DT node. */
	port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
@@ -49,20 +73,30 @@ static int lvds_encoder_probe(struct platform_device *pdev)
		return -EPROBE_DEFER;
	}

	bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_LVDS);
	if (IS_ERR(bridge))
		return PTR_ERR(bridge);
	lvds_encoder->panel_bridge =
		devm_drm_panel_bridge_add(&pdev->dev,
					  panel, DRM_MODE_CONNECTOR_LVDS);
	if (IS_ERR(lvds_encoder->panel_bridge))
		return PTR_ERR(lvds_encoder->panel_bridge);

	/* The panel_bridge bridge is attached to the panel's of_node,
	 * but we need a bridge attached to our of_node for our user
	 * to look up.
	 */
	lvds_encoder->bridge.of_node = pdev->dev.of_node;
	lvds_encoder->bridge.funcs = &funcs;
	drm_bridge_add(&lvds_encoder->bridge);

	platform_set_drvdata(pdev, bridge);
	platform_set_drvdata(pdev, lvds_encoder);

	return 0;
}

static int lvds_encoder_remove(struct platform_device *pdev)
{
	struct drm_bridge *bridge = platform_get_drvdata(pdev);
	struct lvds_encoder *lvds_encoder = platform_get_drvdata(pdev);

	drm_bridge_remove(bridge);
	drm_bridge_remove(&lvds_encoder->bridge);

	return 0;
}
+25 −0
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ struct dw_hdmi {
	struct device *dev;
	struct clk *isfr_clk;
	struct clk *iahb_clk;
	struct clk *cec_clk;
	struct dw_hdmi_i2c *i2c;

	struct hdmi_data_info hdmi_data;
@@ -2382,6 +2383,26 @@ __dw_hdmi_probe(struct platform_device *pdev,
		goto err_isfr;
	}

	hdmi->cec_clk = devm_clk_get(hdmi->dev, "cec");
	if (PTR_ERR(hdmi->cec_clk) == -ENOENT) {
		hdmi->cec_clk = NULL;
	} else if (IS_ERR(hdmi->cec_clk)) {
		ret = PTR_ERR(hdmi->cec_clk);
		if (ret != -EPROBE_DEFER)
			dev_err(hdmi->dev, "Cannot get HDMI cec clock: %d\n",
				ret);

		hdmi->cec_clk = NULL;
		goto err_iahb;
	} else {
		ret = clk_prepare_enable(hdmi->cec_clk);
		if (ret) {
			dev_err(hdmi->dev, "Cannot enable HDMI cec clock: %d\n",
				ret);
			goto err_iahb;
		}
	}

	/* Product and revision IDs */
	hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
		      | (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
@@ -2518,6 +2539,8 @@ err_iahb:
		cec_notifier_put(hdmi->cec_notifier);

	clk_disable_unprepare(hdmi->iahb_clk);
	if (hdmi->cec_clk)
		clk_disable_unprepare(hdmi->cec_clk);
err_isfr:
	clk_disable_unprepare(hdmi->isfr_clk);
err_res:
@@ -2541,6 +2564,8 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)

	clk_disable_unprepare(hdmi->iahb_clk);
	clk_disable_unprepare(hdmi->isfr_clk);
	if (hdmi->cec_clk)
		clk_disable_unprepare(hdmi->cec_clk);

	if (hdmi->i2c)
		i2c_del_adapter(&hdmi->i2c->adap);
Loading