* [PATCH 02/15] gma500: Move the 2D operations into DRM
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
@ 2011-07-15 16:32 ` Alan Cox
2011-07-15 16:32 ` [PATCH 03/15] gma500: add an mmap ioctl Alan Cox
` (13 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:32 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
We currently have a test hack framebuffer mode ioctl, turn that into a DRM
interface.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/accel_2d.c | 60 ++++++++++++++++++++++++++++++++--
drivers/staging/gma500/framebuffer.c | 25 +-------------
drivers/staging/gma500/psb_drm.h | 13 +++++++
drivers/staging/gma500/psb_drv.c | 9 +++--
drivers/staging/gma500/psb_drv.h | 7 +++-
5 files changed, 82 insertions(+), 32 deletions(-)
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c
index c719017..ed00854 100644
--- a/drivers/staging/gma500/accel_2d.c
+++ b/drivers/staging/gma500/accel_2d.c
@@ -105,19 +105,20 @@ static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
* Issue one or more 2D commands to the accelerator. This needs to be
* serialized later when we add the GEM interfaces for acceleration
*/
-int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
+static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
unsigned size)
{
int ret = 0;
int i;
unsigned submit_size;
+ mutex_lock(&dev_priv->mutex_2d);
while (size > 0) {
submit_size = (size < 0x60) ? size : 0x60;
size -= submit_size;
ret = psb_2d_wait_available(dev_priv, submit_size);
if (ret)
- return ret;
+ break;
submit_size <<= 2;
@@ -126,7 +127,8 @@ int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
}
- return 0;
+ mutex_unlock(&dev_priv->mutex_2d);
+ return ret;
}
@@ -326,6 +328,7 @@ int psbfb_sync(struct fb_info *info)
unsigned long _end = jiffies + DRM_HZ;
int busy = 0;
+ mutex_lock(&dev_priv->mutex_2d);
/*
* First idle the 2D engine.
*/
@@ -354,5 +357,56 @@ int psbfb_sync(struct fb_info *info)
_PSB_C2B_STATUS_BUSY) != 0);
out:
+ mutex_unlock(&dev_priv->mutex_2d);
return (busy) ? -EBUSY : 0;
}
+
+int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_2d_op *op = data;
+ u32 *op_ptr = &op->cmd[0];
+ int i;
+ struct drm_gem_object *obj;
+ struct gtt_range *gtt;
+ int err = -EINVAL;
+
+ if (!dev_priv->ops->accel_2d)
+ return -EOPNOTSUPP;
+ if (op->size > PSB_2D_OP_BUFLEN)
+ return -EINVAL;
+
+ /* The GEM object being used. We need to support separate src/dst/etc
+ in the end but for now keep them all the same */
+ obj = drm_gem_object_lookup(dev, file, op->src);
+ if (obj == NULL)
+ return -ENOENT;
+ gtt = container_of(obj, struct gtt_range, gem);
+
+ if (psb_gtt_pin(gtt) < 0)
+ goto bad_2;
+ for (i = 0; i < op->size; i++, op_ptr++) {
+ u32 r = *op_ptr & 0xF0000000;
+ /* Fill in the GTT offsets for the command buffer */
+ if (r == PSB_2D_SRC_SURF_BH ||
+ r == PSB_2D_DST_SURF_BH ||
+ r == PSB_2D_MASK_SURF_BH ||
+ r == PSB_2D_PAT_SURF_BH) {
+ i++;
+ op_ptr++;
+ if (i == op->size)
+ goto bad;
+ if (*op_ptr)
+ goto bad;
+ *op_ptr = gtt->offset;
+ continue;
+ }
+ }
+ psbfb_2d_submit(dev_priv, op->cmd, op->size);
+ err = 0;
+bad:
+ psb_gtt_unpin(gtt);
+bad_2:
+ drm_gem_object_unreference(obj);
+ return err;
+}
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
index 76b986f..d890a50 100644
--- a/drivers/staging/gma500/framebuffer.c
+++ b/drivers/staging/gma500/framebuffer.c
@@ -200,30 +200,7 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
- struct psb_fbdev *fbdev = info->par;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
- struct drm_device *dev = psbfb->base.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 __user *p = (u32 __user *)arg;
- u32 l;
- u32 buf[32];
- switch (cmd) {
- case 0x12345678:
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- if (!dev_priv->ops->accel_2d)
- return -EOPNOTSUPP;
- if (get_user(l, p))
- return -EFAULT;
- if (l > 32)
- return -EMSGSIZE;
- if (copy_from_user(buf, p + 1, l * sizeof(u32)))
- return -EFAULT;
- psbfb_2d_submit(dev_priv, buf, l);
- return 0;
- default:
- return -ENOTTY;
- }
+ return -ENOTTY;
}
static struct fb_ops psbfb_ops = {
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
index 7175117..eef53f3 100644
--- a/drivers/staging/gma500/psb_drm.h
+++ b/drivers/staging/gma500/psb_drm.h
@@ -161,6 +161,7 @@ struct drm_psb_register_rw_arg {
*/
#define DRM_PSB_GEM_CREATE 0x10
+#define DRM_PSB_2D_OP 0x11
#define DRM_PSB_DPST 0x1B
#define DRM_PSB_GAMMA 0x1C
#define DRM_PSB_DPST_BL 0x1D
@@ -190,4 +191,16 @@ struct drm_psb_gem_create {
__u32 pad;
};
+#define PSB_2D_OP_BUFLEN 16
+
+struct drm_psb_2d_op {
+ __u32 src; /* Handles, only src supported right now */
+ __u32 dst;
+ __u32 mask;
+ __u32 pat;
+ __u32 size; /* In dwords of command */
+ __u32 spare; /* And bumps array to u64 align */
+ __u32 cmd[PSB_2D_OP_BUFLEN];
+};
+
#endif
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index a753977..36bb716 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -124,6 +124,9 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
#define DRM_IOCTL_PSB_GEM_CREATE \
DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \
struct drm_psb_gem_create)
+#define DRM_IOCTL_PSB_2D_OP \
+ DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \
+ struct drm_psb_2d_op)
static int psb_sizes_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
@@ -164,7 +167,7 @@ static struct drm_ioctl_desc psb_ioctls[] = {
psb_intel_get_pipe_from_crtc_id, 0),
PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl,
DRM_UNLOCKED | DRM_AUTH),
-
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl, DRM_UNLOCKED),
};
static void psb_lastclose(struct drm_device *dev)
@@ -179,8 +182,7 @@ static void psb_do_takedown(struct drm_device *dev)
static int psb_do_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
+ struct drm_psb_private *dev_priv = dev->dev_private;
struct psb_gtt *pg = &dev_priv->gtt;
uint32_t stolen_gtt;
@@ -221,6 +223,7 @@ static int psb_do_init(struct drm_device *dev)
spin_lock_init(&dev_priv->irqmask_lock);
+ mutex_init(&dev_priv->mutex_2d);
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 12d13ae..db3e356 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -599,6 +599,9 @@ struct drm_psb_private {
bool dsr_enable;
void (*exit_idle)(struct drm_device *dev, u32 update_src, void *p_surfaceAddr, bool check_hw_on_only);
+ /* 2D acceleration */
+ struct mutex mutex_2d;
+
/* FIXME: Arrays anyone ? */
struct mdfld_dsi_encoder *encoder0;
struct mdfld_dsi_encoder *encoder2;
@@ -744,8 +747,8 @@ extern void psbfb_copyarea(struct fb_info *info,
const struct fb_copyarea *region);
extern int psbfb_sync(struct fb_info *info);
extern void psb_spank(struct drm_psb_private *dev_priv);
-extern int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
- unsigned size);
+extern int psb_accel_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file);
/*
* psb_reset.c
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 03/15] gma500: add an mmap ioctl
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
2011-07-15 16:32 ` [PATCH 02/15] gma500: Move the 2D operations into DRM Alan Cox
@ 2011-07-15 16:32 ` Alan Cox
2011-07-15 16:33 ` [PATCH 04/15] gma500: allow the creation of 'stolen' memory objects Alan Cox
` (12 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:32 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
This does the same as the dumb mmap but we want them separated in the ABI
in case a future extension to the dumb interface means we can't treat them
the same way.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/gem.c | 8 ++++++++
drivers/staging/gma500/psb_drm.h | 12 ++++++++++++
drivers/staging/gma500/psb_drv.c | 8 +++++++-
drivers/staging/gma500/psb_drv.h | 2 ++
4 files changed, 29 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c
index 68ecd5f..d7b74b6 100644
--- a/drivers/staging/gma500/gem.c
+++ b/drivers/staging/gma500/gem.c
@@ -261,3 +261,11 @@ int psb_gem_create_ioctl(struct drm_device *dev, void *data,
return psb_gem_create(file, dev, args->size, &args->handle);
}
+int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_psb_gem_mmap *args = data;
+ return dev->driver->dumb_map_offset(file, dev,
+ args->handle, &args->offset);
+}
+
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
index eef53f3..70115a9 100644
--- a/drivers/staging/gma500/psb_drm.h
+++ b/drivers/staging/gma500/psb_drm.h
@@ -162,6 +162,7 @@ struct drm_psb_register_rw_arg {
#define DRM_PSB_GEM_CREATE 0x10
#define DRM_PSB_2D_OP 0x11
+#define DRM_PSB_GEM_MMAP 0x12
#define DRM_PSB_DPST 0x1B
#define DRM_PSB_GAMMA 0x1C
#define DRM_PSB_DPST_BL 0x1D
@@ -203,4 +204,15 @@ struct drm_psb_2d_op {
__u32 cmd[PSB_2D_OP_BUFLEN];
};
+struct drm_psb_gem_mmap {
+ __u32 handle;
+ __u32 pad;
+ /**
+ * Fake offset to use for subsequent mmap call
+ *
+ * This is a fixed-size type for 32/64 compatibility.
+ */
+ __u64 offset;
+};
+
#endif
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 36bb716..b8b9864 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -127,6 +127,9 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
#define DRM_IOCTL_PSB_2D_OP \
DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \
struct drm_psb_2d_op)
+#define DRM_IOCTL_PSB_GEM_MMAP \
+ DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \
+ struct drm_psb_gem_mmap)
static int psb_sizes_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
@@ -167,7 +170,10 @@ static struct drm_ioctl_desc psb_ioctls[] = {
psb_intel_get_pipe_from_crtc_id, 0),
PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl,
DRM_UNLOCKED | DRM_AUTH),
- PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl, DRM_UNLOCKED),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl,
+ DRM_UNLOCKED| DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl,
+ DRM_UNLOCKED | DRM_AUTH),
};
static void psb_lastclose(struct drm_device *dev)
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index db3e356..daf3ca5 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -799,6 +799,8 @@ extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
extern int psb_gem_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
+extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file);
/* psb_device.c */
extern const struct psb_ops psb_chip_ops;
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 04/15] gma500: allow the creation of 'stolen' memory objects
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
2011-07-15 16:32 ` [PATCH 02/15] gma500: Move the 2D operations into DRM Alan Cox
2011-07-15 16:32 ` [PATCH 03/15] gma500: add an mmap ioctl Alan Cox
@ 2011-07-15 16:33 ` Alan Cox
2011-07-15 16:33 ` [PATCH 05/15] gma500: remove the legacy PM method Alan Cox
` (11 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:33 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
For things like cursors and many kinds of framebuffer set up we are actually
best using the stolen memory when possible.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/gem.c | 24 ++++++++++++++++++++++++
drivers/staging/gma500/psb_drm.h | 3 ++-
2 files changed, 26 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c
index d7b74b6..65fdd6b 100644
--- a/drivers/staging/gma500/gem.c
+++ b/drivers/staging/gma500/gem.c
@@ -251,6 +251,21 @@ fail:
}
}
+static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev,
+ int size, u32 *handle)
+{
+ struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1);
+ if (gtt == NULL)
+ return -ENOMEM;
+ if (drm_gem_private_object_init(dev, >t->gem, size) != 0)
+ goto free_gtt;
+ if (drm_gem_handle_create(file, >t->gem, handle) == 0)
+ return 0;
+free_gtt:
+ psb_gtt_free_range(dev, gtt);
+ return -ENOMEM;
+}
+
/*
* GEM interfaces for our specific client
*/
@@ -258,6 +273,15 @@ int psb_gem_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_psb_gem_create *args = data;
+ int ret;
+ if (args->flags & PSB_GEM_CREATE_STOLEN) {
+ ret = psb_gem_create_stolen(file, dev, args->size,
+ &args->handle);
+ if (ret == 0)
+ return 0;
+ /* Fall throguh */
+ args->flags &= ~PSB_GEM_CREATE_STOLEN;
+ }
return psb_gem_create(file, dev, args->size, &args->handle);
}
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
index 70115a9..0da8468 100644
--- a/drivers/staging/gma500/psb_drm.h
+++ b/drivers/staging/gma500/psb_drm.h
@@ -189,7 +189,8 @@ struct psb_drm_dpu_rect {
struct drm_psb_gem_create {
__u64 size;
__u32 handle;
- __u32 pad;
+ __u32 flags;
+#define PSB_GEM_CREATE_STOLEN 1 /* Stolen memory can be used */
};
#define PSB_2D_OP_BUFLEN 16
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 05/15] gma500: remove the legacy PM method
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (2 preceding siblings ...)
2011-07-15 16:33 ` [PATCH 04/15] gma500: allow the creation of 'stolen' memory objects Alan Cox
@ 2011-07-15 16:33 ` Alan Cox
2011-07-15 16:33 ` [PATCH 06/15] gma500: Make crtc count a property of the device Alan Cox
` (10 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:33 UTC (permalink / raw)
To: greg, linux-kernel
From: Octavian Purdila <octavian.purdila@intel.com>
PCI core only prefer one of legacy PM and new PM. And since runtime pm
is implemented, which requires the new PM method, we should remove the
legacy PM method.
Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/power.c | 9 +++++----
drivers/staging/gma500/power.h | 4 ++--
drivers/staging/gma500/psb_drv.c | 6 ++----
3 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
index 5cd5023..972bea7 100644
--- a/drivers/staging/gma500/power.c
+++ b/drivers/staging/gma500/power.c
@@ -185,8 +185,9 @@ static bool gma_resume_pci(struct pci_dev *pdev)
* perform the necessary shut down steps and save enough state that
* we can undo this when resume is called.
*/
-int gma_power_suspend(struct pci_dev *pdev, pm_message_t state)
+int gma_power_suspend(struct device *_dev)
{
+ struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
struct drm_device *dev = pci_get_drvdata(pdev);
struct drm_psb_private *dev_priv = dev->dev_private;
@@ -210,8 +211,9 @@ int gma_power_suspend(struct pci_dev *pdev, pm_message_t state)
*
* Resume the PCI side of the graphics and then the displays
*/
-int gma_power_resume(struct pci_dev *pdev)
+int gma_power_resume(struct device *_dev)
{
+ struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
struct drm_device *dev = pci_get_drvdata(pdev);
mutex_lock(&power_mutex);
@@ -295,8 +297,7 @@ void gma_power_end(struct drm_device *dev)
int psb_runtime_suspend(struct device *dev)
{
- static pm_message_t dummy;
- return gma_power_suspend(to_pci_dev(dev), dummy);
+ return gma_power_suspend(dev);
}
int psb_runtime_resume(struct device *dev)
diff --git a/drivers/staging/gma500/power.h b/drivers/staging/gma500/power.h
index 333b28d..1969d2e 100644
--- a/drivers/staging/gma500/power.h
+++ b/drivers/staging/gma500/power.h
@@ -39,8 +39,8 @@ void gma_power_uninit(struct drm_device *dev);
/*
* The kernel bus power management will call these functions
*/
-int gma_power_suspend(struct pci_dev *pdev, pm_message_t state);
-int gma_power_resume(struct pci_dev *pdev);
+int gma_power_suspend(struct device *dev);
+int gma_power_resume(struct device *dev);
/*
* These are the functions the driver should use to wrap all hw access
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index b8b9864..f96a619 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -1144,6 +1144,8 @@ static void psb_remove(struct pci_dev *pdev)
}
static const struct dev_pm_ops psb_pm_ops = {
+ .resume = gma_power_resume,
+ .suspend = gma_power_suspend,
.runtime_suspend = psb_runtime_suspend,
.runtime_resume = psb_runtime_resume,
.runtime_idle = psb_runtime_idle,
@@ -1205,13 +1207,9 @@ static struct drm_driver driver = {
static struct pci_driver psb_pci_driver = {
.name = DRIVER_NAME,
.id_table = pciidlist,
- .resume = gma_power_resume,
- .suspend = gma_power_suspend,
.probe = psb_probe,
.remove = psb_remove,
-#ifdef CONFIG_PM
.driver.pm = &psb_pm_ops,
-#endif
};
static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 06/15] gma500: Make crtc count a property of the device
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (3 preceding siblings ...)
2011-07-15 16:33 ` [PATCH 05/15] gma500: remove the legacy PM method Alan Cox
@ 2011-07-15 16:33 ` Alan Cox
2011-07-15 16:33 ` [PATCH 07/15] gma500: fix compile warnings when CONFIG_BACKLIGHT_CLASS_DEVICE is not defined Alan Cox
` (9 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:33 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
Octavian Purdila posted a patch that sets num_crtc to 1 for Moorestown, but
Oaktrail has 2 so we need to split Oaktrail/Moorestown more sensibly, and
also cope with some other differences later on.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/framebuffer.c | 2 +-
drivers/staging/gma500/mdfld_device.c | 1 +
drivers/staging/gma500/mrst_device.c | 41 +++++++++++++++++++++++++++++++++
drivers/staging/gma500/psb_device.c | 1 +
drivers/staging/gma500/psb_drv.h | 1 +
5 files changed, 45 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
index d890a50..ebfde13 100644
--- a/drivers/staging/gma500/framebuffer.c
+++ b/drivers/staging/gma500/framebuffer.c
@@ -578,7 +578,7 @@ int psb_fbdev_init(struct drm_device *dev)
dev_priv->fbdev = fbdev;
fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
- drm_fb_helper_init(dev, &fbdev->psb_fb_helper, 2,
+ drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs,
INTELFB_CONN_LIMIT);
drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
index f258b06..f47aeb7 100644
--- a/drivers/staging/gma500/mdfld_device.c
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -691,6 +691,7 @@ const struct psb_ops mdfld_chip_ops = {
.name = "Medfield",
.accel_2d = 0,
.pipes = 3,
+ .crtcs = 2,
.sgx_offset = MRST_SGX_OFFSET,
.chip_setup = mid_chip_setup,
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index 436580d..3d525a0 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -24,9 +24,12 @@
#include "psb_drv.h"
#include "psb_reg.h"
#include "psb_intel_reg.h"
+#include <asm/mrst.h>
#include <asm/intel_scu_ipc.h>
#include "mid_bios.h"
+static const struct psb_ops oaktrail_chip_ops;
+
/* IPC message and command defines used to enable/disable mipi panel voltages */
#define IPC_MSG_PANEL_ON_OFF 0xE9
#define IPC_CMD_PANEL_ON 1
@@ -352,10 +355,48 @@ static int mrst_power_up(struct drm_device *dev)
return 0;
}
+static int mrst_chip_setup(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+#if defined(CONFIG_X86_MRST)
+ if (mrst_identify_cpu())
+ return mid_chip_setup(dev);
+#endif
+ dev_priv->ops = &oaktrail_chip_ops;
+ /* Check - may be better to go via BIOS paths ? */
+ return mid_chip_setup(dev);
+}
+
const struct psb_ops mrst_chip_ops = {
.name = "Moorestown",
.accel_2d = 1,
.pipes = 1,
+ .crtcs = 1,
+ .sgx_offset = MRST_SGX_OFFSET,
+
+ .chip_setup = mrst_chip_setup,
+ .crtc_helper = &mrst_helper_funcs,
+ .crtc_funcs = &psb_intel_crtc_funcs,
+
+ .output_init = mrst_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+ .backlight_init = mrst_backlight_init,
+#endif
+
+ .init_pm = mrst_init_pm,
+ .save_regs = mrst_save_display_registers,
+ .restore_regs = mrst_restore_display_registers,
+ .power_down = mrst_power_down,
+ .power_up = mrst_power_up,
+};
+
+static const struct psb_ops oaktrail_chip_ops = {
+ .name = "Oaktrail",
+ .accel_2d = 1,
+ .pipes = 2,
+ .crtcs = 2,
.sgx_offset = MRST_SGX_OFFSET,
.chip_setup = mid_chip_setup,
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
index 1e117f0..4659132 100644
--- a/drivers/staging/gma500/psb_device.c
+++ b/drivers/staging/gma500/psb_device.c
@@ -331,6 +331,7 @@ const struct psb_ops psb_chip_ops = {
.name = "Poulsbo",
.accel_2d = 1,
.pipes = 2,
+ .crtcs = 2,
.sgx_offset = PSB_SGX_OFFSET,
.chip_setup = psb_chip_setup,
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index daf3ca5..8184c23 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -622,6 +622,7 @@ struct psb_ops {
const char *name;
unsigned int accel_2d:1;
int pipes; /* Number of output pipes */
+ int crtcs; /* Number of CRTCs */
int sgx_offset; /* Base offset of SGX device */
/* Sub functions */
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 07/15] gma500: fix compile warnings when CONFIG_BACKLIGHT_CLASS_DEVICE is not defined
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (4 preceding siblings ...)
2011-07-15 16:33 ` [PATCH 06/15] gma500: Make crtc count a property of the device Alan Cox
@ 2011-07-15 16:33 ` Alan Cox
2011-07-15 16:34 ` [PATCH 08/15] gma500: skip getting modes via DDC on Moorestown Alan Cox
` (8 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:33 UTC (permalink / raw)
To: greg, linux-kernel
From: Octavian Purdila <octavian.purdila@intel.com>
Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
[Fixed up for other changes, and tidied some existing variable names]
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/backlight.c | 2 ++
drivers/staging/gma500/mdfld_dsi_output.c | 5 ++---
drivers/staging/gma500/psb_drv.c | 28 +++++++++++++---------------
drivers/staging/gma500/psb_intel_lvds.c | 19 +++++++------------
4 files changed, 24 insertions(+), 30 deletions(-)
diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
index d3e698b..2079395 100644
--- a/drivers/staging/gma500/backlight.c
+++ b/drivers/staging/gma500/backlight.c
@@ -31,6 +31,8 @@ int gma_backlight_init(struct drm_device *dev)
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
struct drm_psb_private *dev_priv = dev->dev_private;
return dev_priv->ops->backlight_init(dev);
+#else
+ return 0;
#endif
}
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
index e911ef2..ff75ece 100644
--- a/drivers/staging/gma500/mdfld_dsi_output.c
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -467,8 +467,6 @@ static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
uint64_t value)
{
struct drm_encoder * encoder = connector->encoder;
- struct backlight_device * psb_bd;
- struct drm_psb_private * dev_priv = encoder->dev->dev_private;
if (!strcmp(property->name, "scaling mode") && encoder) {
struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
@@ -515,13 +513,14 @@ static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
}
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
} else if (!strcmp(property->name, "backlight") && encoder) {
+ struct drm_psb_private *dev_priv = encoder->dev->dev_private;
+ struct backlight_device *psb_bd = dev_priv->backlight_device;
dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
if (drm_connector_property_set_value(connector, property, value))
goto set_prop_error;
else {
dev_dbg(encoder->dev->dev,
"set brightness to %d", (int)value);
- psb_bd = dev_priv->backlight_device;
if (psb_bd) {
psb_bd->props.brightness = value;
backlight_update_status(psb_bd);
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index f96a619..6b03951ebd 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -536,20 +536,24 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
return -EINVAL;
}
-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+static inline void get_brightness(struct backlight_device *bd)
{
- struct drm_psb_private *dev_priv = psb_priv(dev);
- uint32_t *arg = data;
- struct backlight_device *bd = dev_priv->backlight_device;
- dev_priv->blc_adj2 = *arg;
-
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
if (bd) {
bd->props.brightness = bd->ops->get_brightness(bd);
backlight_update_status(bd);
}
#endif
+}
+
+static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ uint32_t *arg = data;
+
+ dev_priv->blc_adj2 = *arg;
+ get_brightness(dev_priv->backlight_device);
return 0;
}
@@ -558,15 +562,9 @@ static int psb_adb_ioctl(struct drm_device *dev, void *data,
{
struct drm_psb_private *dev_priv = psb_priv(dev);
uint32_t *arg = data;
- struct backlight_device *bd = dev_priv->backlight_device;
- dev_priv->blc_adj1 = *arg;
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- if (bd) {
- bd->props.brightness = bd->ops->get_brightness(bd);
- backlight_update_status(bd);
- }
-#endif
+ dev_priv->blc_adj1 = *arg;
+ get_brightness(dev_priv->backlight_device);
return 0;
}
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index 03132a4..da6f5c8 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -467,8 +467,6 @@ static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
- struct psb_intel_mode_device *mode_dev =
- enc_to_psb_intel_output(encoder)->mode_dev;
struct drm_device *dev = encoder->dev;
struct drm_psb_private *dev_priv = dev->dev_private;
u32 pfit_control;
@@ -571,17 +569,14 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
uint64_t value)
{
struct drm_encoder *encoder = connector->encoder;
- struct drm_psb_private *dev_priv;
if (!encoder)
return -1;
- dev_priv = encoder->dev->dev_private;
-
if (!strcmp(property->name, "scaling mode")) {
struct psb_intel_crtc *crtc =
to_psb_intel_crtc(encoder->crtc);
- uint64_t curValue;
+ uint64_t curval;
if (!crtc)
goto set_prop_error;
@@ -599,10 +594,10 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
if (drm_connector_property_get_value(connector,
property,
- &curValue))
+ &curval))
goto set_prop_error;
- if (curValue == value)
+ if (curval == value)
goto set_prop_done;
if (drm_connector_property_set_value(connector,
@@ -626,8 +621,8 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
goto set_prop_error;
else {
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct backlight_device *bd =
- dev_priv->backlight_device;
+ struct drm_psb_private *devp = encoder->dev->dev_private;
+ struct backlight_device *bd = devp->backlight_device;
if (bd) {
bd->props.brightness = value;
backlight_update_status(bd);
@@ -635,9 +630,9 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
#endif
}
} else if (!strcmp(property->name, "DPMS")) {
- struct drm_encoder_helper_funcs *pEncHFuncs
+ struct drm_encoder_helper_funcs *hfuncs
= encoder->helper_private;
- pEncHFuncs->dpms(encoder, value);
+ hfuncs->dpms(encoder, value);
}
set_prop_done:
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 08/15] gma500: skip getting modes via DDC on Moorestown
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (5 preceding siblings ...)
2011-07-15 16:33 ` [PATCH 07/15] gma500: fix compile warnings when CONFIG_BACKLIGHT_CLASS_DEVICE is not defined Alan Cox
@ 2011-07-15 16:34 ` Alan Cox
2011-07-15 16:34 ` [PATCH 09/15] gma500: Fix cdv warning on unused variable Alan Cox
` (7 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:34 UTC (permalink / raw)
To: greg, linux-kernel
From: Octavian Purdila <octavian.purdila@intel.com>
Moorestown does not have a DDC bus, skip getting modes via DDC. This
fixes the following bug:
BUG: unable to handle kernel NULL pointer dereference at 00000010
IP: [<c1172ff7>] i2c_transfer+0x17/0xb0
*pde = 00000000
Oops: 0000 [#1]
Call Trace:
[<c1153ae9>] drm_do_probe_ddc_edid+0x59/0x90
[<c1153cb4>] drm_get_edid+0x24/0x250
[<c11805d2>] psb_intel_ddc_get_modes+0x22/0x60
[<c117fe11>] psb_intel_lvds_get_modes+0x21/0x80
Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/psb_intel_lvds.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index da6f5c8..53803b2 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -521,7 +521,8 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
psb_intel_output->mode_dev;
int ret = 0;
- ret = psb_intel_ddc_get_modes(psb_intel_output);
+ if (!IS_MRST(dev))
+ ret = psb_intel_ddc_get_modes(psb_intel_output);
if (ret)
return ret;
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 09/15] gma500: Fix cdv warning on unused variable
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (6 preceding siblings ...)
2011-07-15 16:34 ` [PATCH 08/15] gma500: skip getting modes via DDC on Moorestown Alan Cox
@ 2011-07-15 16:34 ` Alan Cox
2011-07-15 16:34 ` [PATCH 10/15] gma500: Add the Oaktrail HDMI support Alan Cox
` (6 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:34 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/cdv_intel_lvds.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/gma500/cdv_intel_lvds.c b/drivers/staging/gma500/cdv_intel_lvds.c
index d9478d5..988b2d0 100644
--- a/drivers/staging/gma500/cdv_intel_lvds.c
+++ b/drivers/staging/gma500/cdv_intel_lvds.c
@@ -353,8 +353,6 @@ static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
- struct psb_intel_mode_device *mode_dev =
- enc_to_psb_intel_output(encoder)->mode_dev;
struct drm_device *dev = encoder->dev;
struct drm_psb_private *dev_priv = dev->dev_private;
u32 pfit_control;
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 10/15] gma500: Add the Oaktrail HDMI support
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (7 preceding siblings ...)
2011-07-15 16:34 ` [PATCH 09/15] gma500: Fix cdv warning on unused variable Alan Cox
@ 2011-07-15 16:34 ` Alan Cox
2011-07-15 16:34 ` [PATCH 11/15] gma500: More Moorestown muddle meddling means MM maybe might modeset Alan Cox
` (5 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:34 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
This differs enough from the Cedarview HDMI sufficiently to want to keep
them separated.
We need to sort out the power management for Oaktrail/Moorestown in order
to plumb this lot into the register handling logic.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/Makefile | 4
drivers/staging/gma500/mrst.h | 35 +
drivers/staging/gma500/mrst_device.c | 246 +++++++--
drivers/staging/gma500/mrst_hdmi.c | 852 ++++++++++++++++++++++++++++++++
drivers/staging/gma500/mrst_hdmi_i2c.c | 327 ++++++++++++
drivers/staging/gma500/psb_drv.c | 2
drivers/staging/gma500/psb_drv.h | 4
7 files changed, 1401 insertions(+), 69 deletions(-)
create mode 100644 drivers/staging/gma500/mrst_hdmi.c
create mode 100644 drivers/staging/gma500/mrst_hdmi_i2c.c
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index e515edf..fe34f18 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -32,7 +32,9 @@ psb_gfx-$(CONFIG_DRM_PSB_CDV) += cdv_device.o \
psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \
mrst_crtc.o \
- mrst_lvds.o
+ mrst_lvds.o \
+ mrst_hdmi.o \
+ mrst_hdmi_i2c.o
psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \
mdfld_output.o \
diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h
index 7bacb9a..b563dbc 100644
--- a/drivers/staging/gma500/mrst.h
+++ b/drivers/staging/gma500/mrst.h
@@ -215,3 +215,38 @@ struct mrst_gct_data {
#define GCT_R10_HEADER_SIZE 16
#define GCT_R10_DISPLAY_DESC_SIZE 28
+
+/*
+ * Moorestown HDMI interfaces
+ */
+
+struct mrst_hdmi_dev {
+ struct pci_dev *dev;
+ void __iomem *regs;
+ unsigned int mmio, mmio_len;
+ int dpms_mode;
+ struct hdmi_i2c_dev *i2c_dev;
+
+ /* register state */
+ u32 saveDPLL_CTRL;
+ u32 saveDPLL_DIV_CTRL;
+ u32 saveDPLL_ADJUST;
+ u32 saveDPLL_UPDATE;
+ u32 saveDPLL_CLK_ENABLE;
+ u32 savePCH_HTOTAL_B;
+ u32 savePCH_HBLANK_B;
+ u32 savePCH_HSYNC_B;
+ u32 savePCH_VTOTAL_B;
+ u32 savePCH_VBLANK_B;
+ u32 savePCH_VSYNC_B;
+ u32 savePCH_PIPEBCONF;
+ u32 savePCH_PIPEBSRC;
+};
+
+extern void mrst_hdmi_setup(struct drm_device *dev);
+extern void mrst_hdmi_teardown(struct drm_device *dev);
+extern int mrst_hdmi_i2c_init(struct pci_dev *dev);
+extern void mrst_hdmi_i2c_exit(struct pci_dev *dev);
+extern void mrst_hdmi_save(struct drm_device *dev);
+extern void mrst_hdmi_restore(struct drm_device *dev);
+extern void mrst_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev);
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index 3d525a0..20677f9 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -38,12 +38,13 @@ static const struct psb_ops oaktrail_chip_ops;
static int mrst_output_init(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
- if (dev_priv->iLVDS_enable) {
+ if (dev_priv->iLVDS_enable)
mrst_lvds_init(dev, &dev_priv->mode_dev);
- return 0;
- }
- dev_err(dev->dev, "DSI is not supported\n");
- return -ENODEV;
+ else
+ dev_err(dev->dev, "DSI is not supported\n");
+ if (dev_priv->hdmi_priv)
+ mrst_hdmi_init(dev, &dev_priv->mode_dev);
+ return 0;
}
/*
@@ -195,8 +196,8 @@ static void mrst_init_pm(struct drm_device *dev)
static int mrst_save_display_registers(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_crtc *crtc;
- struct drm_connector *connector;
+ int i;
+ u32 pp_stat;
/* Display arbitration control + watermarks */
dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
@@ -208,17 +209,91 @@ static int mrst_save_display_registers(struct drm_device *dev)
dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
- /* Save crtc and output state */
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- if (drm_helper_crtc_in_use(crtc))
- crtc->funcs->save(crtc);
- }
+ /* Pipe & plane A info */
+ dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
+ dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
+ dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
+ dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
+ dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
+ dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
+ dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
+ dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
+ dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
+ dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
+ dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
+ dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
+ dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
+ dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
+ dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
+ dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
+ dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
+ dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
+
+ /* Save cursor regs */
+ dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
+ dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
+ dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
+
+ /* Save palette (gamma) */
+ for (i = 0; i < 256; i++)
+ dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
+
+ if (dev_priv->hdmi_priv)
+ mrst_hdmi_save(dev);
+
+ /* Save performance state */
+ dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
+
+ /* LVDS state */
+ dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
+ dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
+ dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
+ dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
+ dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
+ dev_priv->saveLVDS = PSB_RVDC32(LVDS);
+ dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
+ dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
+ dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
+ dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
+
+ /* HW overlay */
+ dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
+ dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+ dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+ dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+ dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+ dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+ dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+
+ /* DPST registers */
+ dev_priv->saveHISTOGRAM_INT_CONTROL_REG = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+ dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+ if (dev_priv->iLVDS_enable) {
+ /* Shut down the panel */
+ PSB_WVDC32(0, PP_CONTROL);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- connector->funcs->save(connector);
+ do {
+ pp_stat = PSB_RVDC32(PP_STATUS);
+ } while (pp_stat & 0x80000000);
- mutex_unlock(&dev->mode_config.mutex);
+ /* Turn off the plane */
+ PSB_WVDC32(0x58000000, DSPACNTR);
+ /* Trigger the plane disable */
+ PSB_WVDC32(0, DSPASURF);
+
+ /* Wait ~4 ticks */
+ msleep(4);
+
+ /* Turn off pipe */
+ PSB_WVDC32(0x0, PIPEACONF);
+ /* Wait ~8 ticks */
+ msleep(8);
+
+ /* Turn off PLLs */
+ PSB_WVDC32(0, MRST_DPLL_A);
+ }
return 0;
}
@@ -231,18 +306,8 @@ static int mrst_save_display_registers(struct drm_device *dev)
static int mrst_restore_display_registers(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_crtc *crtc;
- struct drm_connector *connector;
- int pp_stat;
-
- if (!dev_priv->iLVDS_enable) {
-#ifdef CONFIG_X86_MRST
- intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
- IPC_CMD_PANEL_ON);
- /* FIXME: can we avoid this delay ? */
- msleep(2000); /* wait 2 seconds */
-#endif
- }
+ u32 pp_stat;
+ int i;
/* Display arbitration + watermarks */
PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
@@ -254,54 +319,92 @@ static int mrst_restore_display_registers(struct drm_device *dev)
PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
- /*make sure VGA plane is off. it initializes to on after reset!*/
+ /* Make sure VGA plane is off. it initializes to on after reset!*/
PSB_WVDC32(0x80000000, VGACNTRL);
- mutex_lock(&dev->mode_config.mutex);
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
- if (drm_helper_crtc_in_use(crtc))
- crtc->funcs->restore(crtc);
+ /* set the plls */
+ PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
+ PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- connector->funcs->restore(connector);
+ /* Actually enable it */
+ PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
+ DRM_UDELAY(150);
- mutex_unlock(&dev->mode_config.mutex);
+ /* Restore mode */
+ PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
+ PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
+ PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
+ PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
+ PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
+ PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
+ PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
+ PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
- if (dev_priv->iLVDS_enable) {
- /*shutdown the panel*/
- PSB_WVDC32(0, PP_CONTROL);
- do {
- pp_stat = PSB_RVDC32(PP_STATUS);
- } while (pp_stat & 0x80000000);
+ /* Restore performance mode*/
+ PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
- /* Turn off the plane */
- PSB_WVDC32(0x58000000, DSPACNTR);
- PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
- /* Wait ~4 ticks */
- msleep(4);
- /* Turn off pipe */
- PSB_WVDC32(0x0, PIPEACONF);
- /* Wait ~8 ticks */
- msleep(8);
+ /* Enable the pipe*/
+ if (dev_priv->iLVDS_enable)
+ PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
- /* Turn off PLLs */
- PSB_WVDC32(0, MRST_DPLL_A);
- } else {
- PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
- PSB_WVDC32(0x0, PIPEACONF);
- PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
- while (REG_READ(0x70008) & 0x40000000)
- cpu_relax();
- while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
- != DPI_FIFO_EMPTY)
- cpu_relax();
- PSB_WVDC32(0, DEVICE_READY_REG);
- /* Turn off panel power */
-#ifdef CONFIG_X86_MRST /* FIXME: kill define once modular */
- intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
- IPC_CMD_PANEL_OFF);
-#endif
+ /* Set up the plane*/
+ PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
+ PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
+ PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
+
+ /* Enable the plane */
+ PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
+ PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
+
+ /* Enable Cursor A */
+ PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
+ PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
+ PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
+
+ /* Restore palette (gamma) */
+ for (i = 0; i < 256; i++)
+ PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2));
+
+ if (dev_priv->hdmi_priv)
+ mrst_hdmi_restore(dev);
+
+ if (dev_priv->iLVDS_enable) {
+ PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
+ PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
+ PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
+ PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
+ PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
+ PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
+ PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
+ PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
+ PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
+ PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
}
+
+ /* Wait for cycle delay */
+ do {
+ pp_stat = PSB_RVDC32(PP_STATUS);
+ } while (pp_stat & 0x08000000);
+
+ /* Wait for panel power up */
+ do {
+ pp_stat = PSB_RVDC32(PP_STATUS);
+ } while (pp_stat & 0x10000000);
+
+ /* Restore HW overlay */
+ PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
+
+ /* DPST registers */
+ PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG, HISTOGRAM_INT_CONTROL);
+ PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG, HISTOGRAM_LOGIC_CONTROL);
+ PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
+
return 0;
}
@@ -364,9 +467,15 @@ static int mrst_chip_setup(struct drm_device *dev)
return mid_chip_setup(dev);
#endif
dev_priv->ops = &oaktrail_chip_ops;
+ mrst_hdmi_setup(dev);
/* Check - may be better to go via BIOS paths ? */
return mid_chip_setup(dev);
}
+
+static void oaktrail_teardown(struct drm_device *dev)
+{
+ mrst_hdmi_teardown(dev);
+}
const struct psb_ops mrst_chip_ops = {
.name = "Moorestown",
@@ -400,6 +509,7 @@ static const struct psb_ops oaktrail_chip_ops = {
.sgx_offset = MRST_SGX_OFFSET,
.chip_setup = mid_chip_setup,
+ .chip_teardown = oaktrail_teardown,
.crtc_helper = &mrst_helper_funcs,
.crtc_funcs = &psb_intel_crtc_funcs,
diff --git a/drivers/staging/gma500/mrst_hdmi.c b/drivers/staging/gma500/mrst_hdmi.c
new file mode 100644
index 0000000..d6a5179
--- /dev/null
+++ b/drivers/staging/gma500/mrst_hdmi.c
@@ -0,0 +1,852 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Li Peng <peng.li@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_drv.h"
+
+#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
+#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg))
+
+#define HDMI_HCR 0x1000
+#define HCR_ENABLE_HDCP (1 << 5)
+#define HCR_ENABLE_AUDIO (1 << 2)
+#define HCR_ENABLE_PIXEL (1 << 1)
+#define HCR_ENABLE_TMDS (1 << 0)
+
+#define HDMI_HICR 0x1004
+#define HDMI_HSR 0x1008
+#define HDMI_HISR 0x100C
+#define HDMI_DETECT_HDP (1 << 0)
+
+#define HDMI_VIDEO_REG 0x3000
+#define HDMI_UNIT_EN (1 << 7)
+#define HDMI_MODE_OUTPUT (1 << 0)
+#define HDMI_HBLANK_A 0x3100
+
+#define HDMI_AUDIO_CTRL 0x4000
+#define HDMI_ENABLE_AUDIO (1 << 0)
+
+#define PCH_HTOTAL_B 0x3100
+#define PCH_HBLANK_B 0x3104
+#define PCH_HSYNC_B 0x3108
+#define PCH_VTOTAL_B 0x310C
+#define PCH_VBLANK_B 0x3110
+#define PCH_VSYNC_B 0x3114
+#define PCH_PIPEBSRC 0x311C
+
+#define PCH_PIPEB_DSL 0x3800
+#define PCH_PIPEB_SLC 0x3804
+#define PCH_PIPEBCONF 0x3808
+#define PCH_PIPEBSTAT 0x3824
+
+#define CDVO_DFT 0x5000
+#define CDVO_SLEWRATE 0x5004
+#define CDVO_STRENGTH 0x5008
+#define CDVO_RCOMP 0x500C
+
+#define DPLL_CTRL 0x6000
+#define DPLL_PDIV_SHIFT 16
+#define DPLL_PDIV_MASK (0xf << 16)
+#define DPLL_PWRDN (1 << 4)
+#define DPLL_RESET (1 << 3)
+#define DPLL_FASTEN (1 << 2)
+#define DPLL_ENSTAT (1 << 1)
+#define DPLL_DITHEN (1 << 0)
+
+#define DPLL_DIV_CTRL 0x6004
+#define DPLL_CLKF_MASK 0xffffffc0
+#define DPLL_CLKR_MASK (0x3f)
+
+#define DPLL_CLK_ENABLE 0x6008
+#define DPLL_EN_DISP (1 << 31)
+#define DPLL_SEL_HDMI (1 << 8)
+#define DPLL_EN_HDMI (1 << 1)
+#define DPLL_EN_VGA (1 << 0)
+
+#define DPLL_ADJUST 0x600C
+#define DPLL_STATUS 0x6010
+#define DPLL_UPDATE 0x6014
+#define DPLL_DFT 0x6020
+
+struct intel_range {
+ int min, max;
+};
+
+struct mrst_hdmi_limit {
+ struct intel_range vco, np, nr, nf;
+};
+
+struct mrst_hdmi_clock {
+ int np;
+ int nr;
+ int nf;
+ int dot;
+};
+
+#define VCO_MIN 320000
+#define VCO_MAX 1650000
+#define NP_MIN 1
+#define NP_MAX 15
+#define NR_MIN 1
+#define NR_MAX 64
+#define NF_MIN 2
+#define NF_MAX 4095
+
+static const struct mrst_hdmi_limit mrst_hdmi_limit = {
+ .vco = { .min = VCO_MIN, .max = VCO_MAX },
+ .np = { .min = NP_MIN, .max = NP_MAX },
+ .nr = { .min = NR_MIN, .max = NR_MAX },
+ .nf = { .min = NF_MIN, .max = NF_MAX },
+};
+
+static void wait_for_vblank(struct drm_device *dev)
+{
+ /* FIXME: Can we do this as a sleep ? */
+ /* Wait for 20ms, i.e. one cycle at 50hz. */
+ udelay(20000);
+}
+
+static void scu_busy_loop(void *scu_base)
+{
+ u32 status = 0;
+ u32 loop_count = 0;
+
+ status = readl(scu_base + 0x04);
+ while (status & 1) {
+ udelay(1); /* scu processing time is in few u secods */
+ status = readl(scu_base + 0x04);
+ loop_count++;
+ /* break if scu doesn't reset busy bit after huge retry */
+ if (loop_count > 1000) {
+ DRM_DEBUG_KMS("SCU IPC timed out");
+ return;
+ }
+ }
+}
+
+static void mrst_hdmi_reset(struct drm_device *dev)
+{
+ void *base;
+ /* FIXME: at least make these defines */
+ unsigned int scu_ipc_mmio = 0xff11c000;
+ int scu_len = 1024;
+
+ base = ioremap((resource_size_t)scu_ipc_mmio, scu_len);
+ if (base == NULL) {
+ DRM_ERROR("failed to map SCU mmio\n");
+ return;
+ }
+
+ /* scu ipc: assert hdmi controller reset */
+ writel(0xff11d118, base + 0x0c);
+ writel(0x7fffffdf, base + 0x80);
+ writel(0x42005, base + 0x0);
+ scu_busy_loop(base);
+
+ /* scu ipc: de-assert hdmi controller reset */
+ writel(0xff11d118, base + 0x0c);
+ writel(0x7fffffff, base + 0x80);
+ writel(0x42005, base + 0x0);
+ scu_busy_loop(base);
+
+ iounmap(base);
+}
+
+static void mrst_hdmi_audio_enable(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+
+ HDMI_WRITE(HDMI_HCR, 0x67);
+ HDMI_READ(HDMI_HCR);
+
+ HDMI_WRITE(0x51a8, 0x10);
+ HDMI_READ(0x51a8);
+
+ HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1);
+ HDMI_READ(HDMI_AUDIO_CTRL);
+}
+
+static void mrst_hdmi_audio_disable(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+
+ HDMI_WRITE(0x51a8, 0x0);
+ HDMI_READ(0x51a8);
+
+ HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0);
+ HDMI_READ(HDMI_AUDIO_CTRL);
+
+ HDMI_WRITE(HDMI_HCR, 0x47);
+ HDMI_READ(HDMI_HCR);
+}
+
+void mrst_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
+{
+ struct drm_device *dev = crtc->dev;
+ u32 temp;
+
+ switch (mode) {
+ case DRM_MODE_DPMS_OFF:
+ /* Disable VGACNTRL */
+ REG_WRITE(VGACNTRL, 0x80000000);
+
+ /* Disable plane */
+ temp = REG_READ(DSPBCNTR);
+ if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+ REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
+ REG_READ(DSPBCNTR);
+ /* Flush the plane changes */
+ REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
+ REG_READ(DSPBSURF);
+ }
+
+ /* Disable pipe B */
+ temp = REG_READ(PIPEBCONF);
+ if ((temp & PIPEACONF_ENABLE) != 0) {
+ REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE);
+ REG_READ(PIPEBCONF);
+ }
+
+ /* Disable LNW Pipes, etc */
+ temp = REG_READ(PCH_PIPEBCONF);
+ if ((temp & PIPEACONF_ENABLE) != 0) {
+ REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE);
+ REG_READ(PCH_PIPEBCONF);
+ }
+ /* wait for pipe off */
+ udelay(150);
+ /* Disable dpll */
+ temp = REG_READ(DPLL_CTRL);
+ if ((temp & DPLL_PWRDN) == 0) {
+ REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET));
+ REG_WRITE(DPLL_STATUS, 0x1);
+ }
+ /* wait for dpll off */
+ udelay(150);
+ break;
+ case DRM_MODE_DPMS_ON:
+ case DRM_MODE_DPMS_STANDBY:
+ case DRM_MODE_DPMS_SUSPEND:
+ /* Enable dpll */
+ temp = REG_READ(DPLL_CTRL);
+ if ((temp & DPLL_PWRDN) != 0) {
+ REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET));
+ temp = REG_READ(DPLL_CLK_ENABLE);
+ REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI);
+ REG_READ(DPLL_CLK_ENABLE);
+ }
+ /* wait for dpll warm up */
+ udelay(150);
+
+ /* Enable pipe B */
+ temp = REG_READ(PIPEBCONF);
+ if ((temp & PIPEACONF_ENABLE) == 0) {
+ REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE);
+ REG_READ(PIPEBCONF);
+ }
+
+ /* Enable LNW Pipe B */
+ temp = REG_READ(PCH_PIPEBCONF);
+ if ((temp & PIPEACONF_ENABLE) == 0) {
+ REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE);
+ REG_READ(PCH_PIPEBCONF);
+ }
+ wait_for_vblank(dev);
+
+ /* Enable plane */
+ temp = REG_READ(DSPBCNTR);
+ if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+ REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
+ /* Flush the plane changes */
+ REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
+ REG_READ(DSPBSURF);
+ }
+ psb_intel_crtc_load_lut(crtc);
+ }
+ /* DSPARB */
+ REG_WRITE(DSPARB, 0x00003fbf);
+ /* FW1 */
+ REG_WRITE(0x70034, 0x3f880a0a);
+ /* FW2 */
+ REG_WRITE(0x70038, 0x0b060808);
+ /* FW4 */
+ REG_WRITE(0x70050, 0x08030404);
+ /* FW5 */
+ REG_WRITE(0x70054, 0x04040404);
+ /* LNC Chicken Bits */
+ REG_WRITE(0x70400, 0x4000);
+}
+
+
+static void mrst_hdmi_dpms(struct drm_encoder *encoder, int mode)
+{
+ static int dpms_mode = -1;
+
+ struct drm_device *dev = encoder->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+ u32 temp;
+
+ if (dpms_mode == mode)
+ return;
+
+ if (mode != DRM_MODE_DPMS_ON)
+ temp = 0x0;
+ else
+ temp = 0x99;
+
+ dpms_mode = mode;
+ HDMI_WRITE(HDMI_VIDEO_REG, temp);
+}
+
+static unsigned int htotal_calculate(struct drm_display_mode *mode)
+{
+ u32 htotal, new_crtc_htotal;
+
+ htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16);
+
+ /*
+ * 1024 x 768 new_crtc_htotal = 0x1024;
+ * 1280 x 1024 new_crtc_htotal = 0x0c34;
+ */
+ new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock;
+
+ return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16);
+}
+
+static void mrst_hdmi_find_dpll(struct drm_crtc *crtc, int target,
+ int refclk, struct mrst_hdmi_clock *best_clock)
+{
+ int np_min, np_max, nr_min, nr_max;
+ int np, nr, nf;
+
+ np_min = DIV_ROUND_UP(mrst_hdmi_limit.vco.min, target * 10);
+ np_max = mrst_hdmi_limit.vco.max / (target * 10);
+ if (np_min < mrst_hdmi_limit.np.min)
+ np_min = mrst_hdmi_limit.np.min;
+ if (np_max > mrst_hdmi_limit.np.max)
+ np_max = mrst_hdmi_limit.np.max;
+
+ nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max));
+ nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min));
+ if (nr_min < mrst_hdmi_limit.nr.min)
+ nr_min = mrst_hdmi_limit.nr.min;
+ if (nr_max > mrst_hdmi_limit.nr.max)
+ nr_max = mrst_hdmi_limit.nr.max;
+
+ np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max));
+ nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np));
+ nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk);
+ DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf);
+
+ /*
+ * 1024 x 768 np = 1; nr = 0x26; nf = 0x0fd8000;
+ * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000;
+ */
+ best_clock->np = np;
+ best_clock->nr = nr - 1;
+ best_clock->nf = (nf << 14);
+}
+
+int mrst_crtc_hdmi_mode_set(struct drm_crtc *crtc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode,
+ int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+ int pipe = 1;
+ int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+ int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+ int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+ int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+ int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+ int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+ int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
+ int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
+ int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+ int refclk;
+ struct mrst_hdmi_clock clock;
+ u32 dspcntr, pipeconf, dpll, temp;
+ int dspcntr_reg = DSPBCNTR;
+
+ /* Disable the VGA plane that we never use */
+ REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+ /* XXX: Disable the panel fitter if it was on our pipe */
+
+ /* Disable dpll if necessary */
+ dpll = REG_READ(DPLL_CTRL);
+ if ((dpll & DPLL_PWRDN) == 0) {
+ REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET));
+ REG_WRITE(DPLL_DIV_CTRL, 0x00000000);
+ REG_WRITE(DPLL_STATUS, 0x1);
+ }
+ udelay(150);
+
+ /* reset controller: FIXME - can we sort out the ioremap mess ? */
+ iounmap(hdmi_dev->regs);
+ mrst_hdmi_reset(dev);
+
+ /* program and enable dpll */
+ refclk = 25000;
+ mrst_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock);
+
+ /* Setting DPLL */
+ dpll = REG_READ(DPLL_CTRL);
+ dpll &= ~DPLL_PDIV_MASK;
+ dpll &= ~(DPLL_PWRDN | DPLL_RESET);
+ REG_WRITE(DPLL_CTRL, 0x00000008);
+ REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr));
+ REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1));
+ REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN));
+ REG_WRITE(DPLL_UPDATE, 0x80000000);
+ REG_WRITE(DPLL_CLK_ENABLE, 0x80050102);
+ udelay(150);
+
+ hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
+ if (hdmi_dev->regs == NULL) {
+ DRM_ERROR("failed to do hdmi mmio mapping\n");
+ return -ENOMEM;
+ }
+
+ /* configure HDMI */
+ HDMI_WRITE(0x1004, 0x1fd);
+ HDMI_WRITE(0x2000, 0x1);
+ HDMI_WRITE(0x2008, 0x0);
+ HDMI_WRITE(0x3130, 0x8);
+ HDMI_WRITE(0x101c, 0x1800810);
+
+ temp = htotal_calculate(adjusted_mode);
+ REG_WRITE(htot_reg, temp);
+ REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
+ REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
+ REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
+ REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
+ REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
+ REG_WRITE(pipesrc_reg,
+ ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
+
+ REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16));
+ REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
+ REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
+ REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
+ REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
+ REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
+ REG_WRITE(PCH_PIPEBSRC,
+ ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
+
+ temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
+ HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) | temp);
+
+ REG_WRITE(dspsize_reg,
+ ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+ REG_WRITE(dsppos_reg, 0);
+
+ /* Flush the plane changes */
+ {
+ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+ }
+
+ /* Set up the display plane register */
+ dspcntr = REG_READ(dspcntr_reg);
+ dspcntr |= DISPPLANE_GAMMA_ENABLE;
+ dspcntr |= DISPPLANE_SEL_PIPE_B;
+ dspcntr |= DISPLAY_PLANE_ENABLE;
+
+ /* setup pipeconf */
+ pipeconf = REG_READ(pipeconf_reg);
+ pipeconf |= PIPEACONF_ENABLE;
+
+ REG_WRITE(pipeconf_reg, pipeconf);
+ REG_READ(pipeconf_reg);
+
+ REG_WRITE(PCH_PIPEBCONF, pipeconf);
+ REG_READ(PCH_PIPEBCONF);
+ wait_for_vblank(dev);
+
+ REG_WRITE(dspcntr_reg, dspcntr);
+ wait_for_vblank(dev);
+
+ return 0;
+}
+
+static int mrst_hdmi_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ if (mode->clock > 165000)
+ return MODE_CLOCK_HIGH;
+ if (mode->clock < 20000)
+ return MODE_CLOCK_LOW;
+
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+ return MODE_OK;
+}
+
+static bool mrst_hdmi_mode_fixup(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ return true;
+}
+
+static enum drm_connector_status
+mrst_hdmi_detect(struct drm_connector *connector, bool force)
+{
+ enum drm_connector_status status;
+ struct drm_device *dev = connector->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+ u32 temp;
+
+ temp = HDMI_READ(HDMI_HSR);
+ DRM_DEBUG_KMS("HDMI_HSR %x\n", temp);
+
+ if ((temp & HDMI_DETECT_HDP) != 0)
+ status = connector_status_connected;
+ else
+ status = connector_status_disconnected;
+
+ return status;
+}
+
+static const unsigned char raw_edid[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0,
+ 0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78,
+ 0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5,
+ 0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0,
+ 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35,
+ 0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
+ 0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d
+};
+
+static int mrst_hdmi_get_modes(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct i2c_adapter *i2c_adap;
+ struct edid *edid;
+ struct drm_display_mode *mode, *t;
+ int i = 0, ret = 0;
+
+ i2c_adap = i2c_get_adapter(3);
+ if (i2c_adap == NULL) {
+ DRM_ERROR("No ddc adapter available!\n");
+ edid = (struct edid *)raw_edid;
+ } else {
+ edid = (struct edid *)raw_edid;
+ /* FIXME ? edid = drm_get_edid(connector, i2c_adap); */
+ }
+
+ if (edid) {
+ drm_mode_connector_update_edid_property(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+ connector->display_info.raw_edid = NULL;
+ }
+
+ /*
+ * prune modes that require frame buffer bigger than stolen mem
+ */
+ list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
+ if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) {
+ i++;
+ drm_mode_remove(connector, mode);
+ }
+ }
+ return ret - i;
+}
+
+static void mrst_hdmi_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct drm_device *dev = encoder->dev;
+
+ mrst_hdmi_audio_enable(dev);
+ return;
+}
+
+static void mrst_hdmi_destroy(struct drm_connector *connector)
+{
+ return;
+}
+
+static const struct drm_encoder_helper_funcs mrst_hdmi_helper_funcs = {
+ .dpms = mrst_hdmi_dpms,
+ .mode_fixup = mrst_hdmi_mode_fixup,
+ .prepare = psb_intel_encoder_prepare,
+ .mode_set = mrst_hdmi_mode_set,
+ .commit = psb_intel_encoder_commit,
+};
+
+static const struct drm_connector_helper_funcs
+ mrst_hdmi_connector_helper_funcs = {
+ .get_modes = mrst_hdmi_get_modes,
+ .mode_valid = mrst_hdmi_mode_valid,
+ .best_encoder = psb_intel_best_encoder,
+};
+
+static const struct drm_connector_funcs mrst_hdmi_connector_funcs = {
+ .dpms = drm_helper_connector_dpms,
+ .detect = mrst_hdmi_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = mrst_hdmi_destroy,
+};
+
+static void mrst_hdmi_enc_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs mrst_hdmi_enc_funcs = {
+ .destroy = mrst_hdmi_enc_destroy,
+};
+
+void mrst_hdmi_init(struct drm_device *dev,
+ struct psb_intel_mode_device *mode_dev)
+{
+ struct psb_intel_output *psb_intel_output;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+
+ psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
+ if (!psb_intel_output)
+ return;
+
+ psb_intel_output->mode_dev = mode_dev;
+ connector = &psb_intel_output->base;
+ encoder = &psb_intel_output->enc;
+ drm_connector_init(dev, &psb_intel_output->base,
+ &mrst_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_DVID);
+
+ drm_encoder_init(dev, &psb_intel_output->enc,
+ &mrst_hdmi_enc_funcs,
+ DRM_MODE_ENCODER_TMDS);
+
+ drm_mode_connector_attach_encoder(&psb_intel_output->base,
+ &psb_intel_output->enc);
+
+ psb_intel_output->type = INTEL_OUTPUT_HDMI;
+ drm_encoder_helper_add(encoder, &mrst_hdmi_helper_funcs);
+ drm_connector_helper_add(connector, &mrst_hdmi_connector_helper_funcs);
+
+ connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+ connector->interlace_allowed = false;
+ connector->doublescan_allowed = false;
+ drm_sysfs_connector_add(connector);
+
+ return;
+}
+
+static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
+ {}
+};
+
+void mrst_hdmi_setup(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct pci_dev *pdev;
+ struct mrst_hdmi_dev *hdmi_dev;
+ int ret;
+
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL);
+ if (!pdev)
+ return;
+
+ hdmi_dev = kzalloc(sizeof(struct mrst_hdmi_dev), GFP_KERNEL);
+ if (!hdmi_dev) {
+ dev_err(dev->dev, "failed to allocate memory\n");
+ goto out;
+ }
+
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(dev->dev, "failed to enable hdmi controller\n");
+ goto free;
+ }
+
+ hdmi_dev->mmio = pci_resource_start(pdev, 0);
+ hdmi_dev->mmio_len = pci_resource_len(pdev, 0);
+ hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
+ if (!hdmi_dev->regs) {
+ dev_err(dev->dev, "failed to map hdmi mmio\n");
+ goto free;
+ }
+
+ hdmi_dev->dev = pdev;
+ pci_set_drvdata(pdev, hdmi_dev);
+
+ /* Initialize i2c controller */
+ ret = mrst_hdmi_i2c_init(hdmi_dev->dev);
+ if (ret)
+ dev_err(dev->dev, "HDMI I2C initialization failed\n");
+
+ dev_priv->hdmi_priv = hdmi_dev;
+ mrst_hdmi_audio_disable(dev);
+ return;
+
+free:
+ kfree(hdmi_dev);
+out:
+ return;
+}
+
+void mrst_hdmi_teardown(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+ struct pci_dev *pdev;
+
+ if (hdmi_dev) {
+ pdev = hdmi_dev->dev;
+ pci_set_drvdata(pdev, NULL);
+ mrst_hdmi_i2c_exit(pdev);
+ iounmap(hdmi_dev->regs);
+ kfree(hdmi_dev);
+ pci_dev_put(pdev);
+ }
+}
+
+/* save HDMI register state */
+void mrst_hdmi_save(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+ int i;
+
+ /* dpll */
+ hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL);
+ hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL);
+ hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST);
+ hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE);
+ hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE);
+
+ /* pipe B */
+ dev_priv->savePIPEBCONF = PSB_RVDC32(PIPEBCONF);
+ dev_priv->savePIPEBSRC = PSB_RVDC32(PIPEBSRC);
+ dev_priv->saveHTOTAL_B = PSB_RVDC32(HTOTAL_B);
+ dev_priv->saveHBLANK_B = PSB_RVDC32(HBLANK_B);
+ dev_priv->saveHSYNC_B = PSB_RVDC32(HSYNC_B);
+ dev_priv->saveVTOTAL_B = PSB_RVDC32(VTOTAL_B);
+ dev_priv->saveVBLANK_B = PSB_RVDC32(VBLANK_B);
+ dev_priv->saveVSYNC_B = PSB_RVDC32(VSYNC_B);
+
+ hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF);
+ hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC);
+ hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B);
+ hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B);
+ hdmi_dev->savePCH_HSYNC_B = PSB_RVDC32(PCH_HSYNC_B);
+ hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B);
+ hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B);
+ hdmi_dev->savePCH_VSYNC_B = PSB_RVDC32(PCH_VSYNC_B);
+
+ /* plane */
+ dev_priv->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR);
+ dev_priv->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE);
+ dev_priv->saveDSPBADDR = PSB_RVDC32(DSPBBASE);
+ dev_priv->saveDSPBSURF = PSB_RVDC32(DSPBSURF);
+ dev_priv->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF);
+ dev_priv->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF);
+
+ /* cursor B */
+ dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
+ dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
+ dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
+
+ /* save palette */
+ for (i = 0; i < 256; i++)
+ dev_priv->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2));
+}
+
+/* restore HDMI register state */
+void mrst_hdmi_restore(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
+ int i;
+
+ /* dpll */
+ PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL);
+ PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL);
+ PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST);
+ PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE);
+ PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE);
+ DRM_UDELAY(150);
+
+ /* pipe */
+ PSB_WVDC32(dev_priv->savePIPEBSRC, PIPEBSRC);
+ PSB_WVDC32(dev_priv->saveHTOTAL_B, HTOTAL_B);
+ PSB_WVDC32(dev_priv->saveHBLANK_B, HBLANK_B);
+ PSB_WVDC32(dev_priv->saveHSYNC_B, HSYNC_B);
+ PSB_WVDC32(dev_priv->saveVTOTAL_B, VTOTAL_B);
+ PSB_WVDC32(dev_priv->saveVBLANK_B, VBLANK_B);
+ PSB_WVDC32(dev_priv->saveVSYNC_B, VSYNC_B);
+
+ PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC);
+ PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B);
+ PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B);
+ PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B, PCH_HSYNC_B);
+ PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B);
+ PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B);
+ PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B, PCH_VSYNC_B);
+
+ PSB_WVDC32(dev_priv->savePIPEBCONF, PIPEBCONF);
+ PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF);
+
+ /* plane */
+ PSB_WVDC32(dev_priv->saveDSPBLINOFF, DSPBLINOFF);
+ PSB_WVDC32(dev_priv->saveDSPBSTRIDE, DSPBSTRIDE);
+ PSB_WVDC32(dev_priv->saveDSPBTILEOFF, DSPBTILEOFF);
+ PSB_WVDC32(dev_priv->saveDSPBCNTR, DSPBCNTR);
+ PSB_WVDC32(dev_priv->saveDSPBSURF, DSPBSURF);
+
+ /* cursor B */
+ PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
+ PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
+ PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
+
+ /* restore palette */
+ for (i = 0; i < 256; i++)
+ PSB_WVDC32(dev_priv->save_palette_b[i], PALETTE_B + (i << 2));
+}
diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c
new file mode 100644
index 0000000..351b9d8
--- /dev/null
+++ b/drivers/staging/gma500/mrst_hdmi_i2c.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Li Peng <peng.li@intel.com>
+ */
+
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include "psb_drv.h"
+
+#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
+#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg))
+
+#define HDMI_HCR 0x1000
+#define HCR_DETECT_HDP (1 << 6)
+#define HCR_ENABLE_HDCP (1 << 5)
+#define HCR_ENABLE_AUDIO (1 << 2)
+#define HCR_ENABLE_PIXEL (1 << 1)
+#define HCR_ENABLE_TMDS (1 << 0)
+#define HDMI_HICR 0x1004
+#define HDMI_INTR_I2C_ERROR (1 << 4)
+#define HDMI_INTR_I2C_FULL (1 << 3)
+#define HDMI_INTR_I2C_DONE (1 << 2)
+#define HDMI_INTR_HPD (1 << 0)
+#define HDMI_HSR 0x1008
+#define HDMI_HISR 0x100C
+#define HDMI_HI2CRDB0 0x1200
+#define HDMI_HI2CHCR 0x1240
+#define HI2C_HDCP_WRITE (0 << 2)
+#define HI2C_HDCP_RI_READ (1 << 2)
+#define HI2C_HDCP_READ (2 << 2)
+#define HI2C_EDID_READ (3 << 2)
+#define HI2C_READ_CONTINUE (1 << 1)
+#define HI2C_ENABLE_TRANSACTION (1 << 0)
+
+#define HDMI_ICRH 0x1100
+#define HDMI_HI2CTDR0 0x1244
+#define HDMI_HI2CTDR1 0x1248
+
+#define I2C_STAT_INIT 0
+#define I2C_READ_DONE 1
+#define I2C_TRANSACTION_DONE 2
+
+struct hdmi_i2c_dev {
+ struct i2c_adapter *adap;
+ struct mutex i2c_lock;
+ struct completion complete;
+ int status;
+ struct i2c_msg *msg;
+ int buf_offset;
+};
+
+static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev)
+{
+ u32 temp;
+
+ temp = HDMI_READ(HDMI_HICR);
+ temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE);
+ HDMI_WRITE(HDMI_HICR, temp);
+ HDMI_READ(HDMI_HICR);
+}
+
+static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev)
+{
+ HDMI_WRITE(HDMI_HICR, 0x0);
+ HDMI_READ(HDMI_HICR);
+}
+
+static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
+{
+ struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
+ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+ u32 temp;
+
+ i2c_dev->status = I2C_STAT_INIT;
+ i2c_dev->msg = pmsg;
+ i2c_dev->buf_offset = 0;
+ INIT_COMPLETION(i2c_dev->complete);
+
+ /* Enable I2C transaction */
+ temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION;
+ HDMI_WRITE(HDMI_HI2CHCR, temp);
+ HDMI_READ(HDMI_HI2CHCR);
+
+ while (i2c_dev->status != I2C_TRANSACTION_DONE)
+ wait_for_completion_interruptible_timeout(&i2c_dev->complete,
+ 10 * HZ);
+
+ return 0;
+}
+
+static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg)
+{
+ /*
+ * XXX: i2c write seems isn't useful for EDID probe, don't do anything
+ */
+ return 0;
+}
+
+static int mrst_hdmi_i2c_access(struct i2c_adapter *adap,
+ struct i2c_msg *pmsg,
+ int num)
+{
+ struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
+ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+ int i, err = 0;
+
+ mutex_lock(&i2c_dev->i2c_lock);
+
+ /* Enable i2c unit */
+ HDMI_WRITE(HDMI_ICRH, 0x00008760);
+
+ /* Enable irq */
+ hdmi_i2c_irq_enable(hdmi_dev);
+ for (i = 0; i < num; i++) {
+ if (pmsg->len && pmsg->buf) {
+ if (pmsg->flags & I2C_M_RD)
+ err = xfer_read(adap, pmsg);
+ else
+ err = xfer_write(adap, pmsg);
+ }
+ pmsg++; /* next message */
+ }
+
+ /* Disable irq */
+ hdmi_i2c_irq_disable(hdmi_dev);
+
+ mutex_unlock(&i2c_dev->i2c_lock);
+
+ return i;
+}
+
+static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = {
+ .master_xfer = mrst_hdmi_i2c_access,
+ .functionality = mrst_hdmi_i2c_func,
+};
+
+static struct i2c_adapter mrst_hdmi_i2c_adapter = {
+ .name = "mrst_hdmi_i2c",
+ .nr = 3,
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_DDC,
+ .algo = &mrst_hdmi_i2c_algorithm,
+};
+
+static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev)
+{
+ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+ struct i2c_msg *msg = i2c_dev->msg;
+ u8 *buf = msg->buf;
+ u32 temp;
+ int i, offset;
+
+ offset = i2c_dev->buf_offset;
+ for (i = 0; i < 0x10; i++) {
+ temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4));
+ memcpy(buf + (offset + i * 4), &temp, 4);
+ }
+ i2c_dev->buf_offset += (0x10 * 4);
+
+ /* clearing read buffer full intr */
+ temp = HDMI_READ(HDMI_HISR);
+ HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL);
+ HDMI_READ(HDMI_HISR);
+
+ /* continue read transaction */
+ temp = HDMI_READ(HDMI_HI2CHCR);
+ HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE);
+ HDMI_READ(HDMI_HI2CHCR);
+
+ i2c_dev->status = I2C_READ_DONE;
+ return;
+}
+
+static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev)
+{
+ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+ u32 temp;
+
+ /* clear transaction done intr */
+ temp = HDMI_READ(HDMI_HISR);
+ HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE);
+ HDMI_READ(HDMI_HISR);
+
+
+ temp = HDMI_READ(HDMI_HI2CHCR);
+ HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION);
+ HDMI_READ(HDMI_HI2CHCR);
+
+ i2c_dev->status = I2C_TRANSACTION_DONE;
+ return;
+}
+
+static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev)
+{
+ struct mrst_hdmi_dev *hdmi_dev = dev;
+ struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
+ u32 stat;
+
+ stat = HDMI_READ(HDMI_HISR);
+
+ if (stat & HDMI_INTR_HPD) {
+ HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD);
+ HDMI_READ(HDMI_HISR);
+ }
+
+ if (stat & HDMI_INTR_I2C_FULL)
+ hdmi_i2c_read(hdmi_dev);
+
+ if (stat & HDMI_INTR_I2C_DONE)
+ hdmi_i2c_transaction_done(hdmi_dev);
+
+ complete(&i2c_dev->complete);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * choose alternate function 2 of GPIO pin 52, 53,
+ * which is used by HDMI I2C logic
+ */
+static void mrst_hdmi_i2c_gpio_fix(void)
+{
+ void *base;
+ unsigned int gpio_base = 0xff12c000;
+ int gpio_len = 0x1000;
+ u32 temp;
+
+ base = ioremap((resource_size_t)gpio_base, gpio_len);
+ if (base == NULL) {
+ DRM_ERROR("gpio ioremap fail\n");
+ return;
+ }
+
+ temp = readl(base + 0x44);
+ DRM_DEBUG_DRIVER("old gpio val %x\n", temp);
+ writel((temp | 0x00000a00), (base + 0x44));
+ temp = readl(base + 0x44);
+ DRM_DEBUG_DRIVER("new gpio val %x\n", temp);
+
+ iounmap(base);
+}
+
+int mrst_hdmi_i2c_init(struct pci_dev *dev)
+{
+ struct mrst_hdmi_dev *hdmi_dev;
+ struct hdmi_i2c_dev *i2c_dev;
+ int ret;
+
+ hdmi_dev = pci_get_drvdata(dev);
+
+ i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL);
+ if (i2c_dev == NULL) {
+ DRM_ERROR("Can't allocate interface\n");
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_dev->adap = &mrst_hdmi_i2c_adapter;
+ i2c_dev->status = I2C_STAT_INIT;
+ init_completion(&i2c_dev->complete);
+ mutex_init(&i2c_dev->i2c_lock);
+ i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev);
+ hdmi_dev->i2c_dev = i2c_dev;
+
+ /* Enable HDMI I2C function on gpio */
+ mrst_hdmi_i2c_gpio_fix();
+
+ /* request irq */
+ ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED,
+ mrst_hdmi_i2c_adapter.name, hdmi_dev);
+ if (ret) {
+ DRM_ERROR("Failed to request IRQ for I2C controller\n");
+ goto err;
+ }
+
+ /* Adapter registration */
+ ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter);
+ return ret;
+
+err:
+ kfree(i2c_dev);
+exit:
+ return ret;
+}
+
+void mrst_hdmi_i2c_exit(struct pci_dev *dev)
+{
+ struct mrst_hdmi_dev *hdmi_dev;
+ struct hdmi_i2c_dev *i2c_dev;
+
+ hdmi_dev = pci_get_drvdata(dev);
+ if (i2c_del_adapter(&mrst_hdmi_i2c_adapter))
+ DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n");
+
+ i2c_dev = hdmi_dev->i2c_dev;
+ kfree(i2c_dev);
+ free_irq(dev->irq, hdmi_dev);
+}
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 6b03951ebd..4b740aa 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -261,6 +261,8 @@ static int psb_driver_unload(struct drm_device *dev)
psb_lid_timer_takedown(dev_priv);
gma_intel_opregion_exit(dev);
+ if (dev_priv->ops->chip_teardown)
+ dev_priv->ops->chip_teardown(dev);
psb_do_takedown(dev);
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 8184c23..25275f7 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -375,6 +375,9 @@ struct drm_psb_private {
bool dbi_panel_on2; /* The DBI panel power is on */
u32 dsr_fb_update; /* DSR FB update counter */
+ /* Moorestown HDMI state */
+ struct mrst_hdmi_dev *hdmi_priv;
+
/* Moorestown pipe config register value cache */
uint32_t pipeconf;
uint32_t pipeconf1;
@@ -631,6 +634,7 @@ struct psb_ops {
/* Setup hooks */
int (*chip_setup)(struct drm_device *dev);
+ void (*chip_teardown)(struct drm_device *dev);
/* Display management hooks */
int (*output_init)(struct drm_device *dev);
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 11/15] gma500: More Moorestown muddle meddling means MM maybe might modeset
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (8 preceding siblings ...)
2011-07-15 16:34 ` [PATCH 10/15] gma500: Add the Oaktrail HDMI support Alan Cox
@ 2011-07-15 16:34 ` Alan Cox
2011-07-15 16:35 ` [PATCH 12/15] gma500@ Fix backlight range error Alan Cox
` (4 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:34 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
There are a least three different species we need to deal with and right
now it seems the only way to sort them out is via DMI. Encapsulate the
entire pile somewhere private and out of the way.
Hopefully a saner method will emerge later.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/mrst_device.c | 150 +++++++++++++++++++++++++++++-----
drivers/staging/gma500/mrst_lvds.c | 5 +
drivers/staging/gma500/psb_drv.h | 8 ++
3 files changed, 141 insertions(+), 22 deletions(-)
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index 20677f9..573142f 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -18,6 +18,8 @@
**************************************************************************/
#include <linux/backlight.h>
+#include <linux/module.h>
+#include <linux/dmi.h>
#include <drm/drmP.h>
#include <drm/drm.h>
#include "psb_drm.h"
@@ -28,7 +30,33 @@
#include <asm/intel_scu_ipc.h>
#include "mid_bios.h"
-static const struct psb_ops oaktrail_chip_ops;
+static int devtype;
+
+module_param_named(type, devtype, int, 0600);
+MODULE_PARM_DESC(type, "Moorestown/Oaktrail device type");
+
+#define DEVICE_MOORESTOWN 1
+#define DEVICE_OAKTRAIL 2
+#define DEVICE_MOORESTOWN_MM 3
+
+static int mrst_device_ident(struct drm_device *dev)
+{
+ /* User forced */
+ if (devtype)
+ return devtype;
+ if (dmi_match(DMI_PRODUCT_NAME, "OakTrail") ||
+ dmi_match(DMI_PRODUCT_NAME, "OakTrail platform"))
+ return DEVICE_OAKTRAIL;
+#if defined(CONFIG_X86_MRST)
+ if (dmi_match(DMI_PRODUCT_NAME, "MM") ||
+ dmi_match(DMI_PRODUCT_NAME, "MM 10"))
+ return DEVICE_MOORESTOWN_MM;
+ if (mrst_identify_cpu())
+ return DEVICE_MOORESTOWN;
+#endif
+ return DEVICE_OAKTRAIL;
+}
+
/* IPC message and command defines used to enable/disable mipi panel voltages */
#define IPC_MSG_PANEL_ON_OFF 0xE9
@@ -266,8 +294,10 @@ static int mrst_save_display_registers(struct drm_device *dev)
dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
/* DPST registers */
- dev_priv->saveHISTOGRAM_INT_CONTROL_REG = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
- dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+ dev_priv->saveHISTOGRAM_INT_CONTROL_REG =
+ PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG =
+ PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
if (dev_priv->iLVDS_enable) {
@@ -282,7 +312,7 @@ static int mrst_save_display_registers(struct drm_device *dev)
PSB_WVDC32(0x58000000, DSPACNTR);
/* Trigger the plane disable */
PSB_WVDC32(0, DSPASURF);
-
+
/* Wait ~4 ticks */
msleep(4);
@@ -401,8 +431,10 @@ static int mrst_restore_display_registers(struct drm_device *dev)
PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
/* DPST registers */
- PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG, HISTOGRAM_INT_CONTROL);
- PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG, HISTOGRAM_LOGIC_CONTROL);
+ PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG,
+ HISTOGRAM_INT_CONTROL);
+ PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG,
+ HISTOGRAM_LOGIC_CONTROL);
PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
return 0;
@@ -458,38 +490,44 @@ static int mrst_power_up(struct drm_device *dev)
return 0;
}
-static int mrst_chip_setup(struct drm_device *dev)
+#if defined(CONFIG_X86_MRST)
+static void mrst_lvds_cache_bl(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
-#if defined(CONFIG_X86_MRST)
- if (mrst_identify_cpu())
- return mid_chip_setup(dev);
-#endif
- dev_priv->ops = &oaktrail_chip_ops;
- mrst_hdmi_setup(dev);
- /* Check - may be better to go via BIOS paths ? */
- return mid_chip_setup(dev);
+ intel_scu_ipc_ioread8(0x28, &(dev_priv->saveBKLTCNT));
+ intel_scu_ipc_ioread8(0x29, &(dev_priv->saveBKLTREQ));
+ intel_scu_ipc_ioread8(0x2A, &(dev_priv->saveBKLTBRTL));
}
-static void oaktrail_teardown(struct drm_device *dev)
+static void mrst_mm_bl_power(struct drm_device *dev, bool on)
{
- mrst_hdmi_teardown(dev);
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ if (on) {
+ intel_scu_ipc_iowrite8(0x2A, dev_priv->saveBKLTBRTL);
+ intel_scu_ipc_iowrite8(0x28, dev_priv->saveBKLTCNT);
+ intel_scu_ipc_iowrite8(0x29, dev_priv->saveBKLTREQ);
+ } else {
+ intel_scu_ipc_iowrite8(0x2A, 0);
+ intel_scu_ipc_iowrite8(0x28, 0);
+ intel_scu_ipc_iowrite8(0x29, 0);
+ }
}
-
-const struct psb_ops mrst_chip_ops = {
- .name = "Moorestown",
+
+static const struct psb_ops mrst_mm_chip_ops = {
+ .name = "Moorestown MM ",
.accel_2d = 1,
.pipes = 1,
.crtcs = 1,
.sgx_offset = MRST_SGX_OFFSET,
- .chip_setup = mrst_chip_setup,
.crtc_helper = &mrst_helper_funcs,
.crtc_funcs = &psb_intel_crtc_funcs,
.output_init = mrst_output_init,
+ .lvds_bl_power = mrst_mm_bl_power,
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
.backlight_init = mrst_backlight_init,
#endif
@@ -499,8 +537,17 @@ const struct psb_ops mrst_chip_ops = {
.restore_regs = mrst_restore_display_registers,
.power_down = mrst_power_down,
.power_up = mrst_power_up,
+
+ .i2c_bus = 0,
};
+#endif
+
+static void oaktrail_teardown(struct drm_device *dev)
+{
+ mrst_hdmi_teardown(dev);
+}
+
static const struct psb_ops oaktrail_chip_ops = {
.name = "Oaktrail",
.accel_2d = 1,
@@ -524,5 +571,66 @@ static const struct psb_ops oaktrail_chip_ops = {
.restore_regs = mrst_restore_display_registers,
.power_down = mrst_power_down,
.power_up = mrst_power_up,
+
+ .i2c_bus = 1,
+};
+
+/**
+ * mrst_chip_setup - perform the initial chip init
+ * @dev: Our drm_device
+ *
+ * Figure out which incarnation we are and then scan the firmware for
+ * tables and information.
+ */
+static int mrst_chip_setup(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ switch (mrst_device_ident(dev)) {
+ case DEVICE_OAKTRAIL:
+ /* Dual CRTC, PC compatible, HDMI, I2C #2 */
+ dev_priv->ops = &oaktrail_chip_ops;
+ mrst_hdmi_setup(dev);
+ return mid_chip_setup(dev);
+#if defined(CONFIG_X86_MRST)
+ case DEVICE_MOORESTOWN_MM:
+ /* Single CRTC, No HDMI, I2C #0, BL control */
+ mrst_lvds_cache_bl(dev);
+ dev_priv->ops = &mrst_mm_chip_ops;
+ return mid_chip_setup(dev);
+ case DEVICE_MOORESTOWN:
+ /* Dual CRTC, No HDMI(?), I2C #1 */
+ return mid_chip_setup(dev);
+#endif
+ default:
+ dev_err(dev->dev, "unsupported device type.\n");
+ return -ENODEV;
+ }
+}
+
+const struct psb_ops mrst_chip_ops = {
+ .name = "Moorestown",
+ .accel_2d = 1,
+ .pipes = 2,
+ .crtcs = 2,
+ .sgx_offset = MRST_SGX_OFFSET,
+
+ .chip_setup = mrst_chip_setup,
+ .crtc_helper = &mrst_helper_funcs,
+ .crtc_funcs = &psb_intel_crtc_funcs,
+
+ .output_init = mrst_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+ .backlight_init = mrst_backlight_init,
+#endif
+
+ .init_pm = mrst_init_pm,
+ .save_regs = mrst_save_display_registers,
+ .restore_regs = mrst_restore_display_registers,
+ .power_down = mrst_power_down,
+ .power_up = mrst_power_up,
+
+ .i2c_bus = 2,
};
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index 3e15ecd..108f245 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -58,7 +58,11 @@ static void mrst_lvds_set_power(struct drm_device *dev,
pp_status = REG_READ(PP_STATUS);
} while ((pp_status & (PP_ON | PP_READY)) == PP_READY);
dev_priv->is_lvds_on = true;
+ if (dev_priv->ops->lvds_bl_power)
+ dev_priv->ops->lvds_bl_power(dev, true);
} else {
+ if (dev_priv->ops->lvds_bl_power)
+ dev_priv->ops->lvds_bl_power(dev, false);
REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
~POWER_TARGET_ON);
do {
@@ -67,7 +71,6 @@ static void mrst_lvds_set_power(struct drm_device *dev,
dev_priv->is_lvds_on = false;
pm_request_idle(&dev->pdev->dev);
}
-
gma_power_end(dev);
}
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 25275f7..829657b 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -388,6 +388,11 @@ struct drm_psb_private {
uint32_t dspcntr1;
uint32_t dspcntr2;
+ /* Moorestown MM backlight cache */
+ uint8_t saveBKLTCNT;
+ uint8_t saveBKLTREQ;
+ uint8_t saveBKLTBRTL;
+
/*
* Register state
*/
@@ -644,10 +649,13 @@ struct psb_ops {
int (*restore_regs)(struct drm_device *dev);
int (*power_up)(struct drm_device *dev);
int (*power_down)(struct drm_device *dev);
+
+ void (*lvds_bl_power)(struct drm_device *dev, bool on);
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
/* Backlight */
int (*backlight_init)(struct drm_device *dev);
#endif
+ int i2c_bus; /* I2C bus identifier for Moorestown */
};
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 12/15] gma500@ Fix backlight range error
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (9 preceding siblings ...)
2011-07-15 16:34 ` [PATCH 11/15] gma500: More Moorestown muddle meddling means MM maybe might modeset Alan Cox
@ 2011-07-15 16:35 ` Alan Cox
2011-07-15 16:35 ` [PATCH 13/15] gma500: Use the mrst helpers and power control for mode commit Alan Cox
` (3 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:35 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
If we go out of range we break the pm counts on the error path
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/mrst_device.c | 12 +++++-------
1 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index 573142f..6707faf 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -157,14 +157,12 @@ static int device_backlight_init(struct drm_device *dev)
value /= bl_max_freq;
value /= blc_pwm_precision_factor;
+ if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
+ return -ERANGE;
+
if (gma_power_begin(dev, false)) {
- if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
- return -ERANGE;
- else {
- REG_WRITE(BLC_PWM_CTL2,
- (0x80000000 | REG_READ(BLC_PWM_CTL2)));
- REG_WRITE(BLC_PWM_CTL, value | (value << 16));
- }
+ REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
+ REG_WRITE(BLC_PWM_CTL, value | (value << 16));
gma_power_end(dev);
}
return 0;
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 13/15] gma500: Use the mrst helpers and power control for mode commit
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (10 preceding siblings ...)
2011-07-15 16:35 ` [PATCH 12/15] gma500@ Fix backlight range error Alan Cox
@ 2011-07-15 16:35 ` Alan Cox
2011-07-15 16:35 ` [PATCH 14/15] gma500: resync with Medfield progress Alan Cox
` (2 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:35 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
We want to hit the MM panel backlight when appropriate
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/mrst_lvds.c | 29 +++++++++++++++++++++++++++--
drivers/staging/gma500/psb_drv.h | 2 --
drivers/staging/gma500/psb_intel_lvds.c | 4 ++--
3 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index 108f245..25fde4c 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -147,13 +147,38 @@ static void mrst_lvds_mode_set(struct drm_encoder *encoder,
gma_power_end(dev);
}
+static void mrst_lvds_prepare(struct drm_encoder *encoder)
+{
+ struct drm_device *dev = encoder->dev;
+ struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+
+ if (!gma_power_begin(dev, true))
+ return;
+
+ mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
+ mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
+ BACKLIGHT_DUTY_CYCLE_MASK);
+ mrst_lvds_set_power(dev, output, false);
+ gma_power_end(dev);
+}
+
+static void mrst_lvds_commit(struct drm_encoder *encoder)
+{
+ struct drm_device *dev = encoder->dev;
+ struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+
+ if (mode_dev->backlight_duty_cycle == 0)
+ mode_dev->backlight_duty_cycle =
+ psb_intel_lvds_get_max_backlight(dev);
+ mrst_lvds_set_power(dev, output, true);
+}
static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = {
.dpms = mrst_lvds_dpms,
.mode_fixup = psb_intel_lvds_mode_fixup,
- .prepare = psb_intel_lvds_prepare,
+ .prepare = mrst_intel_lvds_prepare,
.mode_set = mrst_lvds_mode_set,
- .commit = psb_intel_lvds_commit,
+ .commit = mrst_intel_lvds_commit,
};
static struct drm_display_mode lvds_configuration_modes[] = {
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 829657b..194c64f 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -792,8 +792,6 @@ extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs;
extern const struct drm_crtc_funcs psb_intel_crtc_funcs;
/* psb_intel_lvds.c */
-extern void psb_intel_lvds_prepare(struct drm_encoder *encoder);
-extern void psb_intel_lvds_commit(struct drm_encoder *encoder);
extern const struct drm_connector_helper_funcs
psb_intel_lvds_connector_helper_funcs;
extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs;
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index 53803b2..c6436da 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -432,7 +432,7 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
return true;
}
-void psb_intel_lvds_prepare(struct drm_encoder *encoder)
+static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
@@ -450,7 +450,7 @@ void psb_intel_lvds_prepare(struct drm_encoder *encoder)
gma_power_end(dev);
}
-void psb_intel_lvds_commit(struct drm_encoder *encoder)
+static void psb_intel_lvds_commit(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 14/15] gma500: resync with Medfield progress
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (11 preceding siblings ...)
2011-07-15 16:35 ` [PATCH 13/15] gma500: Use the mrst helpers and power control for mode commit Alan Cox
@ 2011-07-15 16:35 ` Alan Cox
2011-07-15 16:35 ` [PATCH 15/15] gma500: Clean up the DPU config and make it runtime Alan Cox
2011-07-15 17:06 ` [PATCH 01/15] gma500: Cursor interface Greg KH
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:35 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/mdfld_dsi_dbi.c | 369 ++++++++---------------
drivers/staging/gma500/mdfld_dsi_dbi.h | 21 -
drivers/staging/gma500/mdfld_dsi_dbi_dpu.h | 3
drivers/staging/gma500/mdfld_dsi_dpi.c | 319 ++++----------------
drivers/staging/gma500/mdfld_dsi_dpi.h | 6
drivers/staging/gma500/mdfld_dsi_output.c | 250 +++++++++-------
drivers/staging/gma500/mdfld_dsi_output.h | 203 -------------
drivers/staging/gma500/mdfld_dsi_pkg_sender.c | 403 +++++++++++++++++++++++++
drivers/staging/gma500/mdfld_dsi_pkg_sender.h | 26 ++
drivers/staging/gma500/mdfld_intel_display.c | 6
drivers/staging/gma500/mdfld_output.c | 8
drivers/staging/gma500/mdfld_output.h | 41 ---
drivers/staging/gma500/mdfld_pyr_cmd.c | 18 -
drivers/staging/gma500/mdfld_tmd_vid.c | 62 ++++
drivers/staging/gma500/mdfld_tpo_cmd.c | 64 +++-
drivers/staging/gma500/mrst_lvds.c | 35 ++
drivers/staging/gma500/psb_drv.h | 7
17 files changed, 917 insertions(+), 924 deletions(-)
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c
index 1421f49..06424f9 100644
--- a/drivers/staging/gma500/mdfld_dsi_dbi.c
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.c
@@ -39,29 +39,10 @@ extern int gfxrtdelay;
int enter_dsr;
struct mdfld_dsi_dbi_output *gdbi_output;
extern bool gbgfxsuspended;
+extern int enable_gfx_rtpm;
extern int gfxrtdelay;
-#ifdef CONFIG_GFX_RTPM
-static void psb_runtimepm_wq_handler(struct work_struct *work);
-DECLARE_DELAYED_WORK(rtpm_work, psb_runtimepm_wq_handler);
-
-void psb_runtimepm_wq_handler(struct work_struct *work)
-{
- struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
-
- if (drm_psb_ospm && !enable_gfx_rtpm) {
- pr_info("Enable GFX runtime_pm\n");
- dev_priv->rpm_enabled = 1;
- enable_gfx_rtpm = 1;
-
- pm_runtime_enable(&gpDrmDevice->pdev->dev);
- pm_runtime_set_active(&gpDrmDevice->pdev->dev);
-
- pm_runtime_allow(&gpDrmDevice->pdev->dev);
- }
-}
-#endif
-
+#define MDFLD_DSR_MAX_IDLE_COUNT 2
/*
* set refreshing area
@@ -80,8 +61,8 @@ int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
return -EINVAL;
}
- /*set column*/
- cmd = set_column_address;
+ /* Set column */
+ cmd = DCS_SET_COLUMN_ADDRESS;
param[0] = x1 >> 8;
param[1] = x1;
param[2] = x2 >> 8;
@@ -98,8 +79,8 @@ int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
goto err_out;
}
- /*set page*/
- cmd = set_page_addr;
+ /* Set page */
+ cmd = DCS_SET_PAGE_ADDRESS;
param[0] = y1 >> 8;
param[1] = y1;
param[2] = y2 >> 8;
@@ -139,56 +120,46 @@ int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
int mode)
{
struct drm_device *dev = dbi_output->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
struct mdfld_dsi_pkg_sender *sender =
mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
u8 param = 0;
u32 err = 0;
- if (!dev_priv->dispstatus && mode != DRM_MODE_DPMS_ON) {
- dev_err(dev->dev, "%s: already OFF ignoring\n", __func__);
- return 0;
- }
- if (dev_priv->dispstatus && mode == DRM_MODE_DPMS_ON) {
- dev_err(dev->dev, "%s: already ON ignoring\n", __func__);
- return 0;
- }
-
if (!sender) {
WARN_ON(1);
return -EINVAL;
}
if (mode == DRM_MODE_DPMS_ON) {
- /*exit sleep mode*/
+ /* Exit sleep mode */
err = mdfld_dsi_send_dcs(sender,
- exit_sleep_mode,
+ DCS_EXIT_SLEEP_MODE,
NULL,
0,
CMD_DATA_SRC_SYSTEM_MEM,
MDFLD_DSI_QUEUE_PACKAGE);
if (err) {
dev_err(dev->dev, "DCS 0x%x sent failed\n",
- exit_sleep_mode);
+ DCS_EXIT_SLEEP_MODE);
goto power_err;
}
- /*set display on*/
+ /* Set display on */
err = mdfld_dsi_send_dcs(sender,
- set_display_on,
+ DCS_SET_DISPLAY_ON,
NULL,
0,
CMD_DATA_SRC_SYSTEM_MEM,
MDFLD_DSI_QUEUE_PACKAGE);
if (err) {
dev_err(dev->dev, "DCS 0x%x sent failed\n",
- set_display_on);
+ DCS_SET_DISPLAY_ON);
goto power_err;
}
/* set tear effect on */
err = mdfld_dsi_send_dcs(sender,
- set_tear_on,
+ DCS_SET_TEAR_ON,
¶m,
1,
CMD_DATA_SRC_SYSTEM_MEM,
@@ -203,53 +174,53 @@ int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
* FIXME: remove this later
*/
err = mdfld_dsi_send_dcs(sender,
- write_mem_start,
+ DCS_WRITE_MEM_START,
NULL,
0,
CMD_DATA_SRC_PIPE,
MDFLD_DSI_QUEUE_PACKAGE);
if (err) {
dev_err(dev->dev, "DCS 0x%x sent failed\n",
- set_display_on);
+ DCS_WRITE_MEM_START);
goto power_err;
}
} else {
- /*set tear effect off */
+ /* Set tear effect off */
err = mdfld_dsi_send_dcs(sender,
- set_tear_off,
+ DCS_SET_TEAR_OFF,
NULL,
0,
CMD_DATA_SRC_SYSTEM_MEM,
MDFLD_DSI_QUEUE_PACKAGE);
if (err) {
dev_err(dev->dev, "DCS 0x%x sent failed\n",
- set_tear_off);
+ DCS_SET_TEAR_OFF);
goto power_err;
}
- /*set display off*/
+ /* Turn display off */
err = mdfld_dsi_send_dcs(sender,
- set_display_off,
+ DCS_SET_DISPLAY_OFF,
NULL,
0,
CMD_DATA_SRC_SYSTEM_MEM,
MDFLD_DSI_QUEUE_PACKAGE);
if (err) {
dev_err(dev->dev, "DCS 0x%x sent failed\n",
- set_display_off);
+ DCS_SET_DISPLAY_OFF);
goto power_err;
}
- /*enter sleep mode*/
+ /* Now enter sleep mode */
err = mdfld_dsi_send_dcs(sender,
- enter_sleep_mode,
+ DCS_ENTER_SLEEP_MODE,
NULL,
0,
CMD_DATA_SRC_SYSTEM_MEM,
MDFLD_DSI_QUEUE_PACKAGE);
if (err) {
dev_err(dev->dev, "DCS 0x%x sent failed\n",
- enter_sleep_mode);
+ DCS_ENTER_SLEEP_MODE);
goto power_err;
}
}
@@ -283,7 +254,6 @@ int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
return ret;
}
-
/*
* Enter DSR
*/
@@ -299,11 +269,12 @@ void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
u32 pipeconf_reg = PIPEACONF;
u32 dspcntr_reg = DSPACNTR;
- dev_priv->is_in_idle = true;
-
if (!dbi_output)
return;
+ /* FIXME check if can go */
+ dev_priv->is_in_idle = true;
+
gdbi_output = dbi_output;
if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
@@ -319,16 +290,17 @@ void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
dev_err(dev->dev, "hw begin failed\n");
return;
}
- /*disable te interrupts. */
+ /* Disable te interrupts */
mdfld_disable_te(dev, pipe);
- /*disable plane*/
+ /* Disable plane */
reg_val = REG_READ(dspcntr_reg);
if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE);
REG_READ(dspcntr_reg);
}
- /*disable pipe*/
+
+ /* Disable pipe */
reg_val = REG_READ(pipeconf_reg);
if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
reg_val &= ~DISPLAY_PLANE_ENABLE;
@@ -338,7 +310,7 @@ void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
mdfldWaitForPipeDisable(dev, pipe);
}
- /*disable DPLL*/
+ /* Disable DPLL */
reg_val = REG_READ(dpll_reg);
if (!(reg_val & DPLL_VCO_ENABLE)) {
reg_val &= ~DPLL_VCO_ENABLE;
@@ -357,10 +329,9 @@ void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
#ifndef CONFIG_MDFLD_DSI_DPU
static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
- int pipe, void *p_surfaceAddr, bool check_hw_on_only)
+ int pipe)
{
struct drm_device *dev = dbi_output->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = dbi_output->base.base.crtc;
struct psb_intel_crtc *psb_crtc = (crtc) ?
to_psb_intel_crtc(crtc) : NULL;
@@ -368,7 +339,6 @@ static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
u32 dpll_reg = MRST_DPLL_A;
u32 pipeconf_reg = PIPEACONF;
u32 dspcntr_reg = DSPACNTR;
- u32 dspsurf_reg = DSPASURF;
u32 reg_offset = 0;
/*if mode setting on-going, back off*/
@@ -380,24 +350,17 @@ static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
dpll_reg = MRST_DPLL_A;
pipeconf_reg = PIPECCONF;
dspcntr_reg = DSPCCNTR;
- dspsurf_reg = DSPCSURF;
reg_offset = MIPIC_REG_OFFSET;
}
- if (check_hw_on_only) {
- if (0/* FIXME!ospm_power_is_hw_on(_DISPLAY_ISLAND)*/) {
- dev_err(dev->dev, "hw begin failed\n");
- return;
- }
- } else if (!gma_power_begin(dev, true)) {
+ if (!gma_power_begin(dev, true)) {
dev_err(dev->dev, "hw begin failed\n");
return;
}
- /*enable DPLL*/
+ /* Enable DPLL */
reg_val = REG_READ(dpll_reg);
if (!(reg_val & DPLL_VCO_ENABLE)) {
-
if (reg_val & MDFLD_PWR_GATE_EN) {
reg_val &= ~MDFLD_PWR_GATE_EN;
REG_WRITE(dpll_reg, reg_val);
@@ -415,7 +378,7 @@ static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
cpu_relax();
}
- /*enable pipe*/
+ /* Enable pipe */
reg_val = REG_READ(pipeconf_reg);
if (!(reg_val & PIPEACONF_ENABLE)) {
reg_val |= PIPEACONF_ENABLE;
@@ -425,7 +388,7 @@ static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
mdfldWaitForPipeEnable(dev, pipe);
}
- /*enable plane*/
+ /* Enable plane */
reg_val = REG_READ(dspcntr_reg);
if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
reg_val |= DISPLAY_PLANE_ENABLE;
@@ -434,15 +397,9 @@ static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
udelay(500);
}
- /* update the surface base address. */
- if (p_surfaceAddr)
- REG_WRITE(dspsurf_reg, *((u32 *)p_surfaceAddr));
-
- if (!check_hw_on_only)
- gma_power_end(dev);
-
- /*enable TE interrupt on this pipe*/
+ /* Enable TE interrupt on this pipe */
mdfld_enable_te(dev, pipe);
+ gma_power_end(dev);
/*clean IN_DSR flag*/
dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
@@ -451,33 +408,33 @@ static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
/*
* Exit from DSR
*/
-void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src,
- void *p_surfaceAddr, bool check_hw_on_only)
+void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src)
{
struct drm_psb_private *dev_priv = dev->dev_private;
struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
struct mdfld_dsi_dbi_output **dbi_output;
int i;
+ int pipe;
+ /* FIXME can go ? */
dev_priv->is_in_idle = false;
dbi_output = dsr_info->dbi_outputs;
#ifdef CONFIG_PM_RUNTIME
if (!enable_gfx_rtpm) {
/* pm_runtime_allow(&gpDrmDevice->pdev->dev); */
-/* schedule_delayed_work(&rtpm_work, 120 * 1000); */
+/* schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */
}
#endif
- /*for each output, exit dsr*/
+ /* For each output, exit dsr */
for (i = 0; i < dsr_info->dbi_output_num; i++) {
- /*if panel has been turned off, skip*/
- if (!dbi_output[i]->dbi_panel_on)
+ /* If panel has been turned off, skip */
+ if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on)
continue;
- if (dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR) {
- enter_dsr = 0;
- mdfld_dbi_output_exit_dsr(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0, p_surfaceAddr, check_hw_on_only);
- }
+ pipe = dbi_output[i]->channel_num ? 2 : 0;
+ enter_dsr = 0;
+ mdfld_dbi_output_exit_dsr(dbi_output[i], pipe);
}
dev_priv->dsr_fb_update |= update_src;
}
@@ -496,7 +453,7 @@ static bool mdfld_dbi_is_in_dsr(struct drm_device *dev)
return true;
}
-/* Perodically update dbi panel */
+/* Periodically update dbi panel */
void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
{
struct drm_psb_private *dev_priv = dev->dev_private;
@@ -504,8 +461,8 @@ void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
struct mdfld_dsi_dbi_output **dbi_outputs;
struct mdfld_dsi_dbi_output *dbi_output;
int i;
- int enter_dsr = 0;
- u32 damage_mask = 0;
+ int can_enter_dsr = 0;
+ u32 damage_mask;
dbi_outputs = dsr_info->dbi_outputs;
dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0];
@@ -514,13 +471,13 @@ void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
return;
if (pipe == 0)
- damage_mask = dev_priv->dsr_fb_update & (MDFLD_DSR_DAMAGE_MASK_0);
+ damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0;
else if (pipe == 2)
- damage_mask = dev_priv->dsr_fb_update & (MDFLD_DSR_DAMAGE_MASK_2);
+ damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2;
else
return;
- /*if FB is damaged and panel is on update on-panel FB*/
+ /* If FB is damaged and panel is on update on-panel FB */
if (damage_mask && dbi_output->dbi_panel_on) {
dbi_output->dsr_fb_update_done = false;
@@ -538,11 +495,24 @@ void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
dbi_output->dsr_idle_count++;
}
- /*try to enter DSR*/
- if (dbi_outputs[0]->dsr_idle_count > 1
- && dbi_outputs[1]->dsr_idle_count > 1) {
+ switch (dsr_info->dbi_output_num) {
+ case 1:
+ if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
+ can_enter_dsr = 1;
+ break;
+ case 2:
+ if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT
+ && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
+ can_enter_dsr = 1;
+ break;
+ default:
+ DRM_ERROR("Wrong DBI output number\n");
+ }
+
+ /* Try to enter DSR */
+ if (can_enter_dsr) {
for (i = 0; i < dsr_info->dbi_output_num; i++) {
- if (!mdfld_dbi_is_in_dsr(dev) &&
+ if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] &&
!(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) {
mdfld_dsi_dbi_enter_dsr(dbi_outputs[i],
dbi_outputs[i]->channel_num ? 2 : 0);
@@ -565,61 +535,6 @@ void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
}
}
-/*timers for DSR*/
-static void mdfld_dsi_dbi_dsr_timer_func(unsigned long data)
-{
- struct drm_device *dev = (struct drm_device *)data;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
- struct timer_list *dsr_timer = &dsr_info->dsr_timer;
- unsigned long flags;
-
- mdfld_dbi_update_panel(dev, 0);
-
- if (dsr_info->dsr_idle_count > 1)
- return;
-
- spin_lock_irqsave(&dsr_info->dsr_timer_lock, flags);
- if (!timer_pending(dsr_timer)) {
- dsr_timer->expires = jiffies + MDFLD_DSR_DELAY;
- add_timer(dsr_timer);
- }
- spin_unlock_irqrestore(&dsr_info->dsr_timer_lock, flags);
-}
-
-static int mdfld_dsi_dbi_dsr_timer_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
- struct timer_list *dsr_timer = &dsr_info->dsr_timer;
- unsigned long flags;
-
- spin_lock_init(&dsr_info->dsr_timer_lock);
- spin_lock_irqsave(&dsr_info->dsr_timer_lock, flags);
-
- init_timer(dsr_timer);
-
- dsr_timer->data = (unsigned long)dev;
- dsr_timer->function = mdfld_dsi_dbi_dsr_timer_func;
- dsr_timer->expires = jiffies + MDFLD_DSR_DELAY;
-
- spin_unlock_irqrestore(&dsr_info->dsr_timer_lock, flags);
- return 0;
-}
-
-void mdfld_dbi_dsr_timer_start(struct mdfld_dbi_dsr_info *dsr_info)
-{
- struct timer_list *dsr_timer = &dsr_info->dsr_timer;
- unsigned long flags;
-
- spin_lock_irqsave(&dsr_info->dsr_timer_lock, flags);
- if (!timer_pending(dsr_timer)) {
- dsr_timer->expires = jiffies + MDFLD_DSR_DELAY;
- add_timer(dsr_timer);
- }
- spin_unlock_irqrestore(&dsr_info->dsr_timer_lock, flags);
-}
-
int mdfld_dbi_dsr_init(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
@@ -643,7 +558,6 @@ void mdfld_dbi_dsr_exit(struct drm_device *dev)
struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
if (dsr_info) {
- del_timer_sync(&dsr_info->dsr_timer);
kfree(dsr_info);
dev_priv->dbi_dsr_info = NULL;
}
@@ -660,13 +574,13 @@ void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
- /*un-ready device*/
+ /* Un-ready device */
REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
- /*init dsi adapter before kicking off*/
+ /* Init dsi adapter before kicking off */
REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
- /*TODO: figure out how to setup these registers*/
+ /* TODO: figure out how to setup these registers */
REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
0x000a0014);
@@ -674,16 +588,16 @@ void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
- /*enable all interrupts*/
+ /* Enable all interrupts */
REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
- /*max value: 20 clock cycles of txclkesc*/
+ /* Max value: 20 clock cycles of txclkesc */
REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
- /*min 21 txclkesc, max: ffffh*/
+ /* Min 21 txclkesc, max: ffffh */
REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
- /*min: 7d0 max: 4e20*/
+ /* Min: 7d0 max: 4e20 */
REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
- /*set up func_prg*/
+ /* Set up func_prg */
val |= lane_count;
val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
val |= DSI_DBI_COLOR_FORMAT_OPTION2;
@@ -692,7 +606,7 @@ void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
- /*de-assert dbi_stall when half of DBI FIFO is empty*/
+ /* De-assert dbi_stall when half of DBI FIFO is empty */
/* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
@@ -718,42 +632,6 @@ static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
#endif
-static int mdfld_dbi_panel_reset(struct mdfld_dsi_dbi_output *output)
-{
- unsigned gpio;
- int ret;
-
- switch (output->channel_num) {
- case 0:
- gpio = 128;
- break;
- case 1:
- gpio = 34;
- break;
- default:
- pr_err("Invalid output\n");
- return -EINVAL;
- }
-
- ret = gpio_request(gpio, "gfx");
- if (ret) {
- pr_err("gpio_rqueset failed\n");
- return ret;
- }
-
- ret = gpio_direction_output(gpio, 1);
- if (ret) {
- pr_err("gpio_direction_output failed\n");
- goto gpio_error;
- }
- gpio_get_value(128);
-gpio_error:
- if (gpio_is_valid(gpio))
- gpio_free(gpio);
-
- return ret;
-}
-
/*
* Init DSI DBI encoder.
* Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
@@ -776,13 +654,44 @@ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
#else
struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
#endif
+ u32 data = 0;
+ int pipe;
int ret;
- if (!pg || !dsi_connector) {
+ if (!pg || !dsi_connector || !p_funcs) {
WARN_ON(1);
return NULL;
}
+ dsi_config = mdfld_dsi_get_config(dsi_connector);
+ pipe = dsi_connector->pipe;
+
+ /*panel hard-reset*/
+ if (p_funcs->reset) {
+ ret = p_funcs->reset(pipe);
+ if (ret) {
+ DRM_ERROR("Panel %d hard-reset failed\n", pipe);
+ return NULL;
+ }
+ }
+ /* Panel drvIC init */
+ if (p_funcs->drv_ic_init)
+ p_funcs->drv_ic_init(dsi_config, pipe);
+
+ /* Panel power mode detect */
+ ret = mdfld_dsi_get_power_mode(dsi_config,
+ &data,
+ MDFLD_DSI_HS_TRANSMISSION);
+ if (ret) {
+ DRM_ERROR("Panel %d get power mode failed\n", pipe);
+ dsi_connector->status = connector_status_disconnected;
+ } else {
+ DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
+ dsi_connector->status = connector_status_connected;
+ }
+
+ /*TODO: get panel info from DDB*/
+
dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
if (!dbi_output) {
dev_err(dev->dev, "No memory\n");
@@ -802,23 +711,10 @@ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
dbi_output->dev = dev;
dbi_output->p_funcs = p_funcs;
-
- /*panel reset*/
- ret = mdfld_dbi_panel_reset(dbi_output);
- if (ret) {
- dev_err(dev->dev, "reset panel error\n");
- goto out_err1;
- }
-
- /*TODO: get panel info from DDB*/
-
- /*get fixed mode*/
- dsi_config = mdfld_dsi_get_config(dsi_connector);
fixed_mode = dsi_config->fixed_mode;
-
dbi_output->panel_fixed_mode = fixed_mode;
- /*create drm encoder object*/
+ /* Create drm encoder object */
connector = &dsi_connector->base.base;
encoder = &dbi_output->base.base;
drm_encoder_init(dev,
@@ -827,10 +723,10 @@ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
DRM_MODE_ENCODER_MIPI);
drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs);
- /*attach to given connector*/
+ /* Attach to given connector */
drm_mode_connector_attach_encoder(connector, encoder);
- /*set possible crtcs and clones*/
+ /* Set possible CRTCs and clones */
if (dsi_connector->pipe) {
encoder->possible_crtcs = (1 << 2);
encoder->possible_clones = (1 << 1);
@@ -842,28 +738,31 @@ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
dev_priv->dsr_fb_update = 0;
dev_priv->dsr_enable = false;
dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr;
-#if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR)
- dev_priv->dsr_enable_config = false;
-#endif /*CONFIG_MDFLD_DSI_DSR*/
dbi_output->first_boot = true;
dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
#ifdef CONFIG_MDFLD_DSI_DPU
- /*add this output to dpu_info*/
- if (dsi_connector->pipe == 0)
- dpu_info->dbi_outputs[0] = dbi_output;
- } else {
- dpu_info->dbi_outputs[1] = dbi_output;
+ /* Add this output to dpu_info */
+ if (dsi_connector->status == connector_status_connected) {
+ if (dsi_connector->pipe == 0)
+ dpu_info->dbi_outputs[0] = dbi_output;
+ else
+ dpu_info->dbi_outputs[1] = dbi_output;
+
+ dpu_info->dbi_output_num++;
}
- dpu_info->dbi_output_num++;
+
#else /*CONFIG_MDFLD_DSI_DPU*/
- /*add this output to dsr_info*/
- if (dsi_connector->pipe == 0)
- dsr_info->dbi_outputs[0] = dbi_output;
- else
- dsr_info->dbi_outputs[1] = dbi_output;
- dsr_info->dbi_output_num++;
+ if (dsi_connector->status == connector_status_connected) {
+ /* Add this output to dsr_info */
+ if (dsi_connector->pipe == 0)
+ dsr_info->dbi_outputs[0] = dbi_output;
+ else
+ dsr_info->dbi_outputs[1] = dbi_output;
+
+ dsr_info->dbi_output_num++;
+ }
#endif
return &dbi_output->base;
out_err1:
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.h b/drivers/staging/gma500/mdfld_dsi_dbi.h
index a51e2f8..a2ec6fd 100644
--- a/drivers/staging/gma500/mdfld_dsi_dbi.h
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.h
@@ -59,9 +59,6 @@ struct mdfld_dsi_dbi_output {
/* Backlight operations */
/* DSR timer */
- spinlock_t dsr_timer_lock;
- struct timer_list dsr_timer;
- void(*dsi_timer_func)(unsigned long data);
u32 dsr_idle_count;
bool dsr_fb_update_done;
@@ -81,22 +78,11 @@ struct mdfld_dbi_dsr_info {
int dbi_output_num;
struct mdfld_dsi_dbi_output *dbi_outputs[2];
- spinlock_t dsr_timer_lock;
- struct timer_list dsr_timer;
u32 dsr_idle_count;
};
#define DBI_CB_TIMEOUT_COUNT 0xffff
-/* DCS commands */
-#define enter_sleep_mode 0x10
-#define exit_sleep_mode 0x11
-#define set_display_off 0x28
-#define set_dispaly_on 0x29
-#define set_column_address 0x2a
-#define set_page_addr 0x2b
-#define write_mem_start 0x2c
-
/* Offsets */
#define CMD_MEM_ADDR_OFFSET 0
@@ -132,7 +118,7 @@ static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output *dbi_output
/* Query the command execution status */
while (retry--)
- if (!(REG_READ(MIPIA_CMD_ADD_REG + reg_offset) & (1 << 10)))
+ if (!(REG_READ(MIPIA_CMD_ADD_REG + reg_offset) & (1 << 0)))
break;
if (!retry) {
@@ -164,13 +150,11 @@ static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output *dbi_output
extern void mdfld_dsi_dbi_output_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev, int pipe);
-extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src,
- void *p_surfaceAddr, bool check_hw_on_only);
+extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src);
extern void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output,
int pipe);
extern int mdfld_dbi_dsr_init(struct drm_device *dev);
extern void mdfld_dbi_dsr_exit(struct drm_device *dev);
-extern void mdfld_dbi_dsr_timer_start(struct mdfld_dbi_dsr_info *dsr_info);
extern struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
struct mdfld_dsi_connector *dsi_connector,
struct panel_funcs *p_funcs);
@@ -178,7 +162,6 @@ extern int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
u8 dcs, u8 *param, u32 num, u8 data_src);
extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
u16 x1, u16 y1, u16 x2, u16 y2);
-extern void mdfld_dbi_dsr_timer_start(struct mdfld_dbi_dsr_info *dsr_info);
extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
int mode);
extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
index 4ca9682..42367ed 100644
--- a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
+++ b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
@@ -90,9 +90,6 @@ static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect *origin,
{
int x1, y1, x2, y2;
- /* PSB_DEBUG_ENTRY("rect (%d, %d, %d, %d)\n",
- rect->x, rect->y, rect->width, rect->height); */
-
x1 = origin->x + origin->width;
y1 = origin->y + origin->height;
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.c b/drivers/staging/gma500/mdfld_dsi_dpi.c
index fce3c20..6e03a91 100644
--- a/drivers/staging/gma500/mdfld_dsi_dpi.c
+++ b/drivers/staging/gma500/mdfld_dsi_dpi.c
@@ -69,26 +69,6 @@ static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
dev_warn(dev->dev, "MIPI: HS CMD FIFO was never cleared!\n");
}
-static void mdfld_wait_for_PIPEA_DISABLE(struct drm_device *dev, u32 pipe)
-{
- u32 pipeconf_reg = PIPEACONF;
- int timeout = 0;
-
- if (pipe == 2)
- pipeconf_reg = PIPECCONF;
-
- udelay(500);
-
- /* This will time out after approximately 2+ seconds */
- while ((timeout < 20000) && (REG_READ(pipeconf_reg) & 0x40000000)) {
- udelay(100);
- timeout++;
- }
-
- if (timeout == 20000)
- dev_warn(dev->dev, "MIPI: PIPE was not disabled!\n");
-}
-
static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
{
u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
@@ -147,8 +127,6 @@ void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
u32 gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG;
u32 gen_ctrl_val = GEN_LONG_WRITE;
- dev_warn(dev->dev, "Enter mrst init TPO MIPI display.\n");
-
if (pipe == 2) {
gen_data_reg = HS_GEN_DATA_REG + MIPIC_REG_OFFSET;
gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
@@ -331,51 +309,8 @@ void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
}
-/* ************************************************************************* *\
- * FUNCTION: mdfld_init_TMD_MIPI
- *
- * DESCRIPTION: This function is called only by mrst_dsi_mode_set and
- * restore_display_registers. since this function does not
- * acquire the mutex, it is important that the calling function
- * does!
-\* ************************************************************************* */
-
-static u32 tmd_cmd_mcap_off[] = {0x000000b2};
-static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
-static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
-static u32 tmd_cmd_set_mode[] = {0x000000b3};
-static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
-static u32 tmd_cmd_set_video_mode[] = {0x00000153};
-static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};//no auto_bl,need add in furtrue
-static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd};
-
-void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
-{
- struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
- if(!sender) {
- WARN_ON(1);
- return;
- }
-
- if(dsi_config->dvr_ic_inited)
- return;
-
- msleep(3);
-
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_mcap_off, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_lane_switch, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_lane_num, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_mode, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_sync_pulse_mode, 1, 0);
- /*TODO: set page and column here*/
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_video_mode, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_backlight, 1, 0);
- mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_backlight_dimming,1,0);
- dsi_config->dvr_ic_inited = 1;
-}
-
-static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, int num_lane, int bpp)
+static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count,
+ int num_lane, int bpp)
{
return (u16)((pixel_clock_count * bpp) / (num_lane * 8));
}
@@ -387,8 +322,8 @@ static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, int num_lane
* use crtc mode values later
*/
int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
- struct mdfld_dsi_dpi_timing *dpi_timing,
- int num_lane, int bpp)
+ struct mdfld_dsi_dpi_timing *dpi_timing,
+ int num_lane, int bpp)
{
int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive;
@@ -408,16 +343,6 @@ int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
pclk_vsync = mode->vsync_end - mode->vsync_start;
pclk_vbp = mode->vtotal - mode->vsync_end;
-#ifdef MIPI_DEBUG_LOG
- printk(KERN_ALERT "[DISPLAY] %s: pclk_hactive = %d\n", __func__, pclk_hactive);
- printk(KERN_ALERT "[DISPLAY] %s: pclk_hfp = %d\n", __func__, pclk_hfp);
- printk(KERN_ALERT "[DISPLAY] %s: pclk_hsync = %d\n", __func__, pclk_hsync);
- printk(KERN_ALERT "[DISPLAY] %s: pclk_hbp = %d\n", __func__, pclk_hbp);
- printk(KERN_ALERT "[DISPLAY] %s: pclk_vactive = %d\n", __func__, pclk_vactive);
- printk(KERN_ALERT "[DISPLAY] %s: pclk_vfp = %d\n", __func__, pclk_vfp);
- printk(KERN_ALERT "[DISPLAY] %s: pclk_vsync = %d\n", __func__, pclk_vsync);
- printk(KERN_ALERT "[DISPLAY] %s: pclk_vbp = %d\n", __func__, pclk_vbp);
-#endif
/*
* byte clock counts were calculated by following formula
* bclock_count = pclk_count * bpp / num_lane / 8
@@ -519,7 +444,6 @@ void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe
void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
{
struct drm_device *dev = output->dev;
- /* struct drm_psb_private *dev_priv = dev->dev_private; */
u32 reg_offset = 0;
if(output->panel_on)
@@ -555,7 +479,6 @@ void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe)
{
struct drm_device *dev = output->dev;
- /* struct drm_psb_private *dev_priv = dev->dev_private; */
u32 reg_offset = 0;
/*if output is on, or mode setting didn't happen, ignore this*/
@@ -576,6 +499,7 @@ static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pip
}
if(REG_READ(MIPIA_DPI_CONTROL_REG + reg_offset) == DSI_DPI_CTRL_HS_SHUTDOWN) {
+ dev_warn(dev->dev, "try to send the same package again, abort!");
goto shutdown_out;
}
@@ -590,6 +514,14 @@ shutdown_out:
/* dev_priv->dpi_panel_on2 = false; */
/* else if (pipe == 0) */
/* dev_priv->dpi_panel_on = false; */
+ /* #ifdef CONFIG_PM_RUNTIME*/
+ /* if (drm_psb_ospm && !enable_gfx_rtpm) { */
+ /* pm_runtime_allow(&gpDrmDevice->pdev->dev); */
+ /* schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000); */
+ /* } */
+ /*if (enable_gfx_rtpm) */
+ /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */
+ /* #endif */
}
void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
@@ -616,7 +548,7 @@ void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
if (mdfld_get_panel_type(dev, pipe) == TMD_VID){
mdfld_dsi_dpi_turn_on(dpi_output, pipe);
} else {
- /*enable mipi port*/
+ /* Enable mipi port */
REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31)));
REG_READ(mipi_reg);
@@ -636,7 +568,7 @@ void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
mdfld_dsi_dpi_shut_down(dpi_output, pipe);
} else {
mdfld_dsi_dpi_shut_down(dpi_output, pipe);
- /*disable mipi port*/
+ /* Disable mipi port */
REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31)));
REG_READ(mipi_reg);
}
@@ -656,8 +588,15 @@ void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
if (mode == DRM_MODE_DPMS_ON)
mdfld_dsi_dpi_set_power(encoder, true);
- else
+ else {
mdfld_dsi_dpi_set_power(encoder, false);
+#if 0 /* FIXME */
+#ifdef CONFIG_PM_RUNTIME
+ if (enable_gfx_rtpm)
+ pm_schedule_suspend(&gpDrmDevice->pdev->dev, gfxrtdelay);
+#endif
+#endif
+ }
}
bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
@@ -694,77 +633,6 @@ void mdfld_dsi_dpi_commit(struct drm_encoder *encoder)
mdfld_dsi_dpi_set_power(encoder, true);
}
-void dsi_debug_MIPI_reg(struct drm_device *dev)
-{
- u32 temp_val = 0;
-
- temp_val = REG_READ(MIPI);
- printk(KERN_ALERT "[DISPLAY] MIPI = %x\n", temp_val);
-
- /* set the lane speed */
- temp_val = REG_READ(MIPI_CONTROL_REG);
- printk(KERN_ALERT "[DISPLAY] MIPI_CONTROL_REG = %x\n", temp_val);
-
- /* Enable all the error interrupt */
- temp_val = REG_READ(INTR_EN_REG);
- printk(KERN_ALERT "[DISPLAY] INTR_EN_REG = %x\n", temp_val);
- temp_val = REG_READ(TURN_AROUND_TIMEOUT_REG);
- printk(KERN_ALERT "[DISPLAY] TURN_AROUND_TIMEOUT_REG = %x\n", temp_val);
- temp_val = REG_READ(DEVICE_RESET_REG);
- printk(KERN_ALERT "[DISPLAY] DEVICE_RESET_REG = %x\n", temp_val);
- temp_val = REG_READ(INIT_COUNT_REG);
- printk(KERN_ALERT "[DISPLAY] INIT_COUNT_REG = %x\n", temp_val);
-
- temp_val = REG_READ(DSI_FUNC_PRG_REG);
- printk(KERN_ALERT "[DISPLAY] DSI_FUNC_PRG_REG = %x\n", temp_val);
-
- temp_val = REG_READ(DPI_RESOLUTION_REG);
- printk(KERN_ALERT "[DISPLAY] DPI_RESOLUTION_REG = %x\n", temp_val);
-
- temp_val = REG_READ(VERT_SYNC_PAD_COUNT_REG);
- printk(KERN_ALERT "[DISPLAY] VERT_SYNC_PAD_COUNT_REG = %x\n", temp_val);
- temp_val = REG_READ(VERT_BACK_PORCH_COUNT_REG);
- printk(KERN_ALERT "[DISPLAY] VERT_BACK_PORCH_COUNT_REG = %x\n", temp_val);
- temp_val = REG_READ(VERT_FRONT_PORCH_COUNT_REG);
- printk(KERN_ALERT "[DISPLAY] VERT_FRONT_PORCH_COUNT_REG = %x\n", temp_val);
-
- temp_val = REG_READ(HORIZ_SYNC_PAD_COUNT_REG);
- printk(KERN_ALERT "[DISPLAY] HORIZ_SYNC_PAD_COUNT_REG = %x\n", temp_val);
- temp_val = REG_READ(HORIZ_BACK_PORCH_COUNT_REG);
- printk(KERN_ALERT "[DISPLAY] HORIZ_BACK_PORCH_COUNT_REG = %x\n", temp_val);
- temp_val = REG_READ(HORIZ_FRONT_PORCH_COUNT_REG);
- printk(KERN_ALERT "[DISPLAY] HORIZ_FRONT_PORCH_COUNT_REG = %x\n", temp_val);
- temp_val = REG_READ(HORIZ_ACTIVE_AREA_COUNT_REG);
- printk(KERN_ALERT "[DISPLAY] HORIZ_ACTIVE_AREA_COUNT_REG = %x\n", temp_val);
-
- temp_val = REG_READ(VIDEO_FMT_REG);
- printk(KERN_ALERT "[DISPLAY] VIDEO_FMT_REG = %x\n", temp_val);
-
- temp_val = REG_READ(HS_TX_TIMEOUT_REG);
- printk(KERN_ALERT "[DISPLAY] HS_TX_TIMEOUT_REG = %x\n", temp_val);
- temp_val = REG_READ(LP_RX_TIMEOUT_REG);
- printk(KERN_ALERT "[DISPLAY] LP_RX_TIMEOUT_REG = %x\n", temp_val);
-
- temp_val = REG_READ(HIGH_LOW_SWITCH_COUNT_REG);
- printk(KERN_ALERT "[DISPLAY] HIGH_LOW_SWITCH_COUNT_REG = %x\n", temp_val);
-
- temp_val = REG_READ(EOT_DISABLE_REG);
- printk(KERN_ALERT "[DISPLAY] EOT_DISABLE_REG = %x\n", temp_val);
-
- temp_val = REG_READ(LP_BYTECLK_REG);
- printk(KERN_ALERT "[DISPLAY] LP_BYTECLK_REG = %x\n", temp_val);
- temp_val = REG_READ(MAX_RET_PAK_REG);
- printk(KERN_ALERT "[DISPLAY] MAX_RET_PAK_REG = %x\n", temp_val);
- temp_val = REG_READ(DPI_CONTROL_REG);
- printk(KERN_ALERT "[DISPLAY] DPI_CONTROL_REG = %x\n", temp_val);
- temp_val = REG_READ(DPHY_PARAM_REG);
- printk(KERN_ALERT "[DISPLAY] DPHY_PARAM_REG = %x\n", temp_val);
-// temp_val = REG_READ(PIPEACONF);
-// printk(KERN_INFO "[DISPLAY] PIPEACONF = %x\n", temp_val);
-// temp_val = REG_READ(DSPACNTR);
-// printk(KERN_INFO "[DISPLAY] DSPACNTR = %x\n", temp_val);
-}
-
void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -804,14 +672,11 @@ void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
REG_WRITE(mipi_reg, mipi);
REG_READ(mipi_reg);
- /* Set up DSI controller DPI interface*/
+ /* Set up DSI controller DPI interface */
mdfld_dsi_dpi_controller_init(dsi_config, pipe);
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
- /* init driver ic */
- mdfld_dsi_tmd_drv_ic_init(dsi_config, pipe);
- } else {
- /*turn on DPI interface*/
+ if (mdfld_get_panel_type(dev, pipe) != TMD_VID) {
+ /* Turn on DPI interface */
mdfld_dsi_dpi_turn_on(dpi_output, pipe);
}
@@ -829,81 +694,15 @@ void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
REG_READ(MIPIA_INTR_STAT_REG + reg_offset),
dpi_output->panel_on);
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
- //mdfld_dsi_dpi_turn_on(dpi_output, pipe);
- } else {
- /* init driver ic */
+ if (mdfld_get_panel_type(dev, pipe) != TMD_VID) {
+ /* Init driver ic */
mdfld_dsi_tpo_ic_init(dsi_config, pipe);
- /*init backlight*/
+ /* Init backlight */
mdfld_dsi_brightness_init(dsi_config, pipe);
}
-
-#ifdef MIPI_DEBUG_LOG
- dsi_debug_MIPI_reg(dev);
-#endif
gma_power_end(dev);
}
-static int mdfld_dpi_panel_reset(int pipe)
-{
- unsigned gpio;
- int ret = 0;
-
- switch(pipe) {
- case 0:
- gpio = 128;
- break;
- case 2:
- gpio = 34;
- break;
- default:
- DRM_ERROR("Invalid output\n");
- return -EINVAL;
- }
-
- ret = gpio_request(gpio, "gfx");
- if(ret) {
- DRM_ERROR("gpio_rqueset failed\n");
- return ret;
- }
- ret = gpio_direction_output(gpio, 1);
- if(ret) {
- DRM_ERROR("gpio_direction_output failed\n");
- goto gpio_error;
- }
-
- gpio_get_value(128);
-
-gpio_error:
- if(gpio_is_valid(gpio))
- gpio_free(gpio);
- return ret;
-}
-
-/**
- * Exit from DSR
- */
-void mdfld_dsi_dpi_exit_idle (struct drm_device *dev, u32 update_src, void *p_surfaceAddr, bool check_hw_on_only)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!gma_power_begin(dev, true)) {
- DRM_ERROR("hw begin failed\n");
- return;
- }
-
- /* update the surface base address. */
- if (p_surfaceAddr) {
- REG_WRITE(DSPASURF, *((u32 *)p_surfaceAddr));
-#if defined(CONFIG_MDFD_DUAL_MIPI)
- REG_WRITE(DSPCSURF, *((u32 *)p_surfaceAddr));
-#endif
- }
- mid_enable_pipe_event(dev_priv, 0);
- psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
- dev_priv->is_in_idle = false;
- dev_priv->dsr_idle_count = 0;
-}
/*
* Init DSI DPI encoder.
@@ -912,40 +711,63 @@ void mdfld_dsi_dpi_exit_idle (struct drm_device *dev, u32 update_src, void *p_su
*/
struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
struct mdfld_dsi_connector *dsi_connector,
- struct panel_funcs*p_funcs)
+ struct panel_funcs *p_funcs)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
struct mdfld_dsi_dpi_output *dpi_output = NULL;
struct mdfld_dsi_config *dsi_config;
struct drm_connector *connector = NULL;
struct drm_encoder *encoder = NULL;
struct drm_display_mode *fixed_mode = NULL;
+ int pipe;
+ u32 data;
int ret;
- if (!dsi_connector) {
+ if (!dsi_connector || !p_funcs) {
WARN_ON(1);
return NULL;
}
+ dsi_config = mdfld_dsi_get_config(dsi_connector);
+ pipe = dsi_connector->pipe;
+
+ /* Panel hard-reset */
+ if (p_funcs->reset) {
+ ret = p_funcs->reset(pipe);
+ if (ret) {
+ DRM_ERROR("Panel %d hard-reset failed\n", pipe);
+ return NULL;
+ }
+ }
+
+ /* Panel drvIC init */
+ if (p_funcs->drv_ic_init)
+ p_funcs->drv_ic_init(dsi_config, pipe);
+
+ /* Panel power mode detect */
+ ret = mdfld_dsi_get_power_mode(dsi_config,
+ &data,
+ MDFLD_DSI_LP_TRANSMISSION);
+ if (ret) {
+ DRM_ERROR("Panel %d get power mode failed\n", pipe);
+ dsi_connector->status = connector_status_disconnected;
+ } else {
+ DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
+ dsi_connector->status = connector_status_connected;
+ }
+
dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
if(!dpi_output) {
dev_err(dev->dev, "No memory for dsi_dpi_output\n");
return NULL;
}
- /* Panel reset */
- ret = mdfld_dpi_panel_reset(dsi_connector->pipe);
- if(ret) {
- DRM_ERROR("reset panel error\n");
- goto out_err1;
- }
-
+
if(dsi_connector->pipe)
dpi_output->panel_on = 0;
-
+ else
dpi_output->panel_on = 0;
-
dpi_output->dev = dev;
+ dpi_output->p_funcs = p_funcs;
dpi_output->first_boot = 1;
/* Get fixed mode */
@@ -973,19 +795,6 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
encoder->possible_crtcs = (1 << 0);
encoder->possible_clones = (1 << 0);
}
-
- dev_priv->dsr_fb_update = 0;
- dev_priv->dsr_enable = false;
- dev_priv->exit_idle = mdfld_dsi_dpi_exit_idle;
-#if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR)
- dev_priv->dsr_enable_config = true;
-#endif /*CONFIG_MDFLD_DSI_DSR*/
-
return &dpi_output->base;
-
-out_err1:
- if(dpi_output)
- kfree(dpi_output);
- return NULL;
}
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.h b/drivers/staging/gma500/mdfld_dsi_dpi.h
index 68e65cc..ed92d45 100644
--- a/drivers/staging/gma500/mdfld_dsi_dpi.h
+++ b/drivers/staging/gma500/mdfld_dsi_dpi.h
@@ -47,6 +47,8 @@ struct mdfld_dsi_dpi_output {
int panel_on;
int first_boot;
+
+ struct panel_funcs *p_funcs;
};
#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) \
@@ -73,8 +75,4 @@ extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output,
int pipe);
extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *si_config,
int pipe);
-extern void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe);
-extern void psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe,
- u32 mask);
-
#endif /*__MDFLD_DSI_DPI_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
index ff75ece..3286c3d 100644
--- a/drivers/staging/gma500/mdfld_dsi_output.c
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -35,55 +35,18 @@
#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
-/* get the CABC LABC from command line. */
static int CABC_control = 1;
static int LABC_control = 1;
-#ifdef MODULE
module_param (CABC_control, int, 0644);
module_param (LABC_control, int, 0644);
-#else
-static int __init parse_CABC_control(char *arg)
-{
- /* CABC control can be passed in as a cmdline parameter */
- /* to enable this feature add CABC=1 to cmdline */
- /* to disable this feature add CABC=0 to cmdline */
- if (!arg)
- return -EINVAL;
-
- if (!strcasecmp(arg, "0"))
- CABC_control = 0;
- else if (!strcasecmp (arg, "1"))
- CABC_control = 1;
-
- return 0;
-}
-early_param ("CABC", parse_CABC_control);
-
-static int __init parse_LABC_control(char *arg)
-{
- /* LABC control can be passed in as a cmdline parameter */
- /* to enable this feature add LABC=1 to cmdline */
- /* to disable this feature add LABC=0 to cmdline */
- if (!arg)
- return -EINVAL;
-
- if (!strcasecmp(arg, "0"))
- LABC_control = 0;
- else if (!strcasecmp (arg, "1"))
- LABC_control = 1;
-
- return 0;
-}
-early_param ("LABC", parse_LABC_control);
-#endif
/**
* make these MCS command global
* we don't need 'movl' everytime we send them.
* FIXME: these datas were provided by OEM, we should get them from GCT.
**/
-static u32 mdfld_dbi_mcs_hysteresis[] = {
+static const u32 mdfld_dbi_mcs_hysteresis[] = {
0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
@@ -91,25 +54,26 @@ static u32 mdfld_dbi_mcs_hysteresis[] = {
0x000000ff,
};
-static u32 mdfld_dbi_mcs_display_profile[] = {
+static const u32 mdfld_dbi_mcs_display_profile[] = {
0x50281450, 0x0000c882, 0x00000000, 0x00000000,
0x00000000,
};
-static u32 mdfld_dbi_mcs_kbbc_profile[] = {
+static const u32 mdfld_dbi_mcs_kbbc_profile[] = {
0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
};
-static u32 mdfld_dbi_mcs_gamma_profile[] = {
+static const u32 mdfld_dbi_mcs_gamma_profile[] = {
0x81111158, 0x88888888, 0x88888888,
};
/*
* write hysteresis values.
*/
-static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config * dsi_config, int pipe)
+static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config,
+ int pipe)
{
- struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+ struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
if(!sender) {
WARN_ON(1);
@@ -124,9 +88,9 @@ static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config * dsi_config, in
/*
* write display profile values.
*/
-static void mdfld_dsi_write_display_profile (struct mdfld_dsi_config * dsi_config, int pipe)
+static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe)
{
- struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+ struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
if(!sender) {
WARN_ON(1);
@@ -143,7 +107,7 @@ static void mdfld_dsi_write_display_profile (struct mdfld_dsi_config * dsi_confi
*/
static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe)
{
- struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+ struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
if(!sender) {
WARN_ON(1);
@@ -155,12 +119,12 @@ static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config,
MDFLD_DSI_SEND_PACKAGE);
}
-/**
+/*
* write gamma setting.
*/
-static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config * dsi_config, int pipe)
+static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe)
{
- struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+ struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
if(!sender) {
WARN_ON(1);
@@ -172,7 +136,7 @@ static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config * dsi_config,
MDFLD_DSI_SEND_PACKAGE);
}
-/**
+/*
* Check and see if the generic control or data buffer is empty and ready.
*/
void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
@@ -193,16 +157,16 @@ void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u3
gen_fifo_stat_reg);
}
-/**
+/*
* Manage the DSI MIPI keyboard and display brightness.
* FIXME: this is exported to OSPM code. should work out an specific
* display interface to OSPM.
*/
-void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe)
+void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
{
- struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
- struct drm_device * dev = sender->dev;
- struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
+ struct drm_device *dev = sender->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
u32 gen_ctrl_val;
if(!sender) {
@@ -223,7 +187,7 @@ void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe)
1,
MDFLD_DSI_SEND_PACKAGE);
- mdfld_dsi_write_hysteresis (dsi_config, pipe);
+ mdfld_dsi_write_hysteresis(dsi_config, pipe);
mdfld_dsi_write_display_profile (dsi_config, pipe);
mdfld_dsi_write_kbbc_profile (dsi_config, pipe);
mdfld_dsi_write_gamma_setting (dsi_config, pipe);
@@ -253,7 +217,7 @@ void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe)
MDFLD_DSI_SEND_PACKAGE);
}
-/**
+/*
* Manage the mipi display brightness.
* TODO: refine this interface later
*/
@@ -262,8 +226,8 @@ void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
struct mdfld_dsi_pkg_sender *sender;
struct drm_psb_private *dev_priv;
struct mdfld_dsi_config *dsi_config;
- u32 gen_ctrl_val = 0;
- int p_type = TMD_VID;
+ u32 gen_ctrl_val;
+ int p_type;
if (!dev || (pipe != 0 && pipe != 2)) {
dev_err(dev->dev, "Invalid parameter\n");
@@ -288,7 +252,8 @@ void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
- dev_dbg(dev->dev, "pipe = %d, gen_ctrl_val = %d. \n", pipe, gen_ctrl_val);
+ dev_dbg(dev->dev,
+ "pipe = %d, gen_ctrl_val = %d. \n", pipe, gen_ctrl_val);
if(p_type == TMD_VID || p_type == TMD_CMD){
/* Set display backlight value */
@@ -344,7 +309,7 @@ void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pip
if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY))
goto shutdown_out;
- /*send shut down package, clean packet send bit first*/
+ /* Send shut down package, clean packet send bit first */
if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset),
(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT));
@@ -432,6 +397,53 @@ startup_out:
gma_power_end(dev);
}
+
+static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
+ u8 dcs,
+ u32 *data,
+ u8 transmission)
+{
+ struct mdfld_dsi_pkg_sender *sender
+ = mdfld_dsi_get_pkg_sender(dsi_config);
+
+ if (!sender || !data) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ if (transmission == MDFLD_DSI_HS_TRANSMISSION)
+ return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1);
+ else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
+ return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1);
+ else
+ return -EINVAL;
+}
+
+int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
+ u32 *mode,
+ u8 transmission)
+{
+ if (!dsi_config || !mode) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission);
+}
+
+int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
+ u32 *result,
+ u8 transmission)
+{
+ if (!dsi_config || !result) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result,
+ transmission);
+}
+
/*
* NOTE: this function was used by OSPM.
* TODO: will be removed later, should work out display interfaces for OSPM
@@ -459,14 +471,18 @@ static void mdfld_dsi_connector_restore(struct drm_connector * connector)
static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force)
{
- return connector_status_connected;
+ struct psb_intel_output *psb_output
+ = to_psb_intel_output(connector);
+ struct mdfld_dsi_connector *dsi_connector
+ = MDFLD_DSI_CONNECTOR(psb_output);
+ return dsi_connector->status;
}
-static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
- struct drm_property * property,
- uint64_t value)
+static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t value)
{
- struct drm_encoder * encoder = connector->encoder;
+ struct drm_encoder *encoder = connector->encoder;
if (!strcmp(property->name, "scaling mode") && encoder) {
struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
@@ -633,9 +649,12 @@ static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
}
/* Then check all display panels + monitors status */
+ /* Make sure that the Display (B) sub-system status isn't i3 when
+ * R/W the DC register, otherwise "Fabric error" issue would occur
+ * during S0i3 state. */
if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL)
& HDMIB_PORT_EN)) {
- /*request rpm idle*/
+ /* Request rpm idle */
if(dev_priv->rpm_enabled)
pm_request_idle(&dev->pdev->dev);
}
@@ -652,8 +671,8 @@ static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
#endif
}
-static struct drm_encoder * mdfld_dsi_connector_best_encoder(
- struct drm_connector * connector)
+static struct drm_encoder *mdfld_dsi_connector_best_encoder(
+ struct drm_connector *connector)
{
struct psb_intel_output * psb_output = to_psb_intel_output(connector);
struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
@@ -755,16 +774,6 @@ mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
mode->vtotal = mode->vdisplay + \
((ti->vblank_hi << 8) | ti->vblank_lo);
mode->clock = ti->pixel_clock * 10;
-
- dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
- dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
- dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
- dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
- dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
- dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
- dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
- dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
- dev_dbg(dev->dev, "clock is %d\n", mode->clock);
} else {
if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
@@ -810,6 +819,44 @@ mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
return mode;
}
+int mdfld_dsi_panel_reset(int pipe)
+{
+ unsigned gpio;
+ int ret = 0;
+
+ switch (pipe) {
+ case 0:
+ gpio = 128;
+ break;
+ case 2:
+ gpio = 34;
+ break;
+ default:
+ DRM_ERROR("Invalid output\n");
+ return -EINVAL;
+ }
+
+ ret = gpio_request(gpio, "gfx");
+ if (ret) {
+ DRM_ERROR("gpio_rqueset failed\n");
+ return ret;
+ }
+
+ ret = gpio_direction_output(gpio, 1);
+ if (ret) {
+ DRM_ERROR("gpio_direction_output failed\n");
+ goto gpio_error;
+ }
+
+ gpio_get_value(128);
+
+gpio_error:
+ if (gpio_is_valid(gpio))
+ gpio_free(gpio);
+
+ return ret;
+}
+
/*
* MIPI output init
* @dev drm device
@@ -819,9 +866,9 @@ mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
* Do the initialization of a MIPI output, including create DRM mode objects
* initialization of DSI output on @pipe
*/
-void mdfld_dsi_output_init(struct drm_device * dev,
+void mdfld_dsi_output_init(struct drm_device *dev,
int pipe,
- struct mdfld_dsi_config * config,
+ struct mdfld_dsi_config *config,
struct panel_funcs* p_cmd_funcs,
struct panel_funcs* p_vid_funcs)
{
@@ -869,7 +916,7 @@ void mdfld_dsi_output_init(struct drm_device * dev,
dsi_config->changed = 1;
dsi_config->dev = dev;
- /*init fixed mode basing on DSI config type*/
+ /* Init fixed mode basing on DSI config type */
if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
@@ -917,12 +964,18 @@ void mdfld_dsi_output_init(struct drm_device * dev,
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
- /*attach properties*/
+ /* Attach properties */
drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
- /*init DBI & DPI encoders*/
- if(p_cmd_funcs) {
+ /* Init DSI package sender on this output */
+ if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
+ DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe);
+ goto dsi_init_err0;
+ }
+
+ /* Init DBI & DPI encoders */
+ if (p_cmd_funcs) {
encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
if(!encoder) {
dev_err(dev->dev, "Create DBI encoder failed\n");
@@ -930,12 +983,6 @@ void mdfld_dsi_output_init(struct drm_device * dev,
}
encoder->private = dsi_config;
dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
- if(pipe == 2)
- dev_priv->encoder2 = encoder;
-
- if(pipe == 0)
- dev_priv->encoder0 = encoder;
-
}
if(p_vid_funcs) {
@@ -946,31 +993,16 @@ void mdfld_dsi_output_init(struct drm_device * dev,
}
encoder->private = dsi_config;
dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
-
- if(pipe == 2)
- dev_priv->encoder2 = encoder;
-
- if(pipe == 0)
- dev_priv->encoder0 = encoder;
}
drm_sysfs_connector_add(connector);
-
- /*init DSI package sender on this output*/
- if(mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
- dev_err(dev->dev,
- "Package Sender initialization failed on pipe %d\n",
- pipe);
- goto dsi_init_err2;
- }
-
- dev_dbg(dev->dev, "successfully\n");
return;
/*TODO: add code to destroy outputs on error*/
-dsi_init_err2:
- drm_sysfs_connector_remove(connector);
dsi_init_err1:
+ /*destroy sender*/
+ mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
+
drm_connector_cleanup(connector);
kfree(dsi_config->fixed_mode);
kfree(dsi_config);
diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h
index 4300f10..4699267 100644
--- a/drivers/staging/gma500/mdfld_dsi_output.h
+++ b/drivers/staging/gma500/mdfld_dsi_output.h
@@ -42,202 +42,6 @@
#include <asm/mrst.h>
-#define DRM_MODE_ENCODER_MIPI 5
-
-/* Medfield DSI controller registers */
-
-#define MIPIA_DEVICE_READY_REG 0xb000
-#define MIPIA_INTR_STAT_REG 0xb004
-#define MIPIA_INTR_EN_REG 0xb008
-#define MIPIA_DSI_FUNC_PRG_REG 0xb00c
-#define MIPIA_HS_TX_TIMEOUT_REG 0xb010
-#define MIPIA_LP_RX_TIMEOUT_REG 0xb014
-#define MIPIA_TURN_AROUND_TIMEOUT_REG 0xb018
-#define MIPIA_DEVICE_RESET_TIMER_REG 0xb01c
-#define MIPIA_DPI_RESOLUTION_REG 0xb020
-#define MIPIA_DBI_FIFO_THROTTLE_REG 0xb024
-#define MIPIA_HSYNC_COUNT_REG 0xb028
-#define MIPIA_HBP_COUNT_REG 0xb02c
-#define MIPIA_HFP_COUNT_REG 0xb030
-#define MIPIA_HACTIVE_COUNT_REG 0xb034
-#define MIPIA_VSYNC_COUNT_REG 0xb038
-#define MIPIA_VBP_COUNT_REG 0xb03c
-#define MIPIA_VFP_COUNT_REG 0xb040
-#define MIPIA_HIGH_LOW_SWITCH_COUNT_REG 0xb044
-#define MIPIA_DPI_CONTROL_REG 0xb048
-#define MIPIA_DPI_DATA_REG 0xb04c
-#define MIPIA_INIT_COUNT_REG 0xb050
-#define MIPIA_MAX_RETURN_PACK_SIZE_REG 0xb054
-#define MIPIA_VIDEO_MODE_FORMAT_REG 0xb058
-#define MIPIA_EOT_DISABLE_REG 0xb05c
-#define MIPIA_LP_BYTECLK_REG 0xb060
-#define MIPIA_LP_GEN_DATA_REG 0xb064
-#define MIPIA_HS_GEN_DATA_REG 0xb068
-#define MIPIA_LP_GEN_CTRL_REG 0xb06c
-#define MIPIA_HS_GEN_CTRL_REG 0xb070
-#define MIPIA_GEN_FIFO_STAT_REG 0xb074
-#define MIPIA_HS_LS_DBI_ENABLE_REG 0xb078
-#define MIPIA_DPHY_PARAM_REG 0xb080
-#define MIPIA_DBI_BW_CTRL_REG 0xb084
-#define MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG 0xb088
-
-#define DSI_DEVICE_READY (0x1)
-#define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1)
-#define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1)
-#define DSI_POWER_STATE_ULPS_OFFSET (0x1)
-
-
-#define DSI_ONE_DATA_LANE (0x1)
-#define DSI_TWO_DATA_LANE (0x2)
-#define DSI_THREE_DATA_LANE (0X3)
-#define DSI_FOUR_DATA_LANE (0x4)
-#define DSI_DPI_VIRT_CHANNEL_OFFSET (0x3)
-#define DSI_DBI_VIRT_CHANNEL_OFFSET (0x5)
-#define DSI_DPI_COLOR_FORMAT_RGB565 (0x01 << 7)
-#define DSI_DPI_COLOR_FORMAT_RGB666 (0x02 << 7)
-#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK (0x03 << 7)
-#define DSI_DPI_COLOR_FORMAT_RGB888 (0x04 << 7)
-#define DSI_DBI_COLOR_FORMAT_OPTION2 (0x05 << 13)
-
-#define DSI_INTR_STATE_RXSOTERROR 1
-
-#define DSI_INTR_STATE_SPL_PKG_SENT (1 << 30)
-#define DSI_INTR_STATE_TE (1 << 31)
-
-#define DSI_HS_TX_TIMEOUT_MASK (0xffffff)
-
-#define DSI_LP_RX_TIMEOUT_MASK (0xffffff)
-
-#define DSI_TURN_AROUND_TIMEOUT_MASK (0x3f)
-
-#define DSI_RESET_TIMER_MASK (0xffff)
-
-#define DSI_DBI_FIFO_WM_HALF (0x0)
-#define DSI_DBI_FIFO_WM_QUARTER (0x1)
-#define DSI_DBI_FIFO_WM_LOW (0x2)
-
-#define DSI_DPI_TIMING_MASK (0xffff)
-
-#define DSI_INIT_TIMER_MASK (0xffff)
-
-#define DSI_DBI_RETURN_PACK_SIZE_MASK (0x3ff)
-
-#define DSI_LP_BYTECLK_MASK (0x0ffff)
-
-#define DSI_HS_CTRL_GEN_SHORT_W0 (0x03)
-#define DSI_HS_CTRL_GEN_SHORT_W1 (0x13)
-#define DSI_HS_CTRL_GEN_SHORT_W2 (0x23)
-#define DSI_HS_CTRL_GEN_R0 (0x04)
-#define DSI_HS_CTRL_GEN_R1 (0x14)
-#define DSI_HS_CTRL_GEN_R2 (0x24)
-#define DSI_HS_CTRL_GEN_LONG_W (0x29)
-#define DSI_HS_CTRL_MCS_SHORT_W0 (0x05)
-#define DSI_HS_CTRL_MCS_SHORT_W1 (0x15)
-#define DSI_HS_CTRL_MCS_R0 (0x06)
-#define DSI_HS_CTRL_MCS_LONG_W (0x39)
-#define DSI_HS_CTRL_VC_OFFSET (0x06)
-#define DSI_HS_CTRL_WC_OFFSET (0x08)
-
-#define DSI_FIFO_GEN_HS_DATA_FULL (1 << 0)
-#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY (1 << 1)
-#define DSI_FIFO_GEN_HS_DATA_EMPTY (1 << 2)
-#define DSI_FIFO_GEN_LP_DATA_FULL (1 << 8)
-#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY (1 << 9)
-#define DSI_FIFO_GEN_LP_DATA_EMPTY (1 << 10)
-#define DSI_FIFO_GEN_HS_CTRL_FULL (1 << 16)
-#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY (1 << 17)
-#define DSI_FIFO_GEN_HS_CTRL_EMPTY (1 << 18)
-#define DSI_FIFO_GEN_LP_CTRL_FULL (1 << 24)
-#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY (1 << 25)
-#define DSI_FIFO_GEN_LP_CTRL_EMPTY (1 << 26)
-#define DSI_FIFO_DBI_EMPTY (1 << 27)
-#define DSI_FIFO_DPI_EMPTY (1 << 28)
-
-#define DSI_DBI_HS_LP_SWITCH_MASK (0x1)
-
-#define DSI_HS_LP_SWITCH_COUNTER_OFFSET (0x0)
-#define DSI_LP_HS_SWITCH_COUNTER_OFFSET (0x16)
-
-#define DSI_DPI_CTRL_HS_SHUTDOWN (0x00000001)
-#define DSI_DPI_CTRL_HS_TURN_ON (0x00000002)
-
-/* Medfield DSI adapter registers */
-#define MIPIA_CONTROL_REG 0xb104
-#define MIPIA_DATA_ADD_REG 0xb108
-#define MIPIA_DATA_LEN_REG 0xb10c
-#define MIPIA_CMD_ADD_REG 0xb110
-#define MIPIA_CMD_LEN_REG 0xb114
-
-enum {
- MDFLD_DSI_ENCODER_DBI = 0,
- MDFLD_DSI_ENCODER_DPI,
-};
-
-enum {
- MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1,
- MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2,
- MDFLD_DSI_VIDEO_BURST_MODE = 3,
-};
-
-#define DSI_DPI_COMPLETE_LAST_LINE (1 << 2)
-#define DSI_DPI_DISABLE_BTA (1 << 3)
-
-struct mdfld_dsi_connector_state {
- u32 mipi_ctrl_reg;
-};
-
-struct mdfld_dsi_encoder_state {
-
-};
-
-struct mdfld_dsi_connector {
- /*
- * This is ugly, but I have to use connector in it! :-(
- * FIXME: use drm_connector instead.
- */
- struct psb_intel_output base;
-
- int pipe;
- void *private;
- void *pkg_sender;
-};
-
-struct mdfld_dsi_encoder {
- struct drm_encoder base;
- void *private;
-};
-
-/*
- * DSI config, consists of one DSI connector, two DSI encoders.
- * DRM will pick up on DSI encoder basing on differents configs.
- */
-struct mdfld_dsi_config {
- struct drm_device *dev;
- struct drm_display_mode *fixed_mode;
- struct drm_display_mode *mode;
-
- struct mdfld_dsi_connector *connector;
- struct mdfld_dsi_encoder *encoders[DRM_CONNECTOR_MAX_ENCODER];
- struct mdfld_dsi_encoder *encoder;
-
- int changed;
-
- int bpp;
- int type;
- int lane_count;
- /*Virtual channel number for this encoder*/
- int channel_num;
- /*video mode configure*/
- int video_mode;
-
- int dvr_ic_inited;
-};
-
-#define MDFLD_DSI_CONNECTOR(psb_output) \
- (container_of(psb_output, struct mdfld_dsi_connector, base))
-
-#define MDFLD_DSI_ENCODER(encoder) \
- (container_of(encoder, struct mdfld_dsi_encoder, base))
static inline struct mdfld_dsi_config *
mdfld_dsi_get_config(struct mdfld_dsi_connector *connector)
@@ -323,5 +127,12 @@ extern void mdfld_dsi_output_init(struct drm_device *dev, int pipe,
struct panel_funcs *p_vid_funcs);
extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config,
int pipe);
+extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
+ u32 *mode,
+ u8 transmission);
+extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
+ u32 *result,
+ u8 transmission);
+extern int mdfld_dsi_panel_reset(int pipe);
#endif /*__MDFLD_DSI_OUTPUT_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
index 745d4ad..9b96a5c 100644
--- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
+++ b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
@@ -29,8 +29,11 @@
#include "mdfld_dsi_output.h"
#include "mdfld_dsi_pkg_sender.h"
#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
-#define MDFLD_DSI_DBI_FIFO_TIMEOUT 100
+#define MDFLD_DSI_DBI_FIFO_TIMEOUT 100
+#define MDFLD_DSI_MAX_RETURN_PACKET_SIZE 512
+#define MDFLD_DSI_READ_MAX_COUNT 5000
static const char * const dsi_errors[] = {
"RX SOT Error",
@@ -404,8 +407,10 @@ static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender,
}
/* Wait for 120 milliseconds in case exit_sleep_mode just be sent */
- if (cmd == enter_sleep_mode)
+ if (cmd == DCS_ENTER_SLEEP_MODE) {
+ /*TODO: replace it with msleep later*/
mdelay(120);
+ }
return 0;
}
@@ -432,16 +437,18 @@ static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender,
}
/* Update panel status */
- if (cmd == enter_sleep_mode) {
+ if (cmd == DCS_ENTER_SLEEP_MODE) {
sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
/*TODO: replace it with msleep later*/
mdelay(120);
- } else if (cmd == exit_sleep_mode) {
+ } else if (cmd == DCS_EXIT_SLEEP_MODE) {
sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
/*TODO: replace it with msleep later*/
mdelay(120);
- }
-
+ } else if (unlikely(cmd == DCS_SOFT_RESET)) {
+ /*TODO: replace it with msleep later*/
+ mdelay(5);
+ }
sender->status = MDFLD_DSI_PKG_SENDER_FREE;
return 0;
@@ -470,6 +477,9 @@ static int do_send_pkg(struct mdfld_dsi_pkg_sender *sender,
case MDFLD_DSI_PKG_GEN_SHORT_WRITE_0:
case MDFLD_DSI_PKG_GEN_SHORT_WRITE_1:
case MDFLD_DSI_PKG_GEN_SHORT_WRITE_2:
+ case MDFLD_DSI_PKG_GEN_READ_0:
+ case MDFLD_DSI_PKG_GEN_READ_1:
+ case MDFLD_DSI_PKG_GEN_READ_2:
ret = send_gen_short_pkg(sender, pkg);
break;
case MDFLD_DSI_PKG_GEN_LONG_WRITE:
@@ -477,6 +487,7 @@ static int do_send_pkg(struct mdfld_dsi_pkg_sender *sender,
break;
case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
+ case MDFLD_DSI_PKG_MCS_READ:
ret = send_mcs_short_pkg(sender, pkg);
break;
case MDFLD_DSI_PKG_MCS_LONG_WRITE:
@@ -548,6 +559,7 @@ static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender *sender,
switch (pipe) {
case 0:
+ /* FIXME: Doesn't this collide with stolen space ? */
phys = pg->gtt_phys_start - 0x1000;
break;
case 2:
@@ -735,6 +747,292 @@ static int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender,
return 0;
}
+static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender,
+ struct mdfld_dsi_pkg *pkg,
+ u32 *data,
+ u16 len)
+{
+ unsigned long flags;
+ struct drm_device *dev = sender->dev;
+ int i;
+ u32 gen_data_reg;
+ int retry = MDFLD_DSI_READ_MAX_COUNT;
+ u8 transmission = pkg->transmission_type;
+
+ /*
+ * do reading.
+ * 0) send out generic read request
+ * 1) polling read data avail interrupt
+ * 2) read data
+ */
+ spin_lock_irqsave(&sender->lock, flags);
+
+ REG_WRITE(sender->mipi_intr_stat_reg, 1 << 29);
+
+ if ((REG_READ(sender->mipi_intr_stat_reg) & (1 << 29)))
+ DRM_ERROR("Can NOT clean read data valid interrupt\n");
+
+ /*send out read request*/
+ send_pkg(sender, pkg);
+
+ pkg_sender_put_pkg_locked(sender, pkg);
+
+ /*polling read data avail interrupt*/
+ while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) {
+ udelay(100);
+ retry--;
+ }
+
+ if (!retry) {
+ spin_unlock_irqrestore(&sender->lock, flags);
+ return -ETIMEDOUT;
+ }
+
+ REG_WRITE(sender->mipi_intr_stat_reg, (1 << 29));
+
+ /*read data*/
+ if (transmission == MDFLD_DSI_HS_TRANSMISSION)
+ gen_data_reg = sender->mipi_hs_gen_data_reg;
+ else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
+ gen_data_reg = sender->mipi_lp_gen_data_reg;
+ else {
+ DRM_ERROR("Unknown transmission");
+ spin_unlock_irqrestore(&sender->lock, flags);
+ return -EINVAL;
+ }
+
+ for (i=0; i<len; i++)
+ *(data + i) = REG_READ(gen_data_reg);
+
+ spin_unlock_irqrestore(&sender->lock, flags);
+
+ return 0;
+}
+
+static int mdfld_dsi_read_gen(struct mdfld_dsi_pkg_sender *sender,
+ u8 param0,
+ u8 param1,
+ u8 param_num,
+ u32 *data,
+ u16 len,
+ u8 transmission)
+{
+ struct mdfld_dsi_pkg *pkg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sender->lock, flags);
+
+ pkg = pkg_sender_get_pkg_locked(sender);
+
+ spin_unlock_irqrestore(&sender->lock,flags);
+
+ if (!pkg) {
+ dev_err(sender->dev->dev, "No pkg memory\n");
+ return -ENOMEM;
+ }
+
+ switch (param_num) {
+ case 0:
+ pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_0;
+ pkg->pkg.short_pkg.cmd = 0;
+ pkg->pkg.short_pkg.param = 0;
+ break;
+ case 1:
+ pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_1;
+ pkg->pkg.short_pkg.cmd = param0;
+ pkg->pkg.short_pkg.param = 0;
+ break;
+ case 2:
+ pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_2;
+ pkg->pkg.short_pkg.cmd = param0;
+ pkg->pkg.short_pkg.param = param1;
+ break;
+ }
+
+ pkg->transmission_type = transmission;
+
+ INIT_LIST_HEAD(&pkg->entry);
+
+ return __read_panel_data(sender, pkg, data, len);
+}
+
+static int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender,
+ u8 cmd,
+ u32 *data,
+ u16 len,
+ u8 transmission)
+{
+ struct mdfld_dsi_pkg *pkg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sender->lock, flags);
+
+ pkg = pkg_sender_get_pkg_locked(sender);
+
+ spin_unlock_irqrestore(&sender->lock, flags);
+
+ if (!pkg) {
+ dev_err(sender->dev->dev, "No pkg memory\n");
+ return -ENOMEM;
+ }
+
+ pkg->pkg_type = MDFLD_DSI_PKG_MCS_READ;
+ pkg->pkg.short_pkg.cmd = cmd;
+ pkg->pkg.short_pkg.param = 0;
+
+ pkg->transmission_type = transmission;
+
+ INIT_LIST_HEAD(&pkg->entry);
+
+ return __read_panel_data(sender, pkg, data, len);
+}
+
+void dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ struct drm_device * dev = dsi_config->dev;
+ u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+ int lane_count = dsi_config->lane_count;
+ u32 val = 0;
+
+ /*un-ready device*/
+ REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+
+ /*init dsi adapter before kicking off*/
+ REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+
+ /*TODO: figure out how to setup these registers*/
+ REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
+ REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), 0x000a0014);
+ REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
+ REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
+ REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
+
+ /*enable all interrupts*/
+ REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+ /*max value: 20 clock cycles of txclkesc*/
+ REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
+ /*min 21 txclkesc, max: ffffh*/
+ REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
+ /*min: 7d0 max: 4e20*/
+ REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
+
+ /*set up max return packet size*/
+ REG_WRITE((MIPIA_MAX_RETURN_PACK_SIZE_REG + reg_offset),
+ MDFLD_DSI_MAX_RETURN_PACKET_SIZE);
+
+ /*set up func_prg*/
+ val |= lane_count;
+ val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
+ val |= DSI_DBI_COLOR_FORMAT_OPTION2;
+ REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+
+ REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
+ REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
+
+ REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+ REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
+ REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+ REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+void dsi_controller_dpi_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ struct drm_device * dev = dsi_config->dev;
+ u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+ int lane_count = dsi_config->lane_count;
+ struct mdfld_dsi_dpi_timing dpi_timing;
+ struct drm_display_mode * mode = dsi_config->mode;
+ u32 val = 0;
+
+ /*un-ready device*/
+ REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+
+ /*init dsi adapter before kicking off*/
+ REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+
+ /*enable all interrupts*/
+ REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+
+ /*set up func_prg*/
+ val |= lane_count;
+ val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
+
+ switch(dsi_config->bpp) {
+ case 16:
+ val |= DSI_DPI_COLOR_FORMAT_RGB565;
+ break;
+ case 18:
+ val |= DSI_DPI_COLOR_FORMAT_RGB666;
+ break;
+ case 24:
+ val |= DSI_DPI_COLOR_FORMAT_RGB888;
+ break;
+ default:
+ DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
+ }
+
+ REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+
+ REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset),
+ (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
+ REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
+
+ /*max value: 20 clock cycles of txclkesc*/
+ REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
+
+ /*min 21 txclkesc, max: ffffh*/
+ REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK);
+
+ REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay);
+
+ /*set DPI timing registers*/
+ mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
+
+ REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
+
+ REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+
+ /*min: 7d0 max: 4e20*/
+ REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0);
+
+ /*set up video mode*/
+ val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
+ REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val);
+
+ REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
+
+ REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+
+ /*TODO: figure out how to setup these registers*/
+ REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
+
+ REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);
+
+ /*set device ready*/
+ REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+static void dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ if (!dsi_config || ((pipe != 0) && (pipe != 2))) {
+ DRM_ERROR("Invalid parameters\n");
+ return;
+ }
+
+ if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
+ dsi_controller_dpi_init(dsi_config, pipe);
+ else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
+ dsi_controller_dbi_init(dsi_config, pipe);
+ else
+ DRM_ERROR("Bad DSI encoder type\n");
+}
+
void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender)
{
process_pkg_list(sender);
@@ -774,7 +1072,7 @@ int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender,
* If dcs is write_mem_start, send it directly using DSI adapter
* interface
*/
- if (dcs == write_mem_start) {
+ if (dcs == DCS_WRITE_MEM_START) {
if (!spin_trylock(&sender->lock))
return -EAGAIN;
@@ -944,6 +1242,69 @@ int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
MDFLD_DSI_LP_TRANSMISSION, delay);
}
+int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender,
+ u8 param0,
+ u8 param1,
+ u8 param_num,
+ u32 *data,
+ u16 len)
+{
+ if (!sender || !data || param_num < 0 || param_num > 2
+ || !data || !len) {
+ DRM_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ return mdfld_dsi_read_gen(sender, param0, param1, param_num,
+ data, len, MDFLD_DSI_HS_TRANSMISSION);
+
+}
+
+int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender,
+ u8 param0,
+ u8 param1,
+ u8 param_num,
+ u32 *data,
+ u16 len)
+{
+ if (!sender || !data || param_num < 0 || param_num > 2
+ || !data || !len) {
+ DRM_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ return mdfld_dsi_read_gen(sender, param0, param1, param_num,
+ data, len, MDFLD_DSI_LP_TRANSMISSION);
+}
+
+int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender,
+ u8 cmd,
+ u32 *data,
+ u16 len)
+{
+ if (!sender || !data || !len) {
+ DRM_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ return mdfld_dsi_read_mcs(sender, cmd, data, len,
+ MDFLD_DSI_HS_TRANSMISSION);
+}
+
+int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender,
+ u8 cmd,
+ u32 *data,
+ u16 len)
+{
+ if (!sender || !data || !len) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ return mdfld_dsi_read_mcs(sender, cmd, data, len,
+ MDFLD_DSI_LP_TRANSMISSION);
+}
+
int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
int pipe)
{
@@ -956,6 +1317,7 @@ int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
struct psb_gtt *pg = &dev_priv->gtt;
int i;
struct mdfld_dsi_pkg *pkg, *tmp;
+ u32 mipi_val = 0;
if (!dsi_connector) {
WARN_ON(1);
@@ -1018,7 +1380,7 @@ int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
pkg_sender->pipeconf_reg = PIPECCONF;
pkg_sender->dsplinoff_reg = DSPCLINOFF;
pkg_sender->dspsurf_reg = DSPCSURF;
- pkg_sender->pipestat_reg = 72024;
+ pkg_sender->pipestat_reg = PIPECSTAT;
pkg_sender->mipi_intr_stat_reg =
MIPIA_INTR_STAT_REG + MIPIC_REG_OFFSET;
@@ -1059,6 +1421,31 @@ int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
INIT_LIST_HEAD(&pkg->entry);
list_add_tail(&pkg->entry, &pkg_sender->free_list);
}
+
+ /*
+ * For video mode, don't enable DPI timing output here,
+ * will init the DPI timing output during mode setting.
+ */
+ if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
+ mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+ else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
+ mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX
+ | TE_TRIGGER_GPIO_PIN;
+ else
+ DRM_ERROR("Bad DSI encoder type\n");
+
+ if (pipe == 0) {
+ mipi_val |= 0x2;
+ REG_WRITE(MIPI, mipi_val);
+ REG_READ(MIPI);
+ } else if (pipe == 2) {
+ REG_WRITE(MIPI_C, mipi_val);
+ REG_READ(MIPI_C);
+ }
+
+ /*do dsi controller init*/
+ dsi_controller_init(dsi_config, pipe);
+
return 0;
pkg_alloc_err:
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
index 296b1ea..f24abc7 100644
--- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
+++ b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
@@ -36,9 +36,13 @@ enum {
MDFLD_DSI_PKG_GEN_SHORT_WRITE_0 = 0x03,
MDFLD_DSI_PKG_GEN_SHORT_WRITE_1 = 0x13,
MDFLD_DSI_PKG_GEN_SHORT_WRITE_2 = 0x23,
+ MDFLD_DSI_PKG_GEN_READ_0 = 0x04,
+ MDFLD_DSI_PKG_GEN_READ_1 = 0x14,
+ MDFLD_DSI_PKG_GEN_READ_2 = 0x24,
MDFLD_DSI_PKG_GEN_LONG_WRITE = 0x29,
MDFLD_DSI_PKG_MCS_SHORT_WRITE_0 = 0x05,
MDFLD_DSI_PKG_MCS_SHORT_WRITE_1 = 0x15,
+ MDFLD_DSI_PKG_MCS_READ = 0x06,
MDFLD_DSI_PKG_MCS_LONG_WRITE = 0x39,
};
@@ -132,6 +136,18 @@ struct mdfld_dsi_pkg_sender {
u32 mipi_cmd_len_reg;
};
+/* DCS definitions */
+#define DCS_SOFT_RESET 0x01
+#define DCS_ENTER_SLEEP_MODE 0x10
+#define DCS_EXIT_SLEEP_MODE 0x11
+#define DCS_SET_DISPLAY_OFF 0x28
+#define DCS_SET_DISPLAY_ON 0x29
+#define DCS_SET_COLUMN_ADDRESS 0x2a
+#define DCS_SET_PAGE_ADDRESS 0x2b
+#define DCS_WRITE_MEM_START 0x2c
+#define DCS_SET_TEAR_OFF 0x34
+#define DCS_SET_TEAR_ON 0x35
+
extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
int pipe);
extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender);
@@ -153,6 +169,16 @@ extern int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
u32 *data, u32 len, int delay);
extern int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
u32 *data, u32 len, int delay);
+
+extern int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender,
+ u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
+extern int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender,
+ u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
+extern int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender,
+ u8 cmd, u32 *data, u16 len);
+extern int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender,
+ u8 cmd, u32 *data, u16 len);
+
extern void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender);
#endif /* __MDFLD_DSI_PKG_SENDER_H__ */
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
index fa84990..ac74a8d 100644
--- a/drivers/staging/gma500/mdfld_intel_display.c
+++ b/drivers/staging/gma500/mdfld_intel_display.c
@@ -140,7 +140,6 @@ static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t width, uint32_t height)
{
struct drm_device *dev = crtc->dev;
- struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
int pipe = psb_intel_crtc->pipe;
uint32_t control = CURACNTR;
@@ -263,7 +262,7 @@ static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
case 0:
#ifndef CONFIG_MDFLD_DSI_DPU
if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0))
- mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_0, 0, 0);
+ mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_0);
#else /*CONFIG_MDFLD_DSI_DPU*/
rect.x = x;
rect.y = y;
@@ -279,7 +278,7 @@ static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
case 2:
#ifndef CONFIG_MDFLD_DSI_DPU
if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2))
- mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_2, 0, 0);
+ mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_2);
#else /*CONFIG_MDFLD_DSI_DPU*/
mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect);
mdfld_dpu_exit_dsr(dev);
@@ -354,7 +353,6 @@ int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_f
/* struct drm_i915_master_private *master_priv; */
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
int pipe = psb_intel_crtc->pipe;
unsigned long start, offset;
int dsplinoff = DSPALINOFF;
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c
index 7e11401..ffa2c1f 100644
--- a/drivers/staging/gma500/mdfld_output.c
+++ b/drivers/staging/gma500/mdfld_output.c
@@ -100,7 +100,6 @@ static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type)
mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
break;
case PYR_VID:
- /*pyr_vid_init(dev, p_vid_funcs); */
mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
break;
case TPO: /* TPO panel supports both cmd & vid interfaces */
@@ -135,10 +134,15 @@ int mdfld_output_init(struct drm_device *dev)
dev_info(dev->dev, "panel 1: type is %d\n", type);
init_panel(dev, 0, type);
+#ifdef CONFIG_MDFD_DUAL_MIPI
/* MIPI panel 2 */
type = mdfld_get_panel_type(dev, 2);
dev_info(dev->dev, "panel 2: type is %d\n", type);
init_panel(dev, 2, type);
-
+#endif
+#ifdef CONFIG_MDFD_HDMI
+ /* HDMI panel */
+ init_panel(dev, 0, HDMI);
+#endif
return 0;
}
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h
index 70f2302a..e747fdb 100644
--- a/drivers/staging/gma500/mdfld_output.h
+++ b/drivers/staging/gma500/mdfld_output.h
@@ -28,47 +28,6 @@
#ifndef MDFLD_OUTPUT_H
#define MDFLD_OUTPUT_H
-#include "psb_drv.h"
-
-/* Panel types */
-enum {
- TPO_CMD,
- TPO_VID,
- TMD_CMD,
- TMD_VID,
- PYR_CMD,
- PYR_VID,
- TPO,
- TMD,
- PYR,
- HDMI,
- GCT_DETECT
-};
-
-/* Junk that belongs elsewhere */
-#define TPO_PANEL_WIDTH 84
-#define TPO_PANEL_HEIGHT 46
-#define TMD_PANEL_WIDTH 39
-#define TMD_PANEL_HEIGHT 71
-#define PYR_PANEL_WIDTH 53
-#define PYR_PANEL_HEIGHT 95
-
-/* Panel interface */
-struct panel_info {
- u32 width_mm;
- u32 height_mm;
-};
-
-struct mdfld_dsi_dbi_output;
-
-struct panel_funcs {
- const struct drm_encoder_funcs *encoder_funcs;
- const struct drm_encoder_helper_funcs *encoder_helper_funcs;
- struct drm_display_mode *(*get_config_mode) (struct drm_device *);
- void (*update_fb) (struct mdfld_dsi_dbi_output *, int);
- int (*get_panel_info) (struct drm_device *, int, struct panel_info *);
-};
-
int mdfld_output_init(struct drm_device *dev);
int mdfld_panel_dpi(struct drm_device *dev);
int mdfld_get_panel_type(struct drm_device *dev, int pipe);
diff --git a/drivers/staging/gma500/mdfld_pyr_cmd.c b/drivers/staging/gma500/mdfld_pyr_cmd.c
index 0d89384..5f38e8d 100644
--- a/drivers/staging/gma500/mdfld_pyr_cmd.c
+++ b/drivers/staging/gma500/mdfld_pyr_cmd.c
@@ -188,7 +188,7 @@ static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
- /* In-ready device */
+ /* Un-ready device */
REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
/* Init dsi adapter before kicking off */
@@ -394,25 +394,13 @@ static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
struct mdfld_dsi_dbi_output *dbi_output =
MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
struct drm_device *dev = dbi_output->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- static bool bdispoff;
dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
- if (mode == DRM_MODE_DPMS_ON) {
- if (/*gbgfxsuspended && */bdispoff) {
- bdispoff = false;
- dev_priv->dispstatus = true;
- /*gbgfxsuspended = false;
- */
- mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D, 0, 0);
- }
+ if (mode == DRM_MODE_DPMS_ON)
pyr_dsi_dbi_set_power(encoder, true);
- } else {
- bdispoff = true;
- dev_priv->dispstatus = false;
+ else
pyr_dsi_dbi_set_power(encoder, false);
- }
}
/*
diff --git a/drivers/staging/gma500/mdfld_tmd_vid.c b/drivers/staging/gma500/mdfld_tmd_vid.c
index b29c905..affdc09 100644
--- a/drivers/staging/gma500/mdfld_tmd_vid.c
+++ b/drivers/staging/gma500/mdfld_tmd_vid.c
@@ -114,6 +114,66 @@ static int tmd_vid_get_panel_info(struct drm_device *dev,
return 0;
}
+/*
+ * mdfld_init_TMD_MIPI - initialise a TMD interface
+ * @dsi_config: configuration
+ * @pipe: pipe to configure
+ *
+ * This function is called only by mrst_dsi_mode_set and
+ * restore_display_registers. since this function does not
+ * acquire the mutex, it is important that the calling function
+ * does!
+ */
+
+
+static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config,
+ int pipe)
+{
+ static u32 tmd_cmd_mcap_off[] = {0x000000b2};
+ static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
+ static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
+ static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef};
+ static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef};
+ static u32 tmd_cmd_set_mode[] = {0x000000b3};
+ static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
+ static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df};
+ static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055};
+ static u32 tmd_cmd_set_video_mode[] = {0x00000153};
+ /*no auto_bl,need add in furture*/
+ static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};
+ static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd};
+
+ struct mdfld_dsi_pkg_sender *sender
+ = mdfld_dsi_get_pkg_sender(dsi_config);
+
+ DRM_INFO("Enter mdfld init TMD MIPI display.\n");
+
+ if (!sender) {
+ DRM_ERROR("Cannot get sender\n");
+ return;
+ }
+
+ if (dsi_config->dvr_ic_inited)
+ return;
+
+ msleep(3);
+
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_mcap_off, 1, 0);
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_lane_switch, 1, 0);
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_lane_num, 1, 0);
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock0, 1, 0);
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock1, 1, 0);
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_mode, 1, 0);
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_sync_pulse_mode, 1, 0);
+ mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_column, 2, 0);
+ mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_page, 2, 0);
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_video_mode, 1, 0);
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_backlight, 1, 0);
+ mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_backlight_dimming, 1, 0);
+
+ dsi_config->dvr_ic_inited = 1;
+}
+
/* TMD DPI encoder helper funcs */
static const struct drm_encoder_helper_funcs
mdfld_tpo_dpi_encoder_helper_funcs = {
@@ -141,4 +201,6 @@ void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs)
p_funcs->get_config_mode = &tmd_vid_get_config_mode;
p_funcs->update_fb = NULL;
p_funcs->get_panel_info = tmd_vid_get_panel_info;
+ p_funcs->reset = mdfld_dsi_panel_reset;
+ p_funcs->drv_ic_init = mdfld_dsi_tmd_drv_ic_init;
}
diff --git a/drivers/staging/gma500/mdfld_tpo_cmd.c b/drivers/staging/gma500/mdfld_tpo_cmd.c
index d2e1818..4cf7647 100644
--- a/drivers/staging/gma500/mdfld_tpo_cmd.c
+++ b/drivers/staging/gma500/mdfld_tpo_cmd.c
@@ -126,11 +126,15 @@ static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
struct mdfld_dsi_dbi_output *dbi_output =
MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
- /*struct drm_device *dev = dbi_output->dev;*/
+ struct mdfld_dsi_config *dsi_config =
+ mdfld_dsi_encoder_get_config(dsi_encoder);
+ struct mdfld_dsi_pkg_sender *sender =
+ mdfld_dsi_encoder_get_pkg_sender(dsi_encoder);
struct drm_device *dev = encoder->dev;
struct drm_psb_private *dev_priv = dev->dev_private;
u32 reg_offset = 0;
int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
+ u32 data = 0;
dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n",
pipe, on ? "On" : "Off",
@@ -190,9 +194,33 @@ static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
}
}
+ /*
+ * FIXME: this is a WA for TPO panel crash on DPMS on & off around
+ * 83 times. the root cause of this issue is that Booster in
+ * drvIC crashed. Add this WA so that we can resume the driver IC
+ * once we found that booster has a fault
+ */
+ mdfld_dsi_get_power_mode(dsi_config,
+ &data,
+ MDFLD_DSI_HS_TRANSMISSION);
+
+ if (on && data && !(data & (1 << 7))) {
+ /* Soft reset */
+ mdfld_dsi_send_dcs(sender,
+ DCS_SOFT_RESET,
+ NULL,
+ 0,
+ CMD_DATA_SRC_PIPE,
+ MDFLD_DSI_SEND_PACKAGE);
+
+ /* Init drvIC */
+ if (dbi_output->p_funcs->drv_ic_init)
+ dbi_output->p_funcs->drv_ic_init(dsi_config,
+ pipe);
+ }
+
out_err:
gma_power_end(dev);
-
if (ret)
dev_err(dev->dev, "failed\n");
}
@@ -253,14 +281,6 @@ static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder,
return;
}
- /* Set up pipe related registers */
- REG_WRITE(mipi_reg, mipi_val);
- REG_READ(mipi_reg);
-
- mdfld_dsi_controller_dbi_init(dsi_config, pipe);
-
- msleep(20);
-
REG_WRITE(dspcntr_reg, dspcntr_val);
REG_READ(dspcntr_reg);
@@ -268,7 +288,7 @@ static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder,
msleep(20);
/* Send exit_sleep_mode DCS */
- ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode,
+ ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_EXIT_SLEEP_MODE,
NULL, 0, CMD_DATA_SRC_SYSTEM_MEM);
if (ret) {
dev_err(dev->dev, "sent exit_sleep_mode faild\n");
@@ -276,7 +296,7 @@ static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder,
}
/* Send set_tear_on DCS */
- ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on,
+ ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_SET_TEAR_ON,
¶m, 1, CMD_DATA_SRC_SYSTEM_MEM);
if (ret) {
dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
@@ -284,11 +304,6 @@ static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder,
}
/* Do some init stuff */
- mdfld_dsi_brightness_init(dsi_config, pipe);
-
- mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset),
- HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-
REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
REG_READ(pipeconf_reg);
@@ -375,23 +390,24 @@ static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
* if everything goes right, hw_begin will resume them all
* during set_power.
*/
- if (bdispoff)
- mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D, 0, 0);
+ if (bdispoff /* FIXME && gbgfxsuspended */) {
+ mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D);
+ bdispoff = false;
+ dev_priv->dispstatus = true;
+ }
mdfld_dsi_dbi_set_power(encoder, true);
/* FIXME if (gbgfxsuspended)
gbgfxsuspended = false; */
- bdispoff = false;
- dev_priv->dispstatus = true;
} else {
/*
* I am not sure whether this is the perfect place to
* turn rpm on since we still have a lot of CRTC turnning
* on work to do.
*/
- mdfld_dsi_dbi_set_power(encoder, false);
bdispoff = true;
dev_priv->dispstatus = false;
+ mdfld_dsi_dbi_set_power(encoder, false);
}
}
@@ -446,7 +462,7 @@ static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
REG_READ(dspsurf_reg);
mdfld_dsi_send_dcs(sender,
- write_mem_start,
+ DCS_WRITE_MEM_START,
NULL,
0,
CMD_DATA_SRC_PIPE,
@@ -492,4 +508,6 @@ void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
p_funcs->get_config_mode = &tpo_cmd_get_config_mode;
p_funcs->update_fb = mdfld_dsi_dbi_update_fb;
p_funcs->get_panel_info = tpo_cmd_get_panel_info;
+ p_funcs->reset = mdfld_dsi_panel_reset;
+ p_funcs->drv_ic_init = mdfld_dsi_brightness_init;
}
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index 25fde4c..ac791c4 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -58,11 +58,11 @@ static void mrst_lvds_set_power(struct drm_device *dev,
pp_status = REG_READ(PP_STATUS);
} while ((pp_status & (PP_ON | PP_READY)) == PP_READY);
dev_priv->is_lvds_on = true;
- if (dev_priv->ops->lvds_bl_power)
- dev_priv->ops->lvds_bl_power(dev, true);
+ if (dev_priv->ops->lvds_bl_power)
+ dev_priv->ops->lvds_bl_power(dev, true);
} else {
- if (dev_priv->ops->lvds_bl_power)
- dev_priv->ops->lvds_bl_power(dev, false);
+ if (dev_priv->ops->lvds_bl_power)
+ dev_priv->ops->lvds_bl_power(dev, false);
REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
~POWER_TARGET_ON);
do {
@@ -151,6 +151,7 @@ static void mrst_lvds_prepare(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+ struct psb_intel_mode_device *mode_dev = output->mode_dev;
if (!gma_power_begin(dev, true))
return;
@@ -162,23 +163,43 @@ static void mrst_lvds_prepare(struct drm_encoder *encoder)
gma_power_end(dev);
}
+static u32 mrst_lvds_get_max_backlight(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ u32 ret;
+
+ if (gma_power_begin(dev, false)) {
+ ret = ((REG_READ(BLC_PWM_CTL) &
+ BACKLIGHT_MODULATION_FREQ_MASK) >>
+ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+ gma_power_end(dev);
+ } else
+ ret = ((dev_priv->saveBLC_PWM_CTL &
+ BACKLIGHT_MODULATION_FREQ_MASK) >>
+ BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+ return ret;
+}
+
static void mrst_lvds_commit(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+ struct psb_intel_mode_device *mode_dev = output->mode_dev;
if (mode_dev->backlight_duty_cycle == 0)
mode_dev->backlight_duty_cycle =
- psb_intel_lvds_get_max_backlight(dev);
+ mrst_lvds_get_max_backlight(dev);
mrst_lvds_set_power(dev, output, true);
}
static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = {
.dpms = mrst_lvds_dpms,
.mode_fixup = psb_intel_lvds_mode_fixup,
- .prepare = mrst_intel_lvds_prepare,
+ .prepare = mrst_lvds_prepare,
.mode_set = mrst_lvds_mode_set,
- .commit = mrst_intel_lvds_commit,
+ .commit = mrst_lvds_commit,
};
static struct drm_display_mode lvds_configuration_modes[] = {
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 194c64f..72f487a 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -31,6 +31,7 @@
#include "gtt.h"
#include "power.h"
#include "mrst.h"
+#include "medfield.h"
/* Append new drm mode definition here, align with libdrm definition */
#define DRM_MODE_SCALE_NO_SCALE 2
@@ -216,8 +217,8 @@ enum {
#define MDFLD_DSR_OVERLAY_0 (1 << 4)
#define MDFLD_DSR_OVERLAY_2 (1 << 5)
#define MDFLD_DSR_MIPI_CONTROL (1 << 6)
-#define MDFLD_DSR_DAMAGE_MASK_0 (1 << 0) | (1 << 2) | (1 << 4)
-#define MDFLD_DSR_DAMAGE_MASK_2 (1 << 1) | (1 << 3) | (1 << 5)
+#define MDFLD_DSR_DAMAGE_MASK_0 ((1 << 0) | (1 << 2) | (1 << 4))
+#define MDFLD_DSR_DAMAGE_MASK_2 ((1 << 1) | (1 << 3) | (1 << 5))
#define MDFLD_DSR_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
#define MDFLD_DSR_RR 45
@@ -605,7 +606,7 @@ struct drm_psb_private {
uint32_t dsr_idle_count;
bool is_in_idle;
bool dsr_enable;
- void (*exit_idle)(struct drm_device *dev, u32 update_src, void *p_surfaceAddr, bool check_hw_on_only);
+ void (*exit_idle)(struct drm_device *dev, u32 update_src);
/* 2D acceleration */
struct mutex mutex_2d;
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 15/15] gma500: Clean up the DPU config and make it runtime
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (12 preceding siblings ...)
2011-07-15 16:35 ` [PATCH 14/15] gma500: resync with Medfield progress Alan Cox
@ 2011-07-15 16:35 ` Alan Cox
2011-07-15 17:06 ` [PATCH 01/15] gma500: Cursor interface Greg KH
14 siblings, 0 replies; 16+ messages in thread
From: Alan Cox @ 2011-07-15 16:35 UTC (permalink / raw)
To: greg, linux-kernel
From: Alan Cox <alan@linux.intel.com>
We really don't want this all done by ifdeffery - and this isn't any need
as it's fairly easy to sort out.
Signed-off-by: Alan Cox <alan@linux.intel.com>
---
drivers/staging/gma500/Makefile | 1
drivers/staging/gma500/mdfld_dsi_dbi.c | 19 -
drivers/staging/gma500/mdfld_dsi_dbi_dpu.c | 778 ++++++++++++++++++++++++++
drivers/staging/gma500/mdfld_dsi_output.c | 8
drivers/staging/gma500/mdfld_intel_display.c | 49 +-
drivers/staging/gma500/mdfld_output.c | 42 +
drivers/staging/gma500/mdfld_output.h | 2
drivers/staging/gma500/mdfld_pyr_cmd.c | 7
drivers/staging/gma500/mdfld_tpo_cmd.c | 6
drivers/staging/gma500/psb_drv.c | 11
10 files changed, 845 insertions(+), 78 deletions(-)
create mode 100644 drivers/staging/gma500/mdfld_dsi_dbi_dpu.c
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index fe34f18..c729868 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -46,6 +46,7 @@ psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \
mdfld_dsi_dpi.o \
mdfld_dsi_output.o \
mdfld_dsi_dbi.o \
+ mdfld_dsi_dbi_dpu.o \
mdfld_intel_display.o
obj-$(CONFIG_DRM_PSB) += psb_gfx.o
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c
index 06424f9..02e17c9 100644
--- a/drivers/staging/gma500/mdfld_dsi_dbi.c
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.c
@@ -327,7 +327,6 @@ void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
}
}
-#ifndef CONFIG_MDFLD_DSI_DPU
static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
int pipe)
{
@@ -562,7 +561,6 @@ void mdfld_dbi_dsr_exit(struct drm_device *dev)
dev_priv->dbi_dsr_info = NULL;
}
}
-#endif
void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
int pipe)
@@ -648,12 +646,8 @@ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
struct drm_encoder *encoder = NULL;
struct drm_display_mode *fixed_mode = NULL;
struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL;
-
-#ifdef CONFIG_MDFLD_DSI_DPU
struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
-#else
struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
-#endif
u32 data = 0;
int pipe;
int ret;
@@ -742,20 +736,16 @@ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
dbi_output->first_boot = true;
dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
-#ifdef CONFIG_MDFLD_DSI_DPU
- /* Add this output to dpu_info */
- if (dsi_connector->status == connector_status_connected) {
+ /* Add this output to dpu_info if in DPU mode */
+ if (dpu_info && dsi_connector->status == connector_status_connected) {
if (dsi_connector->pipe == 0)
dpu_info->dbi_outputs[0] = dbi_output;
else
dpu_info->dbi_outputs[1] = dbi_output;
dpu_info->dbi_output_num++;
- }
-
-#else /*CONFIG_MDFLD_DSI_DPU*/
- if (dsi_connector->status == connector_status_connected) {
- /* Add this output to dsr_info */
+ } else if (dsi_connector->status == connector_status_connected) {
+ /* Add this output to dsr_info if not */
if (dsi_connector->pipe == 0)
dsr_info->dbi_outputs[0] = dbi_output;
else
@@ -763,7 +753,6 @@ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
dsr_info->dbi_output_num++;
}
-#endif
return &dbi_output->base;
out_err1:
kfree(dbi_output);
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c
new file mode 100644
index 0000000..98ec990
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright © 2010-2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jim Liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_dbi.h"
+
+/*
+ * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock
+ */
+
+static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info *dpu_info,
+ mdfld_plane_t plane,
+ struct psb_drm_dpu_rect *damaged_rect)
+{
+ int x, y;
+ int new_x, new_y;
+ struct psb_drm_dpu_rect *rect;
+ struct psb_drm_dpu_rect *pipe_rect;
+ int cursor_size;
+ struct mdfld_cursor_info *cursor;
+ mdfld_plane_t fb_plane;
+
+ if (plane == MDFLD_CURSORA) {
+ cursor = &dpu_info->cursors[0];
+ x = dpu_info->cursors[0].x;
+ y = dpu_info->cursors[0].y;
+ cursor_size = dpu_info->cursors[0].size;
+ pipe_rect = &dpu_info->damage_pipea;
+ fb_plane = MDFLD_PLANEA;
+ } else {
+ cursor = &dpu_info->cursors[1];
+ x = dpu_info->cursors[1].x;
+ y = dpu_info->cursors[1].y;
+ cursor_size = dpu_info->cursors[1].size;
+ pipe_rect = &dpu_info->damage_pipec;
+ fb_plane = MDFLD_PLANEC;
+ }
+ new_x = damaged_rect->x;
+ new_y = damaged_rect->y;
+
+ if (x == new_x && y == new_y)
+ return 0;
+
+ rect = &dpu_info->damaged_rects[plane];
+ /* Move to right */
+ if (new_x >= x) {
+ if (new_y > y) {
+ rect->x = x;
+ rect->y = y;
+ rect->width = (new_x + cursor_size) - x;
+ rect->height = (new_y + cursor_size) - y;
+ goto cursor_out;
+ } else {
+ rect->x = x;
+ rect->y = new_y;
+ rect->width = (new_x + cursor_size) - x;
+ rect->height = (y - new_y);
+ goto cursor_out;
+ }
+ } else {
+ if (new_y > y) {
+ rect->x = new_x;
+ rect->y = y;
+ rect->width = (x + cursor_size) - new_x;
+ rect->height = new_y - y;
+ goto cursor_out;
+ } else {
+ rect->x = new_x;
+ rect->y = new_y;
+ rect->width = (x + cursor_size) - new_x;
+ rect->height = (y + cursor_size) - new_y;
+ }
+ }
+cursor_out:
+ if (new_x < 0)
+ cursor->x = 0;
+ else if (new_x > 864)
+ cursor->x = 864;
+ else
+ cursor->x = new_x;
+
+ if (new_y < 0)
+ cursor->y = 0;
+ else if (new_y > 480)
+ cursor->y = 480;
+ else
+ cursor->y = new_y;
+
+ /*
+ * FIXME: this is a workaround for cursor plane update,
+ * remove it later!
+ */
+ rect->x = 0;
+ rect->y = 0;
+ rect->width = 864;
+ rect->height = 480;
+
+ mdfld_check_boundary(dpu_info, rect);
+ mdfld_dpu_region_extent(pipe_rect, rect);
+
+ /* Update pending status of dpu_info */
+ dpu_info->pending |= (1 << plane);
+ /* Update fb panel as well */
+ dpu_info->pending |= (1 << fb_plane);
+ return 0;
+}
+
+static int mdfld_fb_damage(struct mdfld_dbi_dpu_info *dpu_info,
+ mdfld_plane_t plane,
+ struct psb_drm_dpu_rect *damaged_rect)
+{
+ struct psb_drm_dpu_rect *rect;
+
+ if (plane == MDFLD_PLANEA)
+ rect = &dpu_info->damage_pipea;
+ else
+ rect = &dpu_info->damage_pipec;
+
+ mdfld_check_boundary(dpu_info, damaged_rect);
+
+ /* Add fb damage area to this pipe */
+ mdfld_dpu_region_extent(rect, damaged_rect);
+
+ /* Update pending status of dpu_info */
+ dpu_info->pending |= (1 << plane);
+ return 0;
+}
+
+/* Do nothing here, right now */
+static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info *dpu_info,
+ mdfld_plane_t plane,
+ struct psb_drm_dpu_rect *damaged_rect)
+{
+ return 0;
+}
+
+int mdfld_dbi_dpu_report_damage(struct drm_device *dev,
+ mdfld_plane_t plane,
+ struct psb_drm_dpu_rect *rect)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+ int ret = 0;
+
+ /* DPU not in use, no damage reporting needed */
+ if (dpu_info == NULL)
+ return 0;
+
+ spin_lock(&dpu_info->dpu_update_lock);
+
+ switch (plane) {
+ case MDFLD_PLANEA:
+ case MDFLD_PLANEC:
+ mdfld_fb_damage(dpu_info, plane, rect);
+ break;
+ case MDFLD_CURSORA:
+ case MDFLD_CURSORC:
+ mdfld_cursor_damage(dpu_info, plane, rect);
+ break;
+ case MDFLD_OVERLAYA:
+ case MDFLD_OVERLAYC:
+ mdfld_overlay_damage(dpu_info, plane, rect);
+ break;
+ default:
+ DRM_ERROR("Invalid plane type %d\n", plane);
+ ret = -EINVAL;
+ }
+ spin_unlock(&dpu_info->dpu_update_lock);
+ return ret;
+}
+
+int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv;
+ struct mdfld_dbi_dpu_info *dpu_info;
+ struct mdfld_dsi_config *dsi_config;
+ struct psb_drm_dpu_rect rect;
+ int i;
+
+ if (!dev) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ dev_priv = dev->dev_private;
+ dpu_info = dev_priv->dbi_dpu_info;
+
+ /* This is fine - we may be in non DPU mode */
+ if (!dpu_info)
+ return -EINVAL;
+
+ for (i = 0; i < dpu_info->dbi_output_num; i++) {
+ dsi_config = dev_priv->dsi_configs[i];
+ if (dsi_config) {
+ rect.x = rect.y = 0;
+ rect.width = dsi_config->fixed_mode->hdisplay;
+ rect.height = dsi_config->fixed_mode->vdisplay;
+ mdfld_dbi_dpu_report_damage(dev,
+ i ? (MDFLD_PLANEC) : (MDFLD_PLANEA),
+ &rect);
+ }
+ }
+ /* Exit DSR state */
+ mdfld_dpu_exit_dsr(dev);
+ return 0;
+}
+
+int mdfld_dsi_dbi_dsr_off(struct drm_device *dev,
+ struct psb_drm_dpu_rect *rect)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, rect);
+
+ /* If dual display mode */
+ if (dpu_info->dbi_output_num == 2)
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, rect);
+
+ /* Force dsi to exit DSR mode */
+ mdfld_dpu_exit_dsr(dev);
+ return 0;
+}
+
+static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
+ mdfld_plane_t plane)
+{
+ struct drm_device *dev = dpu_info->dev;
+ u32 curpos_reg = CURAPOS;
+ u32 curbase_reg = CURABASE;
+ u32 curcntr_reg = CURACNTR;
+ struct mdfld_cursor_info *cursor = &dpu_info->cursors[0];
+
+ if (plane == MDFLD_CURSORC) {
+ curpos_reg = CURCPOS;
+ curbase_reg = CURCBASE;
+ curcntr_reg = CURCCNTR;
+ cursor = &dpu_info->cursors[1];
+ }
+
+ REG_WRITE(curcntr_reg, REG_READ(curcntr_reg));
+ REG_WRITE(curpos_reg,
+ (((cursor->x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
+ ((cursor->y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT)));
+ REG_WRITE(curbase_reg, REG_READ(curbase_reg));
+}
+
+static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
+ mdfld_plane_t plane)
+{
+ u32 pipesrc_reg = PIPEASRC;
+ u32 dspsize_reg = DSPASIZE;
+ u32 dspoff_reg = DSPALINOFF;
+ u32 dspsurf_reg = DSPASURF;
+ u32 dspstride_reg = DSPASTRIDE;
+ u32 stride;
+ struct psb_drm_dpu_rect *rect = &dpu_info->damage_pipea;
+ struct drm_device *dev = dpu_info->dev;
+
+ if (plane == MDFLD_PLANEC) {
+ pipesrc_reg = PIPECSRC;
+ dspsize_reg = DSPCSIZE;
+ dspoff_reg = DSPCLINOFF;
+ dspsurf_reg = DSPCSURF;
+ dspstride_reg = DSPCSTRIDE;
+ rect = &dpu_info->damage_pipec;
+ }
+
+ stride = REG_READ(dspstride_reg);
+ /* FIXME: should I do the pipe src update here? */
+ REG_WRITE(pipesrc_reg, ((rect->width - 1) << 16) | (rect->height - 1));
+ /* Flush plane */
+ REG_WRITE(dspsize_reg, ((rect->height - 1) << 16) | (rect->width - 1));
+ REG_WRITE(dspoff_reg, ((rect->x * 4) + (rect->y * stride)));
+ REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+
+ /*
+ * TODO: wait for flip finished and restore the pipesrc reg,
+ * or cursor will be show at a wrong position
+ */
+}
+
+static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info *dpu_info,
+ mdfld_plane_t plane)
+{
+}
+
+/*
+ * TODO: we are still in dbi normal mode now, we will try to use partial
+ * mode later.
+ */
+static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output *dbi_output,
+ struct mdfld_dbi_dpu_info *dpu_info, int pipe)
+{
+ u8 *cb_addr = (u8 *)dbi_output->dbi_cb_addr;
+ u32 *index;
+ struct psb_drm_dpu_rect *rect = pipe ?
+ (&dpu_info->damage_pipec) : (&dpu_info->damage_pipea);
+
+ /* FIXME: lock command buffer, this may lead to a deadlock,
+ as we already hold the dpu_update_lock */
+ if (!spin_trylock(&dbi_output->cb_lock)) {
+ DRM_ERROR("lock command buffer failed, try again\n");
+ return -EAGAIN;
+ }
+
+ index = &dbi_output->cb_write;
+
+ if (*index) {
+ DRM_ERROR("DBI command buffer unclean\n");
+ return -EAGAIN;
+ }
+
+ /* Column address */
+ *(cb_addr + ((*index)++)) = set_column_address;
+ *(cb_addr + ((*index)++)) = rect->x >> 8;
+ *(cb_addr + ((*index)++)) = rect->x;
+ *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1) >> 8;
+ *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1);
+
+ *index = 8;
+
+ /* Page address */
+ *(cb_addr + ((*index)++)) = set_page_addr;
+ *(cb_addr + ((*index)++)) = rect->y >> 8;
+ *(cb_addr + ((*index)++)) = rect->y;
+ *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1) >> 8;
+ *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1);
+
+ *index = 16;
+
+ /*write memory*/
+ *(cb_addr + ((*index)++)) = write_mem_start;
+
+ return 0;
+}
+
+static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
+{
+ u32 cmd_phy = dbi_output->dbi_cb_phy;
+ u32 *index = &dbi_output->cb_write;
+ int reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+ struct drm_device *dev = dbi_output->dev;
+
+ if (*index == 0 || !dbi_output)
+ return 0;
+
+ REG_WRITE((MIPIA_CMD_LEN_REG + reg_offset), 0x010505);
+ REG_WRITE((MIPIA_CMD_ADD_REG + reg_offset), cmd_phy | 3);
+
+ *index = 0;
+
+ /* FIXME: unlock command buffer */
+ spin_unlock(&dbi_output->cb_lock);
+ return 0;
+}
+
+static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output *dbi_output,
+ struct mdfld_dbi_dpu_info *dpu_info, int pipe)
+{
+ struct drm_device *dev = dbi_output->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ mdfld_plane_t cursor_plane = MDFLD_CURSORA;
+ mdfld_plane_t fb_plane = MDFLD_PLANEA;
+ mdfld_plane_t overlay_plane = MDFLD_OVERLAYA;
+ int ret = 0;
+ u32 plane_mask = MDFLD_PIPEA_PLANE_MASK;
+
+ /* Damaged rects on this pipe */
+ if (pipe) {
+ cursor_plane = MDFLD_CURSORC;
+ fb_plane = MDFLD_PLANEC;
+ overlay_plane = MDFLD_OVERLAYC;
+ plane_mask = MDFLD_PIPEC_PLANE_MASK;
+ }
+
+ /*update cursor which assigned to @pipe*/
+ if (dpu_info->pending & (1 << cursor_plane))
+ mdfld_dpu_cursor_plane_flush(dpu_info, cursor_plane);
+
+ /*update fb which assigned to @pipe*/
+ if (dpu_info->pending & (1 << fb_plane))
+ mdfld_dpu_fb_plane_flush(dpu_info, fb_plane);
+
+ /* TODO: update overlay */
+ if (dpu_info->pending & (1 << overlay_plane))
+ mdfld_dpu_overlay_plane_flush(dpu_info, overlay_plane);
+
+ /* Flush damage area to panel fb */
+ if (dpu_info->pending & plane_mask) {
+ ret = mdfld_dbi_prepare_cb(dbi_output, dpu_info, pipe);
+ /*
+ * TODO: remove b_dsr_enable later,
+ * added it so that text console could boot smoothly
+ */
+ /* Clean pending flags on this pipe */
+ if (!ret && dev_priv->b_dsr_enable) {
+ dpu_info->pending &= ~plane_mask;
+ /* Reset overlay pipe damage rect */
+ mdfld_dpu_init_damage(dpu_info, pipe);
+ }
+ }
+ return ret;
+}
+
+static int mdfld_dpu_update_fb(struct drm_device *dev)
+{
+ struct drm_crtc *crtc;
+ struct psb_intel_crtc *psb_crtc;
+ struct mdfld_dsi_dbi_output **dbi_output;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+ bool pipe_updated[2];
+ unsigned long irq_flags;
+ u32 dpll_reg = MRST_DPLL_A;
+ u32 dspcntr_reg = DSPACNTR;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 dsplinoff_reg = DSPALINOFF;
+ u32 dspsurf_reg = DSPASURF;
+ u32 mipi_state_reg = MIPIA_INTR_STAT_REG;
+ u32 reg_offset = 0;
+ int pipe;
+ int i;
+ int ret;
+
+ dbi_output = dpu_info->dbi_outputs;
+ pipe_updated[0] = pipe_updated[1] = false;
+
+ if (!gma_power_begin(dev, true))
+ return -EAGAIN;
+
+ /* Try to prevent any new damage reports */
+ if (!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags))
+ return -EAGAIN;
+
+ for (i = 0; i < dpu_info->dbi_output_num; i++) {
+ crtc = dbi_output[i]->base.base.crtc;
+ psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL;
+
+ pipe = dbi_output[i]->channel_num ? 2 : 0;
+
+ if (pipe == 2) {
+ dspcntr_reg = DSPCCNTR;
+ pipeconf_reg = PIPECCONF;
+ dsplinoff_reg = DSPCLINOFF;
+ dspsurf_reg = DSPCSURF;
+ reg_offset = MIPIC_REG_OFFSET;
+ }
+
+ if (!(REG_READ((MIPIA_GEN_FIFO_STAT_REG + reg_offset))
+ & (1 << 27)) ||
+ !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
+ !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
+ !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
+ dev_err(dev->dev,
+ "DBI FIFO is busy, DSI %d state %x\n",
+ pipe,
+ REG_READ(mipi_state_reg + reg_offset));
+ continue;
+ }
+
+ /*
+ * If DBI output is in a exclusive state then the pipe
+ * change won't be updated
+ */
+ if (dbi_output[i]->dbi_panel_on &&
+ !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) &&
+ !(psb_crtc &&
+ psb_crtc->mode_flags & MODE_SETTING_ON_GOING) &&
+ !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
+ ret = mdfld_dpu_update_pipe(dbi_output[i],
+ dpu_info, dbi_output[i]->channel_num ? 2 : 0);
+ if (!ret)
+ pipe_updated[i] = true;
+ }
+ }
+
+ for (i = 0; i < dpu_info->dbi_output_num; i++)
+ if (pipe_updated[i])
+ mdfld_dbi_flush_cb(dbi_output[i],
+ dbi_output[i]->channel_num ? 2 : 0);
+
+ spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags);
+ gma_power_end(dev);
+ return 0;
+}
+
+static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
+ int pipe)
+{
+ struct drm_device *dev = dbi_output->dev;
+ struct drm_crtc *crtc = dbi_output->base.base.crtc;
+ struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc)
+ : NULL;
+ u32 reg_val;
+ u32 dpll_reg = MRST_DPLL_A;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 dspcntr_reg = DSPACNTR;
+ u32 dspbase_reg = DSPABASE;
+ u32 dspsurf_reg = DSPASURF;
+ u32 reg_offset = 0;
+
+ if (!dbi_output)
+ return 0;
+
+ /*if mode setting on-going, back off*/
+ if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+ (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
+ return -EAGAIN;
+
+ if (pipe == 2) {
+ dpll_reg = MRST_DPLL_A;
+ pipeconf_reg = PIPECCONF;
+ dspcntr_reg = DSPCCNTR;
+ dspbase_reg = MDFLD_DSPCBASE;
+ dspsurf_reg = DSPCSURF;
+
+ reg_offset = MIPIC_REG_OFFSET;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+ return -EAGAIN;
+
+ /* Enable DPLL */
+ reg_val = REG_READ(dpll_reg);
+ if (!(reg_val & DPLL_VCO_ENABLE)) {
+
+ if (reg_val & MDFLD_PWR_GATE_EN) {
+ reg_val &= ~MDFLD_PWR_GATE_EN;
+ REG_WRITE(dpll_reg, reg_val);
+ REG_READ(dpll_reg);
+ udelay(500);
+ }
+
+ reg_val |= DPLL_VCO_ENABLE;
+ REG_WRITE(dpll_reg, reg_val);
+ REG_READ(dpll_reg);
+ udelay(500);
+
+ /* FIXME: add timeout */
+ while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
+ cpu_relax();
+ }
+
+ /* Enable pipe */
+ reg_val = REG_READ(pipeconf_reg);
+ if (!(reg_val & PIPEACONF_ENABLE)) {
+ reg_val |= PIPEACONF_ENABLE;
+ REG_WRITE(pipeconf_reg, reg_val);
+ REG_READ(pipeconf_reg);
+ udelay(500);
+ mdfldWaitForPipeEnable(dev, pipe);
+ }
+
+ /* Enable plane */
+ reg_val = REG_READ(dspcntr_reg);
+ if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
+ reg_val |= DISPLAY_PLANE_ENABLE;
+ REG_WRITE(dspcntr_reg, reg_val);
+ REG_READ(dspcntr_reg);
+ udelay(500);
+ }
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ /*clean IN_DSR flag*/
+ dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+
+ return 0;
+}
+
+int mdfld_dpu_exit_dsr(struct drm_device *dev)
+{
+ struct mdfld_dsi_dbi_output **dbi_output;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+ int i;
+ int pipe;
+
+ dbi_output = dpu_info->dbi_outputs;
+
+ for (i = 0; i < dpu_info->dbi_output_num; i++) {
+ /* If this output is not in DSR mode, don't call exit dsr */
+ if (dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)
+ __mdfld_dbi_exit_dsr(dbi_output[i],
+ dbi_output[i]->channel_num ? 2 : 0);
+ }
+
+ /* Enable TE interrupt */
+ for (i = 0; i < dpu_info->dbi_output_num; i++) {
+ /* If this output is not in DSR mode, don't call exit dsr */
+ pipe = dbi_output[i]->channel_num ? 2 : 0;
+ if (dbi_output[i]->dbi_panel_on && pipe) {
+ mdfld_disable_te(dev, 0);
+ mdfld_enable_te(dev, 2);
+ } else if (dbi_output[i]->dbi_panel_on && !pipe) {
+ mdfld_disable_te(dev, 2);
+ mdfld_enable_te(dev, 0);
+ }
+ }
+ return 0;
+}
+
+static int mdfld_dpu_enter_dsr(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+ struct mdfld_dsi_dbi_output **dbi_output;
+ int i;
+
+ dbi_output = dpu_info->dbi_outputs;
+
+ for (i = 0; i < dpu_info->dbi_output_num; i++) {
+ /* If output is off or already in DSR state, don't re-enter */
+ if (dbi_output[i]->dbi_panel_on &&
+ !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
+ mdfld_dsi_dbi_enter_dsr(dbi_output[i],
+ dbi_output[i]->channel_num ? 2 : 0);
+ }
+ }
+
+ return 0;
+}
+
+static void mdfld_dbi_dpu_timer_func(unsigned long data)
+{
+ struct drm_device *dev = (struct drm_device *)data;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+ struct timer_list *dpu_timer = &dpu_info->dpu_timer;
+ unsigned long flags;
+
+ if (dpu_info->pending) {
+ dpu_info->idle_count = 0;
+ /* Update panel fb with damaged area */
+ mdfld_dpu_update_fb(dev);
+ } else {
+ dpu_info->idle_count++;
+ }
+
+ if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
+ mdfld_dpu_enter_dsr(dev);
+ /* Stop timer by return */
+ return;
+ }
+
+ spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+ if (!timer_pending(dpu_timer)) {
+ dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+ add_timer(dpu_timer);
+ }
+ spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+}
+
+void mdfld_dpu_update_panel(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+
+ if (dpu_info->pending) {
+ dpu_info->idle_count = 0;
+
+ /*update panel fb with damaged area*/
+ mdfld_dpu_update_fb(dev);
+ } else {
+ dpu_info->idle_count++;
+ }
+
+ if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
+ /*enter dsr*/
+ mdfld_dpu_enter_dsr(dev);
+ }
+}
+
+static int mdfld_dbi_dpu_timer_init(struct drm_device *dev,
+ struct mdfld_dbi_dpu_info *dpu_info)
+{
+ struct timer_list *dpu_timer = &dpu_info->dpu_timer;
+ unsigned long flags;
+
+ spin_lock_init(&dpu_info->dpu_timer_lock);
+ spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+
+ init_timer(dpu_timer);
+
+ dpu_timer->data = (unsigned long)dev;
+ dpu_timer->function = mdfld_dbi_dpu_timer_func;
+ dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+
+ spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+
+ return 0;
+}
+
+void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info)
+{
+ struct timer_list *dpu_timer = &dpu_info->dpu_timer;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+ if (!timer_pending(dpu_timer)) {
+ dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+ add_timer(dpu_timer);
+ }
+ spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+}
+
+int mdfld_dbi_dpu_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+
+ if (!dpu_info || IS_ERR(dpu_info)) {
+ dpu_info = kzalloc(sizeof(struct mdfld_dbi_dpu_info),
+ GFP_KERNEL);
+ if (!dpu_info) {
+ DRM_ERROR("No memory\n");
+ return -ENOMEM;
+ }
+ dev_priv->dbi_dpu_info = dpu_info;
+ }
+
+ dpu_info->dev = dev;
+
+ dpu_info->cursors[0].size = MDFLD_CURSOR_SIZE;
+ dpu_info->cursors[1].size = MDFLD_CURSOR_SIZE;
+
+ /*init dpu_update_lock*/
+ spin_lock_init(&dpu_info->dpu_update_lock);
+
+ /*init dpu refresh timer*/
+ mdfld_dbi_dpu_timer_init(dev, dpu_info);
+
+ /*init pipe damage area*/
+ mdfld_dpu_init_damage(dpu_info, 0);
+ mdfld_dpu_init_damage(dpu_info, 2);
+
+ return 0;
+}
+
+void mdfld_dbi_dpu_exit(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
+
+ if (!dpu_info)
+ return;
+
+ del_timer_sync(&dpu_info->dpu_timer);
+ kfree(dpu_info);
+ dev_priv->dbi_dpu_info = NULL;
+}
+
+
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
index 3286c3d..7536095 100644
--- a/drivers/staging/gma500/mdfld_dsi_output.c
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -46,7 +46,7 @@ module_param (LABC_control, int, 0644);
* we don't need 'movl' everytime we send them.
* FIXME: these datas were provided by OEM, we should get them from GCT.
**/
-static const u32 mdfld_dbi_mcs_hysteresis[] = {
+static u32 mdfld_dbi_mcs_hysteresis[] = {
0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
@@ -54,16 +54,16 @@ static const u32 mdfld_dbi_mcs_hysteresis[] = {
0x000000ff,
};
-static const u32 mdfld_dbi_mcs_display_profile[] = {
+static u32 mdfld_dbi_mcs_display_profile[] = {
0x50281450, 0x0000c882, 0x00000000, 0x00000000,
0x00000000,
};
-static const u32 mdfld_dbi_mcs_kbbc_profile[] = {
+static u32 mdfld_dbi_mcs_kbbc_profile[] = {
0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
};
-static const u32 mdfld_dbi_mcs_gamma_profile[] = {
+static u32 mdfld_dbi_mcs_gamma_profile[] = {
0x81111158, 0x88888888, 0x88888888,
};
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
index ac74a8d..aa2ff55 100644
--- a/drivers/staging/gma500/mdfld_intel_display.c
+++ b/drivers/staging/gma500/mdfld_intel_display.c
@@ -28,10 +28,7 @@
#include "psb_intel_display.h"
#include "mdfld_dsi_dbi.h"
#include "mdfld_dsi_dpi.h"
-//#include "mdfld_dsi_output.h"
-#ifdef CONFIG_MDFLD_DSI_DPU
#include "mdfld_dsi_dbi_dpu.h"
-#endif
#include <linux/pm_runtime.h>
@@ -232,25 +229,23 @@ static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc,
REG_WRITE(base, addr);
gma_power_end(dev);
}
-#if 0
- /* FIXME: COnvert to GEM */
- /* unpin the old bo */
- if (psb_intel_crtc->cursor_bo && psb_intel_crtc->cursor_bo != bo) {
- mode_dev->bo_unpin_for_scanout(dev, psb_intel_crtc->cursor_bo);
- psb_intel_crtc->cursor_bo = bo;
+ /* unpin the old GEM object */
+ if (psb_intel_crtc->cursor_obj) {
+ gt = container_of(psb_intel_crtc->cursor_obj,
+ struct gtt_range, gem);
+ psb_gtt_unpin(gt);
+ drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+ psb_intel_crtc->cursor_obj = obj;
}
-#endif
return 0;
}
static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
{
struct drm_device *dev = crtc->dev;
-#ifndef CONFIG_MDFLD_DSI_DPU
struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
-#else
+ struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info;
struct psb_drm_dpu_rect rect;
-#endif
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
int pipe = psb_intel_crtc->pipe;
uint32_t pos = CURAPOS;
@@ -260,29 +255,25 @@ static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
switch (pipe) {
case 0:
-#ifndef CONFIG_MDFLD_DSI_DPU
- if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0))
- mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_0);
-#else /*CONFIG_MDFLD_DSI_DPU*/
- rect.x = x;
- rect.y = y;
+ if (dpu_info) {
+ rect.x = x;
+ rect.y = y;
- mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect);
- mdfld_dpu_exit_dsr(dev);
-#endif
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect);
+ mdfld_dpu_exit_dsr(dev);
+ } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0))
+ mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_0);
break;
case 1:
pos = CURBPOS;
base = CURBBASE;
break;
case 2:
-#ifndef CONFIG_MDFLD_DSI_DPU
- if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2))
- mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_2);
-#else /*CONFIG_MDFLD_DSI_DPU*/
- mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect);
- mdfld_dpu_exit_dsr(dev);
-#endif
+ if (dpu_info) {
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect);
+ mdfld_dpu_exit_dsr(dev);
+ } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2))
+ mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_2);
pos = CURCPOS;
base = CURCBASE;
break;
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c
index ffa2c1f..ee55f87 100644
--- a/drivers/staging/gma500/mdfld_output.c
+++ b/drivers/staging/gma500/mdfld_output.c
@@ -30,6 +30,7 @@
#include "mdfld_dsi_dpi.h"
#include "mdfld_dsi_output.h"
#include "mdfld_output.h"
+#include "mdfld_dsi_dbi_dpu.h"
#include "displays/tpo_cmd.h"
#include "displays/tpo_vid.h"
@@ -39,6 +40,17 @@
#include "displays/pyr_vid.h"
/* #include "displays/hdmi.h" */
+static int mdfld_dual_mipi;
+static int mdfld_hdmi;
+static int mdfld_dpu;
+
+module_param(mdfld_dual_mipi, int, 0600);
+MODULE_PARM_DESC(mdfld_dual_mipi, "Enable dual MIPI configuration");
+module_param(mdfld_hdmi, int, 0600);
+MODULE_PARM_DESC(mdfld_hdmi, "Enable Medfield HDMI");
+module_param(mdfld_dpu, int, 0600);
+MODULE_PARM_DESC(mdfld_dpu, "Enable Medfield DPU");
+
/* For now a single type per device is all we cope with */
int mdfld_get_panel_type(struct drm_device *dev, int pipe)
{
@@ -134,15 +146,25 @@ int mdfld_output_init(struct drm_device *dev)
dev_info(dev->dev, "panel 1: type is %d\n", type);
init_panel(dev, 0, type);
-#ifdef CONFIG_MDFD_DUAL_MIPI
- /* MIPI panel 2 */
- type = mdfld_get_panel_type(dev, 2);
- dev_info(dev->dev, "panel 2: type is %d\n", type);
- init_panel(dev, 2, type);
-#endif
-#ifdef CONFIG_MDFD_HDMI
- /* HDMI panel */
- init_panel(dev, 0, HDMI);
-#endif
+ if (mdfld_dual_mipi) {
+ /* MIPI panel 2 */
+ type = mdfld_get_panel_type(dev, 2);
+ dev_info(dev->dev, "panel 2: type is %d\n", type);
+ init_panel(dev, 2, type);
+ }
+ if (mdfld_hdmi)
+ /* HDMI panel */
+ init_panel(dev, 0, HDMI);
return 0;
}
+
+void mdfld_output_setup(struct drm_device *dev)
+{
+ /* FIXME: this is not the right place for this stuff ! */
+ if (IS_MFLD(dev)) {
+ if (mdfld_dpu)
+ mdfld_dbi_dpu_init(dev);
+ else
+ mdfld_dbi_dsr_init(dev);
+ }
+}
\ No newline at end of file
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h
index e747fdb..daf33e7 100644
--- a/drivers/staging/gma500/mdfld_output.h
+++ b/drivers/staging/gma500/mdfld_output.h
@@ -36,4 +36,6 @@ void mdfld_disable_crtc (struct drm_device *dev, int pipe);
extern const struct drm_crtc_helper_funcs mdfld_helper_funcs;
extern const struct drm_crtc_funcs mdfld_intel_crtc_funcs;
+extern void mdfld_output_setup(struct drm_device *dev);
+
#endif
diff --git a/drivers/staging/gma500/mdfld_pyr_cmd.c b/drivers/staging/gma500/mdfld_pyr_cmd.c
index 5f38e8d..523f2d8 100644
--- a/drivers/staging/gma500/mdfld_pyr_cmd.c
+++ b/drivers/staging/gma500/mdfld_pyr_cmd.c
@@ -29,7 +29,7 @@
#include "mdfld_dsi_dpi.h"
#include "mdfld_dsi_output.h"
#include "mdfld_output.h"
-
+#include "mdfld_dsi_dbi_dpu.h"
#include "mdfld_dsi_pkg_sender.h"
#include "displays/pyr_cmd.h"
@@ -374,16 +374,11 @@ static void pyr_dsi_dbi_commit(struct drm_encoder *encoder)
if (dbi_output->channel_num == 1) {
dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
-#ifdef CONFIG_MDFLD_DSI_DPU
/* If DPU enabled report a fullscreen damage */
mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
-#endif
} else {
dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
-
-#ifdef CONFIG_MDFLD_DSI_DPU
mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
-#endif
}
dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
}
diff --git a/drivers/staging/gma500/mdfld_tpo_cmd.c b/drivers/staging/gma500/mdfld_tpo_cmd.c
index 4cf7647..c7f7c9c 100644
--- a/drivers/staging/gma500/mdfld_tpo_cmd.c
+++ b/drivers/staging/gma500/mdfld_tpo_cmd.c
@@ -29,7 +29,7 @@
#include "mdfld_dsi_dpi.h"
#include "mdfld_dsi_output.h"
#include "mdfld_output.h"
-
+#include "mdfld_dsi_dbi_dpu.h"
#include "mdfld_dsi_pkg_sender.h"
#include "displays/tpo_cmd.h"
@@ -359,15 +359,11 @@ static void mdfld_dsi_dbi_commit(struct drm_encoder *encoder)
if (dbi_output->channel_num == 1) {
dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
-#ifdef CONFIG_MDFLD_DSI_DPU
/*if dpu enabled report a fullscreen damage*/
mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
-#endif
} else {
dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
-#ifdef CONFIG_MDFLD_DSI_DPU
mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
-#endif
}
dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
}
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 4b740aa..b2cdce7 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -421,15 +421,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
#if defined(CONFIG_DRM_PSB_MFLD)
/* FIXME: this is not the right place for this stuff ! */
- if (IS_MFLD(dev)) {
-#ifdef CONFIG_MDFLD_DSI_DPU
- /*init dpu info*/
- mdfld_dbi_dpu_init(dev);
-#else
- mdfld_dbi_dsr_init(dev);
-#endif /*CONFIG_MDFLD_DSI_DPU*/
- /* INIT_WORK(&dev_priv->te_work, mdfld_te_handler_work);*/
- }
+ mdfld_output_setup(dev);
#endif
if (drm_psb_no_fb == 0) {
psb_modeset_init(dev);
@@ -444,6 +436,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
switch (psb_intel_output->type) {
case INTEL_OUTPUT_LVDS:
+ case INTEL_OUTPUT_MIPI:
ret = gma_backlight_init(dev);
break;
}
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH 01/15] gma500: Cursor interface
2011-07-15 16:31 [PATCH 01/15] gma500: Cursor interface Alan Cox
` (13 preceding siblings ...)
2011-07-15 16:35 ` [PATCH 15/15] gma500: Clean up the DPU config and make it runtime Alan Cox
@ 2011-07-15 17:06 ` Greg KH
14 siblings, 0 replies; 16+ messages in thread
From: Greg KH @ 2011-07-15 17:06 UTC (permalink / raw)
To: Alan Cox; +Cc: linux-kernel
After this series applied, I get:
drivers/staging/gma500/psb_drv.h:34:22: fatal error: medfield.h: No such file or directory
:(
^ permalink raw reply [flat|nested] 16+ messages in thread