From 16eb5f4379b2097438a224381be3b4d9e56ac979 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 2 Oct 2013 10:15:18 +0200 Subject: drm: kill ->gem_init_object() and friends All drivers embed gem-objects into their own buffer objects. There is no reason to keep drm_gem_object_alloc(), gem->driver_private and ->gem_init_object() anymore. New drivers are highly encouraged to do the same. There is no benefit in allocating gem-objects separately. Cc: Dave Airlie Cc: Alex Deucher Cc: Daniel Vetter Cc: Jerome Glisse Cc: Rob Clark Cc: Inki Dae Cc: Ben Skeggs Cc: Patrik Jakobsson Signed-off-by: David Herrmann Acked-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/gem.c | 5 ----- drivers/gpu/drm/gma500/psb_drv.c | 1 - drivers/gpu/drm/gma500/psb_drv.h | 1 - 3 files changed, 7 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index 10ae8c52d06f..e2db48a81ed0 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -29,11 +29,6 @@ #include #include "psb_drv.h" -int psb_gem_init_object(struct drm_gem_object *obj) -{ - return -EINVAL; -} - void psb_gem_free_object(struct drm_gem_object *obj) { struct gtt_range *gtt = container_of(obj, struct gtt_range, gem); diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index fcb4e9ff1f20..30dceb43690b 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -646,7 +646,6 @@ static struct drm_driver driver = { .preclose = psb_driver_preclose, .postclose = psb_driver_close, - .gem_init_object = psb_gem_init_object, .gem_free_object = psb_gem_free_object, .gem_vm_ops = &psb_gem_vm_ops, .dumb_create = psb_gem_dumb_create, diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 4535ac7708f8..6856bce58445 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -837,7 +837,6 @@ extern const struct drm_connector_helper_funcs extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs; /* gem.c */ -extern int psb_gem_init_object(struct drm_gem_object *obj); extern void psb_gem_free_object(struct drm_gem_object *obj); extern int psb_gem_get_aperture(struct drm_device *dev, void *data, struct drm_file *file); -- cgit v1.2.1 From ba0bf1200ec75722c558c56f58c596ff42a3b494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 4 Oct 2013 14:53:33 +0300 Subject: drm: Make vblank_disable_allowed bool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vblank_disable_allowed is only ever 0 or 1, so make it a bool. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/psb_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 30dceb43690b..dd607f820a26 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -359,7 +359,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) drm_irq_install(dev); - dev->vblank_disable_allowed = 1; + dev->vblank_disable_allowed = true; dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ -- cgit v1.2.1 From 5380e9293b865d88de04de6e5324726d8c5b53c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 4 Oct 2013 14:53:36 +0300 Subject: drm: Collect per-crtc vblank stuff to a struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_vblank_init() is too ugly. Make it a bit easier on the eye by collecting all the per-crtc vblank counters, timestamps etc. to a structure and just allocate an array of those. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/psb_irq.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 029eccf30137..ba4830342d34 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -271,15 +271,15 @@ void psb_irq_preinstall(struct drm_device *dev) if (gma_power_is_on(dev)) PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank_enabled[0]) + if (dev->vblank[0].enabled) dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; - if (dev->vblank_enabled[1]) + if (dev->vblank[1].enabled) dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; /* FIXME: Handle Medfield irq mask - if (dev->vblank_enabled[1]) + if (dev->vblank[1].enabled) dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; - if (dev->vblank_enabled[2]) + if (dev->vblank[2].enabled) dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; */ @@ -305,17 +305,17 @@ int psb_irq_postinstall(struct drm_device *dev) PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank_enabled[0]) + if (dev->vblank[0].enabled) psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); else psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[1]) + if (dev->vblank[1].enabled) psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); else psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[2]) + if (dev->vblank[2].enabled) psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); else psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); @@ -339,13 +339,13 @@ void psb_irq_uninstall(struct drm_device *dev) PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank_enabled[0]) + if (dev->vblank[0].enabled) psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[1]) + if (dev->vblank[1].enabled) psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[2]) + if (dev->vblank[2].enabled) psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | @@ -456,7 +456,7 @@ static int psb_vblank_do_wait(struct drm_device *dev, { unsigned int cur_vblank; int ret = 0; - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, dev->vblank.queue, 3 * DRM_HZ, (((cur_vblank = atomic_read(counter)) - *sequence) <= (1 << 23))); *sequence = cur_vblank; -- cgit v1.2.1 From ffbab09bf939975b62ec233c426bf7df0dd4cea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 4 Oct 2013 14:53:40 +0300 Subject: drm: Remove pci_vendor and pci_device from struct drm_device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can get the PCI vendor and device IDs via dev->pdev. So we can drop the duplicated information. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/psb_drv.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 6856bce58445..0bab46bd73d2 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -44,10 +44,10 @@ enum { CHIP_MFLD_0130 = 3, /* Medfield */ }; -#define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108) -#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100) -#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130) -#define IS_CDV(dev) (((dev)->pci_device & 0xfff0) == 0x0be0) +#define IS_PSB(dev) (((dev)->pdev->device & 0xfffe) == 0x8108) +#define IS_MRST(dev) (((dev)->pdev->device & 0xfffc) == 0x4100) +#define IS_MFLD(dev) (((dev)->pdev->device & 0xfff8) == 0x0130) +#define IS_CDV(dev) (((dev)->pdev->device & 0xfff0) == 0x0be0) /* * Driver definitions -- cgit v1.2.1 From 92b6f89f6b85f433ddac1f4a9eb0962dc96380fe Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 8 Oct 2013 17:44:47 +0200 Subject: drm: Add separate Kconfig option for fbdev helpers For drivers which might want to disable fbdev legacy support. Select the new option in all drivers for now, so this shouldn't result in any change. Drivers need some work anyway to make fbdev support optional (if they have it implemented, that is), so the recommended way to expose this is by adding per-driver options. At least as long as most drivers don't support disabling the fbdev support. v2: Update for new drm drivers msm and rcar-du. Note that Rob's msm driver can already take advantage of this, which allows us to build msm without any fbdev depencies in the kernel! v3: Move the MODULE_* stuff from the fbdev helper file to drm_crtc_helper.c. Cc: David Herrmann Cc: Rob Clark Reviewed-by: Rob Clark Acked-by: Dave Airlie Reviewed-by: Chon Ming Lee Signed-off-by: Daniel Vetter --- drivers/gpu/drm/gma500/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig index 1f6e2dfaaeae..508cf99a292d 100644 --- a/drivers/gpu/drm/gma500/Kconfig +++ b/drivers/gpu/drm/gma500/Kconfig @@ -5,6 +5,7 @@ config DRM_GMA500 select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT select DRM_KMS_HELPER + select DRM_KMS_FB_HELPER select DRM_TTM # GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915 select ACPI_VIDEO if ACPI -- cgit v1.2.1 From 5bdebb183c9702a8c57a01dff09337be3de337a6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 11 Oct 2013 14:07:25 +1000 Subject: drm/sysfs: sort out minor and connector device object lifetimes. So drm was abusing device lifetimes, by having embedded device structures in the minor and connector it meant that the lifetime of the internal drm objects (drm_minor and drm_connector) were tied to the lifetime of the device files in sysfs, so if something kept those files opened the current code would kfree the objects and things would go downhill from there. Now in reality there is no need for these lifetimes to be so intertwined, especailly with hotplugging of devices where we wish to remove the sysfs and userspace facing pieces before we can unwind the internal objects due to open userspace files or mmaps, so split the objects out so the struct device is no longer embedded and do what fbdev does and just allocate and remove the sysfs inodes separately. Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index f4eb43573cad..f88a1815d87c 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -666,7 +666,7 @@ cdv_intel_dp_i2c_init(struct gma_connector *connector, strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1); intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0'; intel_dp->adapter.algo_data = &intel_dp->algo; - intel_dp->adapter.dev.parent = &connector->base.kdev; + intel_dp->adapter.dev.parent = connector->base.kdev; if (is_edp(encoder)) cdv_intel_edp_panel_vdd_on(encoder); -- cgit v1.2.1 From 4f224661096ca0d945324d661cf7c897ac6eb8e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 17 Oct 2013 13:35:02 +0300 Subject: drm/gma500: Return -ENOENT when a mode object can't be found MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's be a bit more consistent with our error values. Signed-off-by: Ville Syrjälä Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/psb_drv.c | 4 ++-- drivers/gpu/drm/gma500/psb_intel_display.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index dd607f820a26..679f95313c29 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -449,7 +449,7 @@ static int psb_gamma_ioctl(struct drm_device *dev, void *data, obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR); if (!obj) { dev_dbg(dev->dev, "Invalid Connector object.\n"); - return -EINVAL; + return -ENOENT; } connector = obj_to_connector(obj); @@ -491,7 +491,7 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR); if (!obj) { - ret = -EINVAL; + ret = -ENOENT; goto mode_op_out; } diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 97f8a03fee43..c8841ac6c8f1 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -572,7 +572,7 @@ int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, if (!drmmode_obj) { dev_err(dev->dev, "no such CRTC id\n"); - return -EINVAL; + return -ENOENT; } crtc = to_gma_crtc(obj_to_crtc(drmmode_obj)); -- cgit v1.2.1 From 9d3e2f5304c77c2f4dcb96f03307575b25597b9a Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Mon, 16 Sep 2013 17:46:17 +0200 Subject: drm/gma500: Add Minnowboard to the IS_MRST() macro Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/psb_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 0bab46bd73d2..b26d029a2e81 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -45,7 +45,7 @@ enum { }; #define IS_PSB(dev) (((dev)->pdev->device & 0xfffe) == 0x8108) -#define IS_MRST(dev) (((dev)->pdev->device & 0xfffc) == 0x4100) +#define IS_MRST(dev) (((dev)->pdev->device & 0xfff0) == 0x4100) #define IS_MFLD(dev) (((dev)->pdev->device & 0xfff8) == 0x0130) #define IS_CDV(dev) (((dev)->pdev->device & 0xfff0) == 0x0be0) -- cgit v1.2.1 From cf8efd3afeff02fed2e2937ab3006618919bf65a Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Mon, 16 Sep 2013 17:54:54 +0200 Subject: drm/gma500: Add chip specific sdvo masks Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/cdv_device.c | 1 + drivers/gpu/drm/gma500/framebuffer.c | 2 +- drivers/gpu/drm/gma500/oaktrail_device.c | 1 + drivers/gpu/drm/gma500/psb_device.c | 1 + drivers/gpu/drm/gma500/psb_drv.h | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 162f686c532d..5a9a6a3063a8 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -634,6 +634,7 @@ const struct psb_ops cdv_chip_ops = { .crtcs = 2, .hdmi_mask = (1 << 0) | (1 << 1), .lvds_mask = (1 << 1), + .sdvo_mask = (1 << 0), .cursor_needs_phys = 0, .sgx_offset = MRST_SGX_OFFSET, .chip_setup = cdv_chip_setup, diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 01dd7d225762..94b3fec22c28 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -714,7 +714,7 @@ static void psb_setup_outputs(struct drm_device *dev) clone_mask = (1 << INTEL_OUTPUT_ANALOG); break; case INTEL_OUTPUT_SDVO: - crtc_mask = ((1 << 0) | (1 << 1)); + crtc_mask = dev_priv->ops->sdvo_mask; clone_mask = (1 << INTEL_OUTPUT_SDVO); break; case INTEL_OUTPUT_LVDS: diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 08747fd7105c..80798517d93e 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -546,6 +546,7 @@ const struct psb_ops oaktrail_chip_ops = { .crtcs = 2, .hdmi_mask = (1 << 1), .lvds_mask = (1 << 0), + .sdvo_mask = (1 << 1), .cursor_needs_phys = 0, .sgx_offset = MRST_SGX_OFFSET, diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index 697678619bd1..23fb33f1471b 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -373,6 +373,7 @@ const struct psb_ops psb_chip_ops = { .crtcs = 2, .hdmi_mask = (1 << 0), .lvds_mask = (1 << 1), + .sdvo_mask = (1 << 0), .cursor_needs_phys = 1, .sgx_offset = PSB_SGX_OFFSET, .chip_setup = psb_chip_setup, diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index b26d029a2e81..fd93756f41d1 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -672,6 +672,7 @@ struct psb_ops { int sgx_offset; /* Base offset of SGX device */ int hdmi_mask; /* Mask of HDMI CRTCs */ int lvds_mask; /* Mask of LVDS CRTCs */ + int sdvo_mask; /* Mask of SDVO CRTCs */ int cursor_needs_phys; /* If cursor base reg need physical address */ /* Sub functions */ -- cgit v1.2.1 From 2657929d4e7c0a4db5456cc2c9a230a68b07813d Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Mon, 16 Sep 2013 18:02:40 +0200 Subject: drm/gma500: Add support for aux pci vdc device Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/psb_drv.c | 32 +++++++++++++++++++++++++++++++- drivers/gpu/drm/gma500/psb_drv.h | 21 ++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 679f95313c29..1199180667c9 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -251,6 +251,12 @@ static int psb_driver_unload(struct drm_device *dev) iounmap(dev_priv->sgx_reg); dev_priv->sgx_reg = NULL; } + if (dev_priv->aux_reg) { + iounmap(dev_priv->aux_reg); + dev_priv->aux_reg = NULL; + } + if (dev_priv->aux_pdev) + pci_dev_put(dev_priv->aux_pdev); /* Destroy VBT data */ psb_intel_destroy_bios(dev); @@ -266,7 +272,7 @@ static int psb_driver_unload(struct drm_device *dev) static int psb_driver_load(struct drm_device *dev, unsigned long chipset) { struct drm_psb_private *dev_priv; - unsigned long resource_start; + unsigned long resource_start, resource_len; unsigned long irqflags; int ret = -ENOMEM; struct drm_connector *connector; @@ -296,6 +302,30 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) if (!dev_priv->sgx_reg) goto out_err; + if (IS_MRST(dev)) { + dev_priv->aux_pdev = pci_get_bus_and_slot(0, PCI_DEVFN(3, 0)); + + if (dev_priv->aux_pdev) { + resource_start = pci_resource_start(dev_priv->aux_pdev, + PSB_AUX_RESOURCE); + resource_len = pci_resource_len(dev_priv->aux_pdev, + PSB_AUX_RESOURCE); + dev_priv->aux_reg = ioremap_nocache(resource_start, + resource_len); + if (!dev_priv->aux_reg) + goto out_err; + + DRM_DEBUG_KMS("Found aux vdc"); + } else { + /* Couldn't find the aux vdc so map to primary vdc */ + dev_priv->aux_reg = dev_priv->vdc_reg; + DRM_DEBUG_KMS("Couldn't find aux pci device"); + } + dev_priv->gmbus_reg = dev_priv->aux_reg; + } else { + dev_priv->gmbus_reg = dev_priv->vdc_reg; + } + psb_intel_opregion_setup(dev); ret = dev_priv->ops->chip_setup(dev); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index fd93756f41d1..dc7a8dec68e5 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -75,6 +75,7 @@ enum { * PCI resource identifiers */ #define PSB_MMIO_RESOURCE 0 +#define PSB_AUX_RESOURCE 0 #define PSB_GATT_RESOURCE 2 #define PSB_GTT_RESOURCE 3 /* @@ -455,6 +456,7 @@ struct psb_ops; struct drm_psb_private { struct drm_device *dev; + struct pci_dev *aux_pdev; /* Currently only used by mrst */ const struct psb_ops *ops; const struct psb_offset *regmap; @@ -486,6 +488,7 @@ struct drm_psb_private { uint8_t __iomem *sgx_reg; uint8_t __iomem *vdc_reg; + uint8_t __iomem *aux_reg; /* Auxillary vdc pipe regs */ uint32_t gatt_free_offset; /* @@ -532,6 +535,7 @@ struct drm_psb_private { /* gmbus */ struct intel_gmbus *gmbus; + uint8_t __iomem *gmbus_reg; /* Used by SDVO */ int crt_ddc_pin; @@ -928,16 +932,31 @@ static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg) return ioread32(dev_priv->vdc_reg + reg); } +static inline uint32_t REGISTER_READ_AUX(struct drm_device *dev, uint32_t reg) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + return ioread32(dev_priv->aux_reg + reg); +} + #define REG_READ(reg) REGISTER_READ(dev, (reg)) +#define REG_READ_AUX(reg) REGISTER_READ_AUX(dev, (reg)) static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg, - uint32_t val) + uint32_t val) { struct drm_psb_private *dev_priv = dev->dev_private; iowrite32((val), dev_priv->vdc_reg + (reg)); } +static inline void REGISTER_WRITE_AUX(struct drm_device *dev, uint32_t reg, + uint32_t val) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + iowrite32((val), dev_priv->aux_reg + (reg)); +} + #define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val)) +#define REG_WRITE_AUX(reg, val) REGISTER_WRITE_AUX(dev, (reg), (val)) static inline void REGISTER_WRITE16(struct drm_device *dev, uint32_t reg, uint32_t val) -- cgit v1.2.1 From 86bd4103254adf7f3d32fa5c2578162c9e27b205 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Mon, 16 Sep 2013 18:36:37 +0200 Subject: drm/gma500: Add aux device support for gmbus Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/intel_gmbus.c | 90 ++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 41 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/intel_gmbus.c b/drivers/gpu/drm/gma500/intel_gmbus.c index 62cd42e88f28..566d330aaeea 100644 --- a/drivers/gpu/drm/gma500/intel_gmbus.c +++ b/drivers/gpu/drm/gma500/intel_gmbus.c @@ -51,6 +51,9 @@ #define wait_for(COND, MS) _wait_for(COND, MS, 1) #define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) +#define GMBUS_REG_READ(reg) ioread32(dev_priv->gmbus_reg + (reg)) +#define GMBUS_REG_WRITE(reg, val) iowrite32((val), dev_priv->gmbus_reg + (reg)) + /* Intel GPIO access functions */ #define I2C_RISEFALL_TIME 20 @@ -71,7 +74,8 @@ struct intel_gpio { void gma_intel_i2c_reset(struct drm_device *dev) { - REG_WRITE(GMBUS0, 0); + struct drm_psb_private *dev_priv = dev->dev_private; + GMBUS_REG_WRITE(GMBUS0, 0); } static void intel_i2c_quirk_set(struct drm_psb_private *dev_priv, bool enable) @@ -98,11 +102,10 @@ static void intel_i2c_quirk_set(struct drm_psb_private *dev_priv, bool enable) static u32 get_reserved(struct intel_gpio *gpio) { struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; u32 reserved = 0; /* On most chips, these bits must be preserved in software. */ - reserved = REG_READ(gpio->reg) & + reserved = GMBUS_REG_READ(gpio->reg) & (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE); @@ -113,29 +116,26 @@ static int get_clock(void *data) { struct intel_gpio *gpio = data; struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; u32 reserved = get_reserved(gpio); - REG_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); - REG_WRITE(gpio->reg, reserved); - return (REG_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; + GMBUS_REG_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); + GMBUS_REG_WRITE(gpio->reg, reserved); + return (GMBUS_REG_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; } static int get_data(void *data) { struct intel_gpio *gpio = data; struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; u32 reserved = get_reserved(gpio); - REG_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); - REG_WRITE(gpio->reg, reserved); - return (REG_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0; + GMBUS_REG_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); + GMBUS_REG_WRITE(gpio->reg, reserved); + return (GMBUS_REG_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0; } static void set_clock(void *data, int state_high) { struct intel_gpio *gpio = data; struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; u32 reserved = get_reserved(gpio); u32 clock_bits; @@ -145,15 +145,14 @@ static void set_clock(void *data, int state_high) clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK; - REG_WRITE(gpio->reg, reserved | clock_bits); - REG_READ(gpio->reg); /* Posting */ + GMBUS_REG_WRITE(gpio->reg, reserved | clock_bits); + GMBUS_REG_READ(gpio->reg); /* Posting */ } static void set_data(void *data, int state_high) { struct intel_gpio *gpio = data; struct drm_psb_private *dev_priv = gpio->dev_priv; - struct drm_device *dev = dev_priv->dev; u32 reserved = get_reserved(gpio); u32 data_bits; @@ -163,8 +162,8 @@ static void set_data(void *data, int state_high) data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK; - REG_WRITE(gpio->reg, reserved | data_bits); - REG_READ(gpio->reg); + GMBUS_REG_WRITE(gpio->reg, reserved | data_bits); + GMBUS_REG_READ(gpio->reg); } static struct i2c_adapter * @@ -251,7 +250,6 @@ gmbus_xfer(struct i2c_adapter *adapter, struct intel_gmbus, adapter); struct drm_psb_private *dev_priv = adapter->algo_data; - struct drm_device *dev = dev_priv->dev; int i, reg_offset; if (bus->force_bit) @@ -260,28 +258,30 @@ gmbus_xfer(struct i2c_adapter *adapter, reg_offset = 0; - REG_WRITE(GMBUS0 + reg_offset, bus->reg0); + GMBUS_REG_WRITE(GMBUS0 + reg_offset, bus->reg0); for (i = 0; i < num; i++) { u16 len = msgs[i].len; u8 *buf = msgs[i].buf; if (msgs[i].flags & I2C_M_RD) { - REG_WRITE(GMBUS1 + reg_offset, - GMBUS_CYCLE_WAIT | (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | - (len << GMBUS_BYTE_COUNT_SHIFT) | - (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | - GMBUS_SLAVE_READ | GMBUS_SW_RDY); - REG_READ(GMBUS2+reg_offset); + GMBUS_REG_WRITE(GMBUS1 + reg_offset, + GMBUS_CYCLE_WAIT | + (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | + (len << GMBUS_BYTE_COUNT_SHIFT) | + (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | + GMBUS_SLAVE_READ | GMBUS_SW_RDY); + GMBUS_REG_READ(GMBUS2+reg_offset); do { u32 val, loop = 0; - if (wait_for(REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) + if (wait_for(GMBUS_REG_READ(GMBUS2 + reg_offset) & + (GMBUS_SATOER | GMBUS_HW_RDY), 50)) goto timeout; - if (REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) + if (GMBUS_REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) goto clear_err; - val = REG_READ(GMBUS3 + reg_offset); + val = GMBUS_REG_READ(GMBUS3 + reg_offset); do { *buf++ = val & 0xff; val >>= 8; @@ -295,18 +295,20 @@ gmbus_xfer(struct i2c_adapter *adapter, val |= *buf++ << (8 * loop); } while (--len && ++loop < 4); - REG_WRITE(GMBUS3 + reg_offset, val); - REG_WRITE(GMBUS1 + reg_offset, + GMBUS_REG_WRITE(GMBUS3 + reg_offset, val); + GMBUS_REG_WRITE(GMBUS1 + reg_offset, (i + 1 == num ? GMBUS_CYCLE_STOP : GMBUS_CYCLE_WAIT) | (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) | (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); - REG_READ(GMBUS2+reg_offset); + GMBUS_REG_READ(GMBUS2+reg_offset); while (len) { - if (wait_for(REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) + if (wait_for(GMBUS_REG_READ(GMBUS2 + reg_offset) & + (GMBUS_SATOER | GMBUS_HW_RDY), 50)) goto timeout; - if (REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) + if (GMBUS_REG_READ(GMBUS2 + reg_offset) & + GMBUS_SATOER) goto clear_err; val = loop = 0; @@ -314,14 +316,14 @@ gmbus_xfer(struct i2c_adapter *adapter, val |= *buf++ << (8 * loop); } while (--len && ++loop < 4); - REG_WRITE(GMBUS3 + reg_offset, val); - REG_READ(GMBUS2+reg_offset); + GMBUS_REG_WRITE(GMBUS3 + reg_offset, val); + GMBUS_REG_READ(GMBUS2+reg_offset); } } - if (i + 1 < num && wait_for(REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50)) + if (i + 1 < num && wait_for(GMBUS_REG_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50)) goto timeout; - if (REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) + if (GMBUS_REG_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) goto clear_err; } @@ -332,20 +334,20 @@ clear_err: * of resetting the GMBUS controller and so clearing the * BUS_ERROR raised by the slave's NAK. */ - REG_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT); - REG_WRITE(GMBUS1 + reg_offset, 0); + GMBUS_REG_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT); + GMBUS_REG_WRITE(GMBUS1 + reg_offset, 0); done: /* Mark the GMBUS interface as disabled. We will re-enable it at the * start of the next xfer, till then let it sleep. */ - REG_WRITE(GMBUS0 + reg_offset, 0); + GMBUS_REG_WRITE(GMBUS0 + reg_offset, 0); return i; timeout: DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", bus->reg0 & 0xff, bus->adapter.name); - REG_WRITE(GMBUS0 + reg_offset, 0); + GMBUS_REG_WRITE(GMBUS0 + reg_offset, 0); /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); @@ -399,6 +401,11 @@ int gma_intel_setup_gmbus(struct drm_device *dev) if (dev_priv->gmbus == NULL) return -ENOMEM; + if (IS_MRST(dev)) + dev_priv->gmbus_reg = dev_priv->aux_reg; + else + dev_priv->gmbus_reg = dev_priv->vdc_reg; + for (i = 0; i < GMBUS_NUM_PORTS; i++) { struct intel_gmbus *bus = &dev_priv->gmbus[i]; @@ -487,6 +494,7 @@ void gma_intel_teardown_gmbus(struct drm_device *dev) i2c_del_adapter(&bus->adapter); } + dev_priv->gmbus_reg = NULL; /* iounmap is done in driver_unload */ kfree(dev_priv->gmbus); dev_priv->gmbus = NULL; } -- cgit v1.2.1 From ac6113ebb70d4bc7018db4e73f923653347da743 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Wed, 6 Nov 2013 22:31:18 +0100 Subject: drm/gma500/mrst: Add SDVO clock calculation We start off by adding SDVO limits and converting all limits to the generic gma_limit_t stuct. Then we separate clock calculations for LVDS and SDVO. This will be cleaned up later but keep it simple for now. Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/oaktrail_crtc.c | 175 ++++++++++++++++++++++++--------- 1 file changed, 126 insertions(+), 49 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index 54c98962b73e..bde3065f7422 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -26,24 +26,10 @@ #include "gma_display.h" #include "power.h" -struct psb_intel_range_t { - int min, max; -}; - -struct oaktrail_limit_t { - struct psb_intel_range_t dot, m, p1; -}; - -struct oaktrail_clock_t { - /* derived values */ - int dot; - int m; - int p1; -}; - -#define MRST_LIMIT_LVDS_100L 0 -#define MRST_LIMIT_LVDS_83 1 -#define MRST_LIMIT_LVDS_100 2 +#define MRST_LIMIT_LVDS_100L 0 +#define MRST_LIMIT_LVDS_83 1 +#define MRST_LIMIT_LVDS_100 2 +#define MRST_LIMIT_SDVO 3 #define MRST_DOT_MIN 19750 #define MRST_DOT_MAX 120000 @@ -57,21 +43,40 @@ struct oaktrail_clock_t { #define MRST_P1_MAX_0 7 #define MRST_P1_MAX_1 8 -static const struct oaktrail_limit_t oaktrail_limits[] = { +static bool mrst_lvds_find_best_pll(const struct gma_limit_t *limit, + struct drm_crtc *crtc, int target, + int refclk, struct gma_clock_t *best_clock); + +static bool mrst_sdvo_find_best_pll(const struct gma_limit_t *limit, + struct drm_crtc *crtc, int target, + int refclk, struct gma_clock_t *best_clock); + +static const struct gma_limit_t mrst_limits[] = { { /* MRST_LIMIT_LVDS_100L */ .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L}, .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, + .find_pll = mrst_lvds_find_best_pll, }, { /* MRST_LIMIT_LVDS_83L */ .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83}, .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0}, + .find_pll = mrst_lvds_find_best_pll, }, { /* MRST_LIMIT_LVDS_100 */ .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100}, .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, + .find_pll = mrst_lvds_find_best_pll, + }, + { /* MRST_LIMIT_SDVO */ + .vco = {.min = 1400000, .max = 2800000}, + .n = {.min = 3, .max = 7}, + .m = {.min = 80, .max = 137}, + .p1 = {.min = 1, .max = 2}, + .p2 = {.dot_limit = 200000, .p2_slow = 10, .p2_fast = 10}, + .find_pll = mrst_sdvo_find_best_pll, }, }; @@ -82,9 +87,10 @@ static const u32 oaktrail_m_converts[] = { 0x12, 0x09, 0x24, 0x32, 0x39, 0x1c, }; -static const struct oaktrail_limit_t *oaktrail_limit(struct drm_crtc *crtc) +static const struct gma_limit_t *mrst_limit(struct drm_crtc *crtc, + int refclk) { - const struct oaktrail_limit_t *limit = NULL; + const struct gma_limit_t *limit = NULL; struct drm_device *dev = crtc->dev; struct drm_psb_private *dev_priv = dev->dev_private; @@ -92,45 +98,100 @@ static const struct oaktrail_limit_t *oaktrail_limit(struct drm_crtc *crtc) || gma_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) { switch (dev_priv->core_freq) { case 100: - limit = &oaktrail_limits[MRST_LIMIT_LVDS_100L]; + limit = &mrst_limits[MRST_LIMIT_LVDS_100L]; break; case 166: - limit = &oaktrail_limits[MRST_LIMIT_LVDS_83]; + limit = &mrst_limits[MRST_LIMIT_LVDS_83]; break; case 200: - limit = &oaktrail_limits[MRST_LIMIT_LVDS_100]; + limit = &mrst_limits[MRST_LIMIT_LVDS_100]; break; } + } else if (gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { + limit = &mrst_limits[MRST_LIMIT_SDVO]; } else { limit = NULL; - dev_err(dev->dev, "oaktrail_limit Wrong display type.\n"); + dev_err(dev->dev, "mrst_limit Wrong display type.\n"); } return limit; } /** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ -static void oaktrail_clock(int refclk, struct oaktrail_clock_t *clock) +static void mrst_lvds_clock(int refclk, struct gma_clock_t *clock) { clock->dot = (refclk * clock->m) / (14 * clock->p1); } -static void mrstPrintPll(char *prefix, struct oaktrail_clock_t *clock) +static void mrst_print_pll(struct gma_clock_t *clock) { - pr_debug("%s: dotclock = %d, m = %d, p1 = %d.\n", - prefix, clock->dot, clock->m, clock->p1); + DRM_DEBUG_DRIVER("dotclock=%d, m=%d, m1=%d, m2=%d, n=%d, p1=%d, p2=%d\n", + clock->dot, clock->m, clock->m1, clock->m2, clock->n, + clock->p1, clock->p2); +} + +static bool mrst_sdvo_find_best_pll(const struct gma_limit_t *limit, + struct drm_crtc *crtc, int target, + int refclk, struct gma_clock_t *best_clock) +{ + struct gma_clock_t clock; + u32 target_vco, actual_freq; + s32 freq_error, min_error = 100000; + + memset(best_clock, 0, sizeof(*best_clock)); + + for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { + for (clock.n = limit->n.min; clock.n <= limit->n.max; + clock.n++) { + for (clock.p1 = limit->p1.min; + clock.p1 <= limit->p1.max; clock.p1++) { + /* p2 value always stored in p2_slow on SDVO */ + clock.p = clock.p1 * limit->p2.p2_slow; + target_vco = target * clock.p; + + /* VCO will increase at this point so break */ + if (target_vco > limit->vco.max) + break; + + if (target_vco < limit->vco.min) + continue; + + actual_freq = (refclk * clock.m) / + (clock.n * clock.p); + freq_error = 10000 - + ((target * 10000) / actual_freq); + + if (freq_error < -min_error) { + /* freq_error will start to decrease at + this point so break */ + break; + } + + if (freq_error < 0) + freq_error = -freq_error; + + if (freq_error < min_error) { + min_error = freq_error; + *best_clock = clock; + } + } + } + if (min_error == 0) + break; + } + + return min_error == 0; } /** * Returns a set of divisors for the desired target clock with the given refclk, * or FALSE. Divisor values are the actual divisors for */ -static bool -mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk, - struct oaktrail_clock_t *best_clock) +static bool mrst_lvds_find_best_pll(const struct gma_limit_t *limit, + struct drm_crtc *crtc, int target, + int refclk, struct gma_clock_t *best_clock) { - struct oaktrail_clock_t clock; - const struct oaktrail_limit_t *limit = oaktrail_limit(crtc); + struct gma_clock_t clock; int err = target; memset(best_clock, 0, sizeof(*best_clock)); @@ -140,7 +201,7 @@ mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk, clock.p1++) { int this_err; - oaktrail_clock(refclk, &clock); + mrst_lvds_clock(refclk, &clock); this_err = abs(clock.dot - target); if (this_err < err) { @@ -149,7 +210,6 @@ mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk, } } } - dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err); return err != target; } @@ -297,7 +357,8 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, int pipe = gma_crtc->pipe; const struct psb_offset *map = &dev_priv->regmap[pipe]; int refclk = 0; - struct oaktrail_clock_t clock; + struct gma_clock_t clock; + const struct gma_limit_t *limit; u32 dpll = 0, fp = 0, dspcntr, pipeconf; bool ok, is_sdvo = false; bool is_lvds = false; @@ -418,21 +479,30 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, if (is_mipi) goto oaktrail_crtc_mode_set_exit; - refclk = dev_priv->core_freq * 1000; dpll = 0; /*BIT16 = 0 for 100MHz reference */ - ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock); + refclk = is_sdvo ? 96000 : dev_priv->core_freq * 1000; + limit = mrst_limit(crtc, refclk); + ok = limit->find_pll(limit, crtc, adjusted_mode->clock, + refclk, &clock); - if (!ok) { - dev_dbg(dev->dev, "mrstFindBestPLL fail in oaktrail_crtc_mode_set.\n"); - } else { - dev_dbg(dev->dev, "oaktrail_crtc_mode_set pixel clock = %d," - "m = %x, p1 = %x.\n", clock.dot, clock.m, - clock.p1); + if (is_sdvo) { + /* Convert calculated values to register values */ + clock.p1 = (1L << (clock.p1 - 1)); + clock.m -= 2; + clock.n = (1L << (clock.n - 1)); } - fp = oaktrail_m_converts[(clock.m - MRST_M_MIN)] << 8; + if (!ok) + DRM_ERROR("Failed to find proper PLL settings"); + + mrst_print_pll(&clock); + + if (is_sdvo) + fp = clock.n << 16 | clock.m; + else + fp = oaktrail_m_converts[(clock.m - MRST_M_MIN)] << 8; dpll |= DPLL_VGA_MODE_DIS; @@ -456,12 +526,13 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, /* compute bitmask from p1 value */ - dpll |= (1 << (clock.p1 - 2)) << 17; + if (is_sdvo) + dpll |= clock.p1 << 16; // dpll |= (1 << (clock.p1 - 1)) << 16; + else + dpll |= (1 << (clock.p1 - 2)) << 17; dpll |= DPLL_VCO_ENABLE; - mrstPrintPll("chosen", &clock); - if (dpll & DPLL_VCO_ENABLE) { REG_WRITE(map->fp0, fp); REG_WRITE(map->dpll, dpll & ~DPLL_VCO_ENABLE); @@ -565,3 +636,9 @@ const struct drm_crtc_helper_funcs oaktrail_helper_funcs = { .commit = gma_crtc_commit, }; +/* Not used yet */ +const struct gma_clock_funcs mrst_clock_funcs = { + .clock = mrst_lvds_clock, + .limit = mrst_limit, + .pll_is_valid = gma_pll_is_valid, +}; -- cgit v1.2.1 From b97b8287a39d1fe6f8aa1b83405f669634ff8401 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Thu, 7 Nov 2013 00:14:18 +0100 Subject: drm/gma500/mrst: Add aux register writes when programming pipe On SDVO pipes (always Pipe B on mrst) we have to sequentially write the aux vdc. We might be able to skip programming the primary vdc in some/most places but we don't care about that now. Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/oaktrail_crtc.c | 241 ++++++++++++++++++--------------- drivers/gpu/drm/gma500/psb_drv.h | 27 ++++ 2 files changed, 162 insertions(+), 106 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index bde3065f7422..ef4f0766a385 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -227,6 +227,8 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode) int pipe = gma_crtc->pipe; const struct psb_offset *map = &dev_priv->regmap[pipe]; u32 temp; + int i; + int need_aux = gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ? 1 : 0; if (pipe == 1) { oaktrail_crtc_hdmi_dpms(crtc, mode); @@ -243,35 +245,45 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: - /* Enable the DPLL */ - temp = REG_READ(map->dpll); - if ((temp & DPLL_VCO_ENABLE) == 0) { - REG_WRITE(map->dpll, temp); - REG_READ(map->dpll); - /* Wait for the clocks to stabilize. */ - udelay(150); - REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE); - REG_READ(map->dpll); - /* Wait for the clocks to stabilize. */ - udelay(150); - REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE); - REG_READ(map->dpll); - /* Wait for the clocks to stabilize. */ - udelay(150); - } - /* Enable the pipe */ - temp = REG_READ(map->conf); - if ((temp & PIPEACONF_ENABLE) == 0) - REG_WRITE(map->conf, temp | PIPEACONF_ENABLE); - /* Enable the plane */ - temp = REG_READ(map->cntr); - if ((temp & DISPLAY_PLANE_ENABLE) == 0) { - REG_WRITE(map->cntr, - temp | DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(map->base, REG_READ(map->base)); - } + for (i = 0; i <= need_aux; i++) { + /* Enable the DPLL */ + temp = REG_READ_WITH_AUX(map->dpll, i); + if ((temp & DPLL_VCO_ENABLE) == 0) { + REG_WRITE_WITH_AUX(map->dpll, temp, i); + REG_READ_WITH_AUX(map->dpll, i); + /* Wait for the clocks to stabilize. */ + udelay(150); + REG_WRITE_WITH_AUX(map->dpll, + temp | DPLL_VCO_ENABLE, i); + REG_READ_WITH_AUX(map->dpll, i); + /* Wait for the clocks to stabilize. */ + udelay(150); + REG_WRITE_WITH_AUX(map->dpll, + temp | DPLL_VCO_ENABLE, i); + REG_READ_WITH_AUX(map->dpll, i); + /* Wait for the clocks to stabilize. */ + udelay(150); + } + + /* Enable the pipe */ + temp = REG_READ_WITH_AUX(map->conf, i); + if ((temp & PIPEACONF_ENABLE) == 0) { + REG_WRITE_WITH_AUX(map->conf, + temp | PIPEACONF_ENABLE, i); + } + /* Enable the plane */ + temp = REG_READ_WITH_AUX(map->cntr, i); + if ((temp & DISPLAY_PLANE_ENABLE) == 0) { + REG_WRITE_WITH_AUX(map->cntr, + temp | DISPLAY_PLANE_ENABLE, + i); + /* Flush the plane changes */ + REG_WRITE_WITH_AUX(map->base, + REG_READ_WITH_AUX(map->base, i), i); + } + + } gma_crtc_load_lut(crtc); /* Give the overlay scaler a chance to enable @@ -283,35 +295,40 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode) * if it's on this pipe */ /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ - /* Disable the VGA plane that we never use */ - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - /* Disable display plane */ - temp = REG_READ(map->cntr); - if ((temp & DISPLAY_PLANE_ENABLE) != 0) { - REG_WRITE(map->cntr, - temp & ~DISPLAY_PLANE_ENABLE); - /* Flush the plane changes */ - REG_WRITE(map->base, REG_READ(map->base)); - REG_READ(map->base); - } + for (i = 0; i <= need_aux; i++) { + /* Disable the VGA plane that we never use */ + REG_WRITE_WITH_AUX(VGACNTRL, VGA_DISP_DISABLE, i); + /* Disable display plane */ + temp = REG_READ_WITH_AUX(map->cntr, i); + if ((temp & DISPLAY_PLANE_ENABLE) != 0) { + REG_WRITE_WITH_AUX(map->cntr, + temp & ~DISPLAY_PLANE_ENABLE, i); + /* Flush the plane changes */ + REG_WRITE_WITH_AUX(map->base, + REG_READ(map->base), i); + REG_READ_WITH_AUX(map->base, i); + } - /* Next, disable display pipes */ - temp = REG_READ(map->conf); - if ((temp & PIPEACONF_ENABLE) != 0) { - REG_WRITE(map->conf, temp & ~PIPEACONF_ENABLE); - REG_READ(map->conf); - } - /* Wait for for the pipe disable to take effect. */ - gma_wait_for_vblank(dev); + /* Next, disable display pipes */ + temp = REG_READ_WITH_AUX(map->conf, i); + if ((temp & PIPEACONF_ENABLE) != 0) { + REG_WRITE_WITH_AUX(map->conf, + temp & ~PIPEACONF_ENABLE, i); + REG_READ_WITH_AUX(map->conf, i); + } + /* Wait for for the pipe disable to take effect. */ + gma_wait_for_vblank(dev); + + temp = REG_READ_WITH_AUX(map->dpll, i); + if ((temp & DPLL_VCO_ENABLE) != 0) { + REG_WRITE_WITH_AUX(map->dpll, + temp & ~DPLL_VCO_ENABLE, i); + REG_READ_WITH_AUX(map->dpll, i); + } - temp = REG_READ(map->dpll); - if ((temp & DPLL_VCO_ENABLE) != 0) { - REG_WRITE(map->dpll, temp & ~DPLL_VCO_ENABLE); - REG_READ(map->dpll); + /* Wait for the clocks to turn off. */ + udelay(150); } - - /* Wait for the clocks to turn off. */ - udelay(150); break; } @@ -367,6 +384,8 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, struct gma_encoder *gma_encoder = NULL; uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; struct drm_connector *connector; + int i; + int need_aux = gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ? 1 : 0; if (pipe == 1) return oaktrail_crtc_hdmi_mode_set(crtc, mode, adjusted_mode, x, y, old_fb); @@ -401,15 +420,17 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, } /* Disable the VGA plane that we never use */ - REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); + for (i = 0; i <= need_aux; i++) + REG_WRITE_WITH_AUX(VGACNTRL, VGA_DISP_DISABLE, i); /* Disable the panel fitter if it was on our pipe */ if (oaktrail_panel_fitter_pipe(dev) == pipe) REG_WRITE(PFIT_CONTROL, 0); - REG_WRITE(map->src, - ((mode->crtc_hdisplay - 1) << 16) | - (mode->crtc_vdisplay - 1)); + for (i = 0; i <= need_aux; i++) { + REG_WRITE_WITH_AUX(map->src, ((mode->crtc_hdisplay - 1) << 16) | + (mode->crtc_vdisplay - 1), i); + } if (gma_encoder) drm_object_property_get_value(&connector->base, @@ -426,35 +447,39 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; - REG_WRITE(map->htotal, (mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); - REG_WRITE(map->vtotal, (mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); - REG_WRITE(map->hblank, - (adjusted_mode->crtc_hblank_start - offsetX - 1) | - ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); - REG_WRITE(map->hsync, - (adjusted_mode->crtc_hsync_start - offsetX - 1) | - ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); - REG_WRITE(map->vblank, - (adjusted_mode->crtc_vblank_start - offsetY - 1) | - ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); - REG_WRITE(map->vsync, - (adjusted_mode->crtc_vsync_start - offsetY - 1) | - ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); + for (i = 0; i <= need_aux; i++) { + REG_WRITE_WITH_AUX(map->htotal, (mode->crtc_hdisplay - 1) | + ((adjusted_mode->crtc_htotal - 1) << 16), i); + REG_WRITE_WITH_AUX(map->vtotal, (mode->crtc_vdisplay - 1) | + ((adjusted_mode->crtc_vtotal - 1) << 16), i); + REG_WRITE_WITH_AUX(map->hblank, + (adjusted_mode->crtc_hblank_start - offsetX - 1) | + ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16), i); + REG_WRITE_WITH_AUX(map->hsync, + (adjusted_mode->crtc_hsync_start - offsetX - 1) | + ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16), i); + REG_WRITE_WITH_AUX(map->vblank, + (adjusted_mode->crtc_vblank_start - offsetY - 1) | + ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16), i); + REG_WRITE_WITH_AUX(map->vsync, + (adjusted_mode->crtc_vsync_start - offsetY - 1) | + ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16), i); + } } else { - REG_WRITE(map->htotal, (adjusted_mode->crtc_hdisplay - 1) | - ((adjusted_mode->crtc_htotal - 1) << 16)); - REG_WRITE(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) | - ((adjusted_mode->crtc_vtotal - 1) << 16)); - REG_WRITE(map->hblank, (adjusted_mode->crtc_hblank_start - 1) | - ((adjusted_mode->crtc_hblank_end - 1) << 16)); - REG_WRITE(map->hsync, (adjusted_mode->crtc_hsync_start - 1) | - ((adjusted_mode->crtc_hsync_end - 1) << 16)); - REG_WRITE(map->vblank, (adjusted_mode->crtc_vblank_start - 1) | - ((adjusted_mode->crtc_vblank_end - 1) << 16)); - REG_WRITE(map->vsync, (adjusted_mode->crtc_vsync_start - 1) | - ((adjusted_mode->crtc_vsync_end - 1) << 16)); + for (i = 0; i <= need_aux; i++) { + REG_WRITE_WITH_AUX(map->htotal, (adjusted_mode->crtc_hdisplay - 1) | + ((adjusted_mode->crtc_htotal - 1) << 16), i); + REG_WRITE_WITH_AUX(map->vtotal, (adjusted_mode->crtc_vdisplay - 1) | + ((adjusted_mode->crtc_vtotal - 1) << 16), i); + REG_WRITE_WITH_AUX(map->hblank, (adjusted_mode->crtc_hblank_start - 1) | + ((adjusted_mode->crtc_hblank_end - 1) << 16), i); + REG_WRITE_WITH_AUX(map->hsync, (adjusted_mode->crtc_hsync_start - 1) | + ((adjusted_mode->crtc_hsync_end - 1) << 16), i); + REG_WRITE_WITH_AUX(map->vblank, (adjusted_mode->crtc_vblank_start - 1) | + ((adjusted_mode->crtc_vblank_end - 1) << 16), i); + REG_WRITE_WITH_AUX(map->vsync, (adjusted_mode->crtc_vsync_start - 1) | + ((adjusted_mode->crtc_vsync_end - 1) << 16), i); + } } /* Flush the plane changes */ @@ -534,31 +559,35 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, dpll |= DPLL_VCO_ENABLE; if (dpll & DPLL_VCO_ENABLE) { - REG_WRITE(map->fp0, fp); - REG_WRITE(map->dpll, dpll & ~DPLL_VCO_ENABLE); - REG_READ(map->dpll); - /* Check the DPLLA lock bit PIPEACONF[29] */ - udelay(150); + for (i = 0; i <= need_aux; i++) { + REG_WRITE_WITH_AUX(map->fp0, fp, i); + REG_WRITE_WITH_AUX(map->dpll, dpll & ~DPLL_VCO_ENABLE, i); + REG_READ_WITH_AUX(map->dpll, i); + /* Check the DPLLA lock bit PIPEACONF[29] */ + udelay(150); + } } - REG_WRITE(map->fp0, fp); - REG_WRITE(map->dpll, dpll); - REG_READ(map->dpll); - /* Wait for the clocks to stabilize. */ - udelay(150); + for (i = 0; i <= need_aux; i++) { + REG_WRITE_WITH_AUX(map->fp0, fp, i); + REG_WRITE_WITH_AUX(map->dpll, dpll, i); + REG_READ_WITH_AUX(map->dpll, i); + /* Wait for the clocks to stabilize. */ + udelay(150); - /* write it again -- the BIOS does, after all */ - REG_WRITE(map->dpll, dpll); - REG_READ(map->dpll); - /* Wait for the clocks to stabilize. */ - udelay(150); + /* write it again -- the BIOS does, after all */ + REG_WRITE_WITH_AUX(map->dpll, dpll, i); + REG_READ_WITH_AUX(map->dpll, i); + /* Wait for the clocks to stabilize. */ + udelay(150); - REG_WRITE(map->conf, pipeconf); - REG_READ(map->conf); - gma_wait_for_vblank(dev); + REG_WRITE_WITH_AUX(map->conf, pipeconf, i); + REG_READ_WITH_AUX(map->conf, i); + gma_wait_for_vblank(dev); - REG_WRITE(map->cntr, dspcntr); - gma_wait_for_vblank(dev); + REG_WRITE_WITH_AUX(map->cntr, dspcntr, i); + gma_wait_for_vblank(dev); + } oaktrail_crtc_mode_set_exit: gma_power_end(dev); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index dc7a8dec68e5..b59e6588c343 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -941,6 +941,22 @@ static inline uint32_t REGISTER_READ_AUX(struct drm_device *dev, uint32_t reg) #define REG_READ(reg) REGISTER_READ(dev, (reg)) #define REG_READ_AUX(reg) REGISTER_READ_AUX(dev, (reg)) +/* Useful for post reads */ +static inline uint32_t REGISTER_READ_WITH_AUX(struct drm_device *dev, + uint32_t reg, int aux) +{ + uint32_t val; + + if (aux) + val = REG_READ_AUX(reg); + else + val = REG_READ(reg); + + return val; +} + +#define REG_READ_WITH_AUX(reg, aux) REGISTER_READ_WITH_AUX(dev, (reg), (aux)) + static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg, uint32_t val) { @@ -958,6 +974,17 @@ static inline void REGISTER_WRITE_AUX(struct drm_device *dev, uint32_t reg, #define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val)) #define REG_WRITE_AUX(reg, val) REGISTER_WRITE_AUX(dev, (reg), (val)) +static inline void REGISTER_WRITE_WITH_AUX(struct drm_device *dev, uint32_t reg, + uint32_t val, int aux) +{ + if (aux) + REG_WRITE_AUX(reg, val); + else + REG_WRITE(reg, val); +} + +#define REG_WRITE_WITH_AUX(reg, val, aux) REGISTER_WRITE_WITH_AUX(dev, (reg), (val), (aux)) + static inline void REGISTER_WRITE16(struct drm_device *dev, uint32_t reg, uint32_t val) { -- cgit v1.2.1 From 5aac788323dfdd61a6be31734170d644e5d7cb4f Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Thu, 7 Nov 2013 00:22:59 +0100 Subject: drm/gma500/mrst: Properly route oaktrail hdmi hooks Since we can have SDVO on Pipe B we better check the output type instead of pipe number for Oaktrail HDMI. Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/oaktrail_crtc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index ef4f0766a385..25bf206b46f2 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -230,7 +230,7 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode) int i; int need_aux = gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ? 1 : 0; - if (pipe == 1) { + if (gma_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { oaktrail_crtc_hdmi_dpms(crtc, mode); return; } @@ -387,7 +387,7 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, int i; int need_aux = gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ? 1 : 0; - if (pipe == 1) + if (gma_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) return oaktrail_crtc_hdmi_mode_set(crtc, mode, adjusted_mode, x, y, old_fb); if (!gma_power_begin(dev, true)) -- cgit v1.2.1 From fb8e34d561d58297af06b7350d9fdcafced8e1c5 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Thu, 7 Nov 2013 02:21:07 +0100 Subject: drm/gma500/mrst: Add aux register writes to SDVO This turned out to be tricky. Writing to SDVOB on the primary vdc also writes to SDVOB on the aux vdc, but reading it back on the primary vdc always fails. Basically we never read from the primary vdc since we will end up trashing the aux vdc. Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 59 +++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 6f01cdf5e125..07d3a9e6d79b 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -228,24 +228,26 @@ static void psb_intel_sdvo_write_sdvox(struct psb_intel_sdvo *psb_intel_sdvo, u3 { struct drm_device *dev = psb_intel_sdvo->base.base.dev; u32 bval = val, cval = val; - int i; + int i, j; + int need_aux = IS_MRST(dev) ? 1 : 0; - if (psb_intel_sdvo->sdvo_reg == SDVOB) { - cval = REG_READ(SDVOC); - } else { - bval = REG_READ(SDVOB); - } - /* - * Write the registers twice for luck. Sometimes, - * writing them only once doesn't appear to 'stick'. - * The BIOS does this too. Yay, magic - */ - for (i = 0; i < 2; i++) - { - REG_WRITE(SDVOB, bval); - REG_READ(SDVOB); - REG_WRITE(SDVOC, cval); - REG_READ(SDVOC); + for (j = 0; j <= need_aux; j++) { + if (psb_intel_sdvo->sdvo_reg == SDVOB) + cval = REG_READ_WITH_AUX(SDVOC, j); + else + bval = REG_READ_WITH_AUX(SDVOB, j); + + /* + * Write the registers twice for luck. Sometimes, + * writing them only once doesn't appear to 'stick'. + * The BIOS does this too. Yay, magic + */ + for (i = 0; i < 2; i++) { + REG_WRITE_WITH_AUX(SDVOB, bval, j); + REG_READ_WITH_AUX(SDVOB, j); + REG_WRITE_WITH_AUX(SDVOC, cval, j); + REG_READ_WITH_AUX(SDVOC, j); + } } } @@ -995,6 +997,7 @@ static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder, struct psb_intel_sdvo_dtd input_dtd; int pixel_multiplier = psb_intel_mode_get_pixel_multiplier(adjusted_mode); int rate; + int need_aux = IS_MRST(dev) ? 1 : 0; if (!mode) return; @@ -1060,7 +1063,11 @@ static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder, return; /* Set the SDVO control regs. */ - sdvox = REG_READ(psb_intel_sdvo->sdvo_reg); + if (need_aux) + sdvox = REG_READ_AUX(psb_intel_sdvo->sdvo_reg); + else + sdvox = REG_READ(psb_intel_sdvo->sdvo_reg); + switch (psb_intel_sdvo->sdvo_reg) { case SDVOB: sdvox &= SDVOB_PRESERVE_MASK; @@ -1090,6 +1097,8 @@ static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder); u32 temp; + int i; + int need_aux = IS_MRST(dev) ? 1 : 0; switch (mode) { case DRM_MODE_DPMS_ON: @@ -1108,19 +1117,27 @@ static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) psb_intel_sdvo_set_encoder_power_state(psb_intel_sdvo, mode); if (mode == DRM_MODE_DPMS_OFF) { - temp = REG_READ(psb_intel_sdvo->sdvo_reg); + if (need_aux) + temp = REG_READ_AUX(psb_intel_sdvo->sdvo_reg); + else + temp = REG_READ(psb_intel_sdvo->sdvo_reg); + if ((temp & SDVO_ENABLE) != 0) { psb_intel_sdvo_write_sdvox(psb_intel_sdvo, temp & ~SDVO_ENABLE); } } } else { bool input1, input2; - int i; u8 status; - temp = REG_READ(psb_intel_sdvo->sdvo_reg); + if (need_aux) + temp = REG_READ_AUX(psb_intel_sdvo->sdvo_reg); + else + temp = REG_READ(psb_intel_sdvo->sdvo_reg); + if ((temp & SDVO_ENABLE) == 0) psb_intel_sdvo_write_sdvox(psb_intel_sdvo, temp | SDVO_ENABLE); + for (i = 0; i < 2; i++) gma_wait_for_vblank(dev); -- cgit v1.2.1 From 99d754bb46e41cf88f6e5d96dd3c6c3b9c3bddb3 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Thu, 7 Nov 2013 02:34:12 +0100 Subject: drm/gma500/mrst: Replace WMs and chickenbits with values from EMGD For the minnowboard to work the values found in EMGD are required. This might break Oaktrail but without hardware to test with I cannot really tell (and do not really care). Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/oaktrail_crtc.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index 25bf206b46f2..8195e8592107 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -332,16 +332,15 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode) break; } - /*Set FIFO Watermarks*/ - REG_WRITE(DSPARB, 0x3FFF); - REG_WRITE(DSPFW1, 0x3F88080A); - REG_WRITE(DSPFW2, 0x0b060808); + /* Set FIFO Watermarks (values taken from EMGD) */ + REG_WRITE(DSPARB, 0x3f80); + REG_WRITE(DSPFW1, 0x3f8f0404); + REG_WRITE(DSPFW2, 0x04040f04); REG_WRITE(DSPFW3, 0x0); - REG_WRITE(DSPFW4, 0x08030404); + REG_WRITE(DSPFW4, 0x04040404); REG_WRITE(DSPFW5, 0x04040404); REG_WRITE(DSPFW6, 0x78); - REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000); - /* Must write Bit 14 of the Chicken Bit Register */ + REG_WRITE(DSPCHICKENBIT, REG_READ(DSPCHICKENBIT) | 0xc040); gma_power_end(dev); } -- cgit v1.2.1 From 6528c897966c7d520f18ed4804c31a1f1aa8a3d9 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Thu, 7 Nov 2013 03:04:04 +0100 Subject: drm/gma500/mrst: Setup GMBUS for oaktrail/mrst Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/oaktrail_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 80798517d93e..d7c54b27a473 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -526,6 +526,7 @@ static int oaktrail_chip_setup(struct drm_device *dev) psb_intel_opregion_init(dev); psb_intel_init_bios(dev); } + gma_intel_setup_gmbus(dev); oaktrail_hdmi_setup(dev); return 0; } @@ -534,6 +535,7 @@ static void oaktrail_teardown(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; + gma_intel_teardown_gmbus(dev); oaktrail_hdmi_teardown(dev); if (!dev_priv->has_gct) psb_intel_destroy_bios(dev); -- cgit v1.2.1 From 49a5d87a894681321d43ed80acb1edf705df0aea Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Fri, 8 Nov 2013 16:00:33 +0100 Subject: drm/gma500/mrst: Don't blindly guess a mode for LVDS Previously we always had something hooked up to LVDS so we tried very hard to get a mode. With the Minnowboard this is no longer the case. If no mode can be found over DDC or the firmware we just ignore LVDS. Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/oaktrail_lvds.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c index e77d7214fca4..4c17c93d8d10 100644 --- a/drivers/gpu/drm/gma500/oaktrail_lvds.c +++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c @@ -218,30 +218,6 @@ static const struct drm_encoder_helper_funcs oaktrail_lvds_helper_funcs = { .commit = oaktrail_lvds_commit, }; -static struct drm_display_mode lvds_configuration_modes[] = { - /* hard coded fixed mode for TPO LTPS LPJ040K001A */ - { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 33264, 800, 836, - 846, 1056, 0, 480, 489, 491, 525, 0, 0) }, - /* hard coded fixed mode for LVDS 800x480 */ - { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 30994, 800, 801, - 802, 1024, 0, 480, 481, 482, 525, 0, 0) }, - /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ - { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072, - 1104, 1184, 0, 600, 603, 604, 608, 0, 0) }, - /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ - { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104, - 1136, 1184, 0, 600, 603, 604, 608, 0, 0) }, - /* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */ - { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124, - 1204, 1312, 0, 600, 607, 610, 621, 0, 0) }, - /* hard coded fixed mode for LVDS 1024x768 */ - { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, - 1184, 1344, 0, 768, 771, 777, 806, 0, 0) }, - /* hard coded fixed mode for LVDS 1366x768 */ - { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430, - 1558, 1664, 0, 768, 769, 770, 776, 0, 0) }, -}; - /* Returns the panel fixed mode from configuration. */ static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev, @@ -303,10 +279,10 @@ static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev, mode_dev->panel_fixed_mode = drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); - /* Then guess */ + + /* If we still got no mode then bail */ if (mode_dev->panel_fixed_mode == NULL) - mode_dev->panel_fixed_mode - = drm_mode_duplicate(dev, &lvds_configuration_modes[2]); + return; drm_mode_set_name(mode_dev->panel_fixed_mode); drm_mode_set_crtcinfo(mode_dev->panel_fixed_mode, 0); -- cgit v1.2.1 From cd3fdbe853c47c5890d5362363b59504c2e5fb5f Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Fri, 8 Nov 2013 16:14:08 +0100 Subject: drm/gma500/mrst: Add SDVO to output init Signed-off-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/oaktrail_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index d7c54b27a473..27d3875d895b 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -40,6 +40,9 @@ static int oaktrail_output_init(struct drm_device *dev) dev_err(dev->dev, "DSI is not supported\n"); if (dev_priv->hdmi_priv) oaktrail_hdmi_init(dev, &dev_priv->mode_dev); + + psb_intel_sdvo_init(dev, SDVOB); + return 0; } -- cgit v1.2.1