Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

Merge tag 'imx-drm-next-2016-06-01' of git://git.pengutronix.de/git/pza/linux into drm-fixes

imx-drm updates

- add support for reading LVDS panel EDID over DDC
- enable UYVY/VYUY support
- add support for pixel clock polarity configuration
- honor the native-mode DT property for LVDS
- various fixes and cleanups

* tag 'imx-drm-next-2016-06-01' of git://git.pengutronix.de/git/pza/linux:
  drm/imx: plane: Don't set plane->crtc in ipu_plane_update()
  drm/imx: ipuv3-plane: Constify ipu_plane_funcs
  drm/imx: imx-ldb: honor 'native-mode' property when selecting video mode from DT
  drm/imx: parallel-display: remove dead code
  drm/imx: use bus_flags for pixel clock polarity
  drm/imx: ipuv3-plane: enable UYVY and VYUY formats
  drm/imx: parallel-display: use of_graph_get_endpoint_by_regs helper
  drm/imx: imx-ldb: use of_graph_get_endpoint_by_regs helper
  dt-bindings: imx: ldb: Add ddc-i2c-bus property
  drm/imx: imx-ldb: Add DDC support
parents 35962eae 151787ba
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ Required properties:
   display-timings are used instead.

Optional properties (required if display-timings are used):
 - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
 - display-timings : A node that describes the display timings as defined in
   Documentation/devicetree/bindings/display/display-timing.txt.
 - fsl,data-mapping : should be "spwg" or "jeida"
+8 −5
Original line number Diff line number Diff line
@@ -97,8 +97,8 @@ static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
	return NULL;
}

int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format,
		int hsync_pin, int vsync_pin)
int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
		int hsync_pin, int vsync_pin, u32 bus_flags)
{
	struct imx_drm_crtc_helper_funcs *helper;
	struct imx_drm_crtc *imx_crtc;
@@ -110,14 +110,17 @@ int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format,
	helper = &imx_crtc->imx_drm_helper_funcs;
	if (helper->set_interface_pix_fmt)
		return helper->set_interface_pix_fmt(encoder->crtc,
					bus_format, hsync_pin, vsync_pin);
					bus_format, hsync_pin, vsync_pin,
					bus_flags);
	return 0;
}
EXPORT_SYMBOL_GPL(imx_drm_set_bus_format_pins);
EXPORT_SYMBOL_GPL(imx_drm_set_bus_config);

int imx_drm_set_bus_format(struct drm_encoder *encoder, u32 bus_format)
{
	return imx_drm_set_bus_format_pins(encoder, bus_format, 2, 3);
	return imx_drm_set_bus_config(encoder, bus_format, 2, 3,
				      DRM_BUS_FLAG_DE_HIGH |
				      DRM_BUS_FLAG_PIXDATA_NEGEDGE);
}
EXPORT_SYMBOL_GPL(imx_drm_set_bus_format);

+4 −3
Original line number Diff line number Diff line
@@ -19,7 +19,8 @@ struct imx_drm_crtc_helper_funcs {
	int (*enable_vblank)(struct drm_crtc *crtc);
	void (*disable_vblank)(struct drm_crtc *crtc);
	int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
			u32 bus_format, int hsync_pin, int vsync_pin);
			u32 bus_format, int hsync_pin, int vsync_pin,
			u32 bus_flags);
	const struct drm_crtc_helper_funcs *crtc_helper_funcs;
	const struct drm_crtc_funcs *crtc_funcs;
};
@@ -41,8 +42,8 @@ void imx_drm_mode_config_init(struct drm_device *drm);

struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);

int imx_drm_set_bus_format_pins(struct drm_encoder *encoder,
		u32 bus_format, int hsync_pin, int vsync_pin);
int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
		int hsync_pin, int vsync_pin, u32 bus_flags);
int imx_drm_set_bus_format(struct drm_encoder *encoder,
		u32 bus_format);

+53 −25
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <video/of_display_timing.h>
#include <video/of_videomode.h>
#include <linux/regmap.h>
#include <linux/videodev2.h>
@@ -59,6 +60,7 @@ struct imx_ldb_channel {
	struct drm_encoder encoder;
	struct drm_panel *panel;
	struct device_node *child;
	struct i2c_adapter *ddc;
	int chno;
	void *edid;
	int edid_len;
@@ -107,6 +109,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
			return num_modes;
	}

	if (!imx_ldb_ch->edid && imx_ldb_ch->ddc)
		imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc);

	if (imx_ldb_ch->edid) {
		drm_mode_connector_update_edid_property(connector,
							imx_ldb_ch->edid);
@@ -553,7 +558,8 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)

	for_each_child_of_node(np, child) {
		struct imx_ldb_channel *channel;
		struct device_node *port;
		struct device_node *ddc_node;
		struct device_node *ep;

		ret = of_property_read_u32(child, "reg", &i);
		if (ret || i < 0 || i > 1)
@@ -576,34 +582,55 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
		 * The output port is port@4 with an external 4-port mux or
		 * port@2 with the internal 2-port mux.
		 */
		port = of_graph_get_port_by_id(child, imx_ldb->lvds_mux ? 4 : 2);
		if (port) {
			struct device_node *endpoint, *remote;

			endpoint = of_get_child_by_name(port, "endpoint");
			if (endpoint) {
				remote = of_graph_get_remote_port_parent(endpoint);
		ep = of_graph_get_endpoint_by_regs(child,
						   imx_ldb->lvds_mux ? 4 : 2,
						   -1);
		if (ep) {
			struct device_node *remote;

			remote = of_graph_get_remote_port_parent(ep);
			of_node_put(ep);
			if (remote)
				channel->panel = of_drm_find_panel(remote);
			else
				return -EPROBE_DEFER;
			of_node_put(remote);
			if (!channel->panel) {
				dev_err(dev, "panel not found: %s\n",
					remote->full_name);
				return -EPROBE_DEFER;
			}
		}

		ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
		if (ddc_node) {
			channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
			of_node_put(ddc_node);
			if (!channel->ddc) {
				dev_warn(dev, "failed to get ddc i2c adapter\n");
				return -EPROBE_DEFER;
			}
		}

		if (!channel->ddc) {
			/* if no DDC available, fallback to hardcoded EDID */
			dev_dbg(dev, "no ddc available\n");

		edidp = of_get_property(child, "edid", &channel->edid_len);
			edidp = of_get_property(child, "edid",
						&channel->edid_len);
			if (edidp) {
			channel->edid = kmemdup(edidp, channel->edid_len,
				channel->edid = kmemdup(edidp,
							channel->edid_len,
							GFP_KERNEL);
			} else if (!channel->panel) {
			ret = of_get_drm_display_mode(child, &channel->mode, 0);
				/* fallback to display-timings node */
				ret = of_get_drm_display_mode(child,
							      &channel->mode,
							      OF_USE_NATIVE_MODE);
				if (!ret)
					channel->mode_valid = 1;
			}
		}

		channel->bus_format = of_get_bus_format(dev, child);
		if (channel->bus_format == -EINVAL) {
@@ -647,6 +674,7 @@ static void imx_ldb_unbind(struct device *dev, struct device *master,
		channel->encoder.funcs->destroy(&channel->encoder);

		kfree(channel->edid);
		i2c_put_adapter(channel->ddc);
	}
}

+4 −2
Original line number Diff line number Diff line
@@ -294,8 +294,10 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder)

	switch (tve->mode) {
	case TVE_MODE_VGA:
		imx_drm_set_bus_format_pins(encoder, MEDIA_BUS_FMT_GBR888_1X24,
					    tve->hsync_pin, tve->vsync_pin);
		imx_drm_set_bus_config(encoder, MEDIA_BUS_FMT_GBR888_1X24,
				       tve->hsync_pin, tve->vsync_pin,
				       DRM_BUS_FLAG_DE_HIGH |
				       DRM_BUS_FLAG_PIXDATA_NEGEDGE);
		break;
	case TVE_MODE_TVOUT:
		imx_drm_set_bus_format(encoder, MEDIA_BUS_FMT_YUV8_1X24);
Loading