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

Commit 1f3eb346 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'omapdrm-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux into drm-next



omapdrm changes for v4.20

Big amount of changes from Laurent, reworking the driver towards the
model used by the other DRM drivers by reverting the direction of many
of the operations on the display pipeline. The aim of this work is to
allow omapdrm to use the common DRM panels and bridges.  Not all of the
operations are dealt in these patches, so more work needs to be done.

The only change visible to the user should be the change in module
dependencies: e.g. earlier a panel module depended on an encoder module,
but now the encoder module depends on the panel module, which affects
the order in which to unload the modules.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Tomi Valkeinen <tomi.valkeinen@ti.com>
Link: https://patchwork.freedesktop.org/patch/msgid/9bb1a01b-a632-ce0c-f249-7b5470967e3a@ti.com
parents f5169a17 6ea48430
Loading
Loading
Loading
Loading
+14 −125
Original line number Diff line number Diff line
@@ -18,77 +18,27 @@

struct panel_drv_data {
	struct omap_dss_device dssdev;
	struct omap_dss_device *in;

	struct device *dev;

	struct videomode vm;
};

static const struct videomode tvc_pal_vm = {
	.hactive	= 720,
	.vactive	= 574,
	.pixelclock	= 13500000,
	.hsync_len	= 64,
	.hfront_porch	= 12,
	.hback_porch	= 68,
	.vsync_len	= 5,
	.vfront_porch	= 5,
	.vback_porch	= 41,

	.flags		= DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW |
			  DISPLAY_FLAGS_VSYNC_LOW,
};

#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)

static int tvc_connect(struct omap_dss_device *dssdev)
static int tvc_connect(struct omap_dss_device *src,
		       struct omap_dss_device *dst)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in;
	int r;

	dev_dbg(ddata->dev, "connect\n");

	if (omapdss_device_is_connected(dssdev))
		return 0;

	in = omapdss_of_find_source_for_first_ep(ddata->dev->of_node);
	if (IS_ERR(in)) {
		dev_err(ddata->dev, "failed to find video source\n");
		return PTR_ERR(in);
	}

	r = in->ops.atv->connect(in, dssdev);
	if (r) {
		omap_dss_put_device(in);
		return r;
	}

	ddata->in = in;
	return 0;
}

static void tvc_disconnect(struct omap_dss_device *dssdev)
static void tvc_disconnect(struct omap_dss_device *src,
			   struct omap_dss_device *dst)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	dev_dbg(ddata->dev, "disconnect\n");

	if (!omapdss_device_is_connected(dssdev))
		return;

	in->ops.atv->disconnect(in, dssdev);

	omap_dss_put_device(in);
	ddata->in = NULL;
}

static int tvc_enable(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;
	struct omap_dss_device *src = dssdev->src;
	int r;

	dev_dbg(ddata->dev, "enable\n");
@@ -99,9 +49,7 @@ static int tvc_enable(struct omap_dss_device *dssdev)
	if (omapdss_device_is_enabled(dssdev))
		return 0;

	in->ops.atv->set_timings(in, &ddata->vm);

	r = in->ops.atv->enable(in);
	r = src->ops->enable(src);
	if (r)
		return r;

@@ -113,83 +61,30 @@ static int tvc_enable(struct omap_dss_device *dssdev)
static void tvc_disable(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;
	struct omap_dss_device *src = dssdev->src;

	dev_dbg(ddata->dev, "disable\n");

	if (!omapdss_device_is_enabled(dssdev))
		return;

	in->ops.atv->disable(in);
	src->ops->disable(src);

	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}

static void tvc_set_timings(struct omap_dss_device *dssdev,
			    struct videomode *vm)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	ddata->vm = *vm;
	dssdev->panel.vm = *vm;

	in->ops.atv->set_timings(in, vm);
}

static void tvc_get_timings(struct omap_dss_device *dssdev,
			    struct videomode *vm)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);

	*vm = ddata->vm;
}

static int tvc_check_timings(struct omap_dss_device *dssdev,
			     struct videomode *vm)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	return in->ops.atv->check_timings(in, vm);
}

static u32 tvc_get_wss(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	return in->ops.atv->get_wss(in);
}

static int tvc_set_wss(struct omap_dss_device *dssdev, u32 wss)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	return in->ops.atv->set_wss(in, wss);
}

static struct omap_dss_driver tvc_driver = {
static const struct omap_dss_device_ops tvc_ops = {
	.connect		= tvc_connect,
	.disconnect		= tvc_disconnect,

	.enable			= tvc_enable,
	.disable		= tvc_disable,

	.set_timings		= tvc_set_timings,
	.get_timings		= tvc_get_timings,
	.check_timings		= tvc_check_timings,

	.get_wss		= tvc_get_wss,
	.set_wss		= tvc_set_wss,
};

static int tvc_probe(struct platform_device *pdev)
{
	struct panel_drv_data *ddata;
	struct omap_dss_device *dssdev;
	int r;

	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
	if (!ddata)
@@ -198,20 +93,15 @@ static int tvc_probe(struct platform_device *pdev)
	platform_set_drvdata(pdev, ddata);
	ddata->dev = &pdev->dev;

	ddata->vm = tvc_pal_vm;

	dssdev = &ddata->dssdev;
	dssdev->driver = &tvc_driver;
	dssdev->ops = &tvc_ops;
	dssdev->dev = &pdev->dev;
	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
	dssdev->owner = THIS_MODULE;
	dssdev->panel.vm = tvc_pal_vm;
	dssdev->of_ports = BIT(0);

	r = omapdss_register_display(dssdev);
	if (r) {
		dev_err(&pdev->dev, "Failed to register panel\n");
		return r;
	}
	omapdss_display_init(dssdev);
	omapdss_device_register(dssdev);

	return 0;
}
@@ -221,10 +111,9 @@ static int __exit tvc_remove(struct platform_device *pdev)
	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
	struct omap_dss_device *dssdev = &ddata->dssdev;

	omapdss_unregister_display(&ddata->dssdev);
	omapdss_device_unregister(&ddata->dssdev);

	tvc_disable(dssdev);
	tvc_disconnect(dssdev);

	return 0;
}
+22 −153
Original line number Diff line number Diff line
@@ -19,30 +19,8 @@

#include "../dss/omapdss.h"

static const struct videomode dvic_default_vm = {
	.hactive	= 640,
	.vactive	= 480,

	.pixelclock	= 23500000,

	.hfront_porch	= 48,
	.hsync_len	= 32,
	.hback_porch	= 80,

	.vfront_porch	= 3,
	.vsync_len	= 4,
	.vback_porch	= 7,

	.flags		= DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH |
			  DISPLAY_FLAGS_SYNC_NEGEDGE | DISPLAY_FLAGS_DE_HIGH |
			  DISPLAY_FLAGS_PIXDATA_POSEDGE,
};

struct panel_drv_data {
	struct omap_dss_device dssdev;
	struct omap_dss_device *in;

	struct videomode vm;

	struct i2c_adapter *i2c_adapter;

@@ -57,49 +35,20 @@ struct panel_drv_data {

#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)

static int dvic_connect(struct omap_dss_device *dssdev)
static int dvic_connect(struct omap_dss_device *src,
			struct omap_dss_device *dst)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in;
	int r;

	if (omapdss_device_is_connected(dssdev))
		return 0;

	in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
	if (IS_ERR(in)) {
		dev_err(dssdev->dev, "failed to find video source\n");
		return PTR_ERR(in);
	}

	r = in->ops.dvi->connect(in, dssdev);
	if (r) {
		omap_dss_put_device(in);
		return r;
	}

	ddata->in = in;
	return 0;
}

static void dvic_disconnect(struct omap_dss_device *dssdev)
static void dvic_disconnect(struct omap_dss_device *src,
			    struct omap_dss_device *dst)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	if (!omapdss_device_is_connected(dssdev))
		return;

	in->ops.dvi->disconnect(in, dssdev);

	omap_dss_put_device(in);
	ddata->in = NULL;
}

static int dvic_enable(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;
	struct omap_dss_device *src = dssdev->src;
	int r;

	if (!omapdss_device_is_connected(dssdev))
@@ -108,9 +57,7 @@ static int dvic_enable(struct omap_dss_device *dssdev)
	if (omapdss_device_is_enabled(dssdev))
		return 0;

	in->ops.dvi->set_timings(in, &ddata->vm);

	r = in->ops.dvi->enable(in);
	r = src->ops->enable(src);
	if (r)
		return r;

@@ -121,46 +68,16 @@ static int dvic_enable(struct omap_dss_device *dssdev)

static void dvic_disable(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;
	struct omap_dss_device *src = dssdev->src;

	if (!omapdss_device_is_enabled(dssdev))
		return;

	in->ops.dvi->disable(in);
	src->ops->disable(src);

	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}

static void dvic_set_timings(struct omap_dss_device *dssdev,
			     struct videomode *vm)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	ddata->vm = *vm;
	dssdev->panel.vm = *vm;

	in->ops.dvi->set_timings(in, vm);
}

static void dvic_get_timings(struct omap_dss_device *dssdev,
			     struct videomode *vm)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);

	*vm = ddata->vm;
}

static int dvic_check_timings(struct omap_dss_device *dssdev,
			      struct videomode *vm)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	return in->ops.dvi->check_timings(in, vm);
}

static int dvic_ddc_read(struct i2c_adapter *adapter,
		unsigned char *buf, u16 count, u8 offset)
{
@@ -198,12 +115,6 @@ static int dvic_read_edid(struct omap_dss_device *dssdev,
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	int r, l, bytes_read;

	if (ddata->hpd_gpio && !gpiod_get_value_cansleep(ddata->hpd_gpio))
		return -ENODEV;

	if (!ddata->i2c_adapter)
		return -ENODEV;

	l = min(EDID_LENGTH, len);
	r = dvic_ddc_read(ddata->i2c_adapter, edid, l, 0);
	if (r)
@@ -243,78 +154,41 @@ static bool dvic_detect(struct omap_dss_device *dssdev)
	return r == 0;
}

static int dvic_register_hpd_cb(struct omap_dss_device *dssdev,
static void dvic_register_hpd_cb(struct omap_dss_device *dssdev,
				 void (*cb)(void *cb_data,
					    enum drm_connector_status status),
				 void *cb_data)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);

	if (!ddata->hpd_gpio)
		return -ENOTSUPP;

	mutex_lock(&ddata->hpd_lock);
	ddata->hpd_cb = cb;
	ddata->hpd_cb_data = cb_data;
	mutex_unlock(&ddata->hpd_lock);
	return 0;
}

static void dvic_unregister_hpd_cb(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);

	if (!ddata->hpd_gpio)
		return;

	mutex_lock(&ddata->hpd_lock);
	ddata->hpd_cb = NULL;
	ddata->hpd_cb_data = NULL;
	mutex_unlock(&ddata->hpd_lock);
}

static void dvic_enable_hpd(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);

	if (!ddata->hpd_gpio)
		return;

	mutex_lock(&ddata->hpd_lock);
	ddata->hpd_enabled = true;
	mutex_unlock(&ddata->hpd_lock);
}

static void dvic_disable_hpd(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);

	if (!ddata->hpd_gpio)
		return;

	mutex_lock(&ddata->hpd_lock);
	ddata->hpd_enabled = false;
	mutex_unlock(&ddata->hpd_lock);
}

static struct omap_dss_driver dvic_driver = {
static const struct omap_dss_device_ops dvic_ops = {
	.connect	= dvic_connect,
	.disconnect	= dvic_disconnect,

	.enable		= dvic_enable,
	.disable	= dvic_disable,

	.set_timings	= dvic_set_timings,
	.get_timings	= dvic_get_timings,
	.check_timings	= dvic_check_timings,

	.read_edid	= dvic_read_edid,
	.detect		= dvic_detect,

	.register_hpd_cb	= dvic_register_hpd_cb,
	.unregister_hpd_cb	= dvic_unregister_hpd_cb,
	.enable_hpd		= dvic_enable_hpd,
	.disable_hpd		= dvic_disable_hpd,
};

static irqreturn_t dvic_hpd_isr(int irq, void *data)
@@ -396,28 +270,24 @@ static int dvic_probe(struct platform_device *pdev)
	if (r)
		return r;

	ddata->vm = dvic_default_vm;

	dssdev = &ddata->dssdev;
	dssdev->driver = &dvic_driver;
	dssdev->ops = &dvic_ops;
	dssdev->dev = &pdev->dev;
	dssdev->type = OMAP_DISPLAY_TYPE_DVI;
	dssdev->owner = THIS_MODULE;
	dssdev->panel.vm = dvic_default_vm;
	dssdev->of_ports = BIT(0);

	r = omapdss_register_display(dssdev);
	if (r) {
		dev_err(&pdev->dev, "Failed to register panel\n");
		goto err_reg;
	}
	if (ddata->hpd_gpio)
		dssdev->ops_flags |= OMAP_DSS_DEVICE_OP_DETECT
				  |  OMAP_DSS_DEVICE_OP_HPD;
	if (ddata->i2c_adapter)
		dssdev->ops_flags |= OMAP_DSS_DEVICE_OP_DETECT
				  |  OMAP_DSS_DEVICE_OP_EDID;

	return 0;
	omapdss_display_init(dssdev);
	omapdss_device_register(dssdev);

err_reg:
	i2c_put_adapter(ddata->i2c_adapter);
	mutex_destroy(&ddata->hpd_lock);

	return r;
	return 0;
}

static int __exit dvic_remove(struct platform_device *pdev)
@@ -425,10 +295,9 @@ static int __exit dvic_remove(struct platform_device *pdev)
	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
	struct omap_dss_device *dssdev = &ddata->dssdev;

	omapdss_unregister_display(&ddata->dssdev);
	omapdss_device_unregister(&ddata->dssdev);

	dvic_disable(dssdev);
	dvic_disconnect(dssdev);

	i2c_put_adapter(ddata->i2c_adapter);

+45 −232
Original line number Diff line number Diff line
@@ -10,95 +10,41 @@
 */

#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/mutex.h>

#include <drm/drm_edid.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#include "../dss/omapdss.h"

static const struct videomode hdmic_default_vm = {
	.hactive	= 640,
	.vactive	= 480,
	.pixelclock	= 25175000,
	.hsync_len	= 96,
	.hfront_porch	= 16,
	.hback_porch	= 48,
	.vsync_len	= 2,
	.vfront_porch	= 11,
	.vback_porch	= 31,

	.flags		= DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
};

struct panel_drv_data {
	struct omap_dss_device dssdev;
	struct omap_dss_device *in;
	void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
	void *hpd_cb_data;
	bool hpd_enabled;
	struct mutex hpd_lock;

	struct device *dev;

	struct videomode vm;

	int hpd_gpio;
	struct gpio_desc *hpd_gpio;
};

#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)

static int hdmic_connect(struct omap_dss_device *dssdev)
static int hdmic_connect(struct omap_dss_device *src,
			 struct omap_dss_device *dst)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in;
	int r;

	dev_dbg(ddata->dev, "connect\n");

	if (omapdss_device_is_connected(dssdev))
		return 0;

	in = omapdss_of_find_source_for_first_ep(ddata->dev->of_node);
	if (IS_ERR(in)) {
		dev_err(ddata->dev, "failed to find video source\n");
		return PTR_ERR(in);
	}

	r = in->ops.hdmi->connect(in, dssdev);
	if (r) {
		omap_dss_put_device(in);
		return r;
	}

	ddata->in = in;
	return 0;
}

static void hdmic_disconnect(struct omap_dss_device *dssdev)
static void hdmic_disconnect(struct omap_dss_device *src,
			     struct omap_dss_device *dst)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	dev_dbg(ddata->dev, "disconnect\n");

	if (!omapdss_device_is_connected(dssdev))
		return;

	in->ops.hdmi->disconnect(in, dssdev);

	omap_dss_put_device(in);
	ddata->in = NULL;
}

static int hdmic_enable(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;
	struct omap_dss_device *src = dssdev->src;
	int r;

	dev_dbg(ddata->dev, "enable\n");
@@ -109,9 +55,7 @@ static int hdmic_enable(struct omap_dss_device *dssdev)
	if (omapdss_device_is_enabled(dssdev))
		return 0;

	in->ops.hdmi->set_timings(in, &ddata->vm);

	r = in->ops.hdmi->enable(in);
	r = src->ops->enable(src);
	if (r)
		return r;

@@ -123,171 +67,58 @@ static int hdmic_enable(struct omap_dss_device *dssdev)
static void hdmic_disable(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;
	struct omap_dss_device *src = dssdev->src;

	dev_dbg(ddata->dev, "disable\n");

	if (!omapdss_device_is_enabled(dssdev))
		return;

	in->ops.hdmi->disable(in);
	src->ops->disable(src);

	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}

static void hdmic_set_timings(struct omap_dss_device *dssdev,
			      struct videomode *vm)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	ddata->vm = *vm;
	dssdev->panel.vm = *vm;

	in->ops.hdmi->set_timings(in, vm);
}

static void hdmic_get_timings(struct omap_dss_device *dssdev,
			      struct videomode *vm)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);

	*vm = ddata->vm;
}

static int hdmic_check_timings(struct omap_dss_device *dssdev,
			       struct videomode *vm)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	return in->ops.hdmi->check_timings(in, vm);
}

static int hdmic_read_edid(struct omap_dss_device *dssdev,
		u8 *edid, int len)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	return in->ops.hdmi->read_edid(in, edid, len);
}

static bool hdmic_detect(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;
	bool connected;

	if (gpio_is_valid(ddata->hpd_gpio))
		connected = gpio_get_value_cansleep(ddata->hpd_gpio);
	else
		connected = in->ops.hdmi->detect(in);
	if (!connected && in->ops.hdmi->lost_hotplug)
		in->ops.hdmi->lost_hotplug(in);
	return connected;
	return gpiod_get_value_cansleep(ddata->hpd_gpio);
}

static int hdmic_register_hpd_cb(struct omap_dss_device *dssdev,
static void hdmic_register_hpd_cb(struct omap_dss_device *dssdev,
				  void (*cb)(void *cb_data,
					    enum drm_connector_status status),
				  void *cb_data)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	if (gpio_is_valid(ddata->hpd_gpio)) {
	mutex_lock(&ddata->hpd_lock);
	ddata->hpd_cb = cb;
	ddata->hpd_cb_data = cb_data;
	mutex_unlock(&ddata->hpd_lock);
		return 0;
	} else if (in->ops.hdmi->register_hpd_cb) {
		return in->ops.hdmi->register_hpd_cb(in, cb, cb_data);
	}

	return -ENOTSUPP;
}

static void hdmic_unregister_hpd_cb(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	if (gpio_is_valid(ddata->hpd_gpio)) {
	mutex_lock(&ddata->hpd_lock);
	ddata->hpd_cb = NULL;
	ddata->hpd_cb_data = NULL;
	mutex_unlock(&ddata->hpd_lock);
	} else if (in->ops.hdmi->unregister_hpd_cb) {
		in->ops.hdmi->unregister_hpd_cb(in);
	}
}

static void hdmic_enable_hpd(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	if (gpio_is_valid(ddata->hpd_gpio)) {
		mutex_lock(&ddata->hpd_lock);
		ddata->hpd_enabled = true;
		mutex_unlock(&ddata->hpd_lock);
	} else if (in->ops.hdmi->enable_hpd) {
		in->ops.hdmi->enable_hpd(in);
	}
}

static void hdmic_disable_hpd(struct omap_dss_device *dssdev)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	if (gpio_is_valid(ddata->hpd_gpio)) {
		mutex_lock(&ddata->hpd_lock);
		ddata->hpd_enabled = false;
		mutex_unlock(&ddata->hpd_lock);
	} else if (in->ops.hdmi->disable_hpd) {
		in->ops.hdmi->disable_hpd(in);
}
}

static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	return in->ops.hdmi->set_hdmi_mode(in, hdmi_mode);
}

static int hdmic_set_infoframe(struct omap_dss_device *dssdev,
		const struct hdmi_avi_infoframe *avi)
{
	struct panel_drv_data *ddata = to_panel_data(dssdev);
	struct omap_dss_device *in = ddata->in;

	return in->ops.hdmi->set_infoframe(in, avi);
}

static struct omap_dss_driver hdmic_driver = {
static const struct omap_dss_device_ops hdmic_ops = {
	.connect		= hdmic_connect,
	.disconnect		= hdmic_disconnect,

	.enable			= hdmic_enable,
	.disable		= hdmic_disable,

	.set_timings		= hdmic_set_timings,
	.get_timings		= hdmic_get_timings,
	.check_timings		= hdmic_check_timings,

	.read_edid		= hdmic_read_edid,
	.detect			= hdmic_detect,
	.register_hpd_cb	= hdmic_register_hpd_cb,
	.unregister_hpd_cb	= hdmic_unregister_hpd_cb,
	.enable_hpd		= hdmic_enable_hpd,
	.disable_hpd		= hdmic_disable_hpd,
	.set_hdmi_mode		= hdmic_set_hdmi_mode,
	.set_hdmi_infoframe	= hdmic_set_infoframe,
};

static irqreturn_t hdmic_hpd_isr(int irq, void *data)
@@ -295,7 +126,7 @@ static irqreturn_t hdmic_hpd_isr(int irq, void *data)
	struct panel_drv_data *ddata = data;

	mutex_lock(&ddata->hpd_lock);
	if (ddata->hpd_enabled && ddata->hpd_cb) {
	if (ddata->hpd_cb) {
		enum drm_connector_status status;

		if (hdmic_detect(&ddata->dssdev))
@@ -310,26 +141,11 @@ static irqreturn_t hdmic_hpd_isr(int irq, void *data)
	return IRQ_HANDLED;
}

static int hdmic_probe_of(struct platform_device *pdev)
{
	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
	struct device_node *node = pdev->dev.of_node;
	int gpio;

	/* HPD GPIO */
	gpio = of_get_named_gpio(node, "hpd-gpios", 0);
	if (gpio_is_valid(gpio))
		ddata->hpd_gpio = gpio;
	else
		ddata->hpd_gpio = -ENODEV;

	return 0;
}

static int hdmic_probe(struct platform_device *pdev)
{
	struct panel_drv_data *ddata;
	struct omap_dss_device *dssdev;
	struct gpio_desc *gpio;
	int r;

	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
@@ -339,20 +155,20 @@ static int hdmic_probe(struct platform_device *pdev)
	platform_set_drvdata(pdev, ddata);
	ddata->dev = &pdev->dev;

	r = hdmic_probe_of(pdev);
	if (r)
		return r;

	mutex_init(&ddata->hpd_lock);

	if (gpio_is_valid(ddata->hpd_gpio)) {
		r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
				GPIOF_DIR_IN, "hdmi_hpd");
		if (r)
			return r;
	/* HPD GPIO */
	gpio = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
	if (IS_ERR(gpio)) {
		dev_err(&pdev->dev, "failed to parse HPD gpio\n");
		return PTR_ERR(gpio);
	}

	ddata->hpd_gpio = gpio;

	if (ddata->hpd_gpio) {
		r = devm_request_threaded_irq(&pdev->dev,
				gpio_to_irq(ddata->hpd_gpio),
				gpiod_to_irq(ddata->hpd_gpio),
				NULL, hdmic_hpd_isr,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
				IRQF_ONESHOT,
@@ -361,20 +177,18 @@ static int hdmic_probe(struct platform_device *pdev)
			return r;
	}

	ddata->vm = hdmic_default_vm;

	dssdev = &ddata->dssdev;
	dssdev->driver = &hdmic_driver;
	dssdev->ops = &hdmic_ops;
	dssdev->dev = &pdev->dev;
	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
	dssdev->owner = THIS_MODULE;
	dssdev->panel.vm = hdmic_default_vm;
	dssdev->of_ports = BIT(0);
	dssdev->ops_flags = ddata->hpd_gpio
			  ? OMAP_DSS_DEVICE_OP_DETECT | OMAP_DSS_DEVICE_OP_HPD
			  : 0;

	r = omapdss_register_display(dssdev);
	if (r) {
		dev_err(&pdev->dev, "Failed to register panel\n");
		return r;
	}
	omapdss_display_init(dssdev);
	omapdss_device_register(dssdev);

	return 0;
}
@@ -384,10 +198,9 @@ static int __exit hdmic_remove(struct platform_device *pdev)
	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
	struct omap_dss_device *dssdev = &ddata->dssdev;

	omapdss_unregister_display(&ddata->dssdev);
	omapdss_device_unregister(&ddata->dssdev);

	hdmic_disable(dssdev);
	hdmic_disconnect(dssdev);

	return 0;
}
+24 −108

File changed.

Preview size limit exceeded, changes collapsed.

+40 −147

File changed.

Preview size limit exceeded, changes collapsed.

Loading