aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/tilcdc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tilcdc')
-rw-r--r--drivers/gpu/drm/tilcdc/Kconfig1
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_crtc.c51
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c11
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_slave.c28
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_tfp410.c1
5 files changed, 56 insertions, 36 deletions
diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig
index 7a4d1010690..7c3ef79fcb3 100644
--- a/drivers/gpu/drm/tilcdc/Kconfig
+++ b/drivers/gpu/drm/tilcdc/Kconfig
@@ -2,6 +2,7 @@ config DRM_TILCDC
tristate "DRM Support for TI LCDC Display Controller"
depends on DRM && OF && ARM
select DRM_KMS_HELPER
+ select DRM_KMS_FB_HELPER
select DRM_KMS_CMA_HELPER
select DRM_GEM_CMA_HELPER
select VIDEOMODE_HELPERS
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index 7418dcd986d..d642d4a0213 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -15,7 +15,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <linux/kfifo.h>
+#include "drm_flip_work.h"
#include "tilcdc_drv.h"
#include "tilcdc_regs.h"
@@ -35,21 +35,18 @@ struct tilcdc_crtc {
struct drm_framebuffer *scanout[2];
/* for deferred fb unref's: */
- DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *);
- struct work_struct work;
+ struct drm_flip_work unref_work;
};
#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
-static void unref_worker(struct work_struct *work)
+static void unref_worker(struct drm_flip_work *work, void *val)
{
struct tilcdc_crtc *tilcdc_crtc =
- container_of(work, struct tilcdc_crtc, work);
+ container_of(work, struct tilcdc_crtc, unref_work);
struct drm_device *dev = tilcdc_crtc->base.dev;
- struct drm_framebuffer *fb;
mutex_lock(&dev->mode_config.mutex);
- while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb))
- drm_framebuffer_unreference(fb);
+ drm_framebuffer_unreference(val);
mutex_unlock(&dev->mode_config.mutex);
}
@@ -68,21 +65,16 @@ static void set_scanout(struct drm_crtc *crtc, int n)
};
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
struct drm_device *dev = crtc->dev;
+ struct tilcdc_drm_private *priv = dev->dev_private;
pm_runtime_get_sync(dev->dev);
tilcdc_write(dev, base_reg[n], tilcdc_crtc->start);
tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end);
if (tilcdc_crtc->scanout[n]) {
- if (kfifo_put(&tilcdc_crtc->unref_fifo,
- (const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) {
- struct tilcdc_drm_private *priv = dev->dev_private;
- queue_work(priv->wq, &tilcdc_crtc->work);
- } else {
- dev_err(dev->dev, "unref fifo full!\n");
- drm_framebuffer_unreference(tilcdc_crtc->scanout[n]);
- }
+ drm_flip_work_queue(&tilcdc_crtc->unref_work, tilcdc_crtc->scanout[n]);
+ drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
}
- tilcdc_crtc->scanout[n] = crtc->fb;
+ tilcdc_crtc->scanout[n] = crtc->primary->fb;
drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
tilcdc_crtc->dirty &= ~stat[n];
pm_runtime_put_sync(dev->dev);
@@ -92,7 +84,7 @@ static void update_scanout(struct drm_crtc *crtc)
{
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
struct drm_device *dev = crtc->dev;
- struct drm_framebuffer *fb = crtc->fb;
+ struct drm_framebuffer *fb = crtc->primary->fb;
struct drm_gem_cma_object *gem;
unsigned int depth, bpp;
@@ -149,14 +141,15 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON);
drm_crtc_cleanup(crtc);
- WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo));
- kfifo_free(&tilcdc_crtc->unref_fifo);
+ drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
+
kfree(tilcdc_crtc);
}
static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event)
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags)
{
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
struct drm_device *dev = crtc->dev;
@@ -166,7 +159,7 @@ static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
return -EBUSY;
}
- crtc->fb = fb;
+ crtc->primary->fb = fb;
tilcdc_crtc->event = event;
update_scanout(crtc);
@@ -346,7 +339,7 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
if (priv->rev == 2) {
unsigned int depth, bpp;
- drm_fb_get_bpp_depth(crtc->fb->pixel_format, &depth, &bpp);
+ drm_fb_get_bpp_depth(crtc->primary->fb->pixel_format, &depth, &bpp);
switch (bpp) {
case 16:
break;
@@ -379,7 +372,12 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
else
tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
- if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ /*
+ * use value from adjusted_mode here as this might have been
+ * changed as part of the fixup for slave encoders to solve the
+ * issue where tilcdc timings are not VESA compliant
+ */
+ if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
else
tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
@@ -666,14 +664,13 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
- ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL);
+ ret = drm_flip_work_init(&tilcdc_crtc->unref_work, 16,
+ "unref", unref_worker);
if (ret) {
dev_err(dev->dev, "could not allocate unref FIFO\n");
goto fail;
}
- INIT_WORK(&tilcdc_crtc->work, unref_worker);
-
ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
if (ret < 0)
goto fail;
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 40b71da5a21..b20b69488dc 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -268,7 +268,7 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags)
}
pm_runtime_get_sync(dev->dev);
- ret = drm_irq_install(dev);
+ ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
pm_runtime_put_sync(dev->dev);
if (ret < 0) {
dev_err(dev->dev, "failed to install IRQ handler\n");
@@ -311,7 +311,7 @@ static void tilcdc_lastclose(struct drm_device *dev)
drm_fbdev_cma_restore_mode(priv->fbdev);
}
-static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS)
+static irqreturn_t tilcdc_irq(int irq, void *arg)
{
struct drm_device *dev = arg;
struct tilcdc_drm_private *priv = dev->dev_private;
@@ -444,7 +444,7 @@ static int tilcdc_mm_show(struct seq_file *m, void *arg)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
- return drm_mm_dump_table(m, dev->mm_private);
+ return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
}
static struct drm_info_list tilcdc_debugfs_list[] = {
@@ -497,7 +497,6 @@ static const struct file_operations fops = {
#endif
.poll = drm_poll,
.read = drm_read,
- .fasync = drm_fasync,
.llseek = no_llseek,
.mmap = drm_gem_cma_mmap,
};
@@ -519,7 +518,7 @@ static struct drm_driver tilcdc_driver = {
.gem_vm_ops = &drm_gem_cma_vm_ops,
.dumb_create = drm_gem_cma_dumb_create,
.dumb_map_offset = drm_gem_cma_dumb_map_offset,
- .dumb_destroy = drm_gem_cma_dumb_destroy,
+ .dumb_destroy = drm_gem_dumb_destroy,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = tilcdc_debugfs_init,
.debugfs_cleanup = tilcdc_debugfs_cleanup,
@@ -595,7 +594,7 @@ static int tilcdc_pdev_probe(struct platform_device *pdev)
static int tilcdc_pdev_remove(struct platform_device *pdev)
{
- drm_platform_exit(&tilcdc_driver, pdev);
+ drm_put_dev(platform_get_drvdata(pdev));
return 0;
}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
index dfffaf01402..595068ba2d5 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
@@ -16,7 +16,6 @@
*/
#include <linux/i2c.h>
-#include <linux/of_i2c.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/consumer.h>
#include <drm/drm_encoder_slave.h>
@@ -73,13 +72,38 @@ static void slave_encoder_prepare(struct drm_encoder *encoder)
tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info);
}
+static bool slave_encoder_fixup(struct drm_encoder *encoder,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ /*
+ * tilcdc does not generate VESA-complient sync but aligns
+ * VS on the second edge of HS instead of first edge.
+ * We use adjusted_mode, to fixup sync by aligning both rising
+ * edges and add HSKEW offset to let the slave encoder fix it up.
+ */
+ adjusted_mode->hskew = mode->hsync_end - mode->hsync_start;
+ adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW;
+
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC) {
+ adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC;
+ adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC;
+ } else {
+ adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC;
+ adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC;
+ }
+
+ return drm_i2c_encoder_mode_fixup(encoder, mode, adjusted_mode);
+}
+
+
static const struct drm_encoder_funcs slave_encoder_funcs = {
.destroy = slave_encoder_destroy,
};
static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = {
.dpms = drm_i2c_encoder_dpms,
- .mode_fixup = drm_i2c_encoder_mode_fixup,
+ .mode_fixup = slave_encoder_fixup,
.prepare = slave_encoder_prepare,
.commit = drm_i2c_encoder_commit,
.mode_set = drm_i2c_encoder_mode_set,
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
index 925c7cddeff..c38b56b268a 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
@@ -16,7 +16,6 @@
*/
#include <linux/i2c.h>
-#include <linux/of_i2c.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/pinmux.h>