Commit 67c366de authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Helge Deller

fbdev: omapfb: panel-dsi-cm: switch to using gpiod API

Switch the driver from legacy gpio API that is deprecated to the newer
gpiod API that respects line polarities described in ACPI/DT.

Note that because existing DTSes specify incorrect polarity of reset
lines (active high) and GPU drivers have adopted to this, we follow
the suit and use inverted values when controlling reset lines.
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: default avatarHelge Deller <deller@gmx.de>
parent 6378085b
...@@ -10,8 +10,9 @@ ...@@ -10,8 +10,9 @@
#include <linux/backlight.h> #include <linux/backlight.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -20,7 +21,6 @@ ...@@ -20,7 +21,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <video/omapfb_dss.h> #include <video/omapfb_dss.h>
#include <video/mipi_display.h> #include <video/mipi_display.h>
...@@ -53,8 +53,8 @@ struct panel_drv_data { ...@@ -53,8 +53,8 @@ struct panel_drv_data {
unsigned long hw_guard_wait; /* max guard time in jiffies */ unsigned long hw_guard_wait; /* max guard time in jiffies */
/* panel HW configuration from DT or platform data */ /* panel HW configuration from DT or platform data */
int reset_gpio; struct gpio_desc *reset_gpio;
int ext_te_gpio; struct gpio_desc *ext_te_gpio;
bool use_dsi_backlight; bool use_dsi_backlight;
...@@ -250,8 +250,8 @@ static int dsicm_enter_ulps(struct panel_drv_data *ddata) ...@@ -250,8 +250,8 @@ static int dsicm_enter_ulps(struct panel_drv_data *ddata)
if (r) if (r)
goto err; goto err;
if (gpio_is_valid(ddata->ext_te_gpio)) if (ddata->ext_te_gpio)
disable_irq(gpio_to_irq(ddata->ext_te_gpio)); disable_irq(gpiod_to_irq(ddata->ext_te_gpio));
in->ops.dsi->disable(in, false, true); in->ops.dsi->disable(in, false, true);
...@@ -292,8 +292,8 @@ static int dsicm_exit_ulps(struct panel_drv_data *ddata) ...@@ -292,8 +292,8 @@ static int dsicm_exit_ulps(struct panel_drv_data *ddata)
goto err2; goto err2;
} }
if (gpio_is_valid(ddata->ext_te_gpio)) if (ddata->ext_te_gpio)
enable_irq(gpio_to_irq(ddata->ext_te_gpio)); enable_irq(gpiod_to_irq(ddata->ext_te_gpio));
dsicm_queue_ulps_work(ddata); dsicm_queue_ulps_work(ddata);
...@@ -306,8 +306,8 @@ static int dsicm_exit_ulps(struct panel_drv_data *ddata) ...@@ -306,8 +306,8 @@ static int dsicm_exit_ulps(struct panel_drv_data *ddata)
r = dsicm_panel_reset(ddata); r = dsicm_panel_reset(ddata);
if (!r) { if (!r) {
if (gpio_is_valid(ddata->ext_te_gpio)) if (ddata->ext_te_gpio)
enable_irq(gpio_to_irq(ddata->ext_te_gpio)); enable_irq(gpiod_to_irq(ddata->ext_te_gpio));
ddata->ulps_enabled = false; ddata->ulps_enabled = false;
} }
err1: err1:
...@@ -556,16 +556,19 @@ static const struct attribute_group dsicm_attr_group = { ...@@ -556,16 +556,19 @@ static const struct attribute_group dsicm_attr_group = {
static void dsicm_hw_reset(struct panel_drv_data *ddata) static void dsicm_hw_reset(struct panel_drv_data *ddata)
{ {
if (!gpio_is_valid(ddata->reset_gpio)) /*
return; * Note that we appear to activate the reset line here. However
* existing DTSes specified incorrect polarity for it (active high),
gpio_set_value(ddata->reset_gpio, 1); * so in fact this deasserts the reset line.
*/
gpiod_set_value_cansleep(ddata->reset_gpio, 1);
udelay(10); udelay(10);
/* reset the panel */ /* reset the panel */
gpio_set_value(ddata->reset_gpio, 0); gpiod_set_value_cansleep(ddata->reset_gpio, 0);
/* assert reset */ /* keep reset asserted */
udelay(10); udelay(10);
gpio_set_value(ddata->reset_gpio, 1); /* release reset line */
gpiod_set_value_cansleep(ddata->reset_gpio, 1);
/* wait after releasing reset */ /* wait after releasing reset */
usleep_range(5000, 10000); usleep_range(5000, 10000);
} }
...@@ -886,7 +889,7 @@ static int dsicm_update(struct omap_dss_device *dssdev, ...@@ -886,7 +889,7 @@ static int dsicm_update(struct omap_dss_device *dssdev,
if (r) if (r)
goto err; goto err;
if (ddata->te_enabled && gpio_is_valid(ddata->ext_te_gpio)) { if (ddata->te_enabled && ddata->ext_te_gpio) {
schedule_delayed_work(&ddata->te_timeout_work, schedule_delayed_work(&ddata->te_timeout_work,
msecs_to_jiffies(250)); msecs_to_jiffies(250));
atomic_set(&ddata->do_update, 1); atomic_set(&ddata->do_update, 1);
...@@ -933,7 +936,7 @@ static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable) ...@@ -933,7 +936,7 @@ static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
else else
r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_TEAR_OFF); r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_TEAR_OFF);
if (!gpio_is_valid(ddata->ext_te_gpio)) if (!ddata->ext_te_gpio)
in->ops.dsi->enable_te(in, enable); in->ops.dsi->enable_te(in, enable);
/* possible panel bug */ /* possible panel bug */
...@@ -1115,41 +1118,6 @@ static struct omap_dss_driver dsicm_ops = { ...@@ -1115,41 +1118,6 @@ static struct omap_dss_driver dsicm_ops = {
.memory_read = dsicm_memory_read, .memory_read = dsicm_memory_read,
}; };
static int dsicm_probe_of(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct panel_drv_data *ddata = platform_get_drvdata(pdev);
struct omap_dss_device *in;
int gpio;
gpio = of_get_named_gpio(node, "reset-gpios", 0);
if (!gpio_is_valid(gpio)) {
dev_err(&pdev->dev, "failed to parse reset gpio\n");
return gpio;
}
ddata->reset_gpio = gpio;
gpio = of_get_named_gpio(node, "te-gpios", 0);
if (gpio_is_valid(gpio) || gpio == -ENOENT) {
ddata->ext_te_gpio = gpio;
} else {
dev_err(&pdev->dev, "failed to parse TE gpio\n");
return gpio;
}
in = omapdss_of_find_source_for_first_ep(node);
if (IS_ERR(in)) {
dev_err(&pdev->dev, "failed to find video source\n");
return PTR_ERR(in);
}
ddata->in = in;
/* TODO: ulps, backlight */
return 0;
}
static int dsicm_probe(struct platform_device *pdev) static int dsicm_probe(struct platform_device *pdev)
{ {
struct backlight_properties props; struct backlight_properties props;
...@@ -1171,9 +1139,12 @@ static int dsicm_probe(struct platform_device *pdev) ...@@ -1171,9 +1139,12 @@ static int dsicm_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ddata); platform_set_drvdata(pdev, ddata);
ddata->pdev = pdev; ddata->pdev = pdev;
r = dsicm_probe_of(pdev); ddata->in = omapdss_of_find_source_for_first_ep(pdev->dev.of_node);
if (r) r = PTR_ERR_OR_ZERO(ddata->in);
if (r) {
dev_err(&pdev->dev, "failed to find video source: %d\n", r);
return r; return r;
}
ddata->timings.x_res = 864; ddata->timings.x_res = 864;
ddata->timings.y_res = 480; ddata->timings.y_res = 480;
...@@ -1200,24 +1171,27 @@ static int dsicm_probe(struct platform_device *pdev) ...@@ -1200,24 +1171,27 @@ static int dsicm_probe(struct platform_device *pdev)
atomic_set(&ddata->do_update, 0); atomic_set(&ddata->do_update, 0);
if (gpio_is_valid(ddata->reset_gpio)) { ddata->reset_gpio = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
r = devm_gpio_request_one(dev, ddata->reset_gpio, r = PTR_ERR_OR_ZERO(ddata->reset_gpio);
GPIOF_OUT_INIT_LOW, "taal rst");
if (r) { if (r) {
dev_err(dev, "failed to request reset gpio\n"); dev_err(&pdev->dev, "Failed to request reset gpio: %d\n", r);
return r; return r;
} }
}
if (gpio_is_valid(ddata->ext_te_gpio)) { gpiod_set_consumer_name(ddata->reset_gpio, "taal rst");
r = devm_gpio_request_one(dev, ddata->ext_te_gpio,
GPIOF_IN, "taal irq"); ddata->ext_te_gpio = devm_gpiod_get_optional(&pdev->dev, "te",
GPIOD_IN);
r = PTR_ERR_OR_ZERO(ddata->ext_te_gpio);
if (r) { if (r) {
dev_err(dev, "GPIO request failed\n"); dev_err(&pdev->dev, "Failed to request TE gpio: %d\n", r);
return r; return r;
} }
r = devm_request_irq(dev, gpio_to_irq(ddata->ext_te_gpio), if (ddata->ext_te_gpio) {
gpiod_set_consumer_name(ddata->ext_te_gpio, "taal irq");
r = devm_request_irq(dev, gpiod_to_irq(ddata->ext_te_gpio),
dsicm_te_isr, dsicm_te_isr,
IRQF_TRIGGER_RISING, IRQF_TRIGGER_RISING,
"taal vsync", ddata); "taal vsync", ddata);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment