summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/gma500
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/gma500')
-rw-r--r--drivers/gpu/drm/gma500/Kconfig41
-rw-r--r--drivers/gpu/drm/gma500/Makefile52
-rw-r--r--drivers/gpu/drm/gma500/accel_2d.c364
-rw-r--r--drivers/gpu/drm/gma500/backlight.c131
-rw-r--r--drivers/gpu/drm/gma500/cdv_device.c205
-rw-r--r--drivers/gpu/drm/gma500/cdv_device.h31
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_crt.c144
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_display.c1039
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_dp.c547
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_hdmi.c208
-rw-r--r--drivers/gpu/drm/gma500/cdv_intel_lvds.c336
-rw-r--r--drivers/gpu/drm/gma500/fbdev.c196
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c706
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.h34
-rw-r--r--drivers/gpu/drm/gma500/gem.c511
-rw-r--r--drivers/gpu/drm/gma500/gem.h51
-rw-r--r--drivers/gpu/drm/gma500/gma_device.c51
-rw-r--r--drivers/gpu/drm/gma500/gma_device.h14
-rw-r--r--drivers/gpu/drm/gma500/gma_display.c811
-rw-r--r--drivers/gpu/drm/gma500/gma_display.h90
-rw-r--r--drivers/gpu/drm/gma500/gtt.c635
-rw-r--r--drivers/gpu/drm/gma500/gtt.h53
-rw-r--r--drivers/gpu/drm/gma500/intel_bios.c82
-rw-r--r--drivers/gpu/drm/gma500/intel_bios.h62
-rw-r--r--drivers/gpu/drm/gma500/intel_gmbus.c126
-rw-r--r--drivers/gpu/drm/gma500/intel_i2c.c57
-rw-r--r--drivers/gpu/drm/gma500/mdfld_device.c551
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_dpi.c1016
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_dpi.h79
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_output.c615
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_output.h377
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c688
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h92
-rw-r--r--drivers/gpu/drm/gma500/mdfld_intel_display.c1054
-rw-r--r--drivers/gpu/drm/gma500/mdfld_output.c74
-rw-r--r--drivers/gpu/drm/gma500/mdfld_output.h77
-rw-r--r--drivers/gpu/drm/gma500/mdfld_tmd_vid.c201
-rw-r--r--drivers/gpu/drm/gma500/mdfld_tpo_vid.c124
-rw-r--r--drivers/gpu/drm/gma500/mid_bios.c54
-rw-r--r--drivers/gpu/drm/gma500/mid_bios.h15
-rw-r--r--drivers/gpu/drm/gma500/mmu.c345
-rw-r--r--drivers/gpu/drm/gma500/mmu.h84
-rw-r--r--drivers/gpu/drm/gma500/oaktrail.h16
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_crtc.c559
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_device.c128
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_hdmi.c115
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c28
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_lvds.c227
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_lvds_i2c.c169
-rw-r--r--drivers/gpu/drm/gma500/opregion.c56
-rw-r--r--drivers/gpu/drm/gma500/power.c196
-rw-r--r--drivers/gpu/drm/gma500/power.h22
-rw-r--r--drivers/gpu/drm/gma500/psb_device.c187
-rw-r--r--drivers/gpu/drm/gma500/psb_device.h12
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c799
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h550
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_display.c1039
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_display.h25
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_drv.h146
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_lvds.c304
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_modes.c51
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_reg.h58
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_sdvo.c439
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.c520
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.h42
-rw-r--r--drivers/gpu/drm/gma500/psb_lid.c94
-rw-r--r--drivers/gpu/drm/gma500/psb_reg.h28
-rw-r--r--drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c829
-rw-r--r--drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h38
69 files changed, 5051 insertions, 13649 deletions
diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig
index 1f6e2dfaaeae..a2acaa699dd5 100644
--- a/drivers/gpu/drm/gma500/Kconfig
+++ b/drivers/gpu/drm/gma500/Kconfig
@@ -1,38 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-only
config DRM_GMA500
- tristate "Intel GMA5/600 KMS Framebuffer"
- depends on DRM && PCI && X86
- select FB_CFB_COPYAREA
- select FB_CFB_FILLRECT
- select FB_CFB_IMAGEBLIT
+ tristate "Intel GMA500/600/3600/3650 KMS Framebuffer"
+ depends on DRM && PCI && X86 && HAS_IOPORT
+ select DRM_CLIENT_SELECTION
select DRM_KMS_HELPER
- select DRM_TTM
+ select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION
+ select I2C
+ select I2C_ALGOBIT
# GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915
select ACPI_VIDEO if ACPI
select BACKLIGHT_CLASS_DEVICE if ACPI
- select VIDEO_OUTPUT_CONTROL if ACPI
select INPUT if ACPI
+ select X86_PLATFORM_DEVICES if ACPI
+ select ACPI_WMI if ACPI
help
Say yes for an experimental 2D KMS framebuffer driver for the
- Intel GMA500 ('Poulsbo') and other Intel IMG based graphics
- devices.
-
-config DRM_GMA600
- bool "Intel GMA600 support (Experimental)"
- depends on DRM_GMA500
- help
- Say yes to include support for GMA600 (Intel Moorestown/Oaktrail)
- platforms with LVDS ports. MIPI is not currently supported.
-
-config DRM_GMA3600
- bool "Intel GMA3600/3650 support (Experimental)"
- depends on DRM_GMA500
- help
- Say yes to include basic support for Intel GMA3600/3650 (Intel
- Cedar Trail) platforms.
-
-config DRM_MEDFIELD
- bool "Intel Medfield support (Experimental)"
- depends on DRM_GMA500 && X86_INTEL_MID
- help
- Say yes to include support for the Intel Medfield platform.
-
+ Intel GMA500 (Poulsbo), Intel GMA600 (Moorestown/Oak Trail) and
+ Intel GMA3600/3650 (Cedar Trail).
diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile
index 7a2d40a5c1e1..58fed80c7392 100644
--- a/drivers/gpu/drm/gma500/Makefile
+++ b/drivers/gpu/drm/gma500/Makefile
@@ -1,52 +1,42 @@
+# SPDX-License-Identifier: GPL-2.0
#
# KMS driver for the GMA500
#
-ccflags-y += -I$(srctree)/include/drm
gma500_gfx-y += \
- accel_2d.o \
backlight.o \
+ cdv_device.o \
+ cdv_intel_crt.o \
+ cdv_intel_display.o \
+ cdv_intel_dp.o \
+ cdv_intel_hdmi.o \
+ cdv_intel_lvds.o \
framebuffer.o \
gem.o \
+ gma_device.o \
+ gma_display.o \
gtt.o \
intel_bios.o \
- intel_i2c.o \
intel_gmbus.o \
+ intel_i2c.o \
+ mid_bios.o \
mmu.o \
+ oaktrail_device.o \
+ oaktrail_crtc.o \
+ oaktrail_hdmi.o \
+ oaktrail_hdmi_i2c.o \
+ oaktrail_lvds.o \
+ oaktrail_lvds_i2c.o \
power.o \
+ psb_device.o \
psb_drv.o \
psb_intel_display.o \
psb_intel_lvds.o \
psb_intel_modes.o \
psb_intel_sdvo.o \
- psb_lid.o \
- psb_irq.o \
- psb_device.o \
- mid_bios.o
-
-gma500_gfx-$(CONFIG_ACPI) += opregion.o \
-
-gma500_gfx-$(CONFIG_DRM_GMA3600) += cdv_device.o \
- cdv_intel_crt.o \
- cdv_intel_display.o \
- cdv_intel_hdmi.o \
- cdv_intel_lvds.o \
- cdv_intel_dp.o
-
-gma500_gfx-$(CONFIG_DRM_GMA600) += oaktrail_device.o \
- oaktrail_crtc.o \
- oaktrail_lvds.o \
- oaktrail_hdmi.o \
- oaktrail_hdmi_i2c.o
+ psb_irq.o
-gma500_gfx-$(CONFIG_DRM_MEDFIELD) += mdfld_device.o \
- mdfld_output.o \
- mdfld_intel_display.o \
- mdfld_dsi_output.o \
- mdfld_dsi_dpi.o \
- mdfld_dsi_pkg_sender.o \
- mdfld_tpo_vid.o \
- mdfld_tmd_vid.o \
- tc35876x-dsi-lvds.o
+gma500_gfx-$(CONFIG_ACPI) += opregion.o
+gma500_gfx-$(CONFIG_DRM_FBDEV_EMULATION) += fbdev.o
obj-$(CONFIG_DRM_GMA500) += gma500_gfx.o
diff --git a/drivers/gpu/drm/gma500/accel_2d.c b/drivers/gpu/drm/gma500/accel_2d.c
deleted file mode 100644
index d5ef1a5793c8..000000000000
--- a/drivers/gpu/drm/gma500/accel_2d.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- **************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "framebuffer.h"
-
-/**
- * psb_spank - reset the 2D engine
- * @dev_priv: our PSB DRM device
- *
- * Soft reset the graphics engine and then reload the necessary registers.
- * We use this at initialisation time but it will become relevant for
- * accelerated X later
- */
-void psb_spank(struct drm_psb_private *dev_priv)
-{
- PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
- _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
- _PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
- _PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
- PSB_RSGX32(PSB_CR_SOFT_RESET);
-
- msleep(1);
-
- PSB_WSGX32(0, PSB_CR_SOFT_RESET);
- wmb();
- PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT,
- PSB_CR_BIF_CTRL);
- wmb();
- (void) PSB_RSGX32(PSB_CR_BIF_CTRL);
-
- msleep(1);
- PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT,
- PSB_CR_BIF_CTRL);
- (void) PSB_RSGX32(PSB_CR_BIF_CTRL);
- PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
-}
-
-/**
- * psb2_2d_wait_available - wait for FIFO room
- * @dev_priv: our DRM device
- * @size: size (in dwords) of the command we want to issue
- *
- * Wait until there is room to load the FIFO with our data. If the
- * device is not responding then reset it
- */
-static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
- unsigned size)
-{
- uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
- unsigned long t = jiffies + HZ;
-
- while (avail < size) {
- avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
- if (time_after(jiffies, t)) {
- psb_spank(dev_priv);
- return -EIO;
- }
- }
- return 0;
-}
-
-/**
- * psb_2d_submit - submit a 2D command
- * @dev_priv: our DRM device
- * @cmdbuf: command to issue
- * @size: length (in dwords)
- *
- * Issue one or more 2D commands to the accelerator. This needs to be
- * serialized later when we add the GEM interfaces for acceleration
- */
-static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
- unsigned size)
-{
- int ret = 0;
- int i;
- unsigned submit_size;
- unsigned long flags;
-
- spin_lock_irqsave(&dev_priv->lock_2d, flags);
- while (size > 0) {
- submit_size = (size < 0x60) ? size : 0x60;
- size -= submit_size;
- ret = psb_2d_wait_available(dev_priv, submit_size);
- if (ret)
- break;
-
- submit_size <<= 2;
-
- for (i = 0; i < submit_size; i += 4)
- PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
-
- (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
- }
- spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
- return ret;
-}
-
-
-/**
- * psb_accel_2d_copy_direction - compute blit order
- * @xdir: X direction of move
- * @ydir: Y direction of move
- *
- * Compute the correct order setings to ensure that an overlapping blit
- * correctly copies all the pixels.
- */
-static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
-{
- if (xdir < 0)
- return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
- PSB_2D_COPYORDER_TR2BL;
- else
- return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
- PSB_2D_COPYORDER_TL2BR;
-}
-
-/**
- * psb_accel_2d_copy - accelerated 2D copy
- * @dev_priv: our DRM device
- * @src_offset in bytes
- * @src_stride in bytes
- * @src_format psb 2D format defines
- * @dst_offset in bytes
- * @dst_stride in bytes
- * @dst_format psb 2D format defines
- * @src_x offset in pixels
- * @src_y offset in pixels
- * @dst_x offset in pixels
- * @dst_y offset in pixels
- * @size_x of the copied area
- * @size_y of the copied area
- *
- * Format and issue a 2D accelerated copy command.
- */
-static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
- uint32_t src_offset, uint32_t src_stride,
- uint32_t src_format, uint32_t dst_offset,
- uint32_t dst_stride, uint32_t dst_format,
- uint16_t src_x, uint16_t src_y,
- uint16_t dst_x, uint16_t dst_y,
- uint16_t size_x, uint16_t size_y)
-{
- uint32_t blit_cmd;
- uint32_t buffer[10];
- uint32_t *buf;
- uint32_t direction;
-
- buf = buffer;
-
- direction =
- psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
-
- if (direction == PSB_2D_COPYORDER_BR2TL ||
- direction == PSB_2D_COPYORDER_TR2BL) {
- src_x += size_x - 1;
- dst_x += size_x - 1;
- }
- if (direction == PSB_2D_COPYORDER_BR2TL ||
- direction == PSB_2D_COPYORDER_BL2TR) {
- src_y += size_y - 1;
- dst_y += size_y - 1;
- }
-
- blit_cmd =
- PSB_2D_BLIT_BH |
- PSB_2D_ROT_NONE |
- PSB_2D_DSTCK_DISABLE |
- PSB_2D_SRCCK_DISABLE |
- PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
-
- *buf++ = PSB_2D_FENCE_BH;
- *buf++ =
- PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
- PSB_2D_DST_STRIDE_SHIFT);
- *buf++ = dst_offset;
- *buf++ =
- PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
- PSB_2D_SRC_STRIDE_SHIFT);
- *buf++ = src_offset;
- *buf++ =
- PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
- (src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
- *buf++ = blit_cmd;
- *buf++ =
- (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
- PSB_2D_DST_YSTART_SHIFT);
- *buf++ =
- (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
- PSB_2D_DST_YSIZE_SHIFT);
- *buf++ = PSB_2D_FLUSH_BH;
-
- return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
-}
-
-/**
- * psbfb_copyarea_accel - copyarea acceleration for /dev/fb
- * @info: our framebuffer
- * @a: copyarea parameters from the framebuffer core
- *
- * Perform a 2D copy via the accelerator
- */
-static void psbfb_copyarea_accel(struct fb_info *info,
- const struct fb_copyarea *a)
-{
- struct psb_fbdev *fbdev = info->par;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
- struct drm_device *dev = psbfb->base.dev;
- struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
- struct drm_psb_private *dev_priv = dev->dev_private;
- uint32_t offset;
- uint32_t stride;
- uint32_t src_format;
- uint32_t dst_format;
-
- if (!fb)
- return;
-
- offset = psbfb->gtt->offset;
- stride = fb->pitches[0];
-
- switch (fb->depth) {
- case 8:
- src_format = PSB_2D_SRC_332RGB;
- dst_format = PSB_2D_DST_332RGB;
- break;
- case 15:
- src_format = PSB_2D_SRC_555RGB;
- dst_format = PSB_2D_DST_555RGB;
- break;
- case 16:
- src_format = PSB_2D_SRC_565RGB;
- dst_format = PSB_2D_DST_565RGB;
- break;
- case 24:
- case 32:
- /* this is wrong but since we don't do blending its okay */
- src_format = PSB_2D_SRC_8888ARGB;
- dst_format = PSB_2D_DST_8888ARGB;
- break;
- default:
- /* software fallback */
- cfb_copyarea(info, a);
- return;
- }
-
- if (!gma_power_begin(dev, false)) {
- cfb_copyarea(info, a);
- return;
- }
- psb_accel_2d_copy(dev_priv,
- offset, stride, src_format,
- offset, stride, dst_format,
- a->sx, a->sy, a->dx, a->dy, a->width, a->height);
- gma_power_end(dev);
-}
-
-/**
- * psbfb_copyarea - 2D copy interface
- * @info: our framebuffer
- * @region: region to copy
- *
- * Copy an area of the framebuffer console either by the accelerator
- * or directly using the cfb helpers according to the request
- */
-void psbfb_copyarea(struct fb_info *info,
- const struct fb_copyarea *region)
-{
- if (unlikely(info->state != FBINFO_STATE_RUNNING))
- return;
-
- /* Avoid the 8 pixel erratum */
- if (region->width == 8 || region->height == 8 ||
- (info->flags & FBINFO_HWACCEL_DISABLED))
- return cfb_copyarea(info, region);
-
- psbfb_copyarea_accel(info, region);
-}
-
-/**
- * psbfb_sync - synchronize 2D
- * @info: our framebuffer
- *
- * Wait for the 2D engine to quiesce so that we can do CPU
- * access to the framebuffer again
- */
-int psbfb_sync(struct fb_info *info)
-{
- 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;
- unsigned long _end = jiffies + DRM_HZ;
- int busy = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&dev_priv->lock_2d, flags);
- /*
- * First idle the 2D engine.
- */
-
- if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
- ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
- goto out;
-
- do {
- busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
- cpu_relax();
- } while (busy && !time_after_eq(jiffies, _end));
-
- if (busy)
- busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
- if (busy)
- goto out;
-
- do {
- busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
- _PSB_C2B_STATUS_BUSY) != 0);
- cpu_relax();
- } while (busy && !time_after_eq(jiffies, _end));
- if (busy)
- busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
- _PSB_C2B_STATUS_BUSY) != 0);
-
-out:
- spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
- return (busy) ? -EBUSY : 0;
-}
diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c
index 143eba3309c5..c8f1716a12d5 100644
--- a/drivers/gpu/drm/gma500/backlight.c
+++ b/drivers/gpu/drm/gma500/backlight.c
@@ -1,94 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* GMA500 Backlight Interface
*
* Copyright (c) 2009-2011, Intel Corporation.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors: Eric Knopp
- *
*/
+#include <linux/backlight.h>
+
+#include <acpi/video.h>
+
+#include <drm/drm_print.h>
+
#include "psb_drv.h"
#include "psb_intel_reg.h"
#include "psb_intel_drv.h"
#include "intel_bios.h"
#include "power.h"
-static void do_gma_backlight_set(struct drm_device *dev)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *dev_priv = dev->dev_private;
- backlight_update_status(dev_priv->backlight_device);
-#endif
-}
-
void gma_backlight_enable(struct drm_device *dev)
{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
dev_priv->backlight_enabled = true;
- if (dev_priv->backlight_device) {
- dev_priv->backlight_device->props.brightness = dev_priv->backlight_level;
- do_gma_backlight_set(dev);
- }
-#endif
+ dev_priv->ops->backlight_set(dev, dev_priv->backlight_level);
}
void gma_backlight_disable(struct drm_device *dev)
{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
dev_priv->backlight_enabled = false;
- if (dev_priv->backlight_device) {
- dev_priv->backlight_device->props.brightness = 0;
- do_gma_backlight_set(dev);
- }
-#endif
+ dev_priv->ops->backlight_set(dev, 0);
}
void gma_backlight_set(struct drm_device *dev, int v)
{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
dev_priv->backlight_level = v;
- if (dev_priv->backlight_device && dev_priv->backlight_enabled) {
- dev_priv->backlight_device->props.brightness = v;
- do_gma_backlight_set(dev);
- }
-#endif
+ if (dev_priv->backlight_enabled)
+ dev_priv->ops->backlight_set(dev, v);
}
+static int gma_backlight_get_brightness(struct backlight_device *bd)
+{
+ struct drm_device *dev = bl_get_data(bd);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
+ if (dev_priv->ops->backlight_get)
+ return dev_priv->ops->backlight_get(dev);
+
+ return dev_priv->backlight_level;
+}
+
+static int gma_backlight_update_status(struct backlight_device *bd)
+{
+ struct drm_device *dev = bl_get_data(bd);
+ int level = backlight_get_brightness(bd);
+
+ /* Percentage 1-100% being valid */
+ if (level < 1)
+ level = 1;
+
+ gma_backlight_set(dev, level);
+ return 0;
+}
+
+static const struct backlight_ops gma_backlight_ops __maybe_unused = {
+ .get_brightness = gma_backlight_get_brightness,
+ .update_status = gma_backlight_update_status,
+};
+
int gma_backlight_init(struct drm_device *dev)
{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct backlight_properties props __maybe_unused = {};
+ int ret;
+
dev_priv->backlight_enabled = true;
- return dev_priv->ops->backlight_init(dev);
-#else
- return 0;
+ dev_priv->backlight_level = 100;
+
+ ret = dev_priv->ops->backlight_init(dev);
+ if (ret)
+ return ret;
+
+ if (!acpi_video_backlight_use_native()) {
+ drm_info(dev, "Skipping %s backlight registration\n",
+ dev_priv->ops->backlight_name);
+ return 0;
+ }
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+ props.brightness = dev_priv->backlight_level;
+ props.max_brightness = PSB_MAX_BRIGHTNESS;
+ props.type = BACKLIGHT_RAW;
+
+ dev_priv->backlight_device =
+ backlight_device_register(dev_priv->ops->backlight_name,
+ dev->dev, dev,
+ &gma_backlight_ops, &props);
+ if (IS_ERR(dev_priv->backlight_device))
+ return PTR_ERR(dev_priv->backlight_device);
#endif
+
+ return 0;
}
void gma_backlight_exit(struct drm_device *dev)
{
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- struct drm_psb_private *dev_priv = dev->dev_private;
- if (dev_priv->backlight_device) {
- dev_priv->backlight_device->props.brightness = 0;
- backlight_update_status(dev_priv->backlight_device);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
+ if (dev_priv->backlight_device)
backlight_device_unregister(dev_priv->backlight_device);
- }
#endif
}
diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c
index 23e14e93991f..fd6ea8998dbe 100644
--- a/drivers/gpu/drm/gma500/cdv_device.c
+++ b/drivers/gpu/drm/gma500/cdv_device.c
@@ -1,31 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-only
/**************************************************************************
* Copyright (c) 2011, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
-#include <linux/backlight.h>
-#include <drm/drmP.h>
+#include <linux/delay.h>
+
#include <drm/drm.h>
-#include <drm/gma_drm.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_print.h>
+
+#include "cdv_device.h"
+#include "gma_device.h"
+#include "intel_bios.h"
#include "psb_drv.h"
-#include "psb_reg.h"
#include "psb_intel_reg.h"
-#include "intel_bios.h"
-#include "cdv_device.h"
+#include "psb_reg.h"
#define VGA_SR_INDEX 0x3c4
#define VGA_SR_DATA 0x3c5
@@ -48,7 +39,7 @@ static void cdv_disable_vga(struct drm_device *dev)
static int cdv_output_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
drm_mode_create_scaling_mode_property(dev);
@@ -72,14 +63,10 @@ static int cdv_output_init(struct drm_device *dev)
return 0;
}
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
/*
* Cedartrail Backlght Interfaces
*/
-static struct backlight_device *cdv_backlight_device;
-
static int cdv_backlight_combination_mode(struct drm_device *dev)
{
return REG_READ(BLC_PWM_CTL2) & PWM_LEGACY_MODE;
@@ -102,32 +89,26 @@ static u32 cdv_get_max_backlight(struct drm_device *dev)
return max;
}
-static int cdv_get_brightness(struct backlight_device *bd)
+static int cdv_get_brightness(struct drm_device *dev)
{
- struct drm_device *dev = bl_get_data(bd);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
u32 val = REG_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
if (cdv_backlight_combination_mode(dev)) {
u8 lbpc;
val &= ~1;
- pci_read_config_byte(dev->pdev, 0xF4, &lbpc);
+ pci_read_config_byte(pdev, 0xF4, &lbpc);
val *= lbpc;
}
return (val * 100)/cdv_get_max_backlight(dev);
-
}
-static int cdv_set_brightness(struct backlight_device *bd)
+static void cdv_set_brightness(struct drm_device *dev, int level)
{
- struct drm_device *dev = bl_get_data(bd);
- int level = bd->props.brightness;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
u32 blc_pwm_ctl;
- /* Percentage 1-100% being valid */
- if (level < 1)
- level = 1;
-
level *= cdv_get_max_backlight(dev);
level /= 100;
@@ -138,44 +119,24 @@ static int cdv_set_brightness(struct backlight_device *bd)
lbpc = level * 0xfe / max + 1;
level /= lbpc;
- pci_write_config_byte(dev->pdev, 0xF4, lbpc);
+ pci_write_config_byte(pdev, 0xF4, lbpc);
}
blc_pwm_ctl = REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
REG_WRITE(BLC_PWM_CTL, (blc_pwm_ctl |
(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
- return 0;
}
-static const struct backlight_ops cdv_ops = {
- .get_brightness = cdv_get_brightness,
- .update_status = cdv_set_brightness,
-};
-
static int cdv_backlight_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct backlight_properties props;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = 100;
- props.type = BACKLIGHT_PLATFORM;
-
- cdv_backlight_device = backlight_device_register("psb-bl",
- NULL, (void *)dev, &cdv_ops, &props);
- if (IS_ERR(cdv_backlight_device))
- return PTR_ERR(cdv_backlight_device);
-
- cdv_backlight_device->props.brightness =
- cdv_get_brightness(cdv_backlight_device);
- backlight_update_status(cdv_backlight_device);
- dev_priv->backlight_device = cdv_backlight_device;
- dev_priv->backlight_enabled = true;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
+ dev_priv->backlight_level = cdv_get_brightness(dev);
+ cdv_set_brightness(dev, dev_priv->backlight_level);
+
return 0;
}
-#endif
-
/*
* Provide the Cedarview specific chip logic and low level methods
* for power management
@@ -184,21 +145,22 @@ static int cdv_backlight_init(struct drm_device *dev)
* for this and the MID devices.
*/
-static inline u32 CDV_MSG_READ32(uint port, uint offset)
+static inline u32 CDV_MSG_READ32(int domain, uint port, uint offset)
{
int mcr = (0x10<<24) | (port << 16) | (offset << 8);
uint32_t ret_val = 0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+ struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0);
pci_write_config_dword(pci_root, 0xD0, mcr);
pci_read_config_dword(pci_root, 0xD4, &ret_val);
pci_dev_put(pci_root);
return ret_val;
}
-static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value)
+static inline void CDV_MSG_WRITE32(int domain, uint port, uint offset,
+ u32 value)
{
int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+ struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0);
pci_write_config_dword(pci_root, 0xD4, value);
pci_write_config_dword(pci_root, 0xD0, mcr);
pci_dev_put(pci_root);
@@ -213,13 +175,15 @@ static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value)
static void cdv_init_pm(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
u32 pwr_cnt;
+ int domain = pci_domain_nr(pdev->bus);
int i;
- dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
+ dev_priv->apm_base = CDV_MSG_READ32(domain, PSB_PUNIT_PORT,
PSB_APMBA) & 0xFFFF;
- dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
+ dev_priv->ospm_base = CDV_MSG_READ32(domain, PSB_PUNIT_PORT,
PSB_OSPMBA) & 0xFFFF;
/* Power status */
@@ -242,6 +206,8 @@ static void cdv_init_pm(struct drm_device *dev)
static void cdv_errata(struct drm_device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+
/* Disable bonus launch.
* CPU and GPU competes for memory and display misses updates and
* flickers. Worst with dual core, dual displays.
@@ -250,7 +216,7 @@ static void cdv_errata(struct drm_device *dev)
* Bonus Launch to work around the issue, by degrading
* performance.
*/
- CDV_MSG_WRITE32(3, 0x30, 0x08027108);
+ CDV_MSG_WRITE32(pci_domain_nr(pdev->bus), 3, 0x30, 0x08027108);
}
/**
@@ -262,13 +228,15 @@ static void cdv_errata(struct drm_device *dev)
*/
static int cdv_save_display_registers(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
struct psb_save_area *regs = &dev_priv->regs;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
dev_dbg(dev->dev, "Saving GPU registers.\n");
- pci_read_config_byte(dev->pdev, 0xF4, &regs->cdv.saveLBB);
+ pci_read_config_byte(pdev, 0xF4, &regs->cdv.saveLBB);
regs->cdv.saveDSPCLK_GATE_D = REG_READ(DSPCLK_GATE_D);
regs->cdv.saveRAMCLK_GATE_D = REG_READ(RAMCLK_GATE_D);
@@ -300,8 +268,10 @@ static int cdv_save_display_registers(struct drm_device *dev)
regs->cdv.saveIER = REG_READ(PSB_INT_ENABLE_R);
regs->cdv.saveIMR = REG_READ(PSB_INT_MASK_R);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter)
connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF);
+ drm_connector_list_iter_end(&conn_iter);
return 0;
}
@@ -316,12 +286,14 @@ static int cdv_save_display_registers(struct drm_device *dev)
*/
static int cdv_restore_display_registers(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
struct psb_save_area *regs = &dev_priv->regs;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
u32 temp;
- pci_write_config_byte(dev->pdev, 0xF4, regs->cdv.saveLBB);
+ pci_write_config_byte(pdev, 0xF4, regs->cdv.saveLBB);
REG_WRITE(DSPCLK_GATE_D, regs->cdv.saveDSPCLK_GATE_D);
REG_WRITE(RAMCLK_GATE_D, regs->cdv.saveRAMCLK_GATE_D);
@@ -374,8 +346,10 @@ static int cdv_restore_display_registers(struct drm_device *dev)
drm_mode_config_reset(dev);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter)
connector->funcs->dpms(connector, DRM_MODE_DPMS_ON);
+ drm_connector_list_iter_end(&conn_iter);
/* Resume the modeset for every activated CRTC */
drm_helper_resume_force_mode(dev);
@@ -384,7 +358,7 @@ static int cdv_restore_display_registers(struct drm_device *dev)
static int cdv_power_down(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 pwr_cnt, pwr_mask, pwr_sts;
int tries = 5;
@@ -406,7 +380,7 @@ static int cdv_power_down(struct drm_device *dev)
static int cdv_power_up(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 pwr_cnt, pwr_mask, pwr_sts;
int tries = 5;
@@ -426,59 +400,22 @@ static int cdv_power_up(struct drm_device *dev)
return 0;
}
-/* FIXME ? - shared with Poulsbo */
-static void cdv_get_core_freq(struct drm_device *dev)
-{
- uint32_t clock;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
- pci_read_config_dword(pci_root, 0xD4, &clock);
- pci_dev_put(pci_root);
-
- switch (clock & 0x07) {
- case 0:
- dev_priv->core_freq = 100;
- break;
- case 1:
- dev_priv->core_freq = 133;
- break;
- case 2:
- dev_priv->core_freq = 150;
- break;
- case 3:
- dev_priv->core_freq = 178;
- break;
- case 4:
- dev_priv->core_freq = 200;
- break;
- case 5:
- case 6:
- case 7:
- dev_priv->core_freq = 266;
- break;
- default:
- dev_priv->core_freq = 0;
- }
-}
-
static void cdv_hotplug_work_func(struct work_struct *work)
{
struct drm_psb_private *dev_priv = container_of(work, struct drm_psb_private,
- hotplug_work);
- struct drm_device *dev = dev_priv->dev;
+ hotplug_work);
+ struct drm_device *dev = &dev_priv->dev;
/* Just fire off a uevent and let userspace tell us what to do */
drm_helper_hpd_irq_event(dev);
-}
+}
/* The core driver has received a hotplug IRQ. We are in IRQ context
so extract the needed information and kick off queued processing */
-
+
static int cdv_hotplug_event(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
schedule_work(&dev_priv->hotplug_work);
REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
return 1;
@@ -494,7 +431,7 @@ static void cdv_hotplug_enable(struct drm_device *dev, bool on)
} else {
REG_WRITE(PORT_HOTPLUG_EN, 0);
REG_WRITE(PORT_HOTPLUG_STAT, REG_READ(PORT_HOTPLUG_STAT));
- }
+ }
}
static const char *force_audio_names[] = {
@@ -506,7 +443,7 @@ static const char *force_audio_names[] = {
void cdv_intel_attach_force_audio_property(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct drm_property *prop;
int i;
@@ -519,7 +456,7 @@ void cdv_intel_attach_force_audio_property(struct drm_connector *connector)
return;
for (i = 0; i < ARRAY_SIZE(force_audio_names); i++)
- drm_property_add_enum(prop, i, i-1, force_audio_names[i]);
+ drm_property_add_enum(prop, i-1, force_audio_names[i]);
dev_priv->force_audio_property = prop;
}
@@ -535,7 +472,7 @@ static const char *broadcast_rgb_names[] = {
void cdv_intel_attach_broadcast_rgb_property(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct drm_property *prop;
int i;
@@ -548,7 +485,7 @@ void cdv_intel_attach_broadcast_rgb_property(struct drm_connector *connector)
return;
for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++)
- drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]);
+ drm_property_add_enum(prop, i, broadcast_rgb_names[i]);
dev_priv->broadcast_rgb_property = prop;
}
@@ -612,13 +549,12 @@ static const struct psb_offset cdv_regmap[2] = {
static int cdv_chip_setup(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
INIT_WORK(&dev_priv->hotplug_work, cdv_hotplug_work_func);
- if (pci_enable_msi(dev->pdev))
- dev_warn(dev->dev, "Enabling MSI failed!\n");
+ dev_priv->use_msi = true;
dev_priv->regmap = cdv_regmap;
- cdv_get_core_freq(dev);
+ gma_get_core_freq(dev);
psb_intel_opregion_init(dev);
psb_intel_init_bios(dev);
cdv_hotplug_enable(dev, false);
@@ -629,30 +565,35 @@ static int cdv_chip_setup(struct drm_device *dev)
const struct psb_ops cdv_chip_ops = {
.name = "GMA3600/3650",
- .accel_2d = 0,
.pipes = 2,
.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,
.errata = cdv_errata,
.crtc_helper = &cdv_intel_helper_funcs,
- .crtc_funcs = &cdv_intel_crtc_funcs,
+ .clock_funcs = &cdv_clock_funcs,
.output_init = cdv_output_init,
.hotplug = cdv_hotplug_event,
.hotplug_enable = cdv_hotplug_enable,
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
.backlight_init = cdv_backlight_init,
-#endif
+ .backlight_get = cdv_get_brightness,
+ .backlight_set = cdv_set_brightness,
+ .backlight_name = "psb-bl",
.init_pm = cdv_init_pm,
.save_regs = cdv_save_display_registers,
.restore_regs = cdv_restore_display_registers,
+ .save_crtc = gma_crtc_save,
+ .restore_crtc = gma_crtc_restore,
.power_down = cdv_power_down,
.power_up = cdv_power_up,
+ .update_wm = cdv_update_wm,
+ .disable_sr = cdv_disable_sr,
};
diff --git a/drivers/gpu/drm/gma500/cdv_device.h b/drivers/gpu/drm/gma500/cdv_device.h
index 9561e17621b3..504d717385cd 100644
--- a/drivers/gpu/drm/gma500/cdv_device.h
+++ b/drivers/gpu/drm/gma500/cdv_device.h
@@ -1,22 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright © 2011 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
+struct drm_crtc;
+struct drm_device;
+struct psb_intel_mode_device;
+
extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs;
-extern const struct drm_crtc_funcs cdv_intel_crtc_funcs;
+extern const struct gma_clock_funcs cdv_clock_funcs;
extern void cdv_intel_crt_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev);
extern void cdv_intel_lvds_init(struct drm_device *dev,
@@ -25,12 +17,5 @@ extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *
int reg);
extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
struct drm_crtc *crtc);
-
-static inline void cdv_intel_wait_for_vblank(struct drm_device *dev)
-{
- /* Wait for 20ms, i.e. one cycle at 50hz. */
- /* FIXME: msleep ?? */
- mdelay(20);
-}
-
-
+extern void cdv_update_wm(struct drm_device *dev, struct drm_crtc *crtc);
+extern void cdv_disable_sr(struct drm_device *dev);
diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c
index 7b8386fc3024..06fe7480e7af 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_crt.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c
@@ -24,16 +24,20 @@
* Eric Anholt <eric@anholt.net>
*/
+#include <linux/delay.h>
#include <linux/i2c.h>
-#include <drm/drmP.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_simple_kms_helper.h>
+#include "cdv_device.h"
#include "intel_bios.h"
+#include "power.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "power.h"
-#include "cdv_device.h"
-#include <linux/pm_runtime.h>
static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
@@ -64,8 +68,8 @@ static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
REG_WRITE(reg, temp);
}
-static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+static enum drm_mode_status cdv_intel_crt_mode_valid(struct drm_connector *connector,
+ const struct drm_display_mode *mode)
{
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
@@ -81,13 +85,6 @@ static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
return MODE_OK;
}
-static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -95,13 +92,12 @@ static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct drm_crtc *crtc = encoder->crtc;
- struct psb_intel_crtc *psb_intel_crtc =
- to_psb_intel_crtc(crtc);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
int dpll_md_reg;
u32 adpa, dpll_md;
u32 adpa_reg;
- if (psb_intel_crtc->pipe == 0)
+ if (gma_crtc->pipe == 0)
dpll_md_reg = DPLL_A_MD;
else
dpll_md_reg = DPLL_B_MD;
@@ -124,7 +120,7 @@ static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
- if (psb_intel_crtc->pipe == 0)
+ if (gma_crtc->pipe == 0)
adpa |= ADPA_PIPE_A_SELECT;
else
adpa |= ADPA_PIPE_B_SELECT;
@@ -133,7 +129,7 @@ static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
}
-/**
+/*
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
*
* \return true if CRT is connected.
@@ -197,20 +193,17 @@ static enum drm_connector_status cdv_intel_crt_detect(
static void cdv_intel_crt_destroy(struct drm_connector *connector)
{
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ struct gma_connector *gma_connector = to_gma_connector(connector);
+ struct gma_i2c_chan *ddc_bus = to_gma_i2c_chan(connector->ddc);
- psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus);
- drm_sysfs_connector_remove(connector);
+ gma_i2c_destroy(ddc_bus);
drm_connector_cleanup(connector);
- kfree(connector);
+ kfree(gma_connector);
}
static int cdv_intel_crt_get_modes(struct drm_connector *connector)
{
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- return psb_intel_ddc_get_modes(connector, &psb_intel_encoder->ddc_bus->adapter);
+ return psb_intel_ddc_get_modes(connector, connector->ddc);
}
static int cdv_intel_crt_set_property(struct drm_connector *connector,
@@ -226,9 +219,8 @@ static int cdv_intel_crt_set_property(struct drm_connector *connector,
static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = {
.dpms = cdv_intel_crt_dpms,
- .mode_fixup = cdv_intel_crt_mode_fixup,
- .prepare = psb_intel_encoder_prepare,
- .commit = psb_intel_encoder_commit,
+ .prepare = gma_encoder_prepare,
+ .commit = gma_encoder_commit,
.mode_set = cdv_intel_crt_mode_set,
};
@@ -244,69 +236,52 @@ static const struct drm_connector_helper_funcs
cdv_intel_crt_connector_helper_funcs = {
.mode_valid = cdv_intel_crt_mode_valid,
.get_modes = cdv_intel_crt_get_modes,
- .best_encoder = psb_intel_best_encoder,
-};
-
-static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = {
- .destroy = cdv_intel_crt_enc_destroy,
+ .best_encoder = gma_best_encoder,
};
void cdv_intel_crt_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev)
{
- struct psb_intel_connector *psb_intel_connector;
- struct psb_intel_encoder *psb_intel_encoder;
+ struct gma_connector *gma_connector;
+ struct gma_encoder *gma_encoder;
+ struct gma_i2c_chan *ddc_bus;
struct drm_connector *connector;
struct drm_encoder *encoder;
+ int ret;
- u32 i2c_reg;
-
- psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
- if (!psb_intel_encoder)
+ gma_encoder = kzalloc(sizeof(struct gma_encoder), GFP_KERNEL);
+ if (!gma_encoder)
return;
- psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
- if (!psb_intel_connector)
- goto failed_connector;
+ gma_connector = kzalloc(sizeof(struct gma_connector), GFP_KERNEL);
+ if (!gma_connector)
+ goto err_free_encoder;
- connector = &psb_intel_connector->base;
+ /* Set up the DDC bus. */
+ ddc_bus = gma_i2c_create(dev, GPIOA, "CRTDDC_A");
+ if (!ddc_bus) {
+ dev_printk(KERN_ERR, dev->dev, "DDC bus registration failed.\n");
+ goto err_free_connector;
+ }
+
+ connector = &gma_connector->base;
connector->polled = DRM_CONNECTOR_POLL_HPD;
- drm_connector_init(dev, connector,
- &cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+ ret = drm_connector_init_with_ddc(dev, connector,
+ &cdv_intel_crt_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA,
+ &ddc_bus->base);
+ if (ret)
+ goto err_ddc_destroy;
- encoder = &psb_intel_encoder->base;
- drm_encoder_init(dev, encoder,
- &cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC);
+ encoder = &gma_encoder->base;
+ ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC);
+ if (ret)
+ goto err_connector_cleanup;
- psb_intel_connector_attach_encoder(psb_intel_connector,
- psb_intel_encoder);
+ gma_connector_attach_encoder(gma_connector, gma_encoder);
- /* Set up the DDC bus. */
- i2c_reg = GPIOA;
- /* Remove the following code for CDV */
- /*
- if (dev_priv->crt_ddc_bus != 0)
- i2c_reg = dev_priv->crt_ddc_bus;
- }*/
- psb_intel_encoder->ddc_bus = psb_intel_i2c_create(dev,
- i2c_reg, "CRTDDC_A");
- if (!psb_intel_encoder->ddc_bus) {
- dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
- "failed.\n");
- goto failed_ddc;
- }
-
- psb_intel_encoder->type = INTEL_OUTPUT_ANALOG;
- /*
- psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT);
- psb_intel_output->crtc_mask = (1 << 0) | (1 << 1);
- */
+ gma_encoder->type = INTEL_OUTPUT_ANALOG;
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
@@ -314,14 +289,15 @@ void cdv_intel_crt_init(struct drm_device *dev,
drm_connector_helper_add(connector,
&cdv_intel_crt_connector_helper_funcs);
- drm_sysfs_connector_add(connector);
-
return;
-failed_ddc:
- drm_encoder_cleanup(&psb_intel_encoder->base);
- drm_connector_cleanup(&psb_intel_connector->base);
- kfree(psb_intel_connector);
-failed_connector:
- kfree(psb_intel_encoder);
+
+err_connector_cleanup:
+ drm_connector_cleanup(&gma_connector->base);
+err_ddc_destroy:
+ gma_i2c_destroy(ddc_bus);
+err_free_connector:
+ kfree(gma_connector);
+err_free_encoder:
+ kfree(gma_encoder);
return;
}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c
index 82430ad8ba62..5942a9d46b02 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_display.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
@@ -1,72 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright © 2006-2011 Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Eric Anholt <eric@anholt.net>
*/
+#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+
+#include "cdv_device.h"
#include "framebuffer.h"
+#include "gma_display.h"
+#include "power.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "psb_intel_display.h"
-#include "power.h"
-#include "cdv_device.h"
-
-struct cdv_intel_range_t {
- int min, max;
-};
-
-struct cdv_intel_p2_t {
- int dot_limit;
- int p2_slow, p2_fast;
-};
-
-struct cdv_intel_clock_t {
- /* given values */
- int n;
- int m1, m2;
- int p1, p2;
- /* derived values */
- int dot;
- int vco;
- int m;
- int p;
-};
+static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
+ struct drm_crtc *crtc, int target,
+ int refclk, struct gma_clock_t *best_clock);
-#define INTEL_P2_NUM 2
-
-struct cdv_intel_limit_t {
- struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1;
- struct cdv_intel_p2_t p2;
- bool (*find_pll)(const struct cdv_intel_limit_t *, struct drm_crtc *,
- int, int, struct cdv_intel_clock_t *);
-};
-
-static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit,
- struct drm_crtc *crtc, int target, int refclk,
- struct cdv_intel_clock_t *best_clock);
-static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target,
- int refclk,
- struct cdv_intel_clock_t *best_clock);
#define CDV_LIMIT_SINGLE_LVDS_96 0
#define CDV_LIMIT_SINGLE_LVDS_100 1
@@ -75,7 +33,7 @@ static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct
#define CDV_LIMIT_DP_27 4
#define CDV_LIMIT_DP_100 5
-static const struct cdv_intel_limit_t cdv_intel_limits[] = {
+static const struct gma_limit_t cdv_intel_limits[] = {
{ /* CDV_SINGLE_LVDS_96MHz */
.dot = {.min = 20000, .max = 115500},
.vco = {.min = 1800000, .max = 3600000},
@@ -85,9 +43,8 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
.m2 = {.min = 58, .max = 158},
.p = {.min = 28, .max = 140},
.p1 = {.min = 2, .max = 10},
- .p2 = {.dot_limit = 200000,
- .p2_slow = 14, .p2_fast = 14},
- .find_pll = cdv_intel_find_best_PLL,
+ .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
+ .find_pll = gma_find_best_pll,
},
{ /* CDV_SINGLE_LVDS_100MHz */
.dot = {.min = 20000, .max = 115500},
@@ -102,7 +59,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
* is 80-224Mhz. Prefer single channel as much as possible.
*/
.p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
- .find_pll = cdv_intel_find_best_PLL,
+ .find_pll = gma_find_best_pll,
},
{ /* CDV_DAC_HDMI_27MHz */
.dot = {.min = 20000, .max = 400000},
@@ -114,7 +71,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
.p = {.min = 5, .max = 90},
.p1 = {.min = 1, .max = 9},
.p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
- .find_pll = cdv_intel_find_best_PLL,
+ .find_pll = gma_find_best_pll,
},
{ /* CDV_DAC_HDMI_96MHz */
.dot = {.min = 20000, .max = 400000},
@@ -126,7 +83,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
.p = {.min = 5, .max = 100},
.p1 = {.min = 1, .max = 10},
.p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
- .find_pll = cdv_intel_find_best_PLL,
+ .find_pll = gma_find_best_pll,
},
{ /* CDV_DP_27MHz */
.dot = {.min = 160000, .max = 272000},
@@ -151,7 +108,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
.p1 = {.min = 1, .max = 10},
.p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10},
.find_pll = cdv_intel_find_dp_pll,
- }
+ }
};
#define _wait_for(COND, MS, W) ({ \
@@ -255,10 +212,10 @@ void cdv_sb_reset(struct drm_device *dev)
*/
static int
cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
- struct cdv_intel_clock_t *clock, bool is_lvds, u32 ddi_select)
+ struct gma_clock_t *clock, bool is_lvds, u32 ddi_select)
{
- struct psb_intel_crtc *psb_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_crtc->pipe;
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ int pipe = gma_crtc->pipe;
u32 m, n_vco, p;
int ret = 0;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
@@ -280,7 +237,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
/* We don't know what the other fields of these regs are, so
* leave them in place.
*/
- /*
+ /*
* The BIT 14:13 of 0x8010/0x8030 is used to select the ref clk
* for the pipe A/B. Display spec 1.06 has wrong definition.
* Correct definition is like below:
@@ -291,7 +248,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
*
* if DPLLA sets 01 and DPLLB sets 02, both use clk from DPLLA
*
- */
+ */
ret = cdv_sb_read(dev, ref_sfr, &ref_value);
if (ret)
return ret;
@@ -405,31 +362,11 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
return 0;
}
-/*
- * Returns whether any encoder on the specified pipe is of the specified type
- */
-static bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct drm_connector *l_entry;
-
- list_for_each_entry(l_entry, &mode_config->connector_list, head) {
- if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(l_entry);
- if (psb_intel_encoder->type == type)
- return true;
- }
- }
- return false;
-}
-
-static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
- int refclk)
+static const struct gma_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
+ int refclk)
{
- const struct cdv_intel_limit_t *limit;
- if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+ const struct gma_limit_t *limit;
+ if (gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
/*
* Now only single-channel LVDS is supported on CDV. If it is
* incorrect, please add the dual-channel LVDS.
@@ -438,8 +375,8 @@ static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
else
limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
- } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
- psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+ } else if (gma_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+ gma_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
if (refclk == 27000)
limit = &cdv_intel_limits[CDV_LIMIT_DP_27];
else
@@ -454,8 +391,7 @@ static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
}
/* m1 is reserved as 0 in CDV, n is a ring counter */
-static void cdv_intel_clock(struct drm_device *dev,
- int refclk, struct cdv_intel_clock_t *clock)
+static void cdv_intel_clock(int refclk, struct gma_clock_t *clock)
{
clock->m = clock->m2 + 2;
clock->p = clock->p1 * clock->p2;
@@ -463,94 +399,18 @@ static void cdv_intel_clock(struct drm_device *dev,
clock->dot = clock->vco / clock->p;
}
-
-#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; }
-static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc,
- const struct cdv_intel_limit_t *limit,
- struct cdv_intel_clock_t *clock)
+static bool cdv_intel_find_dp_pll(const struct gma_limit_t *limit,
+ struct drm_crtc *crtc, int target,
+ int refclk,
+ struct gma_clock_t *best_clock)
{
- if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
- INTELPllInvalid("p1 out of range\n");
- if (clock->p < limit->p.min || limit->p.max < clock->p)
- INTELPllInvalid("p out of range\n");
- /* unnecessary to check the range of m(m1/M2)/n again */
- if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
- INTELPllInvalid("vco out of range\n");
- /* XXX: We may need to be checking "Dot clock"
- * depending on the multiplier, connector, etc.,
- * rather than just a single range.
- */
- if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
- INTELPllInvalid("dot out of range\n");
-
- return true;
-}
-
-static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit,
- struct drm_crtc *crtc, int target, int refclk,
- struct cdv_intel_clock_t *best_clock)
-{
- struct drm_device *dev = crtc->dev;
- struct cdv_intel_clock_t clock;
- int err = target;
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ struct gma_clock_t clock;
+ memset(&clock, 0, sizeof(clock));
- if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
- (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
- /*
- * For LVDS, if the panel is on, just rely on its current
- * settings for dual-channel. We haven't figured out how to
- * reliably set up different single/dual channel state, if we
- * even can.
- */
- if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
- LVDS_CLKB_POWER_UP)
- clock.p2 = limit->p2.p2_fast;
- else
- clock.p2 = limit->p2.p2_slow;
- } else {
- if (target < limit->p2.dot_limit)
- clock.p2 = limit->p2.p2_slow;
- else
- clock.p2 = limit->p2.p2_fast;
- }
-
- memset(best_clock, 0, sizeof(*best_clock));
- clock.m1 = 0;
- /* m1 is reserved as 0 in CDV, n is a ring counter.
- So skip the m1 loop */
- for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
- for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max;
- clock.m2++) {
- for (clock.p1 = limit->p1.min;
- clock.p1 <= limit->p1.max;
- clock.p1++) {
- int this_err;
-
- cdv_intel_clock(dev, refclk, &clock);
-
- if (!cdv_intel_PLL_is_valid(crtc,
- limit, &clock))
- continue;
-
- this_err = abs(clock.dot - target);
- if (this_err < err) {
- *best_clock = clock;
- err = this_err;
- }
- }
- }
- }
-
- return err != target;
-}
-
-static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target,
- int refclk,
- struct cdv_intel_clock_t *best_clock)
-{
- struct cdv_intel_clock_t clock;
- if (refclk == 27000) {
+ switch (refclk) {
+ case 27000:
if (target < 200000) {
clock.p1 = 2;
clock.p2 = 10;
@@ -564,7 +424,9 @@ static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct
clock.m1 = 0;
clock.m2 = 98;
}
- } else if (refclk == 100000) {
+ break;
+
+ case 100000:
if (target < 200000) {
clock.p1 = 2;
clock.p2 = 10;
@@ -578,89 +440,15 @@ static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct
clock.m1 = 0;
clock.m2 = 133;
}
- } else
- return false;
- clock.m = clock.m2 + 2;
- clock.p = clock.p1 * clock.p2;
- clock.vco = (refclk * clock.m) / clock.n;
- clock.dot = clock.vco / clock.p;
- memcpy(best_clock, &clock, sizeof(struct cdv_intel_clock_t));
- return true;
-}
-
-static int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
- 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 psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- int pipe = psb_intel_crtc->pipe;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- unsigned long start, offset;
- u32 dspcntr;
- int ret = 0;
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- /* no fb bound */
- if (!crtc->fb) {
- dev_err(dev->dev, "No FB bound\n");
- goto psb_intel_pipe_cleaner;
- }
-
-
- /* We are displaying this buffer, make sure it is actually loaded
- into the GTT */
- ret = psb_gtt_pin(psbfb->gtt);
- if (ret < 0)
- goto psb_intel_pipe_set_base_exit;
- start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
- REG_WRITE(map->stride, crtc->fb->pitches[0]);
-
- dspcntr = REG_READ(map->cntr);
- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
- switch (crtc->fb->bits_per_pixel) {
- case 8:
- dspcntr |= DISPPLANE_8BPP;
- break;
- case 16:
- if (crtc->fb->depth == 15)
- dspcntr |= DISPPLANE_15_16BPP;
- else
- dspcntr |= DISPPLANE_16BPP;
- break;
- case 24:
- case 32:
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
break;
+
default:
- dev_err(dev->dev, "Unknown color depth\n");
- ret = -EINVAL;
- goto psb_intel_pipe_set_base_exit;
+ return false;
}
- REG_WRITE(map->cntr, dspcntr);
-
- dev_dbg(dev->dev,
- "Writing base %08lX %08lX %d %d\n", start, offset, x, y);
- REG_WRITE(map->base, offset);
- REG_READ(map->base);
- REG_WRITE(map->surf, start);
- REG_READ(map->surf);
-
-psb_intel_pipe_cleaner:
- /* If there was a previous display we can now unpin it */
- if (old_fb)
- psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
-
-psb_intel_pipe_set_base_exit:
- gma_power_end(dev);
- return ret;
+ gma_crtc->clock_funcs->clock(refclk, &clock);
+ memcpy(best_clock, &clock, sizeof(struct gma_clock_t));
+ return true;
}
#define FIFO_PIPEA (1 << 0)
@@ -669,61 +457,18 @@ psb_intel_pipe_set_base_exit:
static bool cdv_intel_pipe_enabled(struct drm_device *dev, int pipe)
{
struct drm_crtc *crtc;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = NULL;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = NULL;
crtc = dev_priv->pipe_to_crtc_mapping[pipe];
- psb_intel_crtc = to_psb_intel_crtc(crtc);
+ gma_crtc = to_gma_crtc(crtc);
- if (crtc->fb == NULL || !psb_intel_crtc->active)
+ if (crtc->primary->fb == NULL || !gma_crtc->active)
return false;
return true;
}
-static bool cdv_intel_single_pipe_active (struct drm_device *dev)
-{
- uint32_t pipe_enabled = 0;
-
- if (cdv_intel_pipe_enabled(dev, 0))
- pipe_enabled |= FIFO_PIPEA;
-
- if (cdv_intel_pipe_enabled(dev, 1))
- pipe_enabled |= FIFO_PIPEB;
-
-
- DRM_DEBUG_KMS("pipe enabled %x\n", pipe_enabled);
-
- if (pipe_enabled == FIFO_PIPEA || pipe_enabled == FIFO_PIPEB)
- return true;
- else
- return false;
-}
-
-static bool is_pipeb_lvds(struct drm_device *dev, struct drm_crtc *crtc)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct drm_connector *connector;
-
- if (psb_intel_crtc->pipe != 1)
- return false;
-
- list_for_each_entry(connector, &mode_config->connector_list, head) {
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
-
- if (!connector->encoder
- || connector->encoder->crtc != crtc)
- continue;
-
- if (psb_intel_encoder->type == INTEL_OUTPUT_LVDS)
- return true;
- }
-
- return false;
-}
-
-static void cdv_intel_disable_self_refresh (struct drm_device *dev)
+void cdv_disable_sr(struct drm_device *dev)
{
if (REG_READ(FW_BLC_SELF) & FW_BLC_SELF_EN) {
@@ -731,7 +476,7 @@ static void cdv_intel_disable_self_refresh (struct drm_device *dev)
REG_WRITE(FW_BLC_SELF, (REG_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN));
REG_READ(FW_BLC_SELF);
- cdv_intel_wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
/* Cedarview workaround to write ovelay plane, which force to leave
* MAX_FIFO state.
@@ -739,15 +484,18 @@ static void cdv_intel_disable_self_refresh (struct drm_device *dev)
REG_WRITE(OV_OVADD, 0/*dev_priv->ovl_offset*/);
REG_READ(OV_OVADD);
- cdv_intel_wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
}
}
-static void cdv_intel_update_watermark (struct drm_device *dev, struct drm_crtc *crtc)
+void cdv_update_wm(struct drm_device *dev, struct drm_crtc *crtc)
{
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
- if (cdv_intel_single_pipe_active(dev)) {
+ /* Is only one pipe enabled? */
+ if (cdv_intel_pipe_enabled(dev, 0) ^ cdv_intel_pipe_enabled(dev, 1)) {
u32 fw;
fw = REG_READ(DSPFW1);
@@ -768,7 +516,9 @@ static void cdv_intel_update_watermark (struct drm_device *dev, struct drm_crtc
/* ignore FW4 */
- if (is_pipeb_lvds(dev, crtc)) {
+ /* Is pipe b lvds ? */
+ if (gma_crtc->pipe == 1 &&
+ gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
REG_WRITE(DSPFW5, 0x00040330);
} else {
fw = (3 << DSP_PLANE_B_FIFO_WM1_SHIFT) |
@@ -780,12 +530,12 @@ static void cdv_intel_update_watermark (struct drm_device *dev, struct drm_crtc
REG_WRITE(DSPFW6, 0x10);
- cdv_intel_wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
/* enable self-refresh for single pipe active */
REG_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
REG_READ(FW_BLC_SELF);
- cdv_intel_wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
} else {
@@ -797,217 +547,13 @@ static void cdv_intel_update_watermark (struct drm_device *dev, struct drm_crtc
REG_WRITE(DSPFW5, 0x01010101);
REG_WRITE(DSPFW6, 0x1d0);
- cdv_intel_wait_for_vblank(dev);
-
- cdv_intel_disable_self_refresh(dev);
-
- }
-}
-
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-static void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int palreg = PALETTE_A;
- int i;
-
- /* The clocks have to be on to load the palette. */
- if (!crtc->enabled)
- return;
-
- switch (psb_intel_crtc->pipe) {
- case 0:
- break;
- case 1:
- palreg = PALETTE_B;
- break;
- case 2:
- palreg = PALETTE_C;
- break;
- default:
- dev_err(dev->dev, "Illegal Pipe Number.\n");
- return;
- }
-
- if (gma_power_begin(dev, false)) {
- for (i = 0; i < 256; i++) {
- REG_WRITE(palreg + 4 * i,
- ((psb_intel_crtc->lut_r[i] +
- psb_intel_crtc->lut_adj[i]) << 16) |
- ((psb_intel_crtc->lut_g[i] +
- psb_intel_crtc->lut_adj[i]) << 8) |
- (psb_intel_crtc->lut_b[i] +
- psb_intel_crtc->lut_adj[i]));
- }
- gma_power_end(dev);
- } else {
- for (i = 0; i < 256; i++) {
- dev_priv->regs.pipe[0].palette[i] =
- ((psb_intel_crtc->lut_r[i] +
- psb_intel_crtc->lut_adj[i]) << 16) |
- ((psb_intel_crtc->lut_g[i] +
- psb_intel_crtc->lut_adj[i]) << 8) |
- (psb_intel_crtc->lut_b[i] +
- psb_intel_crtc->lut_adj[i]);
- }
-
- }
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- u32 temp;
-
- /* XXX: When our outputs are all unaware of DPMS modes other than off
- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
- */
- cdv_intel_disable_self_refresh(dev);
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- if (psb_intel_crtc->active)
- break;
-
- psb_intel_crtc->active = true;
-
- /* 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);
- }
-
- /* Jim Bish - switch plan and pipe per scott */
- /* 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));
- }
-
- udelay(150);
+ gma_wait_for_vblank(dev);
- /* Enable the pipe */
- temp = REG_READ(map->conf);
- if ((temp & PIPEACONF_ENABLE) == 0)
- REG_WRITE(map->conf, temp | PIPEACONF_ENABLE);
-
- temp = REG_READ(map->status);
- temp &= ~(0xFFFF);
- temp |= PIPE_FIFO_UNDERRUN;
- REG_WRITE(map->status, temp);
- REG_READ(map->status);
-
- cdv_intel_crtc_load_lut(crtc);
-
- /* Give the overlay scaler a chance to enable
- * if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, true); TODO */
- break;
- case DRM_MODE_DPMS_OFF:
- if (!psb_intel_crtc->active)
- break;
-
- psb_intel_crtc->active = false;
-
- /* Give the overlay scaler a chance to disable
- * 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);
-
- /* Jim Bish - changed pipe/plane here as well. */
-
- drm_vblank_off(dev, pipe);
- /* Wait for vblank for the disable to take effect */
- cdv_intel_wait_for_vblank(dev);
-
- /* 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 vblank for the disable to take effect. */
- cdv_intel_wait_for_vblank(dev);
-
- udelay(150);
-
- /* 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);
- }
-
- 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);
- break;
+ dev_priv->ops->disable_sr(dev);
}
- cdv_intel_update_watermark(dev, crtc);
- /*Set FIFO Watermarks*/
- REG_WRITE(DSPARB, 0x3F3E);
-}
-
-static void cdv_intel_crtc_prepare(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void cdv_intel_crtc_commit(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
}
-
-/**
+/*
* Return the pipe currently connected to the panel fitter,
* or -1 if the panel fitter is not present or not in use
*/
@@ -1030,43 +576,38 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
struct drm_framebuffer *old_fb)
{
struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ int pipe = gma_crtc->pipe;
const struct psb_offset *map = &dev_priv->regmap[pipe];
int refclk;
- struct cdv_intel_clock_t clock;
+ struct gma_clock_t clock;
u32 dpll = 0, dspcntr, pipeconf;
bool ok;
- bool is_crt = false, is_lvds = false, is_tv = false;
- bool is_hdmi = false, is_dp = false;
- struct drm_mode_config *mode_config = &dev->mode_config;
+ bool is_lvds = false;
+ bool is_dp = false;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
- const struct cdv_intel_limit_t *limit;
+ const struct gma_limit_t *limit;
u32 ddi_select = 0;
bool is_edp = false;
- list_for_each_entry(connector, &mode_config->connector_list, head) {
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ struct gma_encoder *gma_encoder =
+ gma_attached_encoder(connector);
if (!connector->encoder
|| connector->encoder->crtc != crtc)
continue;
- ddi_select = psb_intel_encoder->ddi_select;
- switch (psb_intel_encoder->type) {
+ ddi_select = gma_encoder->ddi_select;
+ switch (gma_encoder->type) {
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
- case INTEL_OUTPUT_TVOUT:
- is_tv = true;
- break;
case INTEL_OUTPUT_ANALOG:
- is_crt = true;
- break;
case INTEL_OUTPUT_HDMI:
- is_hdmi = true;
break;
case INTEL_OUTPUT_DISPLAYPORT:
is_dp = true;
@@ -1075,10 +616,14 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
is_edp = true;
break;
default:
+ drm_connector_list_iter_end(&conn_iter);
DRM_ERROR("invalid output type.\n");
return 0;
}
+
+ break;
}
+ drm_connector_list_iter_end(&conn_iter);
if (dev_priv->dplla_96mhz)
/* low-end sku, 96/100 mhz */
@@ -1094,7 +639,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
* for DP/eDP. When using SSC clock, the ref clk is 100MHz.Otherwise
* it will be 27MHz. From the VBIOS code it seems that the pipe A choose
* 27MHz for DP/eDP while the Pipe B chooses the 100MHz.
- */
+ */
if (pipe == 0)
refclk = 27000;
else
@@ -1107,23 +652,18 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
}
drm_mode_debug_printmodeline(adjusted_mode);
-
- limit = cdv_intel_limit(crtc, refclk);
+
+ limit = gma_crtc->clock_funcs->limit(crtc, refclk);
ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk,
&clock);
if (!ok) {
- dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
+ DRM_ERROR("Couldn't find PLL settings for mode! target: %d, actual: %d",
+ adjusted_mode->clock, clock.dot);
return 0;
}
dpll = DPLL_VGA_MODE_DIS;
- if (is_tv) {
- /* XXX: just matching BIOS for now */
-/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
- dpll |= 3;
- }
-/* dpll |= PLL_REF_INPUT_DREFCLK; */
if (is_dp || is_edp) {
cdv_intel_dp_set_m_n(crtc, mode, adjusted_mode);
@@ -1168,7 +708,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
pipeconf |= PIPE_6BPC;
} else
pipeconf |= PIPE_8BPC;
-
+
/* Set up the display plane register */
dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -1264,355 +804,27 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
REG_WRITE(map->conf, pipeconf);
REG_READ(map->conf);
- cdv_intel_wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
REG_WRITE(map->cntr, dspcntr);
/* Flush the plane changes */
{
- struct drm_crtc_helper_funcs *crtc_funcs =
+ const struct drm_crtc_helper_funcs *crtc_funcs =
crtc->helper_private;
crtc_funcs->mode_set_base(crtc, x, y, old_fb);
}
- cdv_intel_wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
return 0;
}
-
-/**
- * Save HW states of giving crtc
- */
-static void cdv_intel_crtc_save(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
- const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
- uint32_t paletteReg;
- int i;
-
- if (!crtc_state) {
- dev_dbg(dev->dev, "No CRTC state found\n");
- return;
- }
-
- crtc_state->saveDSPCNTR = REG_READ(map->cntr);
- crtc_state->savePIPECONF = REG_READ(map->conf);
- crtc_state->savePIPESRC = REG_READ(map->src);
- crtc_state->saveFP0 = REG_READ(map->fp0);
- crtc_state->saveFP1 = REG_READ(map->fp1);
- crtc_state->saveDPLL = REG_READ(map->dpll);
- crtc_state->saveHTOTAL = REG_READ(map->htotal);
- crtc_state->saveHBLANK = REG_READ(map->hblank);
- crtc_state->saveHSYNC = REG_READ(map->hsync);
- crtc_state->saveVTOTAL = REG_READ(map->vtotal);
- crtc_state->saveVBLANK = REG_READ(map->vblank);
- crtc_state->saveVSYNC = REG_READ(map->vsync);
- crtc_state->saveDSPSTRIDE = REG_READ(map->stride);
-
- /*NOTE: DSPSIZE DSPPOS only for psb*/
- crtc_state->saveDSPSIZE = REG_READ(map->size);
- crtc_state->saveDSPPOS = REG_READ(map->pos);
-
- crtc_state->saveDSPBASE = REG_READ(map->base);
-
- DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
- crtc_state->saveDSPCNTR,
- crtc_state->savePIPECONF,
- crtc_state->savePIPESRC,
- crtc_state->saveFP0,
- crtc_state->saveFP1,
- crtc_state->saveDPLL,
- crtc_state->saveHTOTAL,
- crtc_state->saveHBLANK,
- crtc_state->saveHSYNC,
- crtc_state->saveVTOTAL,
- crtc_state->saveVBLANK,
- crtc_state->saveVSYNC,
- crtc_state->saveDSPSTRIDE,
- crtc_state->saveDSPSIZE,
- crtc_state->saveDSPPOS,
- crtc_state->saveDSPBASE
- );
-
- paletteReg = map->palette;
- for (i = 0; i < 256; ++i)
- crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
-}
-
-/**
- * Restore HW states of giving crtc
- */
-static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
- const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
- uint32_t paletteReg;
- int i;
-
- if (!crtc_state) {
- dev_dbg(dev->dev, "No crtc state\n");
- return;
- }
-
- DRM_DEBUG(
- "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
- REG_READ(map->cntr),
- REG_READ(map->conf),
- REG_READ(map->src),
- REG_READ(map->fp0),
- REG_READ(map->fp1),
- REG_READ(map->dpll),
- REG_READ(map->htotal),
- REG_READ(map->hblank),
- REG_READ(map->hsync),
- REG_READ(map->vtotal),
- REG_READ(map->vblank),
- REG_READ(map->vsync),
- REG_READ(map->stride),
- REG_READ(map->size),
- REG_READ(map->pos),
- REG_READ(map->base)
- );
-
- DRM_DEBUG(
- "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
- crtc_state->saveDSPCNTR,
- crtc_state->savePIPECONF,
- crtc_state->savePIPESRC,
- crtc_state->saveFP0,
- crtc_state->saveFP1,
- crtc_state->saveDPLL,
- crtc_state->saveHTOTAL,
- crtc_state->saveHBLANK,
- crtc_state->saveHSYNC,
- crtc_state->saveVTOTAL,
- crtc_state->saveVBLANK,
- crtc_state->saveVSYNC,
- crtc_state->saveDSPSTRIDE,
- crtc_state->saveDSPSIZE,
- crtc_state->saveDSPPOS,
- crtc_state->saveDSPBASE
- );
-
-
- if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
- REG_WRITE(map->dpll,
- crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
- REG_READ(map->dpll);
- DRM_DEBUG("write dpll: %x\n",
- REG_READ(map->dpll));
- udelay(150);
- }
-
- REG_WRITE(map->fp0, crtc_state->saveFP0);
- REG_READ(map->fp0);
-
- REG_WRITE(map->fp1, crtc_state->saveFP1);
- REG_READ(map->fp1);
-
- REG_WRITE(map->dpll, crtc_state->saveDPLL);
- REG_READ(map->dpll);
- udelay(150);
-
- REG_WRITE(map->htotal, crtc_state->saveHTOTAL);
- REG_WRITE(map->hblank, crtc_state->saveHBLANK);
- REG_WRITE(map->hsync, crtc_state->saveHSYNC);
- REG_WRITE(map->vtotal, crtc_state->saveVTOTAL);
- REG_WRITE(map->vblank, crtc_state->saveVBLANK);
- REG_WRITE(map->vsync, crtc_state->saveVSYNC);
- REG_WRITE(map->stride, crtc_state->saveDSPSTRIDE);
-
- REG_WRITE(map->size, crtc_state->saveDSPSIZE);
- REG_WRITE(map->pos, crtc_state->saveDSPPOS);
-
- REG_WRITE(map->src, crtc_state->savePIPESRC);
- REG_WRITE(map->base, crtc_state->saveDSPBASE);
- REG_WRITE(map->conf, crtc_state->savePIPECONF);
-
- cdv_intel_wait_for_vblank(dev);
-
- REG_WRITE(map->cntr, crtc_state->saveDSPCNTR);
- REG_WRITE(map->base, crtc_state->saveDSPBASE);
-
- cdv_intel_wait_for_vblank(dev);
-
- paletteReg = map->palette;
- for (i = 0; i < 256; ++i)
- REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
-}
-
-static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file_priv,
- uint32_t handle,
- uint32_t width, uint32_t height)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
- uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
- uint32_t temp;
- size_t addr = 0;
- struct gtt_range *gt;
- struct drm_gem_object *obj;
- int ret = 0;
-
- /* if we want to turn of the cursor ignore width and height */
- if (!handle) {
- /* turn off the cursor */
- temp = CURSOR_MODE_DISABLE;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, 0);
- gma_power_end(dev);
- }
-
- /* 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 = NULL;
- }
-
- return 0;
- }
-
- /* Currently we only support 64x64 cursors */
- if (width != 64 || height != 64) {
- dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
- return -EINVAL;
- }
-
- obj = drm_gem_object_lookup(dev, file_priv, handle);
- if (!obj)
- return -ENOENT;
-
- if (obj->size < width * height * 4) {
- dev_dbg(dev->dev, "buffer is to small\n");
- ret = -ENOMEM;
- goto unref_cursor;
- }
-
- gt = container_of(obj, struct gtt_range, gem);
-
- /* Pin the memory into the GTT */
- ret = psb_gtt_pin(gt);
- if (ret) {
- dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
- goto unref_cursor;
- }
-
- addr = gt->offset; /* Or resource.start ??? */
-
- psb_intel_crtc->cursor_addr = addr;
-
- temp = 0;
- /* set the pipe for the cursor */
- temp |= (pipe << 28);
- temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, addr);
- gma_power_end(dev);
- }
-
- /* 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;
- return ret;
-
-unref_cursor:
- drm_gem_object_unreference(obj);
- return ret;
-}
-
-static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t temp = 0;
- uint32_t adder;
-
-
- if (x < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
- x = -x;
- }
- if (y < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
- y = -y;
- }
-
- temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
- temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-
- adder = psb_intel_crtc->cursor_addr;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
- REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
- gma_power_end(dev);
- }
- return 0;
-}
-
-static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
- u16 *green, u16 *blue, uint32_t start, uint32_t size)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int i;
- int end = (start + size > 256) ? 256 : start + size;
-
- for (i = start; i < end; i++) {
- psb_intel_crtc->lut_r[i] = red[i] >> 8;
- psb_intel_crtc->lut_g[i] = green[i] >> 8;
- psb_intel_crtc->lut_b[i] = blue[i] >> 8;
- }
-
- cdv_intel_crtc_load_lut(crtc);
-}
-
-static int cdv_crtc_set_config(struct drm_mode_set *set)
-{
- int ret = 0;
- struct drm_device *dev = set->crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->rpm_enabled)
- return drm_crtc_helper_set_config(set);
-
- pm_runtime_forbid(&dev->pdev->dev);
-
- ret = drm_crtc_helper_set_config(set);
-
- pm_runtime_allow(&dev->pdev->dev);
-
- return ret;
-}
-
/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
/* FIXME: why are we using this, should it be cdv_ in this tree ? */
-static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock)
+static void i8xx_clock(int refclk, struct gma_clock_t *clock)
{
clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
clock->p = clock->p1 * clock->p2;
@@ -1624,13 +836,13 @@ static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock)
static int cdv_intel_crtc_clock_get(struct drm_device *dev,
struct drm_crtc *crtc)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ int pipe = gma_crtc->pipe;
const struct psb_offset *map = &dev_priv->regmap[pipe];
u32 dpll;
u32 fp;
- struct cdv_intel_clock_t clock;
+ struct gma_clock_t clock;
bool is_lvds;
struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
@@ -1703,9 +915,9 @@ static int cdv_intel_crtc_clock_get(struct drm_device *dev,
struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
struct drm_crtc *crtc)
{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ int pipe = gma_crtc->pipe;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
const struct psb_offset *map = &dev_priv->regmap[pipe];
struct drm_display_mode *mode;
@@ -1747,44 +959,17 @@ struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
return mode;
}
-static void cdv_intel_crtc_destroy(struct drm_crtc *crtc)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-
- kfree(psb_intel_crtc->crtc_state);
- drm_crtc_cleanup(crtc);
- kfree(psb_intel_crtc);
-}
-
-static void cdv_intel_crtc_disable(struct drm_crtc *crtc)
-{
- struct gtt_range *gt;
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-
- if (crtc->fb) {
- gt = to_psb_fb(crtc->fb)->gtt;
- psb_gtt_unpin(gt);
- }
-}
-
const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
- .dpms = cdv_intel_crtc_dpms,
- .mode_fixup = cdv_intel_crtc_mode_fixup,
+ .dpms = gma_crtc_dpms,
.mode_set = cdv_intel_crtc_mode_set,
- .mode_set_base = cdv_intel_pipe_set_base,
- .prepare = cdv_intel_crtc_prepare,
- .commit = cdv_intel_crtc_commit,
- .disable = cdv_intel_crtc_disable,
+ .mode_set_base = gma_pipe_set_base,
+ .prepare = gma_crtc_prepare,
+ .commit = gma_crtc_commit,
+ .disable = gma_crtc_disable,
};
-const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
- .save = cdv_intel_crtc_save,
- .restore = cdv_intel_crtc_restore,
- .cursor_set = cdv_intel_crtc_cursor_set,
- .cursor_move = cdv_intel_crtc_cursor_move,
- .gamma_set = cdv_intel_crtc_gamma_set,
- .set_config = cdv_crtc_set_config,
- .destroy = cdv_intel_crtc_destroy,
+const struct gma_clock_funcs cdv_clock_funcs = {
+ .clock = cdv_intel_clock,
+ .limit = cdv_intel_limit,
+ .pll_is_valid = gma_pll_is_valid,
};
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index 88d9ef6b5b4a..54bf626f0524 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -26,15 +26,210 @@
*/
#include <linux/i2c.h>
-#include <linux/slab.h>
#include <linux/module.h>
-#include <drm/drmP.h>
+#include <linux/slab.h>
+
+#include <drm/display/drm_dp_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include "gma_display.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include <drm/drm_dp_helper.h>
+
+/**
+ * struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp
+ * aux algorithm
+ * @running: set by the algo indicating whether an i2c is ongoing or whether
+ * the i2c bus is quiescent
+ * @address: i2c target address for the currently ongoing transfer
+ * @aux_ch: driver callback to transfer a single byte of the i2c payload
+ */
+struct i2c_algo_dp_aux_data {
+ bool running;
+ u16 address;
+ int (*aux_ch) (struct i2c_adapter *adapter,
+ int mode, uint8_t write_byte,
+ uint8_t *read_byte);
+};
+
+/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
+static int
+i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
+ uint8_t write_byte, uint8_t *read_byte)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+ int ret;
+
+ ret = (*algo_data->aux_ch)(adapter, mode,
+ write_byte, read_byte);
+ return ret;
+}
+
+/*
+ * I2C over AUX CH
+ */
+
+/*
+ * Send the address. If the I2C link is running, this 'restarts'
+ * the connection with the new address, this is used for doing
+ * a write followed by a read (as needed for DDC)
+ */
+static int
+i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+ int mode = MODE_I2C_START;
+
+ if (reading)
+ mode |= MODE_I2C_READ;
+ else
+ mode |= MODE_I2C_WRITE;
+ algo_data->address = address;
+ algo_data->running = true;
+ return i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+}
+
+/*
+ * Stop the I2C transaction. This closes out the link, sending
+ * a bare address packet with the MOT bit turned off
+ */
+static void
+i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+ int mode = MODE_I2C_STOP;
+
+ if (reading)
+ mode |= MODE_I2C_READ;
+ else
+ mode |= MODE_I2C_WRITE;
+ if (algo_data->running) {
+ (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+ algo_data->running = false;
+ }
+}
+
+/*
+ * Write a single byte to the current I2C address, the
+ * I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+
+ if (!algo_data->running)
+ return -EIO;
+
+ return i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
+}
+
+/*
+ * Read a single byte from the current I2C address, the
+ * I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
+{
+ struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+
+ if (!algo_data->running)
+ return -EIO;
+
+ return i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
+}
+
+static int
+i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
+ struct i2c_msg *msgs,
+ int num)
+{
+ int ret = 0;
+ bool reading = false;
+ int m;
+ int b;
+
+ for (m = 0; m < num; m++) {
+ u16 len = msgs[m].len;
+ u8 *buf = msgs[m].buf;
+ reading = (msgs[m].flags & I2C_M_RD) != 0;
+ ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
+ if (ret < 0)
+ break;
+ if (reading) {
+ for (b = 0; b < len; b++) {
+ ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
+ if (ret < 0)
+ break;
+ }
+ } else {
+ for (b = 0; b < len; b++) {
+ ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
+ if (ret < 0)
+ break;
+ }
+ }
+ if (ret < 0)
+ break;
+ }
+ if (ret >= 0)
+ ret = num;
+ i2c_algo_dp_aux_stop(adapter, reading);
+ DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
+ return ret;
+}
+
+static u32
+i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+ I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm i2c_dp_aux_algo = {
+ .master_xfer = i2c_algo_dp_aux_xfer,
+ .functionality = i2c_algo_dp_aux_functionality,
+};
+
+static void
+i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
+{
+ (void) i2c_algo_dp_aux_address(adapter, 0, false);
+ (void) i2c_algo_dp_aux_stop(adapter, false);
+}
+
+static int
+i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
+{
+ adapter->algo = &i2c_dp_aux_algo;
+ adapter->retries = 3;
+ i2c_dp_aux_reset_bus(adapter);
+ return 0;
+}
+
+/*
+ * FIXME: This is the old dp aux helper, gma500 is the last driver that needs to
+ * be ported over to the new helper code in drm_dp_helper.c like i915 or radeon.
+ */
+static int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
+{
+ int error;
+
+ error = i2c_dp_aux_prepare_bus(adapter);
+ if (error)
+ return error;
+ error = i2c_add_adapter(adapter);
+ return error;
+}
#define _wait_for(COND, MS, W) ({ \
unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
@@ -47,11 +242,10 @@
if (W && !in_dbg_master()) msleep(W); \
} \
ret__; \
-})
+})
#define wait_for(COND, MS) _wait_for(COND, MS, 1)
-#define DP_LINK_STATUS_SIZE 6
#define DP_LINK_CHECK_TIMEOUT (10 * 1000)
#define DP_LINK_CONFIGURATION_SIZE 9
@@ -68,7 +262,7 @@ struct cdv_intel_dp {
uint8_t link_bw;
uint8_t lane_count;
uint8_t dpcd[4];
- struct psb_intel_encoder *encoder;
+ struct gma_encoder *encoder;
struct i2c_adapter adapter;
struct i2c_algo_dp_aux_data algo;
uint8_t train_set[4];
@@ -109,23 +303,23 @@ static uint32_t dp_vswing_premph_table[] = {
};
/**
* is_edp - is the given port attached to an eDP panel (either CPU or PCH)
- * @intel_dp: DP struct
+ * @encoder: GMA encoder struct
*
* If a CPU or PCH DP output is attached to an eDP panel, this function
* will return true, and false otherwise.
*/
-static bool is_edp(struct psb_intel_encoder *encoder)
+static bool is_edp(struct gma_encoder *encoder)
{
return encoder->type == INTEL_OUTPUT_EDP;
}
-static void cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder);
-static void cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder);
-static void cdv_intel_dp_link_down(struct psb_intel_encoder *encoder);
+static void cdv_intel_dp_start_link_train(struct gma_encoder *encoder);
+static void cdv_intel_dp_complete_link_train(struct gma_encoder *encoder);
+static void cdv_intel_dp_link_down(struct gma_encoder *encoder);
static int
-cdv_intel_dp_max_lane_count(struct psb_intel_encoder *encoder)
+cdv_intel_dp_max_lane_count(struct gma_encoder *encoder)
{
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
int max_lane_count = 4;
@@ -143,7 +337,7 @@ cdv_intel_dp_max_lane_count(struct psb_intel_encoder *encoder)
}
static int
-cdv_intel_dp_max_link_bw(struct psb_intel_encoder *encoder)
+cdv_intel_dp_max_link_bw(struct gma_encoder *encoder)
{
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
@@ -180,7 +374,7 @@ cdv_intel_dp_max_data_rate(int max_link_clock, int max_lanes)
return (max_link_clock * max_lanes * 19) / 20;
}
-static void cdv_intel_edp_panel_vdd_on(struct psb_intel_encoder *intel_encoder)
+static void cdv_intel_edp_panel_vdd_on(struct gma_encoder *intel_encoder)
{
struct drm_device *dev = intel_encoder->base.dev;
struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
@@ -189,7 +383,7 @@ static void cdv_intel_edp_panel_vdd_on(struct psb_intel_encoder *intel_encoder)
if (intel_dp->panel_on) {
DRM_DEBUG_KMS("Skip VDD on because of panel on\n");
return;
- }
+ }
DRM_DEBUG_KMS("\n");
pp = REG_READ(PP_CONTROL);
@@ -200,7 +394,7 @@ static void cdv_intel_edp_panel_vdd_on(struct psb_intel_encoder *intel_encoder)
msleep(intel_dp->panel_power_up_delay);
}
-static void cdv_intel_edp_panel_vdd_off(struct psb_intel_encoder *intel_encoder)
+static void cdv_intel_edp_panel_vdd_off(struct gma_encoder *intel_encoder)
{
struct drm_device *dev = intel_encoder->base.dev;
u32 pp;
@@ -215,7 +409,7 @@ static void cdv_intel_edp_panel_vdd_off(struct psb_intel_encoder *intel_encoder)
}
/* Returns true if the panel was already on when called */
-static bool cdv_intel_edp_panel_on(struct psb_intel_encoder *intel_encoder)
+static bool cdv_intel_edp_panel_on(struct gma_encoder *intel_encoder)
{
struct drm_device *dev = intel_encoder->base.dev;
struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
@@ -236,13 +430,13 @@ static bool cdv_intel_edp_panel_on(struct psb_intel_encoder *intel_encoder)
DRM_DEBUG_KMS("Error in Powering up eDP panel, status %x\n", REG_READ(PP_STATUS));
intel_dp->panel_on = false;
} else
- intel_dp->panel_on = true;
+ intel_dp->panel_on = true;
msleep(intel_dp->panel_power_up_delay);
return false;
}
-static void cdv_intel_edp_panel_off (struct psb_intel_encoder *intel_encoder)
+static void cdv_intel_edp_panel_off (struct gma_encoder *intel_encoder)
{
struct drm_device *dev = intel_encoder->base.dev;
u32 pp, idle_off_mask = PP_ON ;
@@ -252,7 +446,7 @@ static void cdv_intel_edp_panel_off (struct psb_intel_encoder *intel_encoder)
pp = REG_READ(PP_CONTROL);
- if ((pp & POWER_TARGET_ON) == 0)
+ if ((pp & POWER_TARGET_ON) == 0)
return;
intel_dp->panel_on = false;
@@ -267,14 +461,14 @@ static void cdv_intel_edp_panel_off (struct psb_intel_encoder *intel_encoder)
DRM_DEBUG_KMS("PP_STATUS %x\n", REG_READ(PP_STATUS));
if (wait_for((REG_READ(PP_STATUS) & idle_off_mask) == 0, 1000)) {
- DRM_DEBUG_KMS("Error in turning off Panel\n");
+ DRM_DEBUG_KMS("Error in turning off Panel\n");
}
msleep(intel_dp->panel_power_cycle_delay);
DRM_DEBUG_KMS("Over\n");
}
-static void cdv_intel_edp_backlight_on (struct psb_intel_encoder *intel_encoder)
+static void cdv_intel_edp_backlight_on (struct gma_encoder *intel_encoder)
{
struct drm_device *dev = intel_encoder->base.dev;
u32 pp;
@@ -294,7 +488,7 @@ static void cdv_intel_edp_backlight_on (struct psb_intel_encoder *intel_encoder)
gma_backlight_enable(dev);
}
-static void cdv_intel_edp_backlight_off (struct psb_intel_encoder *intel_encoder)
+static void cdv_intel_edp_backlight_off (struct gma_encoder *intel_encoder)
{
struct drm_device *dev = intel_encoder->base.dev;
struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
@@ -310,15 +504,15 @@ static void cdv_intel_edp_backlight_off (struct psb_intel_encoder *intel_encoder
msleep(intel_dp->backlight_off_delay);
}
-static int
+static enum drm_mode_status
cdv_intel_dp_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+ const struct drm_display_mode *mode)
{
- struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector);
+ struct gma_encoder *encoder = gma_attached_encoder(connector);
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
int max_link_clock = cdv_intel_dp_link_clock(cdv_intel_dp_max_link_bw(encoder));
int max_lanes = cdv_intel_dp_max_lane_count(encoder);
- struct drm_psb_private *dev_priv = connector->dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(connector->dev);
if (is_edp(encoder) && intel_dp->panel_fixed_mode) {
if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
@@ -338,7 +532,7 @@ cdv_intel_dp_mode_valid(struct drm_connector *connector,
if (cdv_intel_dp_link_required(mode->clock, 24)
> cdv_intel_dp_max_data_rate(max_link_clock, max_lanes))
return MODE_CLOCK_HIGH;
-
+
}
if (mode->clock < 10000)
return MODE_CLOCK_LOW;
@@ -370,7 +564,7 @@ unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
}
static int
-cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder,
+cdv_intel_dp_aux_ch(struct gma_encoder *encoder,
uint8_t *send, int send_bytes,
uint8_t *recv, int recv_size)
{
@@ -409,7 +603,7 @@ cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder,
for (i = 0; i < send_bytes; i += 4)
REG_WRITE(ch_data + i,
pack_aux(send + i, send_bytes - i));
-
+
/* Send the command and wait for it to complete */
REG_WRITE(ch_ctl,
DP_AUX_CH_CTL_SEND_BUSY |
@@ -426,7 +620,7 @@ cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder,
break;
udelay(100);
}
-
+
/* Clear done status and any errors */
REG_WRITE(ch_ctl,
status |
@@ -462,7 +656,7 @@ cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder,
DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
if (recv_bytes > recv_size)
recv_bytes = recv_size;
-
+
for (i = 0; i < recv_bytes; i += 4)
unpack_aux(REG_READ(ch_data + i),
recv + i, recv_bytes - i);
@@ -472,7 +666,7 @@ cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder,
/* Write data to the aux channel in native mode */
static int
-cdv_intel_dp_aux_native_write(struct psb_intel_encoder *encoder,
+cdv_intel_dp_aux_native_write(struct gma_encoder *encoder,
uint16_t address, uint8_t *send, int send_bytes)
{
int ret;
@@ -482,7 +676,7 @@ cdv_intel_dp_aux_native_write(struct psb_intel_encoder *encoder,
if (send_bytes > 16)
return -1;
- msg[0] = AUX_NATIVE_WRITE << 4;
+ msg[0] = DP_AUX_NATIVE_WRITE << 4;
msg[1] = address >> 8;
msg[2] = address & 0xff;
msg[3] = send_bytes - 1;
@@ -492,9 +686,10 @@ cdv_intel_dp_aux_native_write(struct psb_intel_encoder *encoder,
ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes, &ack, 1);
if (ret < 0)
return ret;
- if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+ ack >>= 4;
+ if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
break;
- else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+ else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
udelay(100);
else
return -EIO;
@@ -504,7 +699,7 @@ cdv_intel_dp_aux_native_write(struct psb_intel_encoder *encoder,
/* Write a single byte to the aux channel in native mode */
static int
-cdv_intel_dp_aux_native_write_1(struct psb_intel_encoder *encoder,
+cdv_intel_dp_aux_native_write_1(struct gma_encoder *encoder,
uint16_t address, uint8_t byte)
{
return cdv_intel_dp_aux_native_write(encoder, address, &byte, 1);
@@ -512,7 +707,7 @@ cdv_intel_dp_aux_native_write_1(struct psb_intel_encoder *encoder,
/* read bytes from a native aux channel */
static int
-cdv_intel_dp_aux_native_read(struct psb_intel_encoder *encoder,
+cdv_intel_dp_aux_native_read(struct gma_encoder *encoder,
uint16_t address, uint8_t *recv, int recv_bytes)
{
uint8_t msg[4];
@@ -522,7 +717,7 @@ cdv_intel_dp_aux_native_read(struct psb_intel_encoder *encoder,
uint8_t ack;
int ret;
- msg[0] = AUX_NATIVE_READ << 4;
+ msg[0] = DP_AUX_NATIVE_READ << 4;
msg[1] = address >> 8;
msg[2] = address & 0xff;
msg[3] = recv_bytes - 1;
@@ -537,12 +732,12 @@ cdv_intel_dp_aux_native_read(struct psb_intel_encoder *encoder,
return -EPROTO;
if (ret < 0)
return ret;
- ack = reply[0];
- if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+ ack = reply[0] >> 4;
+ if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK) {
memcpy(recv, reply + 1, ret - 1);
return ret - 1;
}
- else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+ else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
udelay(100);
else
return -EIO;
@@ -557,7 +752,7 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
struct cdv_intel_dp *intel_dp = container_of(adapter,
struct cdv_intel_dp,
adapter);
- struct psb_intel_encoder *encoder = intel_dp->encoder;
+ struct gma_encoder *encoder = intel_dp->encoder;
uint16_t address = algo_data->address;
uint8_t msg[5];
uint8_t reply[2];
@@ -568,12 +763,12 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
/* Set up the command byte */
if (mode & MODE_I2C_READ)
- msg[0] = AUX_I2C_READ << 4;
+ msg[0] = DP_AUX_I2C_READ << 4;
else
- msg[0] = AUX_I2C_WRITE << 4;
+ msg[0] = DP_AUX_I2C_WRITE << 4;
if (!(mode & MODE_I2C_STOP))
- msg[0] |= AUX_I2C_MOT << 4;
+ msg[0] |= DP_AUX_I2C_MOT << 4;
msg[1] = address >> 8;
msg[2] = address;
@@ -605,16 +800,16 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
return ret;
}
- switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
- case AUX_NATIVE_REPLY_ACK:
+ switch ((reply[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK) {
+ case DP_AUX_NATIVE_REPLY_ACK:
/* I2C-over-AUX Reply field is only valid
* when paired with AUX ACK.
*/
break;
- case AUX_NATIVE_REPLY_NACK:
+ case DP_AUX_NATIVE_REPLY_NACK:
DRM_DEBUG_KMS("aux_ch native nack\n");
return -EREMOTEIO;
- case AUX_NATIVE_REPLY_DEFER:
+ case DP_AUX_NATIVE_REPLY_DEFER:
udelay(100);
continue;
default:
@@ -623,16 +818,16 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
return -EREMOTEIO;
}
- switch (reply[0] & AUX_I2C_REPLY_MASK) {
- case AUX_I2C_REPLY_ACK:
+ switch ((reply[0] >> 4) & DP_AUX_I2C_REPLY_MASK) {
+ case DP_AUX_I2C_REPLY_ACK:
if (mode == MODE_I2C_READ) {
*read_byte = reply[1];
}
return reply_bytes - 1;
- case AUX_I2C_REPLY_NACK:
+ case DP_AUX_I2C_REPLY_NACK:
DRM_DEBUG_KMS("aux_i2c nack\n");
return -EREMOTEIO;
- case AUX_I2C_REPLY_DEFER:
+ case DP_AUX_I2C_REPLY_DEFER:
DRM_DEBUG_KMS("aux_i2c defer\n");
udelay(100);
break;
@@ -647,7 +842,8 @@ cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
}
static int
-cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_encoder *encoder, const char *name)
+cdv_intel_dp_i2c_init(struct gma_connector *connector,
+ struct gma_encoder *encoder, const char *name)
{
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
int ret;
@@ -660,22 +856,20 @@ cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_en
memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter));
intel_dp->adapter.owner = THIS_MODULE;
- intel_dp->adapter.class = I2C_CLASS_DDC;
- strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
- intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
+ strscpy(intel_dp->adapter.name, name);
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);
ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
if (is_edp(encoder))
cdv_intel_edp_panel_vdd_off(encoder);
-
+
return ret;
}
-void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
+static void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
struct drm_display_mode *adjusted_mode)
{
adjusted_mode->hdisplay = fixed_mode->hdisplay;
@@ -697,8 +891,8 @@ static bool
cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
- struct drm_psb_private *dev_priv = encoder->dev->dev_private;
- struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(encoder->dev);
+ struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
int lane_count, clock;
int max_lane_count = cdv_intel_dp_max_lane_count(intel_encoder);
@@ -789,25 +983,25 @@ cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_encoder *encoder;
- struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
int lane_count = 4, bpp = 24;
struct cdv_intel_dp_m_n m_n;
- int pipe = intel_crtc->pipe;
+ int pipe = gma_crtc->pipe;
/*
* Find the lane count in the intel_encoder private
*/
list_for_each_entry(encoder, &mode_config->encoder_list, head) {
- struct psb_intel_encoder *intel_encoder;
+ struct gma_encoder *intel_encoder;
struct cdv_intel_dp *intel_dp;
if (encoder->crtc != crtc)
continue;
- intel_encoder = to_psb_intel_encoder(encoder);
+ intel_encoder = to_gma_encoder(encoder);
intel_dp = intel_encoder->dev_priv;
if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
lane_count = intel_dp->lane_count;
@@ -841,9 +1035,9 @@ static void
cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
- struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+ struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
struct drm_crtc *crtc = encoder->crtc;
- struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
struct drm_device *dev = encoder->dev;
@@ -885,7 +1079,7 @@ cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode
}
/* CPT DP's pipe select is decided in TRANS_DP_CTL */
- if (intel_crtc->pipe == 1)
+ if (gma_crtc->pipe == 1)
intel_dp->DP |= DP_PIPEB_SELECT;
REG_WRITE(intel_dp->output_reg, (intel_dp->DP | DP_PORT_EN));
@@ -900,7 +1094,7 @@ cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode
else
pfit_control = 0;
- pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
+ pfit_control |= gma_crtc->pipe << PFIT_PIPE_SHIFT;
REG_WRITE(PFIT_CONTROL, pfit_control);
}
@@ -908,7 +1102,7 @@ cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode
/* If the sink supports it, try to set the power state appropriately */
-static void cdv_intel_dp_sink_dpms(struct psb_intel_encoder *encoder, int mode)
+static void cdv_intel_dp_sink_dpms(struct gma_encoder *encoder, int mode)
{
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
int ret, i;
@@ -940,7 +1134,7 @@ static void cdv_intel_dp_sink_dpms(struct psb_intel_encoder *encoder, int mode)
static void cdv_intel_dp_prepare(struct drm_encoder *encoder)
{
- struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+ struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
int edp = is_edp(intel_encoder);
if (edp) {
@@ -957,7 +1151,7 @@ static void cdv_intel_dp_prepare(struct drm_encoder *encoder)
static void cdv_intel_dp_commit(struct drm_encoder *encoder)
{
- struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+ struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
int edp = is_edp(intel_encoder);
if (edp)
@@ -971,7 +1165,7 @@ static void cdv_intel_dp_commit(struct drm_encoder *encoder)
static void
cdv_intel_dp_dpms(struct drm_encoder *encoder, int mode)
{
- struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+ struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
struct drm_device *dev = encoder->dev;
uint32_t dp_reg = REG_READ(intel_dp->output_reg);
@@ -1006,7 +1200,7 @@ cdv_intel_dp_dpms(struct drm_encoder *encoder, int mode)
* cases where the sink may still be asleep.
*/
static bool
-cdv_intel_dp_aux_native_read_retry(struct psb_intel_encoder *encoder, uint16_t address,
+cdv_intel_dp_aux_native_read_retry(struct gma_encoder *encoder, uint16_t address,
uint8_t *recv, int recv_bytes)
{
int ret, i;
@@ -1031,7 +1225,7 @@ cdv_intel_dp_aux_native_read_retry(struct psb_intel_encoder *encoder, uint16_t a
* link status information
*/
static bool
-cdv_intel_dp_get_link_status(struct psb_intel_encoder *encoder)
+cdv_intel_dp_get_link_status(struct gma_encoder *encoder)
{
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
return cdv_intel_dp_aux_native_read_retry(encoder,
@@ -1073,39 +1267,10 @@ cdv_intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZ
return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
}
+#define CDV_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_LEVEL_3
-#if 0
-static char *voltage_names[] = {
- "0.4V", "0.6V", "0.8V", "1.2V"
-};
-static char *pre_emph_names[] = {
- "0dB", "3.5dB", "6dB", "9.5dB"
-};
-static char *link_train_names[] = {
- "pattern 1", "pattern 2", "idle", "off"
-};
-#endif
-
-#define CDV_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200
-/*
-static uint8_t
-cdv_intel_dp_pre_emphasis_max(uint8_t voltage_swing)
-{
- switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
- case DP_TRAIN_VOLTAGE_SWING_400:
- return DP_TRAIN_PRE_EMPHASIS_6;
- case DP_TRAIN_VOLTAGE_SWING_600:
- return DP_TRAIN_PRE_EMPHASIS_6;
- case DP_TRAIN_VOLTAGE_SWING_800:
- return DP_TRAIN_PRE_EMPHASIS_3_5;
- case DP_TRAIN_VOLTAGE_SWING_1200:
- default:
- return DP_TRAIN_PRE_EMPHASIS_0;
- }
-}
-*/
static void
-cdv_intel_get_adjust_train(struct psb_intel_encoder *encoder)
+cdv_intel_get_adjust_train(struct gma_encoder *encoder)
{
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
uint8_t v = 0;
@@ -1121,13 +1286,13 @@ cdv_intel_get_adjust_train(struct psb_intel_encoder *encoder)
if (this_p > p)
p = this_p;
}
-
+
if (v >= CDV_DP_VOLTAGE_MAX)
v = CDV_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
if (p == DP_TRAIN_PRE_EMPHASIS_MASK)
p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
+
for (lane = 0; lane < 4; lane++)
intel_dp->train_set[lane] = v | p;
}
@@ -1164,7 +1329,7 @@ cdv_intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_c
DP_LANE_CHANNEL_EQ_DONE|\
DP_LANE_SYMBOL_LOCKED)
static bool
-cdv_intel_channel_eq_ok(struct psb_intel_encoder *encoder)
+cdv_intel_channel_eq_ok(struct gma_encoder *encoder)
{
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
uint8_t lane_align;
@@ -1184,11 +1349,10 @@ cdv_intel_channel_eq_ok(struct psb_intel_encoder *encoder)
}
static bool
-cdv_intel_dp_set_link_train(struct psb_intel_encoder *encoder,
+cdv_intel_dp_set_link_train(struct gma_encoder *encoder,
uint32_t dp_reg_value,
uint8_t dp_train_pat)
{
-
struct drm_device *dev = encoder->base.dev;
int ret;
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
@@ -1211,10 +1375,9 @@ cdv_intel_dp_set_link_train(struct psb_intel_encoder *encoder,
static bool
-cdv_intel_dplink_set_level(struct psb_intel_encoder *encoder,
+cdv_intel_dplink_set_level(struct gma_encoder *encoder,
uint8_t dp_train_pat)
{
-
int ret;
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
@@ -1232,7 +1395,7 @@ cdv_intel_dplink_set_level(struct psb_intel_encoder *encoder,
}
static void
-cdv_intel_dp_set_vswing_premph(struct psb_intel_encoder *encoder, uint8_t signal_level)
+cdv_intel_dp_set_vswing_premph(struct gma_encoder *encoder, uint8_t signal_level)
{
struct drm_device *dev = encoder->base.dev;
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
@@ -1273,7 +1436,7 @@ cdv_intel_dp_set_vswing_premph(struct psb_intel_encoder *encoder, uint8_t signal
cdv_sb_write(dev, ddi_reg->VSwing2, dp_vswing_premph_table[index]);
/* ;gfx_dpio_set_reg(0x814c, 0x40802040) */
- if ((vswing + premph) == DP_TRAIN_VOLTAGE_SWING_1200)
+ if ((vswing + premph) == DP_TRAIN_VOLTAGE_SWING_LEVEL_3)
cdv_sb_write(dev, ddi_reg->VSwing3, 0x70802040);
else
cdv_sb_write(dev, ddi_reg->VSwing3, 0x40802040);
@@ -1292,13 +1455,13 @@ cdv_intel_dp_set_vswing_premph(struct psb_intel_encoder *encoder, uint8_t signal
/* ;gfx_dpio_set_reg(0x8124, 0x00004000) */
index = 2 * premph + 1;
cdv_sb_write(dev, ddi_reg->PreEmph2, dp_vswing_premph_table[index]);
- return;
+ return;
}
/* Enable corresponding port and start training pattern 1 */
static void
-cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder)
+cdv_intel_dp_start_link_train(struct gma_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
@@ -1311,13 +1474,13 @@ cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder)
DP |= DP_PORT_EN;
DP &= ~DP_LINK_TRAIN_MASK;
-
- reg = DP;
+
+ reg = DP;
reg |= DP_LINK_TRAIN_PAT_1;
/* Enable output, wait for it to become active */
REG_WRITE(intel_dp->output_reg, reg);
REG_READ(intel_dp->output_reg);
- psb_intel_wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
DRM_DEBUG_KMS("Link config\n");
/* Write the link configuration data */
@@ -1331,8 +1494,7 @@ cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder)
clock_recovery = false;
DRM_DEBUG_KMS("Start train\n");
- reg = DP | DP_LINK_TRAIN_PAT_1;
-
+ reg = DP | DP_LINK_TRAIN_PAT_1;
for (;;) {
/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
@@ -1385,18 +1547,17 @@ cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder)
}
if (!clock_recovery) {
- DRM_DEBUG_KMS("failure in DP patter 1 training, train set %x\n", intel_dp->train_set[0]);
+ DRM_DEBUG_KMS("failure in DP pattern 1 training, train set %x\n", intel_dp->train_set[0]);
}
-
+
intel_dp->DP = DP;
}
static void
-cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder)
+cdv_intel_dp_complete_link_train(struct gma_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
- bool channel_eq = false;
int tries, cr_tries;
u32 reg;
uint32_t DP = intel_dp->DP;
@@ -1404,10 +1565,9 @@ cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder)
/* channel equalization */
tries = 0;
cr_tries = 0;
- channel_eq = false;
DRM_DEBUG_KMS("\n");
- reg = DP | DP_LINK_TRAIN_PAT_2;
+ reg = DP | DP_LINK_TRAIN_PAT_2;
for (;;) {
@@ -1450,7 +1610,6 @@ cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder)
if (cdv_intel_channel_eq_ok(encoder)) {
DRM_DEBUG_KMS("PT2 train is done\n");
- channel_eq = true;
break;
}
@@ -1478,7 +1637,7 @@ cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder)
}
static void
-cdv_intel_dp_link_down(struct psb_intel_encoder *encoder)
+cdv_intel_dp_link_down(struct gma_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
@@ -1502,8 +1661,7 @@ cdv_intel_dp_link_down(struct psb_intel_encoder *encoder)
REG_READ(intel_dp->output_reg);
}
-static enum drm_connector_status
-cdv_dp_detect(struct psb_intel_encoder *encoder)
+static enum drm_connector_status cdv_dp_detect(struct gma_encoder *encoder)
{
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
enum drm_connector_status status;
@@ -1522,7 +1680,7 @@ cdv_dp_detect(struct psb_intel_encoder *encoder)
return status;
}
-/**
+/*
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
*
* \return true if DP port is connected.
@@ -1531,7 +1689,7 @@ cdv_dp_detect(struct psb_intel_encoder *encoder)
static enum drm_connector_status
cdv_intel_dp_detect(struct drm_connector *connector, bool force)
{
- struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector);
+ struct gma_encoder *encoder = gma_attached_encoder(connector);
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
enum drm_connector_status status;
struct edid *edid = NULL;
@@ -1565,7 +1723,7 @@ cdv_intel_dp_detect(struct drm_connector *connector, bool force)
static int cdv_intel_dp_get_modes(struct drm_connector *connector)
{
- struct psb_intel_encoder *intel_encoder = psb_intel_attached_encoder(connector);
+ struct gma_encoder *intel_encoder = gma_attached_encoder(connector);
struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
struct edid *edid = NULL;
int ret = 0;
@@ -1574,15 +1732,15 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector)
edid = drm_get_edid(connector, &intel_dp->adapter);
if (edid) {
- drm_mode_connector_update_edid_property(connector, edid);
+ drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
}
if (is_edp(intel_encoder)) {
struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
cdv_intel_edp_panel_vdd_off(intel_encoder);
if (ret) {
if (edp && !intel_dp->panel_fixed_mode) {
@@ -1621,7 +1779,7 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector)
static bool
cdv_intel_dp_detect_audio(struct drm_connector *connector)
{
- struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector);
+ struct gma_encoder *encoder = gma_attached_encoder(connector);
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
struct edid *edid;
bool has_audio = false;
@@ -1646,8 +1804,8 @@ cdv_intel_dp_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t val)
{
- struct drm_psb_private *dev_priv = connector->dev->dev_private;
- struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(connector->dev);
+ struct gma_encoder *encoder = gma_attached_encoder(connector);
struct cdv_intel_dp *intel_dp = encoder->dev_priv;
int ret;
@@ -1691,7 +1849,7 @@ done:
struct drm_crtc *crtc = encoder->base.crtc;
drm_crtc_helper_set_mode(crtc, &crtc->mode,
crtc->x, crtc->y,
- crtc->fb);
+ crtc->primary->fb);
}
return 0;
@@ -1700,26 +1858,18 @@ done:
static void
cdv_intel_dp_destroy(struct drm_connector *connector)
{
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- struct cdv_intel_dp *intel_dp = psb_intel_encoder->dev_priv;
+ struct gma_connector *gma_connector = to_gma_connector(connector);
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
+ struct cdv_intel_dp *intel_dp = gma_encoder->dev_priv;
- if (is_edp(psb_intel_encoder)) {
+ if (is_edp(gma_encoder)) {
/* cdv_intel_panel_destroy_backlight(connector->dev); */
- if (intel_dp->panel_fixed_mode) {
- kfree(intel_dp->panel_fixed_mode);
- intel_dp->panel_fixed_mode = NULL;
- }
+ kfree(intel_dp->panel_fixed_mode);
+ intel_dp->panel_fixed_mode = NULL;
}
i2c_del_adapter(&intel_dp->adapter);
- drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
- kfree(connector);
-}
-
-static void cdv_intel_dp_encoder_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
+ kfree(gma_connector);
}
static const struct drm_encoder_helper_funcs cdv_intel_dp_helper_funcs = {
@@ -1741,14 +1891,9 @@ static const struct drm_connector_funcs cdv_intel_dp_connector_funcs = {
static const struct drm_connector_helper_funcs cdv_intel_dp_connector_helper_funcs = {
.get_modes = cdv_intel_dp_get_modes,
.mode_valid = cdv_intel_dp_mode_valid,
- .best_encoder = psb_intel_best_encoder,
+ .best_encoder = gma_best_encoder,
};
-static const struct drm_encoder_funcs cdv_intel_dp_enc_funcs = {
- .destroy = cdv_intel_dp_encoder_destroy,
-};
-
-
static void cdv_intel_dp_add_properties(struct drm_connector *connector)
{
cdv_intel_attach_force_audio_property(connector);
@@ -1758,7 +1903,7 @@ static void cdv_intel_dp_add_properties(struct drm_connector *connector)
/* check the VBT to see whether the eDP is on DP-D port */
static bool cdv_intel_dpc_is_edp(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct child_device_config *p_child;
int i;
@@ -1790,29 +1935,29 @@ static void cdv_disable_intel_clock_gating(struct drm_device *dev)
DPCUNIT_CLOCK_GATE_DISABLE |
DPLSUNIT_CLOCK_GATE_DISABLE |
DPOUNIT_CLOCK_GATE_DISABLE |
- DPIOUNIT_CLOCK_GATE_DISABLE);
+ DPIOUNIT_CLOCK_GATE_DISABLE);
REG_WRITE(DSPCLK_GATE_D, reg_value);
- udelay(500);
+ udelay(500);
}
void
cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg)
{
- struct psb_intel_encoder *psb_intel_encoder;
- struct psb_intel_connector *psb_intel_connector;
+ struct gma_encoder *gma_encoder;
+ struct gma_connector *gma_connector;
struct drm_connector *connector;
struct drm_encoder *encoder;
struct cdv_intel_dp *intel_dp;
const char *name = NULL;
int type = DRM_MODE_CONNECTOR_DisplayPort;
- psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
- if (!psb_intel_encoder)
+ gma_encoder = kzalloc(sizeof(struct gma_encoder), GFP_KERNEL);
+ if (!gma_encoder)
return;
- psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
- if (!psb_intel_connector)
+ gma_connector = kzalloc(sizeof(struct gma_connector), GFP_KERNEL);
+ if (!gma_connector)
goto err_connector;
intel_dp = kzalloc(sizeof(struct cdv_intel_dp), GFP_KERNEL);
if (!intel_dp)
@@ -1821,24 +1966,24 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev
if ((output_reg == DP_C) && cdv_intel_dpc_is_edp(dev))
type = DRM_MODE_CONNECTOR_eDP;
- connector = &psb_intel_connector->base;
- encoder = &psb_intel_encoder->base;
+ connector = &gma_connector->base;
+ encoder = &gma_encoder->base;
drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, type);
- drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS);
+ drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
- psb_intel_connector_attach_encoder(psb_intel_connector, psb_intel_encoder);
+ gma_connector_attach_encoder(gma_connector, gma_encoder);
if (type == DRM_MODE_CONNECTOR_DisplayPort)
- psb_intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+ gma_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
else
- psb_intel_encoder->type = INTEL_OUTPUT_EDP;
+ gma_encoder->type = INTEL_OUTPUT_EDP;
- psb_intel_encoder->dev_priv=intel_dp;
- intel_dp->encoder = psb_intel_encoder;
+ gma_encoder->dev_priv=intel_dp;
+ intel_dp->encoder = gma_encoder;
intel_dp->output_reg = output_reg;
-
+
drm_encoder_helper_add(encoder, &cdv_intel_dp_helper_funcs);
drm_connector_helper_add(connector, &cdv_intel_dp_connector_helper_funcs);
@@ -1846,27 +1991,25 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
- drm_sysfs_connector_add(connector);
-
/* Set up the DDC bus. */
switch (output_reg) {
case DP_B:
name = "DPDDC-B";
- psb_intel_encoder->ddi_select = (DP_MASK | DDI0_SELECT);
+ gma_encoder->ddi_select = (DP_MASK | DDI0_SELECT);
break;
case DP_C:
name = "DPDDC-C";
- psb_intel_encoder->ddi_select = (DP_MASK | DDI1_SELECT);
+ gma_encoder->ddi_select = (DP_MASK | DDI1_SELECT);
break;
}
cdv_disable_intel_clock_gating(dev);
- cdv_intel_dp_i2c_init(psb_intel_connector, psb_intel_encoder, name);
+ cdv_intel_dp_i2c_init(gma_connector, gma_encoder, name);
/* FIXME:fail check */
cdv_intel_dp_add_properties(connector);
- if (is_edp(psb_intel_encoder)) {
+ if (is_edp(gma_encoder)) {
int ret;
struct edp_power_seq cur;
u32 pp_on, pp_off, pp_div;
@@ -1875,7 +2018,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev
pp_on = REG_READ(PP_CONTROL);
pp_on &= ~PANEL_UNLOCK_MASK;
pp_on |= PANEL_UNLOCK_REGS;
-
+
REG_WRITE(PP_CONTROL, pp_on);
pwm_ctrl = REG_READ(BLC_PWM_CTL2);
@@ -1885,7 +2028,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev
pp_on = REG_READ(PP_ON_DELAYS);
pp_off = REG_READ(PP_OFF_DELAYS);
pp_div = REG_READ(PP_DIVISOR);
-
+
/* Pull timing values out of registers */
cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
PANEL_POWER_UP_DELAY_SHIFT;
@@ -1920,22 +2063,22 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev
intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
- cdv_intel_edp_panel_vdd_on(psb_intel_encoder);
- ret = cdv_intel_dp_aux_native_read(psb_intel_encoder, DP_DPCD_REV,
+ cdv_intel_edp_panel_vdd_on(gma_encoder);
+ ret = cdv_intel_dp_aux_native_read(gma_encoder, DP_DPCD_REV,
intel_dp->dpcd,
sizeof(intel_dp->dpcd));
- cdv_intel_edp_panel_vdd_off(psb_intel_encoder);
- if (ret == 0) {
+ cdv_intel_edp_panel_vdd_off(gma_encoder);
+ if (ret <= 0) {
/* if this fails, presume the device is a ghost */
DRM_INFO("failed to retrieve link info, disabling eDP\n");
- cdv_intel_dp_encoder_destroy(encoder);
+ drm_encoder_cleanup(encoder);
cdv_intel_dp_destroy(connector);
- goto err_priv;
+ goto err_connector;
} else {
DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n",
- intel_dp->dpcd[0], intel_dp->dpcd[1],
+ intel_dp->dpcd[0], intel_dp->dpcd[1],
intel_dp->dpcd[2], intel_dp->dpcd[3]);
-
+
}
/* The CDV reference driver moves pnale backlight setup into the displays that
have a backlight: this is a good idea and one we should probably adopt, however
@@ -1945,7 +2088,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev
return;
err_priv:
- kfree(psb_intel_connector);
+ kfree(gma_connector);
err_connector:
- kfree(psb_intel_encoder);
+ kfree(gma_encoder);
}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index 464153d9d2df..8e93ee0d0ccd 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -22,20 +22,22 @@
*
* Authors:
* jim liu <jim.liu@intel.com>
- *
- * FIXME:
- * We should probably make this generic and share it with Medfield
*/
-#include <drm/drmP.h>
+#include <linux/pm_runtime.h>
+
#include <drm/drm.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h>
-#include "psb_intel_drv.h"
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include "cdv_device.h"
#include "psb_drv.h"
+#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "cdv_device.h"
-#include <linux/pm_runtime.h>
/* hdmi control bits */
#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9)
@@ -54,8 +56,6 @@ struct mid_intel_hdmi_priv {
bool has_hdmi_audio;
/* Should set this when detect hotplug */
bool hdmi_device_connected;
- struct mdfld_hdmi_i2c *i2c_bus;
- struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */
struct drm_device *dev;
};
@@ -64,11 +64,11 @@ static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
- struct psb_intel_encoder *psb_intel_encoder = to_psb_intel_encoder(encoder);
- struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv;
+ struct gma_encoder *gma_encoder = to_gma_encoder(encoder);
+ struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv;
u32 hdmib;
struct drm_crtc *crtc = encoder->crtc;
- struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
hdmib = (2 << 10);
@@ -77,7 +77,7 @@ static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
hdmib |= HDMI_HSYNC_ACTIVE_HIGH;
- if (intel_crtc->pipe == 1)
+ if (gma_crtc->pipe == 1)
hdmib |= HDMIB_PIPE_B_SELECT;
if (hdmi_priv->has_hdmi_audio) {
@@ -89,19 +89,11 @@ static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
REG_READ(hdmi_priv->hdmi_reg);
}
-static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
- struct psb_intel_encoder *psb_intel_encoder =
- to_psb_intel_encoder(encoder);
- struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv;
+ struct gma_encoder *gma_encoder = to_gma_encoder(encoder);
+ struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv;
u32 hdmib;
hdmib = REG_READ(hdmi_priv->hdmi_reg);
@@ -116,9 +108,8 @@ static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode)
static void cdv_hdmi_save(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv;
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
+ struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv;
hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg);
}
@@ -126,9 +117,8 @@ static void cdv_hdmi_save(struct drm_connector *connector)
static void cdv_hdmi_restore(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv;
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
+ struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv;
REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB);
REG_READ(hdmi_priv->hdmi_reg);
@@ -137,13 +127,12 @@ static void cdv_hdmi_restore(struct drm_connector *connector)
static enum drm_connector_status cdv_hdmi_detect(
struct drm_connector *connector, bool force)
{
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv;
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
+ struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv;
struct edid *edid = NULL;
enum drm_connector_status status = connector_status_disconnected;
- edid = drm_get_edid(connector, &psb_intel_encoder->i2c_bus->adapter);
+ edid = drm_get_edid(connector, connector->ddc);
hdmi_priv->has_hdmi_sink = false;
hdmi_priv->has_hdmi_audio = false;
@@ -167,7 +156,7 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,
struct drm_encoder *encoder = connector->encoder;
if (!strcmp(property->name, "scaling mode") && encoder) {
- struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc);
+ struct gma_crtc *crtc = to_gma_crtc(encoder->crtc);
bool centre;
uint64_t curValue;
@@ -203,10 +192,10 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,
crtc->saved_mode.vdisplay != 0) {
if (centre) {
if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
- encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
+ encoder->crtc->x, encoder->crtc->y, encoder->crtc->primary->fb))
return -1;
} else {
- struct drm_encoder_helper_funcs *helpers
+ const struct drm_encoder_helper_funcs *helpers
= encoder->helper_private;
helpers->mode_set(encoder, &crtc->saved_mode,
&crtc->saved_adjusted_mode);
@@ -221,22 +210,20 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,
*/
static int cdv_hdmi_get_modes(struct drm_connector *connector)
{
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
struct edid *edid = NULL;
int ret = 0;
- edid = drm_get_edid(connector, &psb_intel_encoder->i2c_bus->adapter);
+ edid = drm_get_edid(connector, connector->ddc);
if (edid) {
- drm_mode_connector_update_edid_property(connector, edid);
+ drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
}
return ret;
}
-static int cdv_hdmi_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+static enum drm_mode_status cdv_hdmi_mode_valid(struct drm_connector *connector,
+ const struct drm_display_mode *mode)
{
if (mode->clock > 165000)
return MODE_CLOCK_HIGH;
@@ -256,35 +243,30 @@ static int cdv_hdmi_mode_valid(struct drm_connector *connector,
static void cdv_hdmi_destroy(struct drm_connector *connector)
{
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ struct gma_connector *gma_connector = to_gma_connector(connector);
+ struct gma_i2c_chan *ddc_bus = to_gma_i2c_chan(connector->ddc);
- if (psb_intel_encoder->i2c_bus)
- psb_intel_i2c_destroy(psb_intel_encoder->i2c_bus);
- drm_sysfs_connector_remove(connector);
+ gma_i2c_destroy(ddc_bus);
drm_connector_cleanup(connector);
- kfree(connector);
+ kfree(gma_connector);
}
static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = {
.dpms = cdv_hdmi_dpms,
- .mode_fixup = cdv_hdmi_mode_fixup,
- .prepare = psb_intel_encoder_prepare,
+ .prepare = gma_encoder_prepare,
.mode_set = cdv_hdmi_mode_set,
- .commit = psb_intel_encoder_commit,
+ .commit = gma_encoder_commit,
};
static const struct drm_connector_helper_funcs
cdv_hdmi_connector_helper_funcs = {
.get_modes = cdv_hdmi_get_modes,
.mode_valid = cdv_hdmi_mode_valid,
- .best_encoder = psb_intel_best_encoder,
+ .best_encoder = gma_best_encoder,
};
static const struct drm_connector_funcs cdv_hdmi_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .save = cdv_hdmi_save,
- .restore = cdv_hdmi_restore,
.detect = cdv_hdmi_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = cdv_hdmi_set_property,
@@ -294,48 +276,71 @@ static const struct drm_connector_funcs cdv_hdmi_connector_funcs = {
void cdv_hdmi_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev, int reg)
{
- struct psb_intel_encoder *psb_intel_encoder;
- struct psb_intel_connector *psb_intel_connector;
+ struct gma_encoder *gma_encoder;
+ struct gma_connector *gma_connector;
struct drm_connector *connector;
- struct drm_encoder *encoder;
struct mid_intel_hdmi_priv *hdmi_priv;
- int ddc_bus;
-
- psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder),
- GFP_KERNEL);
+ struct gma_i2c_chan *ddc_bus;
+ int ddc_reg;
+ int ret;
- if (!psb_intel_encoder)
+ gma_encoder = kzalloc(sizeof(struct gma_encoder), GFP_KERNEL);
+ if (!gma_encoder)
return;
- psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector),
- GFP_KERNEL);
-
- if (!psb_intel_connector)
- goto err_connector;
+ gma_connector = kzalloc(sizeof(struct gma_connector), GFP_KERNEL);
+ if (!gma_connector)
+ goto err_free_encoder;
hdmi_priv = kzalloc(sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL);
-
if (!hdmi_priv)
- goto err_priv;
+ goto err_free_connector;
- connector = &psb_intel_connector->base;
+ connector = &gma_connector->base;
connector->polled = DRM_CONNECTOR_POLL_HPD;
- encoder = &psb_intel_encoder->base;
- drm_connector_init(dev, connector,
- &cdv_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_DVID);
+ gma_connector->save = cdv_hdmi_save;
+ gma_connector->restore = cdv_hdmi_restore;
+
+ switch (reg) {
+ case SDVOB:
+ ddc_reg = GPIOE;
+ gma_encoder->ddi_select = DDI0_SELECT;
+ break;
+ case SDVOC:
+ ddc_reg = GPIOD;
+ gma_encoder->ddi_select = DDI1_SELECT;
+ break;
+ default:
+ DRM_ERROR("unknown reg 0x%x for HDMI\n", reg);
+ goto err_free_hdmi_priv;
+ }
+
+ ddc_bus = gma_i2c_create(dev, ddc_reg,
+ (reg == SDVOB) ? "HDMIB" : "HDMIC");
+ if (!ddc_bus) {
+ dev_err(dev->dev, "No ddc adapter available!\n");
+ goto err_free_hdmi_priv;
+ }
- drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs,
- DRM_MODE_ENCODER_TMDS);
+ ret = drm_connector_init_with_ddc(dev, connector,
+ &cdv_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_DVID,
+ &ddc_bus->base);
+ if (ret)
+ goto err_ddc_destroy;
- psb_intel_connector_attach_encoder(psb_intel_connector,
- psb_intel_encoder);
- psb_intel_encoder->type = INTEL_OUTPUT_HDMI;
+ ret = drm_simple_encoder_init(dev, &gma_encoder->base,
+ DRM_MODE_ENCODER_TMDS);
+ if (ret)
+ goto err_connector_cleanup;
+
+ gma_connector_attach_encoder(gma_connector, gma_encoder);
+ gma_encoder->type = INTEL_OUTPUT_HDMI;
hdmi_priv->hdmi_reg = reg;
hdmi_priv->has_hdmi_sink = false;
- psb_intel_encoder->dev_priv = hdmi_priv;
+ gma_encoder->dev_priv = hdmi_priv;
- drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs);
+ drm_encoder_helper_add(&gma_encoder->base, &cdv_hdmi_helper_funcs);
drm_connector_helper_add(connector,
&cdv_hdmi_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
@@ -346,40 +351,17 @@ void cdv_hdmi_init(struct drm_device *dev,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_FULLSCREEN);
- switch (reg) {
- case SDVOB:
- ddc_bus = GPIOE;
- psb_intel_encoder->ddi_select = DDI0_SELECT;
- break;
- case SDVOC:
- ddc_bus = GPIOD;
- psb_intel_encoder->ddi_select = DDI1_SELECT;
- break;
- default:
- DRM_ERROR("unknown reg 0x%x for HDMI\n", reg);
- goto failed_ddc;
- break;
- }
-
- psb_intel_encoder->i2c_bus = psb_intel_i2c_create(dev,
- ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC");
-
- if (!psb_intel_encoder->i2c_bus) {
- dev_err(dev->dev, "No ddc adapter available!\n");
- goto failed_ddc;
- }
-
- hdmi_priv->hdmi_i2c_adapter =
- &(psb_intel_encoder->i2c_bus->adapter);
hdmi_priv->dev = dev;
- drm_sysfs_connector_add(connector);
return;
-failed_ddc:
- drm_encoder_cleanup(encoder);
+err_connector_cleanup:
drm_connector_cleanup(connector);
-err_priv:
- kfree(psb_intel_connector);
-err_connector:
- kfree(psb_intel_encoder);
+err_ddc_destroy:
+ gma_i2c_destroy(ddc_bus);
+err_free_hdmi_priv:
+ kfree(hdmi_priv);
+err_free_connector:
+ kfree(gma_connector);
+err_free_encoder:
+ kfree(gma_encoder);
}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index d81dbc3368f0..fbe7fe317393 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -1,38 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright © 2006-2011 Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Eric Anholt <eric@anholt.net>
* Dave Airlie <airlied@linux.ie>
* Jesse Barnes <jesse.barnes@intel.com>
*/
-#include <linux/i2c.h>
#include <linux/dmi.h>
-#include <drm/drmP.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include "cdv_device.h"
#include "intel_bios.h"
+#include "power.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
-#include "cdv_device.h"
-/**
+/*
* LVDS I2C backlight control macros
*/
#define BRIGHTNESS_MAX_LEVEL 100
@@ -68,7 +60,7 @@ struct cdv_intel_lvds_priv {
*/
static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 retval;
if (gma_power_begin(dev, false)) {
@@ -85,97 +77,14 @@ static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
return retval;
}
-#if 0
-/*
- * Set LVDS backlight level by I2C command
- */
-static int cdv_lvds_i2c_set_brightness(struct drm_device *dev,
- unsigned int level)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
- u8 out_buf[2];
- unsigned int blc_i2c_brightness;
-
- struct i2c_msg msgs[] = {
- {
- .addr = lvds_i2c_bus->slave_addr,
- .flags = 0,
- .len = 2,
- .buf = out_buf,
- }
- };
-
- blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
- BRIGHTNESS_MASK /
- BRIGHTNESS_MAX_LEVEL);
-
- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
- blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
-
- out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
- out_buf[1] = (u8)blc_i2c_brightness;
-
- if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1)
- return 0;
-
- DRM_ERROR("I2C transfer error\n");
- return -1;
-}
-
-
-static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- u32 max_pwm_blc;
- u32 blc_pwm_duty_cycle;
-
- max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev);
-
- /*BLC_PWM_CTL Should be initiated while backlight device init*/
- BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
-
- blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
-
- if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
- blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
-
- blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
- REG_WRITE(BLC_PWM_CTL,
- (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
- (blc_pwm_duty_cycle));
-
- return 0;
-}
-
/*
- * Set LVDS backlight level either by I2C or PWM
- */
-void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->lvds_bl) {
- DRM_ERROR("NO LVDS Backlight Info\n");
- return;
- }
-
- if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
- cdv_lvds_i2c_set_brightness(dev, level);
- else
- cdv_lvds_pwm_set_brightness(dev, level);
-}
-#endif
-
-/**
* Sets the backlight level.
*
* level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().
*/
static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 blc_pwm_ctl;
if (gma_power_begin(dev, false)) {
@@ -193,13 +102,13 @@ static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
}
}
-/**
+/*
* Sets the power state for the panel.
*/
static void cdv_intel_lvds_set_power(struct drm_device *dev,
struct drm_encoder *encoder, bool on)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 pp_status;
if (!gma_power_begin(dev, true))
@@ -244,11 +153,11 @@ static void cdv_intel_lvds_restore(struct drm_connector *connector)
{
}
-static int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+static enum drm_mode_status cdv_intel_lvds_mode_valid(struct drm_connector *connector,
+ const struct drm_display_mode *mode)
{
struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct drm_display_mode *fixed_mode =
dev_priv->mode_dev.panel_fixed_mode;
@@ -274,7 +183,7 @@ static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
struct drm_encoder *tmp_encoder;
struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
@@ -284,8 +193,7 @@ static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
head) {
if (tmp_encoder != encoder
&& tmp_encoder->crtc == encoder->crtc) {
- printk(KERN_ERR "Can't enable LVDS and another "
- "encoder on the same pipe\n");
+ pr_err("Can't enable LVDS and another encoder on the same pipe\n");
return false;
}
}
@@ -322,7 +230,7 @@ static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
if (!gma_power_begin(dev, true))
@@ -340,7 +248,7 @@ static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
static void cdv_intel_lvds_commit(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
if (mode_dev->backlight_duty_cycle == 0)
@@ -355,9 +263,8 @@ static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(
- encoder->crtc);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(encoder->crtc);
u32 pfit_control;
/*
@@ -379,7 +286,7 @@ static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
else
pfit_control = 0;
- pfit_control |= psb_intel_crtc->pipe << PFIT_PIPE_SHIFT;
+ pfit_control |= gma_crtc->pipe << PFIT_PIPE_SHIFT;
if (dev_priv->lvds_dither)
pfit_control |= PANEL_8TO6_DITHER_ENABLE;
@@ -387,47 +294,27 @@ static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
REG_WRITE(PFIT_CONTROL, pfit_control);
}
-/**
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status cdv_intel_lvds_detect(
- struct drm_connector *connector, bool force)
-{
- return connector_status_connected;
-}
-
-/**
+/*
* Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
*/
static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
int ret;
- ret = psb_intel_ddc_get_modes(connector, &psb_intel_encoder->i2c_bus->adapter);
+ ret = psb_intel_ddc_get_modes(connector, connector->ddc);
if (ret)
return ret;
- /* Didn't get an EDID, so
- * Set wide sync ranges so we get all modes
- * handed to valid_mode for checking
- */
- connector->display_info.min_vfreq = 0;
- connector->display_info.max_vfreq = 200;
- connector->display_info.min_hfreq = 0;
- connector->display_info.max_hfreq = 200;
if (mode_dev->panel_fixed_mode != NULL) {
struct drm_display_mode *mode =
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+ if (!mode)
+ return 0;
+
drm_mode_probed_add(connector, mode);
return 1;
}
@@ -435,23 +322,15 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
return 0;
}
-/**
- * cdv_intel_lvds_destroy - unregister and free LVDS structures
- * @connector: connector to free
- *
- * Unregister the DDC bus for this connector then free the driver private
- * structure.
- */
static void cdv_intel_lvds_destroy(struct drm_connector *connector)
{
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ struct gma_connector *gma_connector = to_gma_connector(connector);
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
- if (psb_intel_encoder->i2c_bus)
- psb_intel_i2c_destroy(psb_intel_encoder->i2c_bus);
- drm_sysfs_connector_remove(connector);
+ gma_i2c_destroy(to_gma_i2c_chan(connector->ddc));
+ gma_i2c_destroy(gma_encoder->i2c_bus);
drm_connector_cleanup(connector);
- kfree(connector);
+ kfree(gma_connector);
}
static int cdv_intel_lvds_set_property(struct drm_connector *connector,
@@ -461,8 +340,7 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,
struct drm_encoder *encoder = connector->encoder;
if (!strcmp(property->name, "scaling mode") && encoder) {
- struct psb_intel_crtc *crtc =
- to_psb_intel_crtc(encoder->crtc);
+ struct gma_crtc *crtc = to_gma_crtc(encoder->crtc);
uint64_t curValue;
if (!crtc)
@@ -498,7 +376,7 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,
&crtc->saved_mode,
encoder->crtc->x,
encoder->crtc->y,
- encoder->crtc->fb))
+ encoder->crtc->primary->fb))
return -1;
}
} else if (!strcmp(property->name, "backlight") && encoder) {
@@ -509,7 +387,7 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,
else
gma_backlight_set(encoder->dev, value);
} else if (!strcmp(property->name, "DPMS") && encoder) {
- struct drm_encoder_helper_funcs *helpers =
+ const struct drm_encoder_helper_funcs *helpers =
encoder->helper_private;
helpers->dpms(encoder, value);
}
@@ -529,29 +407,16 @@ static const struct drm_connector_helper_funcs
cdv_intel_lvds_connector_helper_funcs = {
.get_modes = cdv_intel_lvds_get_modes,
.mode_valid = cdv_intel_lvds_mode_valid,
- .best_encoder = psb_intel_best_encoder,
+ .best_encoder = gma_best_encoder,
};
static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .save = cdv_intel_lvds_save,
- .restore = cdv_intel_lvds_restore,
- .detect = cdv_intel_lvds_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = cdv_intel_lvds_set_property,
.destroy = cdv_intel_lvds_destroy,
};
-
-static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
- .destroy = cdv_intel_lvds_enc_destroy,
-};
-
/*
* Enumerate the child dev array parsed from VBT to check whether
* the LVDS is present.
@@ -562,7 +427,7 @@ static const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
static bool lvds_is_present_in_vbt(struct drm_device *dev,
u8 *i2c_pin)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
int i;
if (!dev_priv->child_dev_num)
@@ -605,6 +470,7 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,
/**
* cdv_intel_lvds_init - setup LVDS connectors on this device
* @dev: drm device
+ * @mode_dev: PSB mode device
*
* Create the connector, register the LVDS DDC bus, and try to figure out what
* modes we can display on the LVDS panel (if present).
@@ -612,56 +478,71 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,
void cdv_intel_lvds_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev)
{
- struct psb_intel_encoder *psb_intel_encoder;
- struct psb_intel_connector *psb_intel_connector;
+ struct gma_encoder *gma_encoder;
+ struct gma_connector *gma_connector;
struct cdv_intel_lvds_priv *lvds_priv;
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_display_mode *scan;
struct drm_crtc *crtc;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_i2c_chan *ddc_bus;
u32 lvds;
int pipe;
+ int ret;
u8 pin;
+ if (!dev_priv->lvds_enabled_in_vbt)
+ return;
+
pin = GMBUS_PORT_PANEL;
if (!lvds_is_present_in_vbt(dev, &pin)) {
DRM_DEBUG_KMS("LVDS is not present in VBT\n");
return;
}
- psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder),
+ gma_encoder = kzalloc(sizeof(struct gma_encoder),
GFP_KERNEL);
- if (!psb_intel_encoder)
+ if (!gma_encoder)
return;
- psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector),
+ gma_connector = kzalloc(sizeof(struct gma_connector),
GFP_KERNEL);
- if (!psb_intel_connector)
- goto failed_connector;
+ if (!gma_connector)
+ goto err_free_encoder;
lvds_priv = kzalloc(sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);
if (!lvds_priv)
- goto failed_lvds_priv;
-
- psb_intel_encoder->dev_priv = lvds_priv;
+ goto err_free_connector;
- connector = &psb_intel_connector->base;
- encoder = &psb_intel_encoder->base;
+ gma_encoder->dev_priv = lvds_priv;
+ connector = &gma_connector->base;
+ gma_connector->save = cdv_intel_lvds_save;
+ gma_connector->restore = cdv_intel_lvds_restore;
+ encoder = &gma_encoder->base;
- drm_connector_init(dev, connector,
- &cdv_intel_lvds_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
+ /* Set up the DDC bus. */
+ ddc_bus = gma_i2c_create(dev, GPIOC, "LVDSDDC_C");
+ if (!ddc_bus) {
+ dev_printk(KERN_ERR, dev->dev,
+ "DDC bus registration " "failed.\n");
+ goto err_free_lvds_priv;
+ }
- drm_encoder_init(dev, encoder,
- &cdv_intel_lvds_enc_funcs,
- DRM_MODE_ENCODER_LVDS);
+ ret = drm_connector_init_with_ddc(dev, connector,
+ &cdv_intel_lvds_connector_funcs,
+ DRM_MODE_CONNECTOR_LVDS,
+ &ddc_bus->base);
+ if (ret)
+ goto err_destroy_ddc;
+ ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS);
+ if (ret)
+ goto err_connector_cleanup;
- psb_intel_connector_attach_encoder(psb_intel_connector,
- psb_intel_encoder);
- psb_intel_encoder->type = INTEL_OUTPUT_LVDS;
+ gma_connector_attach_encoder(gma_connector, gma_encoder);
+ gma_encoder->type = INTEL_OUTPUT_LVDS;
drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);
drm_connector_helper_add(connector,
@@ -682,16 +563,14 @@ void cdv_intel_lvds_init(struct drm_device *dev,
* Set up I2C bus
* FIXME: distroy i2c_bus when exit
*/
- psb_intel_encoder->i2c_bus = psb_intel_i2c_create(dev,
- GPIOB,
- "LVDSBLC_B");
- if (!psb_intel_encoder->i2c_bus) {
+ gma_encoder->i2c_bus = gma_i2c_create(dev, GPIOB, "LVDSBLC_B");
+ if (!gma_encoder->i2c_bus) {
dev_printk(KERN_ERR,
- &dev->pdev->dev, "I2C bus registration failed.\n");
- goto failed_blc_i2c;
+ dev->dev, "I2C bus registration failed.\n");
+ goto err_encoder_cleanup;
}
- psb_intel_encoder->i2c_bus->slave_addr = 0x2C;
- dev_priv->lvds_i2c_bus = psb_intel_encoder->i2c_bus;
+ gma_encoder->i2c_bus->target_addr = 0x2C;
+ dev_priv->lvds_i2c_bus = gma_encoder->i2c_bus;
/*
* LVDS discovery:
@@ -703,22 +582,13 @@ void cdv_intel_lvds_init(struct drm_device *dev,
* if closed, act like it's not there for now
*/
- /* Set up the DDC bus. */
- psb_intel_encoder->ddc_bus = psb_intel_i2c_create(dev,
- GPIOC,
- "LVDSDDC_C");
- if (!psb_intel_encoder->ddc_bus) {
- dev_printk(KERN_ERR, &dev->pdev->dev,
- "DDC bus registration " "failed.\n");
- goto failed_ddc;
- }
-
/*
* Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one.
*/
- psb_intel_ddc_get_modes(connector,
- &psb_intel_encoder->ddc_bus->adapter);
+ mutex_lock(&dev->mode_config.mutex);
+ psb_intel_ddc_get_modes(connector, &ddc_bus->base);
+
list_for_each_entry(scan, &connector->probed_modes, head) {
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
mode_dev->panel_fixed_mode =
@@ -760,7 +630,7 @@ void cdv_intel_lvds_init(struct drm_device *dev,
if (!mode_dev->panel_fixed_mode) {
DRM_DEBUG
("Found no modes on the lvds, ignoring the LVDS\n");
- goto failed_find;
+ goto err_unlock;
}
/* setup PWM */
@@ -777,24 +647,22 @@ void cdv_intel_lvds_init(struct drm_device *dev,
}
out:
- drm_sysfs_connector_add(connector);
+ mutex_unlock(&dev->mode_config.mutex);
return;
-failed_find:
- printk(KERN_ERR "Failed find\n");
- if (psb_intel_encoder->ddc_bus)
- psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus);
-failed_ddc:
- printk(KERN_ERR "Failed DDC\n");
- if (psb_intel_encoder->i2c_bus)
- psb_intel_i2c_destroy(psb_intel_encoder->i2c_bus);
-failed_blc_i2c:
- printk(KERN_ERR "Failed BLC\n");
+err_unlock:
+ mutex_unlock(&dev->mode_config.mutex);
+ gma_i2c_destroy(gma_encoder->i2c_bus);
+err_encoder_cleanup:
drm_encoder_cleanup(encoder);
+err_connector_cleanup:
drm_connector_cleanup(connector);
+err_destroy_ddc:
+ gma_i2c_destroy(ddc_bus);
+err_free_lvds_priv:
kfree(lvds_priv);
-failed_lvds_priv:
- kfree(psb_intel_connector);
-failed_connector:
- kfree(psb_intel_encoder);
+err_free_connector:
+ kfree(gma_connector);
+err_free_encoder:
+ kfree(gma_encoder);
}
diff --git a/drivers/gpu/drm/gma500/fbdev.c b/drivers/gpu/drm/gma500/fbdev.c
new file mode 100644
index 000000000000..c26926babc2a
--- /dev/null
+++ b/drivers/gpu/drm/gma500/fbdev.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**************************************************************************
+ * Copyright (c) 2007-2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+#include <linux/fb.h>
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_framebuffer.h>
+
+#include "gem.h"
+#include "psb_drv.h"
+
+/*
+ * VM area struct
+ */
+
+static vm_fault_t psb_fbdev_vm_fault(struct vm_fault *vmf)
+{
+ struct vm_area_struct *vma = vmf->vma;
+ struct fb_info *info = vma->vm_private_data;
+ unsigned long address = vmf->address - (vmf->pgoff << PAGE_SHIFT);
+ unsigned long pfn = info->fix.smem_start >> PAGE_SHIFT;
+ vm_fault_t err = VM_FAULT_SIGBUS;
+ unsigned long page_num = vma_pages(vma);
+ unsigned long i;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ for (i = 0; i < page_num; ++i) {
+ err = vmf_insert_mixed(vma, address, pfn);
+ if (unlikely(err & VM_FAULT_ERROR))
+ break;
+ address += PAGE_SIZE;
+ ++pfn;
+ }
+
+ return err;
+}
+
+static const struct vm_operations_struct psb_fbdev_vm_ops = {
+ .fault = psb_fbdev_vm_fault,
+};
+
+/*
+ * struct fb_ops
+ */
+
+static int psb_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ if (vma->vm_pgoff != 0)
+ return -EINVAL;
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+ return -EINVAL;
+
+ /*
+ * If this is a GEM object then info->screen_base is the virtual
+ * kernel remapping of the object. FIXME: Review if this is
+ * suitable for our mmap work
+ */
+ vma->vm_ops = &psb_fbdev_vm_ops;
+ vma->vm_private_data = info;
+ vm_flags_set(vma, VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP);
+
+ return 0;
+}
+
+static void psb_fbdev_fb_destroy(struct fb_info *info)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_framebuffer *fb = fb_helper->fb;
+ struct drm_gem_object *obj = fb->obj[0];
+
+ drm_fb_helper_fini(fb_helper);
+
+ drm_framebuffer_unregister_private(fb);
+ drm_framebuffer_cleanup(fb);
+ kfree(fb);
+
+ drm_gem_object_put(obj);
+
+ drm_client_release(&fb_helper->client);
+}
+
+static const struct fb_ops psb_fbdev_fb_ops = {
+ .owner = THIS_MODULE,
+ __FB_DEFAULT_IOMEM_OPS_RDWR,
+ DRM_FB_HELPER_DEFAULT_OPS,
+ __FB_DEFAULT_IOMEM_OPS_DRAW,
+ .fb_mmap = psb_fbdev_fb_mmap,
+ .fb_destroy = psb_fbdev_fb_destroy,
+};
+
+static const struct drm_fb_helper_funcs psb_fbdev_fb_helper_funcs = {
+};
+
+/*
+ * struct drm_driver
+ */
+
+int psb_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct drm_device *dev = fb_helper->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ struct fb_info *info = fb_helper->info;
+ struct drm_framebuffer *fb;
+ struct drm_mode_fb_cmd2 mode_cmd = { };
+ int size;
+ int ret;
+ struct psb_gem_object *backing;
+ struct drm_gem_object *obj;
+ u32 bpp, depth;
+
+ /* No 24-bit packed mode */
+ if (sizes->surface_bpp == 24) {
+ sizes->surface_bpp = 32;
+ sizes->surface_depth = 24;
+ }
+ bpp = sizes->surface_bpp;
+ depth = sizes->surface_depth;
+
+ /*
+ * If the mode does not fit in 32 bit then switch to 16 bit to get
+ * a console on full resolution. The X mode setting server will
+ * allocate its own 32-bit GEM framebuffer.
+ */
+ size = ALIGN(sizes->surface_width * DIV_ROUND_UP(bpp, 8), 64) *
+ sizes->surface_height;
+ size = ALIGN(size, PAGE_SIZE);
+
+ if (size > dev_priv->vram_stolen_size) {
+ sizes->surface_bpp = 16;
+ sizes->surface_depth = 16;
+ }
+ bpp = sizes->surface_bpp;
+ depth = sizes->surface_depth;
+
+ mode_cmd.width = sizes->surface_width;
+ mode_cmd.height = sizes->surface_height;
+ mode_cmd.pitches[0] = ALIGN(mode_cmd.width * DIV_ROUND_UP(bpp, 8), 64);
+ mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
+
+ size = mode_cmd.pitches[0] * mode_cmd.height;
+ size = ALIGN(size, PAGE_SIZE);
+
+ /* Allocate the framebuffer in the GTT with stolen page backing */
+ backing = psb_gem_create(dev, size, "fb", true, PAGE_SIZE);
+ if (IS_ERR(backing))
+ return PTR_ERR(backing);
+ obj = &backing->base;
+
+ fb = psb_framebuffer_create(dev,
+ drm_get_format_info(dev, mode_cmd.pixel_format,
+ mode_cmd.modifier[0]),
+ &mode_cmd, obj);
+ if (IS_ERR(fb)) {
+ ret = PTR_ERR(fb);
+ goto err_drm_gem_object_put;
+ }
+
+ fb_helper->funcs = &psb_fbdev_fb_helper_funcs;
+ fb_helper->fb = fb;
+
+ info->fbops = &psb_fbdev_fb_ops;
+
+ /* Accessed stolen memory directly */
+ info->screen_base = dev_priv->vram_addr + backing->offset;
+ info->screen_size = size;
+
+ drm_fb_helper_fill_info(info, fb_helper, sizes);
+
+ info->fix.smem_start = dev_priv->stolen_base + backing->offset;
+ info->fix.smem_len = size;
+ info->fix.ywrapstep = 0;
+ info->fix.ypanstep = 0;
+ info->fix.mmio_start = pci_resource_start(pdev, 0);
+ info->fix.mmio_len = pci_resource_len(pdev, 0);
+
+ fb_memset_io(info->screen_base, 0, info->screen_size);
+
+ /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
+
+ dev_dbg(dev->dev, "allocated %dx%d fb\n", fb->width, fb->height);
+
+ return 0;
+
+err_drm_gem_object_put:
+ drm_gem_object_put(obj);
+ return ret;
+}
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 8b1b6d923abe..e69b537ded6b 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -1,232 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0-only
/**************************************************************************
* Copyright (c) 2007-2011, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_modeset_helper.h>
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_drv.h"
#include "framebuffer.h"
-#include "gtt.h"
-
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
- struct drm_file *file_priv,
- unsigned int *handle);
+#include "psb_drv.h"
static const struct drm_framebuffer_funcs psb_fb_funcs = {
- .destroy = psb_user_framebuffer_destroy,
- .create_handle = psb_user_framebuffer_create_handle,
-};
-
-#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
-
-static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
- struct psb_fbdev *fbdev = info->par;
- struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
- uint32_t v;
-
- if (!fb)
- return -ENOMEM;
-
- if (regno > 255)
- return 1;
-
- red = CMAP_TOHW(red, info->var.red.length);
- blue = CMAP_TOHW(blue, info->var.blue.length);
- green = CMAP_TOHW(green, info->var.green.length);
- transp = CMAP_TOHW(transp, info->var.transp.length);
-
- v = (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset) |
- (transp << info->var.transp.offset);
-
- if (regno < 16) {
- switch (fb->bits_per_pixel) {
- case 16:
- ((uint32_t *) info->pseudo_palette)[regno] = v;
- break;
- case 24:
- case 32:
- ((uint32_t *) info->pseudo_palette)[regno] = v;
- break;
- }
- }
-
- return 0;
-}
-
-static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
-{
- struct psb_fbdev *fbdev = info->par;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
- struct drm_device *dev = psbfb->base.dev;
-
- /*
- * We have to poke our nose in here. The core fb code assumes
- * panning is part of the hardware that can be invoked before
- * the actual fb is mapped. In our case that isn't quite true.
- */
- if (psbfb->gtt->npage) {
- /* GTT roll shifts in 4K pages, we need to shift the right
- number of pages */
- int pages = info->fix.line_length >> 12;
- psb_gtt_roll(dev, psbfb->gtt, var->yoffset * pages);
- }
- return 0;
-}
-
-static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct psb_framebuffer *psbfb = vma->vm_private_data;
- struct drm_device *dev = psbfb->base.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- int page_num;
- int i;
- unsigned long address;
- int ret;
- unsigned long pfn;
- unsigned long phys_addr = (unsigned long)dev_priv->stolen_base +
- psbfb->gtt->offset;
-
- page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
- address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT);
-
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- for (i = 0; i < page_num; i++) {
- pfn = (phys_addr >> PAGE_SHIFT);
-
- ret = vm_insert_mixed(vma, address, pfn);
- if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
- break;
- else if (unlikely(ret != 0)) {
- ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
- return ret;
- }
- address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
- }
- return VM_FAULT_NOPAGE;
-}
-
-static void psbfb_vm_open(struct vm_area_struct *vma)
-{
-}
-
-static void psbfb_vm_close(struct vm_area_struct *vma)
-{
-}
-
-static const struct vm_operations_struct psbfb_vm_ops = {
- .fault = psbfb_vm_fault,
- .open = psbfb_vm_open,
- .close = psbfb_vm_close
-};
-
-static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
- struct psb_fbdev *fbdev = info->par;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
-
- if (vma->vm_pgoff != 0)
- return -EINVAL;
- if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
- return -EINVAL;
-
- if (!psbfb->addr_space)
- psbfb->addr_space = vma->vm_file->f_mapping;
- /*
- * If this is a GEM object then info->screen_base is the virtual
- * kernel remapping of the object. FIXME: Review if this is
- * suitable for our mmap work
- */
- vma->vm_ops = &psbfb_vm_ops;
- vma->vm_private_data = (void *)psbfb;
- vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
- return 0;
-}
-
-static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
- unsigned long arg)
-{
- return -ENOTTY;
-}
-
-static struct fb_ops psbfb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcolreg = psbfb_setcolreg,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = psbfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_mmap = psbfb_mmap,
- .fb_sync = psbfb_sync,
- .fb_ioctl = psbfb_ioctl,
-};
-
-static struct fb_ops psbfb_roll_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcolreg = psbfb_setcolreg,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_pan_display = psbfb_pan,
- .fb_mmap = psbfb_mmap,
- .fb_ioctl = psbfb_ioctl,
-};
-
-static struct fb_ops psbfb_unaccel_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcolreg = psbfb_setcolreg,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_mmap = psbfb_mmap,
- .fb_ioctl = psbfb_ioctl,
+ .destroy = drm_gem_fb_destroy,
+ .create_handle = drm_gem_fb_create_handle,
};
/**
@@ -234,35 +22,32 @@ static struct fb_ops psbfb_unaccel_ops = {
* @dev: our DRM device
* @fb: framebuffer to set up
* @mode_cmd: mode description
- * @gt: backing object
+ * @obj: backing object
*
* Configure and fill in the boilerplate for our frame buffer. Return
* 0 on success or an error code if we fail.
*/
static int psb_framebuffer_init(struct drm_device *dev,
- struct psb_framebuffer *fb,
- struct drm_mode_fb_cmd2 *mode_cmd,
- struct gtt_range *gt)
+ struct drm_framebuffer *fb,
+ const struct drm_format_info *info,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj)
{
- u32 bpp, depth;
int ret;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+ /*
+ * Reject unknown formats, YUV formats, and formats with more than
+ * 4 bytes per pixel.
+ */
+ if (!info->depth || info->cpp[0] > 4)
+ return -EINVAL;
if (mode_cmd->pitches[0] & 63)
return -EINVAL;
- switch (bpp) {
- case 8:
- case 16:
- case 24:
- case 32:
- break;
- default:
- return -EINVAL;
- }
- drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
- fb->gtt = gt;
- ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
+
+ drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd);
+ fb->obj[0] = obj;
+ ret = drm_framebuffer_init(dev, fb, &psb_fb_funcs);
if (ret) {
dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
return ret;
@@ -273,222 +58,33 @@ static int psb_framebuffer_init(struct drm_device *dev,
/**
* psb_framebuffer_create - create a framebuffer backed by gt
* @dev: our DRM device
+ * @info: pixel format information
* @mode_cmd: the description of the requested mode
- * @gt: the backing object
+ * @obj: the backing object
*
* Create a framebuffer object backed by the gt, and fill in the
* boilerplate required
*
* TODO: review object references
*/
-
-static struct drm_framebuffer *psb_framebuffer_create
- (struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd,
- struct gtt_range *gt)
+struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev,
+ const struct drm_format_info *info,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj)
{
- struct psb_framebuffer *fb;
+ struct drm_framebuffer *fb;
int ret;
fb = kzalloc(sizeof(*fb), GFP_KERNEL);
if (!fb)
return ERR_PTR(-ENOMEM);
- ret = psb_framebuffer_init(dev, fb, mode_cmd, gt);
+ ret = psb_framebuffer_init(dev, fb, info, mode_cmd, obj);
if (ret) {
kfree(fb);
return ERR_PTR(ret);
}
- return &fb->base;
-}
-
-/**
- * psbfb_alloc - allocate frame buffer memory
- * @dev: the DRM device
- * @aligned_size: space needed
- * @force: fall back to GEM buffers if need be
- *
- * Allocate the frame buffer. In the usual case we get a GTT range that
- * is stolen memory backed and life is simple. If there isn't sufficient
- * we fail as we don't have the virtual mapping space to really vmap it
- * and the kernel console code can't handle non linear framebuffers.
- *
- * Re-address this as and if the framebuffer layer grows this ability.
- */
-static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
-{
- struct gtt_range *backing;
- /* Begin by trying to use stolen memory backing */
- backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
- if (backing) {
- if (drm_gem_private_object_init(dev,
- &backing->gem, aligned_size) == 0)
- return backing;
- psb_gtt_free_range(dev, backing);
- }
- return NULL;
-}
-
-/**
- * psbfb_create - create a framebuffer
- * @fbdev: the framebuffer device
- * @sizes: specification of the layout
- *
- * Create a framebuffer to the specifications provided
- */
-static int psbfb_create(struct psb_fbdev *fbdev,
- struct drm_fb_helper_surface_size *sizes)
-{
- struct drm_device *dev = fbdev->psb_fb_helper.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct fb_info *info;
- struct drm_framebuffer *fb;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
- struct drm_mode_fb_cmd2 mode_cmd;
- struct device *device = &dev->pdev->dev;
- int size;
- int ret;
- struct gtt_range *backing;
- u32 bpp, depth;
- int gtt_roll = 0;
- int pitch_lines = 0;
-
- mode_cmd.width = sizes->surface_width;
- mode_cmd.height = sizes->surface_height;
- bpp = sizes->surface_bpp;
- depth = sizes->surface_depth;
-
- /* No 24bit packed */
- if (bpp == 24)
- bpp = 32;
-
- do {
- /*
- * Acceleration via the GTT requires pitch to be
- * power of two aligned. Preferably page but less
- * is ok with some fonts
- */
- mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines);
-
- size = mode_cmd.pitches[0] * mode_cmd.height;
- size = ALIGN(size, PAGE_SIZE);
-
- /* Allocate the fb in the GTT with stolen page backing */
- backing = psbfb_alloc(dev, size);
-
- if (pitch_lines)
- pitch_lines *= 2;
- else
- pitch_lines = 1;
- gtt_roll++;
- } while (backing == NULL && pitch_lines <= 16);
-
- /* The final pitch we accepted if we succeeded */
- pitch_lines /= 2;
-
- if (backing == NULL) {
- /*
- * We couldn't get the space we wanted, fall back to the
- * display engine requirement instead. The HW requires
- * the pitch to be 64 byte aligned
- */
-
- gtt_roll = 0; /* Don't use GTT accelerated scrolling */
- pitch_lines = 64;
-
- mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
-
- size = mode_cmd.pitches[0] * mode_cmd.height;
- size = ALIGN(size, PAGE_SIZE);
-
- /* Allocate the framebuffer in the GTT with stolen page backing */
- backing = psbfb_alloc(dev, size);
- if (backing == NULL)
- return -ENOMEM;
- }
-
- memset(dev_priv->vram_addr + backing->offset, 0, size);
-
- mutex_lock(&dev->struct_mutex);
-
- info = framebuffer_alloc(0, device);
- if (!info) {
- ret = -ENOMEM;
- goto out_err1;
- }
- info->par = fbdev;
-
- mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
-
- ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
- if (ret)
- goto out_unref;
-
- fb = &psbfb->base;
- psbfb->fbdev = info;
-
- fbdev->psb_fb_helper.fb = fb;
- fbdev->psb_fb_helper.fbdev = info;
-
- drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
- strcpy(info->fix.id, "psbdrmfb");
-
- info->flags = FBINFO_DEFAULT;
- if (dev_priv->ops->accel_2d && pitch_lines > 8) /* 2D engine */
- info->fbops = &psbfb_ops;
- else if (gtt_roll) { /* GTT rolling seems best */
- info->fbops = &psbfb_roll_ops;
- info->flags |= FBINFO_HWACCEL_YPAN;
- } else /* Software */
- info->fbops = &psbfb_unaccel_ops;
-
- ret = fb_alloc_cmap(&info->cmap, 256, 0);
- if (ret) {
- ret = -ENOMEM;
- goto out_unref;
- }
-
- info->fix.smem_start = dev->mode_config.fb_base;
- info->fix.smem_len = size;
- info->fix.ywrapstep = gtt_roll;
- info->fix.ypanstep = 0;
-
- /* Accessed stolen memory directly */
- info->screen_base = dev_priv->vram_addr + backing->offset;
- info->screen_size = size;
-
- if (dev_priv->gtt.stolen_size) {
- info->apertures = alloc_apertures(1);
- if (!info->apertures) {
- ret = -ENOMEM;
- goto out_unref;
- }
- info->apertures->ranges[0].base = dev->mode_config.fb_base;
- info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
- }
-
- drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
- sizes->fb_width, sizes->fb_height);
-
- info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
- info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
-
- /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
-
- dev_dbg(dev->dev, "allocated %dx%d fb\n",
- psbfb->base.width, psbfb->base.height);
-
- mutex_unlock(&dev->struct_mutex);
- return 0;
-out_unref:
- if (backing->stolen)
- psb_gtt_free_range(dev, backing);
- else
- drm_gem_object_unreference(&backing->gem);
-out_err1:
- mutex_unlock(&dev->struct_mutex);
- psb_gtt_free_range(dev, backing);
- return ret;
+ return fb;
}
/**
@@ -501,273 +97,107 @@ out_err1:
*/
static struct drm_framebuffer *psb_user_framebuffer_create
(struct drm_device *dev, struct drm_file *filp,
- struct drm_mode_fb_cmd2 *cmd)
+ const struct drm_format_info *info,
+ const struct drm_mode_fb_cmd2 *cmd)
{
- struct gtt_range *r;
struct drm_gem_object *obj;
+ struct drm_framebuffer *fb;
/*
* Find the GEM object and thus the gtt range object that is
* to back this space
*/
- obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]);
+ obj = drm_gem_object_lookup(filp, cmd->handles[0]);
if (obj == NULL)
return ERR_PTR(-ENOENT);
/* Let the core code do all the work */
- r = container_of(obj, struct gtt_range, gem);
- return psb_framebuffer_create(dev, cmd, r);
-}
-
-static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
- u16 blue, int regno)
-{
- struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
+ fb = psb_framebuffer_create(dev, info, cmd, obj);
+ if (IS_ERR(fb))
+ drm_gem_object_put(obj);
- intel_crtc->lut_r[regno] = red >> 8;
- intel_crtc->lut_g[regno] = green >> 8;
- intel_crtc->lut_b[regno] = blue >> 8;
-}
-
-static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
- u16 *green, u16 *blue, int regno)
-{
- struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
-
- *red = intel_crtc->lut_r[regno] << 8;
- *green = intel_crtc->lut_g[regno] << 8;
- *blue = intel_crtc->lut_b[regno] << 8;
-}
-
-static int psbfb_probe(struct drm_fb_helper *helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
- struct drm_device *dev = psb_fbdev->psb_fb_helper.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- int bytespp;
-
- bytespp = sizes->surface_bpp / 8;
- if (bytespp == 3) /* no 24bit packed */
- bytespp = 4;
-
- /* If the mode will not fit in 32bit then switch to 16bit to get
- a console on full resolution. The X mode setting server will
- allocate its own 32bit GEM framebuffer */
- if (ALIGN(sizes->fb_width * bytespp, 64) * sizes->fb_height >
- dev_priv->vram_stolen_size) {
- sizes->surface_bpp = 16;
- sizes->surface_depth = 16;
- }
-
- return psbfb_create(psb_fbdev, sizes);
-}
-
-static struct drm_fb_helper_funcs psb_fb_helper_funcs = {
- .gamma_set = psbfb_gamma_set,
- .gamma_get = psbfb_gamma_get,
- .fb_probe = psbfb_probe,
-};
-
-static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
-{
- struct fb_info *info;
- struct psb_framebuffer *psbfb = &fbdev->pfb;
-
- if (fbdev->psb_fb_helper.fbdev) {
- info = fbdev->psb_fb_helper.fbdev;
- unregister_framebuffer(info);
- if (info->cmap.len)
- fb_dealloc_cmap(&info->cmap);
- framebuffer_release(info);
- }
- drm_fb_helper_fini(&fbdev->psb_fb_helper);
- drm_framebuffer_unregister_private(&psbfb->base);
- drm_framebuffer_cleanup(&psbfb->base);
-
- if (psbfb->gtt)
- drm_gem_object_unreference(&psbfb->gtt->gem);
- return 0;
-}
-
-int psb_fbdev_init(struct drm_device *dev)
-{
- struct psb_fbdev *fbdev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
- if (!fbdev) {
- dev_err(dev->dev, "no memory\n");
- return -ENOMEM;
- }
-
- dev_priv->fbdev = fbdev;
- fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
-
- 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);
-
- /* disable all the possible outputs/crtcs before entering KMS mode */
- drm_helper_disable_unused_functions(dev);
-
- drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
- return 0;
-}
-
-static void psb_fbdev_fini(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->fbdev)
- return;
-
- psb_fbdev_destroy(dev, dev_priv->fbdev);
- kfree(dev_priv->fbdev);
- dev_priv->fbdev = NULL;
-}
-
-static void psbfb_output_poll_changed(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
- drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
-}
-
-/**
- * psb_user_framebuffer_create_handle - add hamdle to a framebuffer
- * @fb: framebuffer
- * @file_priv: our DRM file
- * @handle: returned handle
- *
- * Our framebuffer object is a GTT range which also contains a GEM
- * object. We need to turn it into a handle for userspace. GEM will do
- * the work for us
- */
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
- struct drm_file *file_priv,
- unsigned int *handle)
-{
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
- struct gtt_range *r = psbfb->gtt;
- return drm_gem_handle_create(file_priv, &r->gem, handle);
-}
-
-/**
- * psb_user_framebuffer_destroy - destruct user created fb
- * @fb: framebuffer
- *
- * User framebuffers are backed by GEM objects so all we have to do is
- * clean up a bit and drop the reference, GEM will handle the fallout
- */
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
- struct gtt_range *r = psbfb->gtt;
-
- /* Let DRM do its clean up */
- drm_framebuffer_cleanup(fb);
- /* We are no longer using the resource in GEM */
- drm_gem_object_unreference_unlocked(&r->gem);
- kfree(fb);
+ return fb;
}
static const struct drm_mode_config_funcs psb_mode_funcs = {
.fb_create = psb_user_framebuffer_create,
- .output_poll_changed = psbfb_output_poll_changed,
};
-static int psb_create_backlight_property(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_property *backlight;
-
- if (dev_priv->backlight_property)
- return 0;
-
- backlight = drm_property_create_range(dev, 0, "backlight", 0, 100);
-
- dev_priv->backlight_property = backlight;
-
- return 0;
-}
-
static void psb_setup_outputs(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
drm_mode_create_scaling_mode_property(dev);
- psb_create_backlight_property(dev);
+ /* It is ok for this to fail - we just don't get backlight control */
+ if (!dev_priv->backlight_property)
+ dev_priv->backlight_property = drm_property_create_range(dev, 0,
+ "backlight", 0, 100);
dev_priv->ops->output_init(dev);
- list_for_each_entry(connector, &dev->mode_config.connector_list,
- head) {
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- struct drm_encoder *encoder = &psb_intel_encoder->base;
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
+ struct drm_encoder *encoder = &gma_encoder->base;
int crtc_mask = 0, clone_mask = 0;
/* valid crtcs */
- switch (psb_intel_encoder->type) {
+ switch (gma_encoder->type) {
case INTEL_OUTPUT_ANALOG:
crtc_mask = (1 << 0);
clone_mask = (1 << INTEL_OUTPUT_ANALOG);
break;
case INTEL_OUTPUT_SDVO:
- crtc_mask = ((1 << 0) | (1 << 1));
- clone_mask = (1 << INTEL_OUTPUT_SDVO);
+ crtc_mask = dev_priv->ops->sdvo_mask;
+ clone_mask = 0;
break;
case INTEL_OUTPUT_LVDS:
- crtc_mask = dev_priv->ops->lvds_mask;
- clone_mask = (1 << INTEL_OUTPUT_LVDS);
+ crtc_mask = dev_priv->ops->lvds_mask;
+ clone_mask = 0;
break;
case INTEL_OUTPUT_MIPI:
crtc_mask = (1 << 0);
- clone_mask = (1 << INTEL_OUTPUT_MIPI);
+ clone_mask = 0;
break;
case INTEL_OUTPUT_MIPI2:
crtc_mask = (1 << 2);
- clone_mask = (1 << INTEL_OUTPUT_MIPI2);
+ clone_mask = 0;
break;
case INTEL_OUTPUT_HDMI:
- crtc_mask = dev_priv->ops->hdmi_mask;
+ crtc_mask = dev_priv->ops->hdmi_mask;
clone_mask = (1 << INTEL_OUTPUT_HDMI);
break;
case INTEL_OUTPUT_DISPLAYPORT:
crtc_mask = (1 << 0) | (1 << 1);
- clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT);
+ clone_mask = 0;
break;
case INTEL_OUTPUT_EDP:
crtc_mask = (1 << 1);
- clone_mask = (1 << INTEL_OUTPUT_EDP);
+ clone_mask = 0;
}
encoder->possible_crtcs = crtc_mask;
encoder->possible_clones =
- psb_intel_connector_clones(dev, clone_mask);
+ gma_connector_clones(dev, clone_mask);
}
+ drm_connector_list_iter_end(&conn_iter);
}
void psb_modeset_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
int i;
- drm_mode_config_init(dev);
+ if (drmm_mode_config_init(dev))
+ return;
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
dev->mode_config.funcs = &psb_mode_funcs;
- /* set memory base */
- /* Oaktrail and Poulsbo should use BAR 2*/
- pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
- &(dev->mode_config.fb_base));
-
/* num pipes is 2 for PSB but 1 for Mrst */
for (i = 0; i < dev_priv->num_pipe; i++)
psb_intel_crtc_init(dev, i, mode_dev);
@@ -785,14 +215,8 @@ void psb_modeset_init(struct drm_device *dev)
void psb_modeset_cleanup(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
if (dev_priv->modeset) {
- mutex_lock(&dev->struct_mutex);
-
drm_kms_helper_poll_fini(dev);
- psb_fbdev_fini(dev);
- drm_mode_config_cleanup(dev);
-
- mutex_unlock(&dev->struct_mutex);
}
}
diff --git a/drivers/gpu/drm/gma500/framebuffer.h b/drivers/gpu/drm/gma500/framebuffer.h
index 989558a9e6ee..2fbba4b48841 100644
--- a/drivers/gpu/drm/gma500/framebuffer.h
+++ b/drivers/gpu/drm/gma500/framebuffer.h
@@ -1,47 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2008-2011, Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Eric Anholt <eric@anholt.net>
- *
*/
#ifndef _FRAMEBUFFER_H_
#define _FRAMEBUFFER_H_
-#include <drm/drmP.h>
-#include <drm/drm_fb_helper.h>
-
#include "psb_drv.h"
-struct psb_framebuffer {
- struct drm_framebuffer base;
- struct address_space *addr_space;
- struct fb_info *fbdev;
- struct gtt_range *gtt;
-};
-
-struct psb_fbdev {
- struct drm_fb_helper psb_fb_helper;
- struct psb_framebuffer pfb;
-};
-
-#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
-
-extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
+extern int gma_connector_clones(struct drm_device *dev, int type_mask);
#endif
diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c
index eefd6cc5b80d..2e44a2ac2742 100644
--- a/drivers/gpu/drm/gma500/gem.c
+++ b/drivers/gpu/drm/gma500/gem.c
@@ -1,21 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* psb GEM interface
*
* Copyright (c) 2011, Intel Corporation.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors: Alan Cox
*
* TODO:
@@ -23,132 +11,185 @@
* accelerated operations on a GEM object)
*/
-#include <drm/drmP.h>
+#include <linux/pagemap.h>
+
+#include <asm/set_memory.h>
+
#include <drm/drm.h>
-#include <drm/gma_drm.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vma_manager.h>
+
+#include "gem.h"
#include "psb_drv.h"
-int psb_gem_init_object(struct drm_gem_object *obj)
-{
- return -EINVAL;
-}
+/*
+ * PSB GEM object
+ */
-void psb_gem_free_object(struct drm_gem_object *obj)
+int psb_gem_pin(struct psb_gem_object *pobj)
{
- struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
+ struct drm_gem_object *obj = &pobj->base;
+ struct drm_device *dev = obj->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ u32 gpu_base = dev_priv->gtt.gatt_start;
+ struct page **pages;
+ unsigned int npages;
+ int ret;
- /* Remove the list map if one is present */
- if (obj->map_list.map)
- drm_gem_free_mmap_offset(obj);
- drm_gem_object_release(obj);
+ ret = dma_resv_lock(obj->resv, NULL);
+ if (drm_WARN_ONCE(dev, ret, "dma_resv_lock() failed, ret=%d\n", ret))
+ return ret;
+
+ if (pobj->in_gart || pobj->stolen)
+ goto out; /* already mapped */
+
+ pages = drm_gem_get_pages(obj);
+ if (IS_ERR(pages)) {
+ ret = PTR_ERR(pages);
+ goto err_dma_resv_unlock;
+ }
+
+ npages = obj->size / PAGE_SIZE;
- /* This must occur last as it frees up the memory of the GEM object */
- psb_gtt_free_range(obj->dev, gtt);
+ set_pages_array_wc(pages, npages);
+
+ psb_gtt_insert_pages(dev_priv, &pobj->resource, pages);
+ psb_mmu_insert_pages(psb_mmu_get_default_pd(dev_priv->mmu), pages,
+ (gpu_base + pobj->offset), npages, 0, 0,
+ PSB_MMU_CACHED_MEMORY);
+
+ pobj->pages = pages;
+
+out:
+ ++pobj->in_gart;
+ dma_resv_unlock(obj->resv);
+
+ return 0;
+
+err_dma_resv_unlock:
+ dma_resv_unlock(obj->resv);
+ return ret;
}
-int psb_gem_get_aperture(struct drm_device *dev, void *data,
- struct drm_file *file)
+void psb_gem_unpin(struct psb_gem_object *pobj)
{
- return -EINVAL;
+ struct drm_gem_object *obj = &pobj->base;
+ struct drm_device *dev = obj->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ u32 gpu_base = dev_priv->gtt.gatt_start;
+ unsigned long npages;
+ int ret;
+
+ ret = dma_resv_lock(obj->resv, NULL);
+ if (drm_WARN_ONCE(dev, ret, "dma_resv_lock() failed, ret=%d\n", ret))
+ return;
+
+ WARN_ON(!pobj->in_gart);
+
+ --pobj->in_gart;
+
+ if (pobj->in_gart || pobj->stolen)
+ goto out;
+
+ npages = obj->size / PAGE_SIZE;
+
+ psb_mmu_remove_pages(psb_mmu_get_default_pd(dev_priv->mmu),
+ (gpu_base + pobj->offset), npages, 0, 0);
+ psb_gtt_remove_pages(dev_priv, &pobj->resource);
+
+ /* Reset caching flags */
+ set_pages_array_wb(pobj->pages, npages);
+
+ drm_gem_put_pages(obj, pobj->pages, true, false);
+ pobj->pages = NULL;
+
+out:
+ dma_resv_unlock(obj->resv);
}
-/**
- * psb_gem_dumb_map_gtt - buffer mapping for dumb interface
- * @file: our drm client file
- * @dev: drm device
- * @handle: GEM handle to the object (from dumb_create)
- *
- * Do the necessary setup to allow the mapping of the frame buffer
- * into user memory. We don't have to do much here at the moment.
- */
-int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
- uint32_t handle, uint64_t *offset)
+static vm_fault_t psb_gem_fault(struct vm_fault *vmf);
+
+static void psb_gem_free_object(struct drm_gem_object *obj)
{
- int ret = 0;
- struct drm_gem_object *obj;
+ struct psb_gem_object *pobj = to_psb_gem_object(obj);
- if (!(dev->driver->driver_features & DRIVER_GEM))
- return -ENODEV;
+ /* Undo the mmap pin if we are destroying the object */
+ if (pobj->mmapping)
+ psb_gem_unpin(pobj);
- mutex_lock(&dev->struct_mutex);
+ drm_gem_object_release(obj);
- /* GEM does all our handle to object mapping */
- obj = drm_gem_object_lookup(dev, file, handle);
- if (obj == NULL) {
- ret = -ENOENT;
- goto unlock;
- }
- /* What validation is needed here ? */
+ WARN_ON(pobj->in_gart && !pobj->stolen);
- /* Make it mmapable */
- if (!obj->map_list.map) {
- ret = drm_gem_create_mmap_offset(obj);
- if (ret)
- goto out;
- }
- /* GEM should really work out the hash offsets for us */
- *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
-out:
- drm_gem_object_unreference(obj);
-unlock:
- mutex_unlock(&dev->struct_mutex);
- return ret;
+ release_resource(&pobj->resource);
+ kfree(pobj);
}
-/**
- * psb_gem_create - create a mappable object
- * @file: the DRM file of the client
- * @dev: our device
- * @size: the size requested
- * @handlep: returned handle (opaque number)
- *
- * Create a GEM object, fill in the boilerplate and attach a handle to
- * it so that userspace can speak about it. This does the core work
- * for the various methods that do/will create GEM objects for things
- */
-static int psb_gem_create(struct drm_file *file,
- struct drm_device *dev, uint64_t size, uint32_t *handlep)
+static const struct vm_operations_struct psb_gem_vm_ops = {
+ .fault = psb_gem_fault,
+ .open = drm_gem_vm_open,
+ .close = drm_gem_vm_close,
+};
+
+static const struct drm_gem_object_funcs psb_gem_object_funcs = {
+ .free = psb_gem_free_object,
+ .vm_ops = &psb_gem_vm_ops,
+};
+
+struct psb_gem_object *
+psb_gem_create(struct drm_device *dev, u64 size, const char *name, bool stolen, u32 align)
{
- struct gtt_range *r;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct psb_gem_object *pobj;
+ struct drm_gem_object *obj;
int ret;
- u32 handle;
size = roundup(size, PAGE_SIZE);
- /* Allocate our object - for now a direct gtt range which is not
- stolen memory backed */
- r = psb_gtt_alloc_range(dev, size, "gem", 0);
- if (r == NULL) {
- dev_err(dev->dev, "no memory for %lld byte GEM object\n", size);
- return -ENOSPC;
- }
- /* Initialize the extra goodies GEM needs to do all the hard work */
- if (drm_gem_object_init(dev, &r->gem, size) != 0) {
- psb_gtt_free_range(dev, r);
- /* GEM doesn't give an error code so use -ENOMEM */
- dev_err(dev->dev, "GEM init failed for %lld\n", size);
- return -ENOMEM;
+ pobj = kzalloc(sizeof(*pobj), GFP_KERNEL);
+ if (!pobj)
+ return ERR_PTR(-ENOMEM);
+ obj = &pobj->base;
+
+ /* GTT resource */
+
+ ret = psb_gtt_allocate_resource(dev_priv, &pobj->resource, name, size, align, stolen,
+ &pobj->offset);
+ if (ret)
+ goto err_kfree;
+
+ if (stolen) {
+ pobj->stolen = true;
+ pobj->in_gart = 1;
}
- /* Limit the object to 32bit mappings */
- mapping_set_gfp_mask(r->gem.filp->f_mapping, GFP_KERNEL | __GFP_DMA32);
- /* Give the object a handle so we can carry it more easily */
- ret = drm_gem_handle_create(file, &r->gem, &handle);
- if (ret) {
- dev_err(dev->dev, "GEM handle failed for %p, %lld\n",
- &r->gem, size);
- drm_gem_object_release(&r->gem);
- psb_gtt_free_range(dev, r);
- return ret;
+
+ /* GEM object */
+
+ obj->funcs = &psb_gem_object_funcs;
+
+ if (stolen) {
+ drm_gem_private_object_init(dev, obj, size);
+ } else {
+ ret = drm_gem_object_init(dev, obj, size);
+ if (ret)
+ goto err_release_resource;
+
+ /* Limit the object to 32-bit mappings */
+ mapping_set_gfp_mask(obj->filp->f_mapping, GFP_KERNEL | __GFP_DMA32);
}
- /* We have the initial and handle reference but need only one now */
- drm_gem_object_unreference(&r->gem);
- *handlep = handle;
- return 0;
+
+ return pobj;
+
+err_release_resource:
+ release_resource(&pobj->resource);
+err_kfree:
+ kfree(pobj);
+ return ERR_PTR(ret);
}
/**
* psb_gem_dumb_create - create a dumb buffer
- * @drm_file: our client file
+ * @file: our client file
* @dev: our device
* @args: the requested arguments copied from userspace
*
@@ -159,31 +200,44 @@ static int psb_gem_create(struct drm_file *file,
int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args)
{
- args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
- args->size = args->pitch * args->height;
- return psb_gem_create(file, dev, args->size, &args->handle);
-}
+ size_t pitch, size;
+ struct psb_gem_object *pobj;
+ struct drm_gem_object *obj;
+ u32 handle;
+ int ret;
-/**
- * psb_gem_dumb_destroy - destroy a dumb buffer
- * @file: client file
- * @dev: our DRM device
- * @handle: the object handle
- *
- * Destroy a handle that was created via psb_gem_dumb_create, at least
- * we hope it was created that way. i915 seems to assume the caller
- * does the checking but that might be worth review ! FIXME
- */
-int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
- uint32_t handle)
-{
- /* No special work needed, drop the reference and see what falls out */
- return drm_gem_handle_delete(file, handle);
+ pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
+ pitch = ALIGN(pitch, 64);
+
+ size = pitch * args->height;
+ size = roundup(size, PAGE_SIZE);
+ if (!size)
+ return -EINVAL;
+
+ pobj = psb_gem_create(dev, size, "gem", false, PAGE_SIZE);
+ if (IS_ERR(pobj))
+ return PTR_ERR(pobj);
+ obj = &pobj->base;
+
+ ret = drm_gem_handle_create(file, obj, &handle);
+ if (ret)
+ goto err_drm_gem_object_put;
+
+ drm_gem_object_put(obj);
+
+ args->pitch = pitch;
+ args->size = size;
+ args->handle = handle;
+
+ return 0;
+
+err_drm_gem_object_put:
+ drm_gem_object_put(obj);
+ return ret;
}
/**
* psb_gem_fault - pagefault handler for GEM objects
- * @vma: the VMA of the GEM object
* @vmf: fault detail
*
* Invoked when a fault occurs on an mmap of a GEM managed area. GEM
@@ -198,11 +252,13 @@ int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
* vma->vm_private_data points to the GEM object that is backing this
* mapping.
*/
-int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+static vm_fault_t psb_gem_fault(struct vm_fault *vmf)
{
+ struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *obj;
- struct gtt_range *r;
- int ret;
+ struct psb_gem_object *pobj;
+ int err;
+ vm_fault_t ret;
unsigned long pfn;
pgoff_t page_offset;
struct drm_device *dev;
@@ -210,90 +266,167 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
obj = vma->vm_private_data; /* GEM object */
dev = obj->dev;
- dev_priv = dev->dev_private;
+ dev_priv = to_drm_psb_private(dev);
- r = container_of(obj, struct gtt_range, gem); /* Get the gtt range */
+ pobj = to_psb_gem_object(obj);
/* Make sure we don't parallel update on a fault, nor move or remove
something from beneath our feet */
- mutex_lock(&dev->struct_mutex);
+ mutex_lock(&dev_priv->mmap_mutex);
/* For now the mmap pins the object and it stays pinned. As things
stand that will do us no harm */
- if (r->mmapping == 0) {
- ret = psb_gtt_pin(r);
- if (ret < 0) {
- dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
+ if (pobj->mmapping == 0) {
+ err = psb_gem_pin(pobj);
+ if (err < 0) {
+ dev_err(dev->dev, "gma500: pin failed: %d\n", err);
+ ret = vmf_error(err);
goto fail;
}
- r->mmapping = 1;
+ pobj->mmapping = 1;
}
/* Page relative to the VMA start - we must calculate this ourselves
because vmf->pgoff is the fake GEM offset */
- page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
- >> PAGE_SHIFT;
+ page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
/* CPU view of the page, don't go via the GART for CPU writes */
- if (r->stolen)
- pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
+ if (pobj->stolen)
+ pfn = (dev_priv->stolen_base + pobj->offset) >> PAGE_SHIFT;
else
- pfn = page_to_pfn(r->pages[page_offset]);
- ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
-
+ pfn = page_to_pfn(pobj->pages[page_offset]);
+ ret = vmf_insert_pfn(vma, vmf->address, pfn);
fail:
- mutex_unlock(&dev->struct_mutex);
- switch (ret) {
- case 0:
- case -ERESTARTSYS:
- case -EINTR:
- return VM_FAULT_NOPAGE;
- case -ENOMEM:
- return VM_FAULT_OOM;
- default:
- return VM_FAULT_SIGBUS;
- }
-}
+ mutex_unlock(&dev_priv->mmap_mutex);
-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, &gtt->gem, size) != 0)
- goto free_gtt;
- if (drm_gem_handle_create(file, &gtt->gem, handle) == 0)
- return 0;
-free_gtt:
- psb_gtt_free_range(dev, gtt);
- return -ENOMEM;
+ return ret;
}
/*
- * GEM interfaces for our specific client
+ * Memory management
*/
-int psb_gem_create_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
+
+/* Insert vram stolen pages into the GTT. */
+static void psb_gem_mm_populate_stolen(struct drm_psb_private *pdev)
+{
+ struct drm_device *dev = &pdev->dev;
+ unsigned int pfn_base;
+ unsigned int i, num_pages;
+ uint32_t pte;
+
+ pfn_base = pdev->stolen_base >> PAGE_SHIFT;
+ num_pages = pdev->vram_stolen_size >> PAGE_SHIFT;
+
+ drm_dbg(dev, "Set up %u stolen pages starting at 0x%08x, GTT offset %dK\n",
+ num_pages, pfn_base << PAGE_SHIFT, 0);
+
+ for (i = 0; i < num_pages; ++i) {
+ pte = psb_gtt_mask_pte(pfn_base + i, PSB_MMU_CACHED_MEMORY);
+ iowrite32(pte, pdev->gtt_map + i);
+ }
+
+ (void)ioread32(pdev->gtt_map + i - 1);
+}
+
+int psb_gem_mm_init(struct drm_device *dev)
{
- struct drm_psb_gem_create *args = data;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ unsigned long stolen_size, vram_stolen_size;
+ struct psb_gtt *pg;
int ret;
- if (args->flags & GMA_GEM_CREATE_STOLEN) {
- ret = psb_gem_create_stolen(file, dev, args->size,
- &args->handle);
- if (ret == 0)
- return 0;
- /* Fall throguh */
- args->flags &= ~GMA_GEM_CREATE_STOLEN;
+
+ mutex_init(&dev_priv->mmap_mutex);
+
+ pg = &dev_priv->gtt;
+
+ pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base);
+ vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE;
+
+ stolen_size = vram_stolen_size;
+
+ dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n",
+ dev_priv->stolen_base, vram_stolen_size / 1024);
+
+ pg->stolen_size = stolen_size;
+ dev_priv->vram_stolen_size = vram_stolen_size;
+
+ dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
+ if (!dev_priv->vram_addr) {
+ dev_err(dev->dev, "Failure to map stolen base.\n");
+ ret = -ENOMEM;
+ goto err_mutex_destroy;
}
- return psb_gem_create(file, dev, args->size, &args->handle);
+
+ psb_gem_mm_populate_stolen(dev_priv);
+
+ return 0;
+
+err_mutex_destroy:
+ mutex_destroy(&dev_priv->mmap_mutex);
+ return ret;
}
-int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
+void psb_gem_mm_fini(struct drm_device *dev)
{
- struct drm_psb_gem_mmap *args = data;
- return dev->driver->dumb_map_offset(file, dev,
- args->handle, &args->offset);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
+ iounmap(dev_priv->vram_addr);
+
+ mutex_destroy(&dev_priv->mmap_mutex);
}
+/* Re-insert all pinned GEM objects into GTT. */
+static void psb_gem_mm_populate_resources(struct drm_psb_private *pdev)
+{
+ unsigned int restored = 0, total = 0, size = 0;
+ struct resource *r = pdev->gtt_mem->child;
+ struct drm_device *dev = &pdev->dev;
+ struct psb_gem_object *pobj;
+
+ while (r) {
+ /*
+ * TODO: GTT restoration needs a refactoring, so that we don't have to touch
+ * struct psb_gem_object here. The type represents a GEM object and is
+ * not related to the GTT itself.
+ */
+ pobj = container_of(r, struct psb_gem_object, resource);
+ if (pobj->pages) {
+ psb_gtt_insert_pages(pdev, &pobj->resource, pobj->pages);
+ size += resource_size(&pobj->resource);
+ ++restored;
+ }
+ r = r->sibling;
+ ++total;
+ }
+
+ drm_dbg(dev, "Restored %u of %u gtt ranges (%u KB)", restored, total, (size / 1024));
+}
+
+int psb_gem_mm_resume(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ unsigned long stolen_size, vram_stolen_size;
+ struct psb_gtt *pg;
+
+ pg = &dev_priv->gtt;
+
+ pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base);
+ vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE;
+
+ stolen_size = vram_stolen_size;
+
+ dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", dev_priv->stolen_base,
+ vram_stolen_size / 1024);
+
+ if (stolen_size != pg->stolen_size) {
+ dev_err(dev->dev, "GTT resume error.\n");
+ return -EINVAL;
+ }
+
+ psb_gem_mm_populate_stolen(dev_priv);
+ psb_gem_mm_populate_resources(dev_priv);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/gma500/gem.h b/drivers/gpu/drm/gma500/gem.h
new file mode 100644
index 000000000000..27df6ff4ed37
--- /dev/null
+++ b/drivers/gpu/drm/gma500/gem.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/**************************************************************************
+ * Copyright (c) 2014 Patrik Jakobsson
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+#ifndef _GEM_H
+#define _GEM_H
+
+#include <linux/kernel.h>
+
+#include <drm/drm_gem.h>
+
+struct drm_device;
+
+/*
+ * PSB GEM object
+ */
+
+struct psb_gem_object {
+ struct drm_gem_object base;
+
+ struct resource resource; /* GTT resource for our allocation */
+ u32 offset; /* GTT offset of our object */
+ int in_gart; /* Currently in the GART (ref ct) */
+ bool stolen; /* Backed from stolen RAM */
+ bool mmapping; /* Is mmappable */
+ struct page **pages; /* Backing pages if present */
+};
+
+static inline struct psb_gem_object *to_psb_gem_object(struct drm_gem_object *obj)
+{
+ return container_of(obj, struct psb_gem_object, base);
+}
+
+struct psb_gem_object *
+psb_gem_create(struct drm_device *dev, u64 size, const char *name, bool stolen, u32 align);
+
+int psb_gem_pin(struct psb_gem_object *pobj);
+void psb_gem_unpin(struct psb_gem_object *pobj);
+
+/*
+ * Memory management
+ */
+
+int psb_gem_mm_init(struct drm_device *dev);
+void psb_gem_mm_fini(struct drm_device *dev);
+int psb_gem_mm_resume(struct drm_device *dev);
+
+#endif
diff --git a/drivers/gpu/drm/gma500/gma_device.c b/drivers/gpu/drm/gma500/gma_device.c
new file mode 100644
index 000000000000..954f3a275d81
--- /dev/null
+++ b/drivers/gpu/drm/gma500/gma_device.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+#include "psb_drv.h"
+#include "gma_device.h"
+
+void gma_get_core_freq(struct drm_device *dev)
+{
+ uint32_t clock;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ struct pci_dev *pci_root =
+ pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
+ 0, 0);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
+ /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
+ /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
+
+ pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
+ pci_read_config_dword(pci_root, 0xD4, &clock);
+ pci_dev_put(pci_root);
+
+ switch (clock & 0x07) {
+ case 0:
+ dev_priv->core_freq = 100;
+ break;
+ case 1:
+ dev_priv->core_freq = 133;
+ break;
+ case 2:
+ dev_priv->core_freq = 150;
+ break;
+ case 3:
+ dev_priv->core_freq = 178;
+ break;
+ case 4:
+ dev_priv->core_freq = 200;
+ break;
+ case 5:
+ case 6:
+ case 7:
+ dev_priv->core_freq = 266;
+ break;
+ default:
+ dev_priv->core_freq = 0;
+ }
+}
diff --git a/drivers/gpu/drm/gma500/gma_device.h b/drivers/gpu/drm/gma500/gma_device.h
new file mode 100644
index 000000000000..a8cf31d4b814
--- /dev/null
+++ b/drivers/gpu/drm/gma500/gma_device.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+#ifndef _GMA_DEVICE_H
+#define _GMA_DEVICE_H
+struct drm_device;
+
+extern void gma_get_core_freq(struct drm_device *dev);
+
+#endif
diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c
new file mode 100644
index 000000000000..f65e90d890f4
--- /dev/null
+++ b/drivers/gpu/drm/gma500/gma_display.c
@@ -0,0 +1,811 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright © 2006-2011 Intel Corporation
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/highmem.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_vblank.h>
+
+#include "framebuffer.h"
+#include "gem.h"
+#include "gma_display.h"
+#include "psb_irq.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+
+/*
+ * Returns whether any output on the specified pipe is of the specified type
+ */
+bool gma_pipe_has_type(struct drm_crtc *crtc, int type)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_connector_list_iter conn_iter;
+ struct drm_connector *connector;
+
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ if (connector->encoder && connector->encoder->crtc == crtc) {
+ struct gma_encoder *gma_encoder =
+ gma_attached_encoder(connector);
+ if (gma_encoder->type == type) {
+ drm_connector_list_iter_end(&conn_iter);
+ return true;
+ }
+ }
+ }
+ drm_connector_list_iter_end(&conn_iter);
+
+ return false;
+}
+
+void gma_wait_for_vblank(struct drm_device *dev)
+{
+ /* Wait for 20ms, i.e. one cycle at 50hz. */
+ mdelay(20);
+}
+
+int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ struct drm_framebuffer *fb = crtc->primary->fb;
+ struct psb_gem_object *pobj;
+ int pipe = gma_crtc->pipe;
+ const struct psb_offset *map = &dev_priv->regmap[pipe];
+ unsigned long start, offset;
+ u32 dspcntr;
+ int ret = 0;
+
+ if (!gma_power_begin(dev, true))
+ return 0;
+
+ /* no fb bound */
+ if (!fb) {
+ dev_err(dev->dev, "No FB bound\n");
+ goto gma_pipe_cleaner;
+ }
+
+ pobj = to_psb_gem_object(fb->obj[0]);
+
+ /* We are displaying this buffer, make sure it is actually loaded
+ into the GTT */
+ ret = psb_gem_pin(pobj);
+ if (ret < 0)
+ goto gma_pipe_set_base_exit;
+ start = pobj->offset;
+ offset = y * fb->pitches[0] + x * fb->format->cpp[0];
+
+ REG_WRITE(map->stride, fb->pitches[0]);
+
+ dspcntr = REG_READ(map->cntr);
+ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+
+ switch (fb->format->cpp[0] * 8) {
+ case 8:
+ dspcntr |= DISPPLANE_8BPP;
+ break;
+ case 16:
+ if (fb->format->depth == 15)
+ dspcntr |= DISPPLANE_15_16BPP;
+ else
+ dspcntr |= DISPPLANE_16BPP;
+ break;
+ case 24:
+ case 32:
+ dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+ break;
+ default:
+ dev_err(dev->dev, "Unknown color depth\n");
+ ret = -EINVAL;
+ goto gma_pipe_set_base_exit;
+ }
+ REG_WRITE(map->cntr, dspcntr);
+
+ dev_dbg(dev->dev,
+ "Writing base %08lX %08lX %d %d\n", start, offset, x, y);
+
+ /* FIXME: Investigate whether this really is the base for psb and why
+ the linear offset is named base for the other chips. map->surf
+ should be the base and map->linoff the offset for all chips */
+ if (IS_PSB(dev)) {
+ REG_WRITE(map->base, offset + start);
+ REG_READ(map->base);
+ } else {
+ REG_WRITE(map->base, offset);
+ REG_READ(map->base);
+ REG_WRITE(map->surf, start);
+ REG_READ(map->surf);
+ }
+
+gma_pipe_cleaner:
+ /* If there was a previous display we can now unpin it */
+ if (old_fb)
+ psb_gem_unpin(to_psb_gem_object(old_fb->obj[0]));
+
+gma_pipe_set_base_exit:
+ gma_power_end(dev);
+ return ret;
+}
+
+/* Loads the palette/gamma unit for the CRTC with the prepared values */
+void gma_crtc_load_lut(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ const struct psb_offset *map = &dev_priv->regmap[gma_crtc->pipe];
+ int palreg = map->palette;
+ u16 *r, *g, *b;
+ int i;
+
+ /* The clocks have to be on to load the palette. */
+ if (!crtc->enabled)
+ return;
+
+ r = crtc->gamma_store;
+ g = r + crtc->gamma_size;
+ b = g + crtc->gamma_size;
+
+ if (gma_power_begin(dev, false)) {
+ for (i = 0; i < 256; i++) {
+ REG_WRITE(palreg + 4 * i,
+ (((*r++ >> 8) + gma_crtc->lut_adj[i]) << 16) |
+ (((*g++ >> 8) + gma_crtc->lut_adj[i]) << 8) |
+ ((*b++ >> 8) + gma_crtc->lut_adj[i]));
+ }
+ gma_power_end(dev);
+ } else {
+ for (i = 0; i < 256; i++) {
+ /* FIXME: Why pipe[0] and not pipe[..._crtc->pipe]? */
+ dev_priv->regs.pipe[0].palette[i] =
+ (((*r++ >> 8) + gma_crtc->lut_adj[i]) << 16) |
+ (((*g++ >> 8) + gma_crtc->lut_adj[i]) << 8) |
+ ((*b++ >> 8) + gma_crtc->lut_adj[i]);
+ }
+
+ }
+}
+
+static int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
+ u16 *blue, u32 size,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ gma_crtc_load_lut(crtc);
+
+ return 0;
+}
+
+/*
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+void gma_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ int pipe = gma_crtc->pipe;
+ const struct psb_offset *map = &dev_priv->regmap[pipe];
+ u32 temp;
+
+ /* XXX: When our outputs are all unaware of DPMS modes other than off
+ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+ */
+
+ if (IS_CDV(dev))
+ dev_priv->ops->disable_sr(dev);
+
+ switch (mode) {
+ case DRM_MODE_DPMS_ON:
+ case DRM_MODE_DPMS_STANDBY:
+ case DRM_MODE_DPMS_SUSPEND:
+ if (gma_crtc->active)
+ break;
+
+ gma_crtc->active = true;
+
+ /* 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 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));
+ }
+
+ udelay(150);
+
+ /* Enable the pipe */
+ temp = REG_READ(map->conf);
+ if ((temp & PIPEACONF_ENABLE) == 0)
+ REG_WRITE(map->conf, temp | PIPEACONF_ENABLE);
+
+ temp = REG_READ(map->status);
+ temp &= ~(0xFFFF);
+ temp |= PIPE_FIFO_UNDERRUN;
+ REG_WRITE(map->status, temp);
+ REG_READ(map->status);
+
+ gma_crtc_load_lut(crtc);
+
+ /* Give the overlay scaler a chance to enable
+ * if it's on this pipe */
+ /* psb_intel_crtc_dpms_video(crtc, true); TODO */
+
+ drm_crtc_vblank_on(crtc);
+ break;
+ case DRM_MODE_DPMS_OFF:
+ if (!gma_crtc->active)
+ break;
+
+ gma_crtc->active = false;
+
+ /* Give the overlay scaler a chance to disable
+ * 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);
+
+ /* Turn off vblank interrupts */
+ drm_crtc_vblank_off(crtc);
+
+ /* Wait for vblank for the disable to take effect */
+ gma_wait_for_vblank(dev);
+
+ /* Disable 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);
+ }
+
+ /* Disable pipe */
+ temp = REG_READ(map->conf);
+ if ((temp & PIPEACONF_ENABLE) != 0) {
+ REG_WRITE(map->conf, temp & ~PIPEACONF_ENABLE);
+ REG_READ(map->conf);
+ }
+
+ /* Wait for vblank for the disable to take effect. */
+ gma_wait_for_vblank(dev);
+
+ udelay(150);
+
+ /* Disable DPLL */
+ 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);
+ break;
+ }
+
+ if (IS_CDV(dev))
+ dev_priv->ops->update_wm(dev, crtc);
+
+ /* Set FIFO watermarks */
+ REG_WRITE(DSPARB, 0x3F3E);
+}
+
+static int gma_crtc_cursor_set(struct drm_crtc *crtc,
+ struct drm_file *file_priv, uint32_t handle,
+ uint32_t width, uint32_t height)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ int pipe = gma_crtc->pipe;
+ uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
+ uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
+ uint32_t temp;
+ size_t addr = 0;
+ struct psb_gem_object *pobj;
+ struct psb_gem_object *cursor_pobj = gma_crtc->cursor_pobj;
+ struct drm_gem_object *obj;
+ void *tmp_dst;
+ int ret = 0, i, cursor_pages;
+
+ /* If we didn't get a handle then turn the cursor off */
+ if (!handle) {
+ temp = CURSOR_MODE_DISABLE;
+ if (gma_power_begin(dev, false)) {
+ REG_WRITE(control, temp);
+ REG_WRITE(base, 0);
+ gma_power_end(dev);
+ }
+
+ /* Unpin the old GEM object */
+ if (gma_crtc->cursor_obj) {
+ pobj = to_psb_gem_object(gma_crtc->cursor_obj);
+ psb_gem_unpin(pobj);
+ drm_gem_object_put(gma_crtc->cursor_obj);
+ gma_crtc->cursor_obj = NULL;
+ }
+ return 0;
+ }
+
+ /* Currently we only support 64x64 cursors */
+ if (width != 64 || height != 64) {
+ dev_dbg(dev->dev, "We currently only support 64x64 cursors\n");
+ return -EINVAL;
+ }
+
+ obj = drm_gem_object_lookup(file_priv, handle);
+ if (!obj) {
+ ret = -ENOENT;
+ goto unlock;
+ }
+
+ if (obj->size < width * height * 4) {
+ dev_dbg(dev->dev, "Buffer is too small\n");
+ ret = -ENOMEM;
+ goto unref_cursor;
+ }
+
+ pobj = to_psb_gem_object(obj);
+
+ /* Pin the memory into the GTT */
+ ret = psb_gem_pin(pobj);
+ if (ret) {
+ dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
+ goto unref_cursor;
+ }
+
+ if (dev_priv->ops->cursor_needs_phys) {
+ if (!cursor_pobj) {
+ dev_err(dev->dev, "No hardware cursor mem available");
+ ret = -ENOMEM;
+ goto unref_cursor;
+ }
+
+ cursor_pages = obj->size / PAGE_SIZE;
+ if (cursor_pages > 4)
+ cursor_pages = 4; /* Prevent overflow */
+
+ /* Copy the cursor to cursor mem */
+ tmp_dst = dev_priv->vram_addr + cursor_pobj->offset;
+ for (i = 0; i < cursor_pages; i++) {
+ memcpy_from_page(tmp_dst, pobj->pages[i], 0, PAGE_SIZE);
+ tmp_dst += PAGE_SIZE;
+ }
+
+ addr = gma_crtc->cursor_addr;
+ } else {
+ addr = pobj->offset;
+ gma_crtc->cursor_addr = addr;
+ }
+
+ temp = 0;
+ /* set the pipe for the cursor */
+ temp |= (pipe << 28);
+ temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+
+ if (gma_power_begin(dev, false)) {
+ REG_WRITE(control, temp);
+ REG_WRITE(base, addr);
+ gma_power_end(dev);
+ }
+
+ /* unpin the old bo */
+ if (gma_crtc->cursor_obj) {
+ pobj = to_psb_gem_object(gma_crtc->cursor_obj);
+ psb_gem_unpin(pobj);
+ drm_gem_object_put(gma_crtc->cursor_obj);
+ }
+
+ gma_crtc->cursor_obj = obj;
+unlock:
+ return ret;
+
+unref_cursor:
+ drm_gem_object_put(obj);
+ return ret;
+}
+
+static int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+ struct drm_device *dev = crtc->dev;
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ int pipe = gma_crtc->pipe;
+ uint32_t temp = 0;
+ uint32_t addr;
+
+ if (x < 0) {
+ temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+ x = -x;
+ }
+ if (y < 0) {
+ temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+ y = -y;
+ }
+
+ temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+ temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+ addr = gma_crtc->cursor_addr;
+
+ if (gma_power_begin(dev, false)) {
+ REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
+ REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr);
+ gma_power_end(dev);
+ }
+ return 0;
+}
+
+void gma_crtc_prepare(struct drm_crtc *crtc)
+{
+ const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+void gma_crtc_commit(struct drm_crtc *crtc)
+{
+ const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+void gma_crtc_disable(struct drm_crtc *crtc)
+{
+ struct psb_gem_object *pobj;
+ const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+
+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+
+ if (crtc->primary->fb) {
+ pobj = to_psb_gem_object(crtc->primary->fb->obj[0]);
+ psb_gem_unpin(pobj);
+ }
+}
+
+void gma_crtc_destroy(struct drm_crtc *crtc)
+{
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+
+ if (gma_crtc->cursor_pobj)
+ drm_gem_object_put(&gma_crtc->cursor_pobj->base);
+
+ kfree(gma_crtc->crtc_state);
+ drm_crtc_cleanup(crtc);
+ kfree(gma_crtc);
+}
+
+int gma_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ struct drm_framebuffer *current_fb = crtc->primary->fb;
+ struct drm_framebuffer *old_fb = crtc->primary->old_fb;
+ const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+ int ret;
+
+ if (!crtc_funcs->mode_set_base)
+ return -EINVAL;
+
+ /* Using mode_set_base requires the new fb to be set already. */
+ crtc->primary->fb = fb;
+
+ if (event) {
+ spin_lock_irqsave(&dev->event_lock, flags);
+
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ gma_crtc->page_flip_event = event;
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+
+ /* Call this locked if we want an event at vblank interrupt. */
+ ret = crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb);
+ if (ret) {
+ spin_lock_irqsave(&dev->event_lock, flags);
+ if (gma_crtc->page_flip_event) {
+ gma_crtc->page_flip_event = NULL;
+ drm_crtc_vblank_put(crtc);
+ }
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
+ } else {
+ ret = crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb);
+ }
+
+ /* Restore previous fb in case of failure. */
+ if (ret)
+ crtc->primary->fb = current_fb;
+
+ return ret;
+}
+
+const struct drm_crtc_funcs gma_crtc_funcs = {
+ .cursor_set = gma_crtc_cursor_set,
+ .cursor_move = gma_crtc_cursor_move,
+ .gamma_set = gma_crtc_gamma_set,
+ .set_config = drm_crtc_helper_set_config,
+ .destroy = gma_crtc_destroy,
+ .page_flip = gma_crtc_page_flip,
+ .enable_vblank = gma_crtc_enable_vblank,
+ .disable_vblank = gma_crtc_disable_vblank,
+ .get_vblank_counter = gma_crtc_get_vblank_counter,
+};
+
+/*
+ * Save HW states of given crtc
+ */
+void gma_crtc_save(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ struct psb_intel_crtc_state *crtc_state = gma_crtc->crtc_state;
+ const struct psb_offset *map = &dev_priv->regmap[gma_crtc->pipe];
+ uint32_t palette_reg;
+ int i;
+
+ if (!crtc_state) {
+ dev_err(dev->dev, "No CRTC state found\n");
+ return;
+ }
+
+ crtc_state->saveDSPCNTR = REG_READ(map->cntr);
+ crtc_state->savePIPECONF = REG_READ(map->conf);
+ crtc_state->savePIPESRC = REG_READ(map->src);
+ crtc_state->saveFP0 = REG_READ(map->fp0);
+ crtc_state->saveFP1 = REG_READ(map->fp1);
+ crtc_state->saveDPLL = REG_READ(map->dpll);
+ crtc_state->saveHTOTAL = REG_READ(map->htotal);
+ crtc_state->saveHBLANK = REG_READ(map->hblank);
+ crtc_state->saveHSYNC = REG_READ(map->hsync);
+ crtc_state->saveVTOTAL = REG_READ(map->vtotal);
+ crtc_state->saveVBLANK = REG_READ(map->vblank);
+ crtc_state->saveVSYNC = REG_READ(map->vsync);
+ crtc_state->saveDSPSTRIDE = REG_READ(map->stride);
+
+ /* NOTE: DSPSIZE DSPPOS only for psb */
+ crtc_state->saveDSPSIZE = REG_READ(map->size);
+ crtc_state->saveDSPPOS = REG_READ(map->pos);
+
+ crtc_state->saveDSPBASE = REG_READ(map->base);
+
+ palette_reg = map->palette;
+ for (i = 0; i < 256; ++i)
+ crtc_state->savePalette[i] = REG_READ(palette_reg + (i << 2));
+}
+
+/*
+ * Restore HW states of given crtc
+ */
+void gma_crtc_restore(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ struct psb_intel_crtc_state *crtc_state = gma_crtc->crtc_state;
+ const struct psb_offset *map = &dev_priv->regmap[gma_crtc->pipe];
+ uint32_t palette_reg;
+ int i;
+
+ if (!crtc_state) {
+ dev_err(dev->dev, "No crtc state\n");
+ return;
+ }
+
+ if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
+ REG_WRITE(map->dpll,
+ crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
+ REG_READ(map->dpll);
+ udelay(150);
+ }
+
+ REG_WRITE(map->fp0, crtc_state->saveFP0);
+ REG_READ(map->fp0);
+
+ REG_WRITE(map->fp1, crtc_state->saveFP1);
+ REG_READ(map->fp1);
+
+ REG_WRITE(map->dpll, crtc_state->saveDPLL);
+ REG_READ(map->dpll);
+ udelay(150);
+
+ REG_WRITE(map->htotal, crtc_state->saveHTOTAL);
+ REG_WRITE(map->hblank, crtc_state->saveHBLANK);
+ REG_WRITE(map->hsync, crtc_state->saveHSYNC);
+ REG_WRITE(map->vtotal, crtc_state->saveVTOTAL);
+ REG_WRITE(map->vblank, crtc_state->saveVBLANK);
+ REG_WRITE(map->vsync, crtc_state->saveVSYNC);
+ REG_WRITE(map->stride, crtc_state->saveDSPSTRIDE);
+
+ REG_WRITE(map->size, crtc_state->saveDSPSIZE);
+ REG_WRITE(map->pos, crtc_state->saveDSPPOS);
+
+ REG_WRITE(map->src, crtc_state->savePIPESRC);
+ REG_WRITE(map->base, crtc_state->saveDSPBASE);
+ REG_WRITE(map->conf, crtc_state->savePIPECONF);
+
+ gma_wait_for_vblank(dev);
+
+ REG_WRITE(map->cntr, crtc_state->saveDSPCNTR);
+ REG_WRITE(map->base, crtc_state->saveDSPBASE);
+
+ gma_wait_for_vblank(dev);
+
+ palette_reg = map->palette;
+ for (i = 0; i < 256; ++i)
+ REG_WRITE(palette_reg + (i << 2), crtc_state->savePalette[i]);
+}
+
+void gma_encoder_prepare(struct drm_encoder *encoder)
+{
+ const struct drm_encoder_helper_funcs *encoder_funcs =
+ encoder->helper_private;
+ /* lvds has its own version of prepare see psb_intel_lvds_prepare */
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+void gma_encoder_commit(struct drm_encoder *encoder)
+{
+ const struct drm_encoder_helper_funcs *encoder_funcs =
+ encoder->helper_private;
+ /* lvds has its own version of commit see psb_intel_lvds_commit */
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+void gma_encoder_destroy(struct drm_encoder *encoder)
+{
+ struct gma_encoder *intel_encoder = to_gma_encoder(encoder);
+
+ drm_encoder_cleanup(encoder);
+ kfree(intel_encoder);
+}
+
+/* Currently there is only a 1:1 mapping of encoders and connectors */
+struct drm_encoder *gma_best_encoder(struct drm_connector *connector)
+{
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
+
+ return &gma_encoder->base;
+}
+
+void gma_connector_attach_encoder(struct gma_connector *connector,
+ struct gma_encoder *encoder)
+{
+ connector->encoder = encoder;
+ drm_connector_attach_encoder(&connector->base,
+ &encoder->base);
+}
+
+#define GMA_PLL_INVALID(s) { /* DRM_ERROR(s); */ return false; }
+
+bool gma_pll_is_valid(struct drm_crtc *crtc,
+ const struct gma_limit_t *limit,
+ struct gma_clock_t *clock)
+{
+ if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
+ GMA_PLL_INVALID("p1 out of range");
+ if (clock->p < limit->p.min || limit->p.max < clock->p)
+ GMA_PLL_INVALID("p out of range");
+ if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
+ GMA_PLL_INVALID("m2 out of range");
+ if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
+ GMA_PLL_INVALID("m1 out of range");
+ /* On CDV m1 is always 0 */
+ if (clock->m1 <= clock->m2 && clock->m1 != 0)
+ GMA_PLL_INVALID("m1 <= m2 && m1 != 0");
+ if (clock->m < limit->m.min || limit->m.max < clock->m)
+ GMA_PLL_INVALID("m out of range");
+ if (clock->n < limit->n.min || limit->n.max < clock->n)
+ GMA_PLL_INVALID("n out of range");
+ if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
+ GMA_PLL_INVALID("vco out of range");
+ /* XXX: We may need to be checking "Dot clock"
+ * depending on the multiplier, connector, etc.,
+ * rather than just a single range.
+ */
+ if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
+ GMA_PLL_INVALID("dot out of range");
+
+ return true;
+}
+
+bool gma_find_best_pll(const struct gma_limit_t *limit,
+ struct drm_crtc *crtc, int target, int refclk,
+ struct gma_clock_t *best_clock)
+{
+ struct drm_device *dev = crtc->dev;
+ const struct gma_clock_funcs *clock_funcs =
+ to_gma_crtc(crtc)->clock_funcs;
+ struct gma_clock_t clock;
+ int err = target;
+
+ if (gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+ (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
+ /*
+ * For LVDS, if the panel is on, just rely on its current
+ * settings for dual-channel. We haven't figured out how to
+ * reliably set up different single/dual channel state, if we
+ * even can.
+ */
+ if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+ LVDS_CLKB_POWER_UP)
+ clock.p2 = limit->p2.p2_fast;
+ else
+ clock.p2 = limit->p2.p2_slow;
+ } else {
+ if (target < limit->p2.dot_limit)
+ clock.p2 = limit->p2.p2_slow;
+ else
+ clock.p2 = limit->p2.p2_fast;
+ }
+
+ memset(best_clock, 0, sizeof(*best_clock));
+
+ /* m1 is always 0 on CDV so the outmost loop will run just once */
+ for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
+ for (clock.m2 = limit->m2.min;
+ (clock.m2 < clock.m1 || clock.m1 == 0) &&
+ clock.m2 <= limit->m2.max; clock.m2++) {
+ 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++) {
+ int this_err;
+
+ clock_funcs->clock(refclk, &clock);
+
+ if (!clock_funcs->pll_is_valid(crtc,
+ limit, &clock))
+ continue;
+
+ this_err = abs(clock.dot - target);
+ if (this_err < err) {
+ *best_clock = clock;
+ err = this_err;
+ }
+ }
+ }
+ }
+ }
+
+ return err != target;
+}
diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h
new file mode 100644
index 000000000000..1188a8d61caf
--- /dev/null
+++ b/drivers/gpu/drm/gma500/gma_display.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2006-2011 Intel Corporation
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+ */
+
+#ifndef _GMA_DISPLAY_H_
+#define _GMA_DISPLAY_H_
+
+#include <linux/pm_runtime.h>
+#include <drm/drm_vblank.h>
+
+struct drm_encoder;
+struct drm_mode_set;
+
+struct gma_clock_t {
+ /* given values */
+ int n;
+ int m1, m2;
+ int p1, p2;
+ /* derived values */
+ int dot;
+ int vco;
+ int m;
+ int p;
+};
+
+struct gma_range_t {
+ int min, max;
+};
+
+struct gma_p2_t {
+ int dot_limit;
+ int p2_slow, p2_fast;
+};
+
+struct gma_limit_t {
+ struct gma_range_t dot, vco, n, m, m1, m2, p, p1;
+ struct gma_p2_t p2;
+ bool (*find_pll)(const struct gma_limit_t *, struct drm_crtc *,
+ int target, int refclk,
+ struct gma_clock_t *best_clock);
+};
+
+struct gma_clock_funcs {
+ void (*clock)(int refclk, struct gma_clock_t *clock);
+ const struct gma_limit_t *(*limit)(struct drm_crtc *crtc, int refclk);
+ bool (*pll_is_valid)(struct drm_crtc *crtc,
+ const struct gma_limit_t *limit,
+ struct gma_clock_t *clock);
+};
+
+/* Common pipe related functions */
+extern bool gma_pipe_has_type(struct drm_crtc *crtc, int type);
+extern void gma_wait_for_vblank(struct drm_device *dev);
+extern int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb);
+extern void gma_crtc_load_lut(struct drm_crtc *crtc);
+extern void gma_crtc_dpms(struct drm_crtc *crtc, int mode);
+extern void gma_crtc_prepare(struct drm_crtc *crtc);
+extern void gma_crtc_commit(struct drm_crtc *crtc);
+extern void gma_crtc_disable(struct drm_crtc *crtc);
+extern void gma_crtc_destroy(struct drm_crtc *crtc);
+extern int gma_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event,
+ uint32_t page_flip_flags,
+ struct drm_modeset_acquire_ctx *ctx);
+
+extern void gma_crtc_save(struct drm_crtc *crtc);
+extern void gma_crtc_restore(struct drm_crtc *crtc);
+
+extern const struct drm_crtc_funcs gma_crtc_funcs;
+
+extern void gma_encoder_prepare(struct drm_encoder *encoder);
+extern void gma_encoder_commit(struct drm_encoder *encoder);
+extern void gma_encoder_destroy(struct drm_encoder *encoder);
+
+/* Common clock related functions */
+extern const struct gma_limit_t *gma_limit(struct drm_crtc *crtc, int refclk);
+extern bool gma_pll_is_valid(struct drm_crtc *crtc,
+ const struct gma_limit_t *limit,
+ struct gma_clock_t *clock);
+extern bool gma_find_best_pll(const struct gma_limit_t *limit,
+ struct drm_crtc *crtc, int target, int refclk,
+ struct gma_clock_t *best_clock);
+#endif
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index 1f82183536a3..379bc218aa6b 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -1,26 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2007, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
* Alan Cox <alan@linux.intel.com>
*/
-#include <drm/drmP.h>
-#include <linux/shmem_fs.h>
+#include "gem.h" /* TODO: for struct psb_gem_object, see psb_gtt_restore() */
#include "psb_drv.h"
@@ -28,6 +15,33 @@
* GTT resource allocator - manage page mappings in GTT space
*/
+int psb_gtt_allocate_resource(struct drm_psb_private *pdev, struct resource *res,
+ const char *name, resource_size_t size, resource_size_t align,
+ bool stolen, u32 *offset)
+{
+ struct resource *root = pdev->gtt_mem;
+ resource_size_t start, end;
+ int ret;
+
+ if (stolen) {
+ /* The start of the GTT is backed by stolen pages. */
+ start = root->start;
+ end = root->start + pdev->gtt.stolen_size - 1;
+ } else {
+ /* The rest is backed by system pages. */
+ start = root->start + pdev->gtt.stolen_size;
+ end = root->end;
+ }
+
+ res->name = name;
+ ret = allocate_resource(root, res, size, start, end, align, NULL, NULL);
+ if (ret)
+ return ret;
+ *offset = res->start - root->start;
+
+ return 0;
+}
+
/**
* psb_gtt_mask_pte - generate GTT pte entry
* @pfn: page number to encode
@@ -35,7 +49,7 @@
*
* Set the GTT entry for the appropriate memory type.
*/
-static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
+uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
{
uint32_t mask = PSB_PTE_VALID;
@@ -53,535 +67,246 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
return (pfn << PAGE_SHIFT) | mask;
}
-/**
- * psb_gtt_entry - find the GTT entries for a gtt_range
- * @dev: our DRM device
- * @r: our GTT range
- *
- * Given a gtt_range object return the GTT offset of the page table
- * entries for this gtt_range
- */
-static u32 __iomem *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
+static u32 __iomem *psb_gtt_entry(struct drm_psb_private *pdev, const struct resource *res)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long offset;
+ unsigned long offset = res->start - pdev->gtt_mem->start;
- offset = r->resource.start - dev_priv->gtt_mem->start;
-
- return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
+ return pdev->gtt_map + (offset >> PAGE_SHIFT);
}
-/**
- * psb_gtt_insert - put an object into the GTT
- * @dev: our DRM device
- * @r: our GTT range
- *
- * Take our preallocated GTT range and insert the GEM object into
- * the GTT. This is protected via the gtt mutex which the caller
- * must hold.
- */
-static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
- int resume)
+/* Acquires GTT mutex internally. */
+void psb_gtt_insert_pages(struct drm_psb_private *pdev, const struct resource *res,
+ struct page **pages)
{
+ resource_size_t npages, i;
u32 __iomem *gtt_slot;
u32 pte;
- struct page **pages;
- int i;
- if (r->pages == NULL) {
- WARN_ON(1);
- return -EINVAL;
- }
+ mutex_lock(&pdev->gtt_mutex);
- WARN_ON(r->stolen); /* refcount these maybe ? */
+ /* Write our page entries into the GTT itself */
- gtt_slot = psb_gtt_entry(dev, r);
- pages = r->pages;
+ npages = resource_size(res) >> PAGE_SHIFT;
+ gtt_slot = psb_gtt_entry(pdev, res);
- if (!resume) {
- /* Make sure changes are visible to the GPU */
- set_pages_array_wc(pages, r->npage);
+ for (i = 0; i < npages; ++i, ++gtt_slot) {
+ pte = psb_gtt_mask_pte(page_to_pfn(pages[i]), PSB_MMU_CACHED_MEMORY);
+ iowrite32(pte, gtt_slot);
}
- /* Write our page entries into the GTT itself */
- for (i = r->roll; i < r->npage; i++) {
- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
- iowrite32(pte, gtt_slot++);
- }
- for (i = 0; i < r->roll; i++) {
- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
- iowrite32(pte, gtt_slot++);
- }
/* Make sure all the entries are set before we return */
ioread32(gtt_slot - 1);
- return 0;
+ mutex_unlock(&pdev->gtt_mutex);
}
-/**
- * psb_gtt_remove - remove an object from the GTT
- * @dev: our DRM device
- * @r: our GTT range
- *
- * Remove a preallocated GTT range from the GTT. Overwrite all the
- * page table entries with the dummy page. This is protected via the gtt
- * mutex which the caller must hold.
- */
-static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
+/* Acquires GTT mutex internally. */
+void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *res)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ resource_size_t npages, i;
u32 __iomem *gtt_slot;
u32 pte;
- int i;
-
- WARN_ON(r->stolen);
-
- gtt_slot = psb_gtt_entry(dev, r);
- pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
- for (i = 0; i < r->npage; i++)
- iowrite32(pte, gtt_slot++);
- ioread32(gtt_slot - 1);
- set_pages_array_wb(r->pages, r->npage);
-}
-
-/**
- * psb_gtt_roll - set scrolling position
- * @dev: our DRM device
- * @r: the gtt mapping we are using
- * @roll: roll offset
- *
- * Roll an existing pinned mapping by moving the pages through the GTT.
- * This allows us to implement hardware scrolling on the consoles without
- * a 2D engine
- */
-void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
-{
- u32 __iomem *gtt_slot;
- u32 pte;
- int i;
+ mutex_lock(&pdev->gtt_mutex);
- if (roll >= r->npage) {
- WARN_ON(1);
- return;
- }
+ /* Install scratch page for the resource */
- r->roll = roll;
+ pte = psb_gtt_mask_pte(page_to_pfn(pdev->scratch_page), PSB_MMU_CACHED_MEMORY);
- /* Not currently in the GTT - no worry we will write the mapping at
- the right position when it gets pinned */
- if (!r->stolen && !r->in_gart)
- return;
+ npages = resource_size(res) >> PAGE_SHIFT;
+ gtt_slot = psb_gtt_entry(pdev, res);
- gtt_slot = psb_gtt_entry(dev, r);
+ for (i = 0; i < npages; ++i, ++gtt_slot)
+ iowrite32(pte, gtt_slot);
- for (i = r->roll; i < r->npage; i++) {
- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
- iowrite32(pte, gtt_slot++);
- }
- for (i = 0; i < r->roll; i++) {
- pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
- iowrite32(pte, gtt_slot++);
- }
+ /* Make sure all the entries are set before we return */
ioread32(gtt_slot - 1);
-}
-/**
- * psb_gtt_attach_pages - attach and pin GEM pages
- * @gt: the gtt range
- *
- * Pin and build an in kernel list of the pages that back our GEM object.
- * While we hold this the pages cannot be swapped out. This is protected
- * via the gtt mutex which the caller must hold.
- */
-static int psb_gtt_attach_pages(struct gtt_range *gt)
-{
- struct inode *inode;
- struct address_space *mapping;
- int i;
- struct page *p;
- int pages = gt->gem.size / PAGE_SIZE;
-
- WARN_ON(gt->pages);
-
- /* This is the shared memory object that backs the GEM resource */
- inode = file_inode(gt->gem.filp);
- mapping = inode->i_mapping;
-
- gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
- if (gt->pages == NULL)
- return -ENOMEM;
- gt->npage = pages;
-
- for (i = 0; i < pages; i++) {
- p = shmem_read_mapping_page(mapping, i);
- if (IS_ERR(p))
- goto err;
- gt->pages[i] = p;
- }
- return 0;
-
-err:
- while (i--)
- page_cache_release(gt->pages[i]);
- kfree(gt->pages);
- gt->pages = NULL;
- return PTR_ERR(p);
+ mutex_unlock(&pdev->gtt_mutex);
}
-/**
- * psb_gtt_detach_pages - attach and pin GEM pages
- * @gt: the gtt range
- *
- * Undo the effect of psb_gtt_attach_pages. At this point the pages
- * must have been removed from the GTT as they could now be paged out
- * and move bus address. This is protected via the gtt mutex which the
- * caller must hold.
- */
-static void psb_gtt_detach_pages(struct gtt_range *gt)
+static int psb_gtt_enable(struct drm_psb_private *dev_priv)
{
- int i;
- for (i = 0; i < gt->npage; i++) {
- /* FIXME: do we need to force dirty */
- set_page_dirty(gt->pages[i]);
- page_cache_release(gt->pages[i]);
- }
- kfree(gt->pages);
- gt->pages = NULL;
-}
+ struct drm_device *dev = &dev_priv->dev;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ int ret;
-/**
- * psb_gtt_pin - pin pages into the GTT
- * @gt: range to pin
- *
- * Pin a set of pages into the GTT. The pins are refcounted so that
- * multiple pins need multiple unpins to undo.
- *
- * Non GEM backed objects treat this as a no-op as they are always GTT
- * backed objects.
- */
-int psb_gtt_pin(struct gtt_range *gt)
-{
- int ret = 0;
- struct drm_device *dev = gt->gem.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- mutex_lock(&dev_priv->gtt_mutex);
-
- if (gt->in_gart == 0 && gt->stolen == 0) {
- ret = psb_gtt_attach_pages(gt);
- if (ret < 0)
- goto out;
- ret = psb_gtt_insert(dev, gt, 0);
- if (ret < 0) {
- psb_gtt_detach_pages(gt);
- goto out;
- }
- }
- gt->in_gart++;
-out:
- mutex_unlock(&dev_priv->gtt_mutex);
- return ret;
-}
+ ret = pci_read_config_word(pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
+ if (ret)
+ return pcibios_err_to_errno(ret);
+ ret = pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
+ if (ret)
+ return pcibios_err_to_errno(ret);
-/**
- * psb_gtt_unpin - Drop a GTT pin requirement
- * @gt: range to pin
- *
- * Undoes the effect of psb_gtt_pin. On the last drop the GEM object
- * will be removed from the GTT which will also drop the page references
- * and allow the VM to clean up or page stuff.
- *
- * Non GEM backed objects treat this as a no-op as they are always GTT
- * backed objects.
- */
-void psb_gtt_unpin(struct gtt_range *gt)
-{
- struct drm_device *dev = gt->gem.dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- mutex_lock(&dev_priv->gtt_mutex);
+ dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
+ PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
- WARN_ON(!gt->in_gart);
+ (void)PSB_RVDC32(PSB_PGETBL_CTL);
- gt->in_gart--;
- if (gt->in_gart == 0 && gt->stolen == 0) {
- psb_gtt_remove(dev, gt);
- psb_gtt_detach_pages(gt);
- }
- mutex_unlock(&dev_priv->gtt_mutex);
+ return 0;
}
-/*
- * GTT resource allocator - allocate and manage GTT address space
- */
-
-/**
- * psb_gtt_alloc_range - allocate GTT address space
- * @dev: Our DRM device
- * @len: length (bytes) of address space required
- * @name: resource name
- * @backed: resource should be backed by stolen pages
- *
- * Ask the kernel core to find us a suitable range of addresses
- * to use for a GTT mapping.
- *
- * Returns a gtt_range structure describing the object, or NULL on
- * error. On successful return the resource is both allocated and marked
- * as in use.
- */
-struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
- const char *name, int backed)
+static void psb_gtt_disable(struct drm_psb_private *dev_priv)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct gtt_range *gt;
- struct resource *r = dev_priv->gtt_mem;
- int ret;
- unsigned long start, end;
+ struct drm_device *dev = &dev_priv->dev;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
- if (backed) {
- /* The start of the GTT is the stolen pages */
- start = r->start;
- end = r->start + dev_priv->gtt.stolen_size - 1;
- } else {
- /* The rest we will use for GEM backed objects */
- start = r->start + dev_priv->gtt.stolen_size;
- end = r->end;
- }
+ pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl);
+ PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
- gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
- if (gt == NULL)
- return NULL;
- gt->resource.name = name;
- gt->stolen = backed;
- gt->in_gart = backed;
- gt->roll = 0;
- /* Ensure this is set for non GEM objects */
- gt->gem.dev = dev;
- ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
- len, start, end, PAGE_SIZE, NULL, NULL);
- if (ret == 0) {
- gt->offset = gt->resource.start - r->start;
- return gt;
- }
- kfree(gt);
- return NULL;
+ (void)PSB_RVDC32(PSB_PGETBL_CTL);
}
-/**
- * psb_gtt_free_range - release GTT address space
- * @dev: our DRM device
- * @gt: a mapping created with psb_gtt_alloc_range
- *
- * Release a resource that was allocated with psb_gtt_alloc_range. If the
- * object has been pinned by mmap users we clean this up here currently.
- */
-void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
+void psb_gtt_fini(struct drm_device *dev)
{
- /* Undo the mmap pin if we are destroying the object */
- if (gt->mmapping) {
- psb_gtt_unpin(gt);
- gt->mmapping = 0;
- }
- WARN_ON(gt->in_gart && !gt->stolen);
- release_resource(&gt->resource);
- kfree(gt);
-}
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
-static void psb_gtt_alloc(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- init_rwsem(&dev_priv->gtt.sem);
+ iounmap(dev_priv->gtt_map);
+ psb_gtt_disable(dev_priv);
+ mutex_destroy(&dev_priv->gtt_mutex);
}
-void psb_gtt_takedown(struct drm_device *dev)
+/* Clear GTT. Use a scratch page to avoid accidents or scribbles. */
+static void psb_gtt_clear(struct drm_psb_private *pdev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (dev_priv->gtt_map) {
- iounmap(dev_priv->gtt_map);
- dev_priv->gtt_map = NULL;
- }
- if (dev_priv->gtt_initialized) {
- pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
- dev_priv->gmch_ctrl);
- PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
- (void) PSB_RVDC32(PSB_PGETBL_CTL);
- }
- if (dev_priv->vram_addr)
- iounmap(dev_priv->gtt_map);
-}
-
-int psb_gtt_init(struct drm_device *dev, int resume)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned gtt_pages;
- unsigned long stolen_size, vram_stolen_size;
- unsigned i, num_pages;
- unsigned pfn_base;
- struct psb_gtt *pg;
-
- int ret = 0;
+ resource_size_t pfn_base;
+ unsigned long i;
uint32_t pte;
- if (!resume) {
- mutex_init(&dev_priv->gtt_mutex);
- psb_gtt_alloc(dev);
- }
+ pfn_base = page_to_pfn(pdev->scratch_page);
+ pte = psb_gtt_mask_pte(pfn_base, PSB_MMU_CACHED_MEMORY);
- pg = &dev_priv->gtt;
+ for (i = 0; i < pdev->gtt.gtt_pages; ++i)
+ iowrite32(pte, pdev->gtt_map + i);
- /* Enable the GTT */
- pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
- pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
- dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
+ (void)ioread32(pdev->gtt_map + i - 1);
+}
- dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
- PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
- (void) PSB_RVDC32(PSB_PGETBL_CTL);
+static void psb_gtt_init_ranges(struct drm_psb_private *dev_priv)
+{
+ struct drm_device *dev = &dev_priv->dev;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ struct psb_gtt *pg = &dev_priv->gtt;
+ resource_size_t gtt_phys_start, mmu_gatt_start, gtt_start, gtt_pages,
+ gatt_start, gatt_pages;
+ struct resource *gtt_mem;
/* The root resource we allocate address space from */
- dev_priv->gtt_initialized = 1;
-
- pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
+ gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
/*
- * The video mmu has a hw bug when accessing 0x0D0000000.
- * Make gatt start at 0x0e000,0000. This doesn't actually
- * matter for us but may do if the video acceleration ever
- * gets opened up.
+ * The video MMU has a HW bug when accessing 0x0d0000000. Make
+ * GATT start at 0x0e0000000. This doesn't actually matter for
+ * us now, but maybe will if the video acceleration ever gets
+ * opened up.
*/
- pg->mmu_gatt_start = 0xE0000000;
+ mmu_gatt_start = 0xe0000000;
+
+ gtt_start = pci_resource_start(pdev, PSB_GTT_RESOURCE);
+ gtt_pages = pci_resource_len(pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
- pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
- gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
- >> PAGE_SHIFT;
/* CDV doesn't report this. In which case the system has 64 gtt pages */
- if (pg->gtt_start == 0 || gtt_pages == 0) {
+ if (!gtt_start || !gtt_pages) {
dev_dbg(dev->dev, "GTT PCI BAR not initialized.\n");
gtt_pages = 64;
- pg->gtt_start = dev_priv->pge_ctl;
+ gtt_start = dev_priv->pge_ctl;
}
- pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
- pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
- >> PAGE_SHIFT;
- dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
+ gatt_start = pci_resource_start(pdev, PSB_GATT_RESOURCE);
+ gatt_pages = pci_resource_len(pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT;
- if (pg->gatt_pages == 0 || pg->gatt_start == 0) {
+ if (!gatt_pages || !gatt_start) {
static struct resource fudge; /* Preferably peppermint */
- /* This can occur on CDV systems. Fudge it in this case.
- We really don't care what imaginary space is being allocated
- at this point */
+
+ /*
+ * This can occur on CDV systems. Fudge it in this case. We
+ * really don't care what imaginary space is being allocated
+ * at this point.
+ */
dev_dbg(dev->dev, "GATT PCI BAR not initialized.\n");
- pg->gatt_start = 0x40000000;
- pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
- /* This is a little confusing but in fact the GTT is providing
- a view from the GPU into memory and not vice versa. As such
- this is really allocating space that is not the same as the
- CPU address space on CDV */
+ gatt_start = 0x40000000;
+ gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
+
+ /*
+ * This is a little confusing but in fact the GTT is providing
+ * a view from the GPU into memory and not vice versa. As such
+ * this is really allocating space that is not the same as the
+ * CPU address space on CDV.
+ */
fudge.start = 0x40000000;
fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1;
fudge.name = "fudge";
fudge.flags = IORESOURCE_MEM;
- dev_priv->gtt_mem = &fudge;
+
+ gtt_mem = &fudge;
+ } else {
+ gtt_mem = &pdev->resource[PSB_GATT_RESOURCE];
}
- pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
- vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
- - PAGE_SIZE;
+ pg->gtt_phys_start = gtt_phys_start;
+ pg->mmu_gatt_start = mmu_gatt_start;
+ pg->gtt_start = gtt_start;
+ pg->gtt_pages = gtt_pages;
+ pg->gatt_start = gatt_start;
+ pg->gatt_pages = gatt_pages;
+ dev_priv->gtt_mem = gtt_mem;
+}
- stolen_size = vram_stolen_size;
+int psb_gtt_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct psb_gtt *pg = &dev_priv->gtt;
+ int ret;
- dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n",
- dev_priv->stolen_base, vram_stolen_size / 1024);
+ mutex_init(&dev_priv->gtt_mutex);
- if (resume && (gtt_pages != pg->gtt_pages) &&
- (stolen_size != pg->stolen_size)) {
- dev_err(dev->dev, "GTT resume error.\n");
- ret = -EINVAL;
- goto out_err;
- }
+ ret = psb_gtt_enable(dev_priv);
+ if (ret)
+ goto err_mutex_destroy;
- pg->gtt_pages = gtt_pages;
- pg->stolen_size = stolen_size;
- dev_priv->vram_stolen_size = vram_stolen_size;
+ psb_gtt_init_ranges(dev_priv);
- /*
- * Map the GTT and the stolen memory area
- */
- if (!resume)
- dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
- gtt_pages << PAGE_SHIFT);
+ dev_priv->gtt_map = ioremap(pg->gtt_phys_start, pg->gtt_pages << PAGE_SHIFT);
if (!dev_priv->gtt_map) {
dev_err(dev->dev, "Failure to map gtt.\n");
ret = -ENOMEM;
- goto out_err;
- }
-
- if (!resume)
- dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base,
- stolen_size);
- if (!dev_priv->vram_addr) {
- dev_err(dev->dev, "Failure to map stolen base.\n");
- ret = -ENOMEM;
- goto out_err;
+ goto err_psb_gtt_disable;
}
- /*
- * Insert vram stolen pages into the GTT
- */
+ psb_gtt_clear(dev_priv);
- pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
- num_pages = vram_stolen_size >> PAGE_SHIFT;
- dev_dbg(dev->dev, "Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
- num_pages, pfn_base << PAGE_SHIFT, 0);
- for (i = 0; i < num_pages; ++i) {
- pte = psb_gtt_mask_pte(pfn_base + i, 0);
- iowrite32(pte, dev_priv->gtt_map + i);
- }
-
- /*
- * Init rest of GTT to the scratch page to avoid accidents or scribbles
- */
-
- pfn_base = page_to_pfn(dev_priv->scratch_page);
- pte = psb_gtt_mask_pte(pfn_base, 0);
- for (; i < gtt_pages; ++i)
- iowrite32(pte, dev_priv->gtt_map + i);
-
- (void) ioread32(dev_priv->gtt_map + i - 1);
return 0;
-out_err:
- psb_gtt_takedown(dev);
+err_psb_gtt_disable:
+ psb_gtt_disable(dev_priv);
+err_mutex_destroy:
+ mutex_destroy(&dev_priv->gtt_mutex);
return ret;
}
-int psb_gtt_restore(struct drm_device *dev)
+int psb_gtt_resume(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct resource *r = dev_priv->gtt_mem->child;
- struct gtt_range *range;
- unsigned int restored = 0, total = 0, size = 0;
-
- /* On resume, the gtt_mutex is already initialized */
- mutex_lock(&dev_priv->gtt_mutex);
- psb_gtt_init(dev, 1);
-
- while (r != NULL) {
- range = container_of(r, struct gtt_range, resource);
- if (range->pages) {
- psb_gtt_insert(dev, range, 1);
- size += range->resource.end - range->resource.start;
- restored++;
- }
- r = r->sibling;
- total++;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct psb_gtt *pg = &dev_priv->gtt;
+ unsigned int old_gtt_pages = pg->gtt_pages;
+ int ret;
+
+ /* Enable the GTT */
+ ret = psb_gtt_enable(dev_priv);
+ if (ret)
+ return ret;
+
+ psb_gtt_init_ranges(dev_priv);
+
+ if (old_gtt_pages != pg->gtt_pages) {
+ dev_err(dev->dev, "GTT resume error.\n");
+ ret = -ENODEV;
+ goto err_psb_gtt_disable;
}
- mutex_unlock(&dev_priv->gtt_mutex);
- DRM_DEBUG_DRIVER("Restored %u of %u gtt ranges (%u KB)", restored,
- total, (size / 1024));
- return 0;
+ psb_gtt_clear(dev_priv);
+
+err_psb_gtt_disable:
+ psb_gtt_disable(dev_priv);
+ return ret;
}
diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h
index 6191d10acf33..d5a5fd4466c1 100644
--- a/drivers/gpu/drm/gma500/gtt.h
+++ b/drivers/gpu/drm/gma500/gtt.h
@@ -1,26 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/**************************************************************************
* Copyright (c) 2007-2008, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
#ifndef _PSB_GTT_H_
#define _PSB_GTT_H_
-#include <drm/drmP.h>
+#include <drm/drm_gem.h>
+
+struct drm_psb_private;
/* This wants cleaning up with respect to the psb_dev and un-needed stuff */
struct psb_gtt {
@@ -32,33 +22,20 @@ struct psb_gtt {
unsigned gatt_pages;
unsigned long stolen_size;
unsigned long vram_stolen_size;
- struct rw_semaphore sem;
};
/* Exported functions */
-extern int psb_gtt_init(struct drm_device *dev, int resume);
-extern void psb_gtt_takedown(struct drm_device *dev);
+int psb_gtt_init(struct drm_device *dev);
+void psb_gtt_fini(struct drm_device *dev);
+int psb_gtt_resume(struct drm_device *dev);
-/* Each gtt_range describes an allocation in the GTT area */
-struct gtt_range {
- struct resource resource; /* Resource for our allocation */
- u32 offset; /* GTT offset of our object */
- struct drm_gem_object gem; /* GEM high level stuff */
- int in_gart; /* Currently in the GART (ref ct) */
- bool stolen; /* Backed from stolen RAM */
- bool mmapping; /* Is mmappable */
- struct page **pages; /* Backing pages if present */
- int npage; /* Number of backing pages */
- int roll; /* Roll applied to the GTT entries */
-};
+int psb_gtt_allocate_resource(struct drm_psb_private *pdev, struct resource *res,
+ const char *name, resource_size_t size, resource_size_t align,
+ bool stolen, u32 *offset);
+
+uint32_t psb_gtt_mask_pte(uint32_t pfn, int type);
+void psb_gtt_insert_pages(struct drm_psb_private *pdev, const struct resource *res,
+ struct page **pages);
+void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *res);
-extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
- const char *name, int backed);
-extern void psb_gtt_kref_put(struct gtt_range *gt);
-extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
-extern int psb_gtt_pin(struct gtt_range *gt);
-extern void psb_gtt_unpin(struct gtt_range *gt);
-extern void psb_gtt_roll(struct drm_device *dev,
- struct gtt_range *gt, int roll);
-extern int psb_gtt_restore(struct drm_device *dev);
#endif
diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c
index d3497348c4d5..b60720560830 100644
--- a/drivers/gpu/drm/gma500/intel_bios.c
+++ b/drivers/gpu/drm/gma500/intel_bios.c
@@ -1,33 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2006 Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Eric Anholt <eric@anholt.net>
- *
*/
-#include <drm/drmP.h>
+
+#include <drm/display/drm_dp_helper.h>
#include <drm/drm.h>
-#include <drm/gma_drm.h>
+#include <drm/drm_print.h>
+
+#include "intel_bios.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "intel_bios.h"
-#define SLAVE_ADDR1 0x70
-#define SLAVE_ADDR2 0x72
+#define TARGET_ADDR1 0x70
+#define TARGET_ADDR2 0x72
static void *find_section(struct bdb_header *bdb, int section_id)
{
@@ -63,7 +52,7 @@ parse_edp(struct drm_psb_private *dev_priv, struct bdb_header *bdb)
uint8_t panel_type;
edp = find_section(bdb, BDB_EDP);
-
+
dev_priv->edp.bpp = 18;
if (!edp) {
if (dev_priv->edp.support) {
@@ -93,7 +82,7 @@ parse_edp(struct drm_psb_private *dev_priv, struct bdb_header *bdb)
dev_priv->edp.pps = *edp_pps;
DRM_DEBUG_KMS("EDP timing in vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
- dev_priv->edp.pps.t1_t3, dev_priv->edp.pps.t8,
+ dev_priv->edp.pps.t1_t3, dev_priv->edp.pps.t8,
dev_priv->edp.pps.t9, dev_priv->edp.pps.t10,
dev_priv->edp.pps.t11_t12);
@@ -116,30 +105,30 @@ parse_edp(struct drm_psb_private *dev_priv, struct bdb_header *bdb)
switch (edp_link_params->preemphasis) {
case 0:
- dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0;
+ dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
break;
case 1:
- dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5;
+ dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
break;
case 2:
- dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6;
+ dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
break;
case 3:
- dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5;
+ dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
break;
}
switch (edp_link_params->vswing) {
case 0:
- dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400;
+ dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
break;
case 1:
- dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600;
+ dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
break;
case 2:
- dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800;
+ dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
break;
case 3:
- dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200;
+ dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
break;
}
DRM_DEBUG_KMS("VBT reports EDP: VSwing %d, Preemph %d\n",
@@ -220,7 +209,7 @@ static void parse_backlight_data(struct drm_psb_private *dev_priv,
lvds_bl = kmemdup(vbt_lvds_bl, sizeof(*vbt_lvds_bl), GFP_KERNEL);
if (!lvds_bl) {
- dev_err(dev_priv->dev->dev, "out of memory for backlight data\n");
+ dev_err(dev_priv->dev.dev, "out of memory for backlight data\n");
return;
}
dev_priv->lvds_bl = lvds_bl;
@@ -261,7 +250,7 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),
GFP_KERNEL);
if (panel_fixed_mode == NULL) {
- dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n");
+ dev_err(dev_priv->dev.dev, "out of memory for fixed panel mode\n");
return;
}
@@ -272,7 +261,7 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
drm_mode_debug_printmodeline(panel_fixed_mode);
} else {
- dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n");
+ dev_dbg(dev_priv->dev.dev, "ignoring invalid LVDS VBT\n");
dev_priv->lvds_vbt = 0;
kfree(panel_fixed_mode);
}
@@ -369,10 +358,10 @@ parse_sdvo_device_mapping(struct drm_psb_private *dev_priv,
/* skip the device block if device type is invalid */
continue;
}
- if (p_child->slave_addr != SLAVE_ADDR1 &&
- p_child->slave_addr != SLAVE_ADDR2) {
+ if (p_child->target_addr != TARGET_ADDR1 &&
+ p_child->target_addr != TARGET_ADDR2) {
/*
- * If the slave address is neither 0x70 nor 0x72,
+ * If the target address is neither 0x70 nor 0x72,
* it is not a SDVO device. Skip it.
*/
continue;
@@ -383,22 +372,22 @@ parse_sdvo_device_mapping(struct drm_psb_private *dev_priv,
DRM_DEBUG_KMS("Incorrect SDVO port. Skip it\n");
continue;
}
- DRM_DEBUG_KMS("the SDVO device with slave addr %2x is found on"
+ DRM_DEBUG_KMS("the SDVO device with target addr %2x is found on"
" %s port\n",
- p_child->slave_addr,
+ p_child->target_addr,
(p_child->dvo_port == DEVICE_PORT_DVOB) ?
"SDVOB" : "SDVOC");
p_mapping = &(dev_priv->sdvo_mappings[p_child->dvo_port - 1]);
if (!p_mapping->initialized) {
p_mapping->dvo_port = p_child->dvo_port;
- p_mapping->slave_addr = p_child->slave_addr;
+ p_mapping->target_addr = p_child->target_addr;
p_mapping->dvo_wiring = p_child->dvo_wiring;
p_mapping->ddc_pin = p_child->ddc_pin;
p_mapping->i2c_pin = p_child->i2c_pin;
p_mapping->initialized = 1;
DRM_DEBUG_KMS("SDVO device: dvo=%x, addr=%x, wiring=%d, ddc_pin=%d, i2c_pin=%d\n",
p_mapping->dvo_port,
- p_mapping->slave_addr,
+ p_mapping->target_addr,
p_mapping->dvo_wiring,
p_mapping->ddc_pin,
p_mapping->i2c_pin);
@@ -406,10 +395,10 @@ parse_sdvo_device_mapping(struct drm_psb_private *dev_priv,
DRM_DEBUG_KMS("Maybe one SDVO port is shared by "
"two SDVO device.\n");
}
- if (p_child->slave2_addr) {
+ if (p_child->target2_addr) {
/* Maybe this is a SDVO device with multiple inputs */
/* And the mapping info is not added */
- DRM_DEBUG_KMS("there exists the slave2_addr. Maybe this"
+ DRM_DEBUG_KMS("there exists the target2_addr. Maybe this"
" is a SDVO device with multiple inputs.\n");
}
count++;
@@ -436,6 +425,9 @@ parse_driver_features(struct drm_psb_private *dev_priv,
if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
dev_priv->edp.support = 1;
+ dev_priv->lvds_enabled_in_vbt = driver->lvds_config != 0;
+ DRM_DEBUG_KMS("LVDS VBT config bits: 0x%x\n", driver->lvds_config);
+
/* This bit means to use 96Mhz for DPLL_A or not */
if (driver->primary_lfp_id)
dev_priv->dplla_96mhz = true;
@@ -525,8 +517,8 @@ parse_device_mapping(struct drm_psb_private *dev_priv,
*/
int psb_intel_init_bios(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct pci_dev *pdev = dev->pdev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
struct vbt_header *vbt = NULL;
struct bdb_header *bdb = NULL;
u8 __iomem *bios = NULL;
@@ -584,12 +576,12 @@ int psb_intel_init_bios(struct drm_device *dev)
return 0;
}
-/**
+/*
* Destroy and free VBT data
*/
void psb_intel_destroy_bios(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
kfree(dev_priv->sdvo_lvds_vbt_mode);
kfree(dev_priv->lfp_lvds_vbt_mode);
diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h
index 978ae4b25e82..b5adea2a20c3 100644
--- a/drivers/gpu/drm/gma500/intel_bios.h
+++ b/drivers/gpu/drm/gma500/intel_bios.h
@@ -1,29 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2006 Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Eric Anholt <eric@anholt.net>
- *
*/
#ifndef _INTEL_BIOS_H_
#define _INTEL_BIOS_H_
-#include <drm/drmP.h>
-#include <drm/drm_dp_helper.h>
+struct drm_device;
struct vbt_header {
u8 signature[20]; /**< Always starts with 'VBT$' */
@@ -34,7 +20,7 @@ struct vbt_header {
u8 reserved0;
u32 bdb_offset; /**< from beginning of VBT */
u32 aim_offset[4]; /**< from beginning of VBT */
-} __attribute__((packed));
+} __packed;
struct bdb_header {
@@ -61,7 +47,7 @@ struct vbios_data {
u8 rsvd4; /* popup memory size */
u8 resize_pci_bios;
u8 rsvd5; /* is crt already on ddc2 */
-} __attribute__((packed));
+} __packed;
/*
* There are several types of BIOS data blocks (BDBs), each block has
@@ -133,7 +119,7 @@ struct bdb_general_features {
u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */
u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */
u8 rsvd11:3; /* finish byte */
-} __attribute__((packed));
+} __packed;
/* pre-915 */
#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */
@@ -200,20 +186,20 @@ struct child_device_config {
u16 addin_offset;
u8 dvo_port; /* See Device_PORT_* above */
u8 i2c_pin;
- u8 slave_addr;
+ u8 target_addr;
u8 ddc_pin;
u16 edid_ptr;
u8 dvo_cfg; /* See DEVICE_CFG_* above */
u8 dvo2_port;
u8 i2c2_pin;
- u8 slave2_addr;
+ u8 target2_addr;
u8 ddc2_pin;
u8 capabilities;
u8 dvo_wiring;/* See DEVICE_WIRE_* above */
u8 dvo2_wiring;
u16 extended_type;
u8 dvo_function;
-} __attribute__((packed));
+} __packed;
struct bdb_general_definitions {
@@ -241,7 +227,7 @@ struct bdb_general_definitions {
* number = (block_size - sizeof(bdb_general_definitions))/
* sizeof(child_device_config);
*/
- struct child_device_config devices[0];
+ struct child_device_config devices[];
};
struct bdb_lvds_options {
@@ -256,7 +242,7 @@ struct bdb_lvds_options {
u8 lvds_edid:1;
u8 rsvd2:1;
u8 rsvd4;
-} __attribute__((packed));
+} __packed;
struct bdb_lvds_backlight {
u8 type:2;
@@ -268,7 +254,7 @@ struct bdb_lvds_backlight {
u8 i2caddr;
u8 brightnesscmd;
/*FIXME: more...*/
-} __attribute__((packed));
+} __packed;
/* LFP pointer table contains entries to the struct below */
struct bdb_lvds_lfp_data_ptr {
@@ -278,12 +264,12 @@ struct bdb_lvds_lfp_data_ptr {
u8 dvo_table_size;
u16 panel_pnp_id_offset;
u8 pnp_table_size;
-} __attribute__((packed));
+} __packed;
struct bdb_lvds_lfp_data_ptrs {
u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
struct bdb_lvds_lfp_data_ptr ptr[16];
-} __attribute__((packed));
+} __packed;
/* LFP data has 3 blocks per entry */
struct lvds_fp_timing {
@@ -300,7 +286,7 @@ struct lvds_fp_timing {
u32 pfit_reg;
u32 pfit_reg_val;
u16 terminator;
-} __attribute__((packed));
+} __packed;
struct lvds_dvo_timing {
u16 clock; /**< In 10khz */
@@ -328,7 +314,7 @@ struct lvds_dvo_timing {
u8 vsync_positive:1;
u8 hsync_positive:1;
u8 rsvd2:1;
-} __attribute__((packed));
+} __packed;
struct lvds_pnp_id {
u16 mfg_name;
@@ -336,17 +322,17 @@ struct lvds_pnp_id {
u32 serial;
u8 mfg_week;
u8 mfg_year;
-} __attribute__((packed));
+} __packed;
struct bdb_lvds_lfp_data_entry {
struct lvds_fp_timing fp_timing;
struct lvds_dvo_timing dvo_timing;
struct lvds_pnp_id pnp_id;
-} __attribute__((packed));
+} __packed;
struct bdb_lvds_lfp_data {
struct bdb_lvds_lfp_data_entry data[16];
-} __attribute__((packed));
+} __packed;
struct aimdb_header {
char signature[16];
@@ -354,12 +340,12 @@ struct aimdb_header {
u16 aimdb_version;
u16 aimdb_header_size;
u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
struct aimdb_block {
u8 aimdb_id;
u16 aimdb_size;
-} __attribute__((packed));
+} __packed;
struct vch_panel_data {
u16 fp_timing_offset;
@@ -370,12 +356,12 @@ struct vch_panel_data {
u8 text_fitting_size;
u16 graphics_fitting_offset;
u8 graphics_fitting_size;
-} __attribute__((packed));
+} __packed;
struct vch_bdb_22 {
struct aimdb_block aimdb_block;
struct vch_panel_data panels[16];
-} __attribute__((packed));
+} __packed;
struct bdb_sdvo_lvds_options {
u8 panel_backlight;
@@ -391,7 +377,7 @@ struct bdb_sdvo_lvds_options {
u8 panel_misc_bits_2;
u8 panel_misc_bits_3;
u8 panel_misc_bits_4;
-} __attribute__((packed));
+} __packed;
#define BDB_DRIVER_FEATURE_NO_LVDS 0
#define BDB_DRIVER_FEATURE_INT_LVDS 1
@@ -436,7 +422,7 @@ struct bdb_driver_features {
u8 hdmi_termination;
u8 custom_vbt_version;
-} __attribute__((packed));
+} __packed;
#define EDP_18BPP 0
#define EDP_24BPP 1
diff --git a/drivers/gpu/drm/gma500/intel_gmbus.c b/drivers/gpu/drm/gma500/intel_gmbus.c
index 62cd42e88f28..2b06ba22f9c6 100644
--- a/drivers/gpu/drm/gma500/intel_gmbus.c
+++ b/drivers/gpu/drm/gma500/intel_gmbus.c
@@ -26,13 +26,16 @@
* Eric Anholt <eric@anholt.net>
* Chris Wilson <chris@chris-wilson.co.uk>
*/
-#include <linux/module.h>
-#include <linux/i2c.h>
+
+#include <linux/delay.h>
#include <linux/i2c-algo-bit.h>
-#include <drm/drmP.h>
-#include "psb_intel_drv.h"
-#include <drm/gma_drm.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+
+#include <drm/drm_print.h>
+
#include "psb_drv.h"
+#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
#define _wait_for(COND, MS, W) ({ \
@@ -43,13 +46,16 @@
ret__ = -ETIMEDOUT; \
break; \
} \
- if (W && !(in_atomic() || in_dbg_master())) msleep(W); \
+ if (W && !(in_dbg_master())) \
+ msleep(W); \
} \
ret__; \
})
#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 */
@@ -71,7 +77,8 @@ struct intel_gpio {
void
gma_intel_i2c_reset(struct drm_device *dev)
{
- REG_WRITE(GMBUS0, 0);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ GMBUS_REG_WRITE(GMBUS0, 0);
}
static void intel_i2c_quirk_set(struct drm_psb_private *dev_priv, bool enable)
@@ -98,11 +105,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 +119,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 +148,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 +165,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 *
@@ -196,7 +198,7 @@ intel_gpio_create(struct drm_psb_private *dev_priv, u32 pin)
"gma500 GPIO%c", "?BACDE?F"[pin]);
gpio->adapter.owner = THIS_MODULE;
gpio->adapter.algo_data = &gpio->algo;
- gpio->adapter.dev.parent = &dev_priv->dev->pdev->dev;
+ gpio->adapter.dev.parent = dev_priv->dev.dev;
gpio->algo.setsda = set_data;
gpio->algo.setscl = set_clock;
gpio->algo.getsda = get_data;
@@ -226,7 +228,7 @@ intel_i2c_quirk_xfer(struct drm_psb_private *dev_priv,
adapter);
int ret;
- gma_intel_i2c_reset(dev_priv->dev);
+ gma_intel_i2c_reset(&dev_priv->dev);
intel_i2c_quirk_set(dev_priv, true);
set_data(gpio, 1);
@@ -251,7 +253,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 +261,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 +298,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 +319,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;
}
@@ -330,22 +335,22 @@ gmbus_xfer(struct i2c_adapter *adapter,
clear_err:
/* Toggle the Software Clear Interrupt bit. This has the effect
* of resetting the GMBUS controller and so clearing the
- * BUS_ERROR raised by the slave's NAK.
+ * BUS_ERROR raised by the target'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);
@@ -376,7 +381,7 @@ static const struct i2c_algorithm gmbus_algorithm = {
};
/**
- * intel_gmbus_setup - instantiate all Intel i2c GMBuses
+ * gma_intel_setup_gmbus() - instantiate all Intel i2c GMBuses
* @dev: DRM device
*/
int gma_intel_setup_gmbus(struct drm_device *dev)
@@ -391,7 +396,7 @@ int gma_intel_setup_gmbus(struct drm_device *dev)
"reserved",
"dpd",
};
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
int ret, i;
dev_priv->gmbus = kcalloc(GMBUS_NUM_PORTS, sizeof(struct intel_gmbus),
@@ -399,17 +404,21 @@ 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];
bus->adapter.owner = THIS_MODULE;
- bus->adapter.class = I2C_CLASS_DDC;
snprintf(bus->adapter.name,
sizeof(bus->adapter.name),
"gma500 gmbus %s",
names[i]);
- bus->adapter.dev.parent = &dev->pdev->dev;
+ bus->adapter.dev.parent = dev->dev;
bus->adapter.algo_data = dev_priv;
bus->adapter.algo = &gmbus_algorithm;
@@ -424,12 +433,12 @@ int gma_intel_setup_gmbus(struct drm_device *dev)
bus->force_bit = intel_gpio_create(dev_priv, i);
}
- gma_intel_i2c_reset(dev_priv->dev);
+ gma_intel_i2c_reset(&dev_priv->dev);
return 0;
err:
- while (--i) {
+ while (i--) {
struct intel_gmbus *bus = &dev_priv->gmbus[i];
i2c_del_adapter(&bus->adapter);
}
@@ -472,7 +481,7 @@ void gma_intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
void gma_intel_teardown_gmbus(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
int i;
if (dev_priv->gmbus == NULL)
@@ -487,6 +496,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;
}
diff --git a/drivers/gpu/drm/gma500/intel_i2c.c b/drivers/gpu/drm/gma500/intel_i2c.c
index 98a28c209555..9d02a7b6d9a3 100644
--- a/drivers/gpu/drm/gma500/intel_i2c.c
+++ b/drivers/gpu/drm/gma500/intel_i2c.c
@@ -1,25 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright © 2006-2007 Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Eric Anholt <eric@anholt.net>
*/
+
+#include <linux/delay.h>
#include <linux/export.h>
-#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
+#include <linux/i2c.h>
#include "psb_drv.h"
#include "psb_intel_reg.h"
@@ -32,7 +22,7 @@
static int get_clock(void *data)
{
- struct psb_intel_i2c_chan *chan = data;
+ struct gma_i2c_chan *chan = data;
struct drm_device *dev = chan->drm_dev;
u32 val;
@@ -42,7 +32,7 @@ static int get_clock(void *data)
static int get_data(void *data)
{
- struct psb_intel_i2c_chan *chan = data;
+ struct gma_i2c_chan *chan = data;
struct drm_device *dev = chan->drm_dev;
u32 val;
@@ -52,7 +42,7 @@ static int get_data(void *data)
static void set_clock(void *data, int state_high)
{
- struct psb_intel_i2c_chan *chan = data;
+ struct gma_i2c_chan *chan = data;
struct drm_device *dev = chan->drm_dev;
u32 reserved = 0, clock_bits;
@@ -72,7 +62,7 @@ static void set_clock(void *data, int state_high)
static void set_data(void *data, int state_high)
{
- struct psb_intel_i2c_chan *chan = data;
+ struct gma_i2c_chan *chan = data;
struct drm_device *dev = chan->drm_dev;
u32 reserved = 0, data_bits;
@@ -93,9 +83,8 @@ static void set_data(void *data, int state_high)
}
/**
- * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
+ * gma_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
* @dev: DRM device
- * @output: driver specific output device
* @reg: GPIO reg to use
* @name: name for this bus
*
@@ -113,21 +102,21 @@ static void set_data(void *data, int state_high)
* %GPIOH
* see PRM for details on how these different busses are used.
*/
-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
- const u32 reg, const char *name)
+struct gma_i2c_chan *gma_i2c_create(struct drm_device *dev, const u32 reg,
+ const char *name)
{
- struct psb_intel_i2c_chan *chan;
+ struct gma_i2c_chan *chan;
- chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL);
+ chan = kzalloc(sizeof(struct gma_i2c_chan), GFP_KERNEL);
if (!chan)
goto out_free;
chan->drm_dev = dev;
chan->reg = reg;
- snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
- chan->adapter.owner = THIS_MODULE;
- chan->adapter.algo_data = &chan->algo;
- chan->adapter.dev.parent = &dev->pdev->dev;
+ snprintf(chan->base.name, I2C_NAME_SIZE, "intel drm %s", name);
+ chan->base.owner = THIS_MODULE;
+ chan->base.algo_data = &chan->algo;
+ chan->base.dev.parent = dev->dev;
chan->algo.setsda = set_data;
chan->algo.setscl = set_clock;
chan->algo.getsda = get_data;
@@ -136,9 +125,9 @@ struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
chan->algo.timeout = usecs_to_jiffies(2200);
chan->algo.data = chan;
- i2c_set_adapdata(&chan->adapter, chan);
+ i2c_set_adapdata(&chan->base, chan);
- if (i2c_bit_add_bus(&chan->adapter))
+ if (i2c_bit_add_bus(&chan->base))
goto out_free;
/* JJJ: raise SCL and SDA? */
@@ -154,16 +143,16 @@ out_free:
}
/**
- * psb_intel_i2c_destroy - unregister and free i2c bus resources
- * @output: channel to free
+ * gma_i2c_destroy - unregister and free i2c bus resources
+ * @chan: channel to free
*
* Unregister the adapter from the i2c layer, then free the structure.
*/
-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan)
+void gma_i2c_destroy(struct gma_i2c_chan *chan)
{
if (!chan)
return;
- i2c_del_adapter(&chan->adapter);
+ i2c_del_adapter(&chan->base);
kfree(chan);
}
diff --git a/drivers/gpu/drm/gma500/mdfld_device.c b/drivers/gpu/drm/gma500/mdfld_device.c
deleted file mode 100644
index 265ad0de44a6..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_device.c
+++ /dev/null
@@ -1,551 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#include "psb_drv.h"
-#include "mid_bios.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_output.h"
-#include "tc35876x-dsi-lvds.h"
-
-#include <asm/intel_scu_ipc.h>
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
-#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
-#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-#define BRIGHTNESS_MIN_LEVEL 1
-#define BRIGHTNESS_MAX_LEVEL 100
-#define BRIGHTNESS_MASK 0xFF
-#define BLC_POLARITY_NORMAL 0
-#define BLC_POLARITY_INVERSE 1
-#define BLC_ADJUSTMENT_MAX 100
-
-#define MDFLD_BLC_PWM_PRECISION_FACTOR 10
-#define MDFLD_BLC_MAX_PWM_REG_FREQ 0xFFFE
-#define MDFLD_BLC_MIN_PWM_REG_FREQ 0x2
-
-#define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-#define MDFLD_BACKLIGHT_PWM_CTL_SHIFT (16)
-
-static struct backlight_device *mdfld_backlight_device;
-
-int mdfld_set_brightness(struct backlight_device *bd)
-{
- struct drm_device *dev =
- (struct drm_device *)bl_get_data(mdfld_backlight_device);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int level = bd->props.brightness;
-
- DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
-
- /* Perform value bounds checking */
- if (level < BRIGHTNESS_MIN_LEVEL)
- level = BRIGHTNESS_MIN_LEVEL;
-
- if (gma_power_begin(dev, false)) {
- u32 adjusted_level = 0;
-
- /*
- * Adjust the backlight level with the percent in
- * dev_priv->blc_adj2
- */
- adjusted_level = level * dev_priv->blc_adj2;
- adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
- dev_priv->brightness_adjusted = adjusted_level;
-
- if (mdfld_get_panel_type(dev, 0) == TC35876X) {
- if (dev_priv->dpi_panel_on[0] ||
- dev_priv->dpi_panel_on[2])
- tc35876x_brightness_control(dev,
- dev_priv->brightness_adjusted);
- } else {
- if (dev_priv->dpi_panel_on[0])
- mdfld_dsi_brightness_control(dev, 0,
- dev_priv->brightness_adjusted);
- }
-
- if (dev_priv->dpi_panel_on[2])
- mdfld_dsi_brightness_control(dev, 2,
- dev_priv->brightness_adjusted);
- gma_power_end(dev);
- }
-
- /* cache the brightness for later use */
- dev_priv->brightness = level;
- return 0;
-}
-
-static int mdfld_get_brightness(struct backlight_device *bd)
-{
- struct drm_device *dev =
- (struct drm_device *)bl_get_data(mdfld_backlight_device);
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv->brightness);
-
- /* return locally cached var instead of HW read (due to DPST etc.) */
- return dev_priv->brightness;
-}
-
-static const struct backlight_ops mdfld_ops = {
- .get_brightness = mdfld_get_brightness,
- .update_status = mdfld_set_brightness,
-};
-
-static int device_backlight_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = (struct drm_psb_private *)
- dev->dev_private;
-
- dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
- dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
-
- return 0;
-}
-
-static int mdfld_backlight_init(struct drm_device *dev)
-{
- struct backlight_properties props;
- int ret = 0;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = BRIGHTNESS_MAX_LEVEL;
- props.type = BACKLIGHT_PLATFORM;
- mdfld_backlight_device = backlight_device_register("mdfld-bl",
- NULL, (void *)dev, &mdfld_ops, &props);
-
- if (IS_ERR(mdfld_backlight_device))
- return PTR_ERR(mdfld_backlight_device);
-
- ret = device_backlight_init(dev);
- if (ret)
- return ret;
-
- mdfld_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL;
- mdfld_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL;
- backlight_update_status(mdfld_backlight_device);
- return 0;
-}
-#endif
-
-struct backlight_device *mdfld_get_backlight_device(void)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- return mdfld_backlight_device;
-#else
- return NULL;
-#endif
-}
-
-/*
- * mdfld_save_display_registers
- *
- * Description: We are going to suspend so save current display
- * register state.
- *
- * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
- */
-static int mdfld_save_display_registers(struct drm_device *dev, int pipenum)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct medfield_state *regs = &dev_priv->regs.mdfld;
- struct psb_pipe *pipe = &dev_priv->regs.pipe[pipenum];
- const struct psb_offset *map = &dev_priv->regmap[pipenum];
- int i;
- u32 *mipi_val;
-
- /* register */
- u32 mipi_reg = MIPI;
-
- switch (pipenum) {
- case 0:
- mipi_val = &regs->saveMIPI;
- break;
- case 1:
- mipi_val = &regs->saveMIPI;
- break;
- case 2:
- /* register */
- mipi_reg = MIPI_C;
- /* pointer to values */
- mipi_val = &regs->saveMIPI_C;
- break;
- default:
- DRM_ERROR("%s, invalid pipe number.\n", __func__);
- return -EINVAL;
- }
-
- /* Pipe & plane A info */
- pipe->dpll = PSB_RVDC32(map->dpll);
- pipe->fp0 = PSB_RVDC32(map->fp0);
- pipe->conf = PSB_RVDC32(map->conf);
- pipe->htotal = PSB_RVDC32(map->htotal);
- pipe->hblank = PSB_RVDC32(map->hblank);
- pipe->hsync = PSB_RVDC32(map->hsync);
- pipe->vtotal = PSB_RVDC32(map->vtotal);
- pipe->vblank = PSB_RVDC32(map->vblank);
- pipe->vsync = PSB_RVDC32(map->vsync);
- pipe->src = PSB_RVDC32(map->src);
- pipe->stride = PSB_RVDC32(map->stride);
- pipe->linoff = PSB_RVDC32(map->linoff);
- pipe->tileoff = PSB_RVDC32(map->tileoff);
- pipe->size = PSB_RVDC32(map->size);
- pipe->pos = PSB_RVDC32(map->pos);
- pipe->surf = PSB_RVDC32(map->surf);
- pipe->cntr = PSB_RVDC32(map->cntr);
- pipe->status = PSB_RVDC32(map->status);
-
- /*save palette (gamma) */
- for (i = 0; i < 256; i++)
- pipe->palette[i] = PSB_RVDC32(map->palette + (i << 2));
-
- if (pipenum == 1) {
- regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
- regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
-
- regs->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
- regs->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
- return 0;
- }
-
- *mipi_val = PSB_RVDC32(mipi_reg);
- return 0;
-}
-
-/*
- * mdfld_restore_display_registers
- *
- * Description: We are going to resume so restore display register state.
- *
- * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
- */
-static int mdfld_restore_display_registers(struct drm_device *dev, int pipenum)
-{
- /* To get panel out of ULPS mode. */
- u32 temp = 0;
- u32 device_ready_reg = DEVICE_READY_REG;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct mdfld_dsi_config *dsi_config = NULL;
- struct medfield_state *regs = &dev_priv->regs.mdfld;
- struct psb_pipe *pipe = &dev_priv->regs.pipe[pipenum];
- const struct psb_offset *map = &dev_priv->regmap[pipenum];
- u32 i;
- u32 dpll;
- u32 timeout = 0;
-
- /* register */
- u32 mipi_reg = MIPI;
-
- /* values */
- u32 dpll_val = pipe->dpll;
- u32 mipi_val = regs->saveMIPI;
-
- switch (pipenum) {
- case 0:
- dpll_val &= ~DPLL_VCO_ENABLE;
- dsi_config = dev_priv->dsi_configs[0];
- break;
- case 1:
- dpll_val &= ~DPLL_VCO_ENABLE;
- break;
- case 2:
- mipi_reg = MIPI_C;
- mipi_val = regs->saveMIPI_C;
- dsi_config = dev_priv->dsi_configs[1];
- break;
- default:
- DRM_ERROR("%s, invalid pipe number.\n", __func__);
- return -EINVAL;
- }
-
- /*make sure VGA plane is off. it initializes to on after reset!*/
- PSB_WVDC32(0x80000000, VGACNTRL);
-
- if (pipenum == 1) {
- PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, map->dpll);
- PSB_RVDC32(map->dpll);
-
- PSB_WVDC32(pipe->fp0, map->fp0);
- } else {
-
- dpll = PSB_RVDC32(map->dpll);
-
- if (!(dpll & DPLL_VCO_ENABLE)) {
-
- /* When ungating power of DPLL, needs to wait 0.5us
- before enable the VCO */
- if (dpll & MDFLD_PWR_GATE_EN) {
- dpll &= ~MDFLD_PWR_GATE_EN;
- PSB_WVDC32(dpll, map->dpll);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
- }
-
- PSB_WVDC32(pipe->fp0, map->fp0);
- PSB_WVDC32(dpll_val, map->dpll);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
-
- dpll_val |= DPLL_VCO_ENABLE;
- PSB_WVDC32(dpll_val, map->dpll);
- PSB_RVDC32(map->dpll);
-
- /* wait for DSI PLL to lock */
- while (timeout < 20000 &&
- !(PSB_RVDC32(map->conf) & PIPECONF_DSIPLL_LOCK)) {
- udelay(150);
- timeout++;
- }
-
- if (timeout == 20000) {
- DRM_ERROR("%s, can't lock DSIPLL.\n",
- __func__);
- return -EINVAL;
- }
- }
- }
- /* Restore mode */
- PSB_WVDC32(pipe->htotal, map->htotal);
- PSB_WVDC32(pipe->hblank, map->hblank);
- PSB_WVDC32(pipe->hsync, map->hsync);
- PSB_WVDC32(pipe->vtotal, map->vtotal);
- PSB_WVDC32(pipe->vblank, map->vblank);
- PSB_WVDC32(pipe->vsync, map->vsync);
- PSB_WVDC32(pipe->src, map->src);
- PSB_WVDC32(pipe->status, map->status);
-
- /*set up the plane*/
- PSB_WVDC32(pipe->stride, map->stride);
- PSB_WVDC32(pipe->linoff, map->linoff);
- PSB_WVDC32(pipe->tileoff, map->tileoff);
- PSB_WVDC32(pipe->size, map->size);
- PSB_WVDC32(pipe->pos, map->pos);
- PSB_WVDC32(pipe->surf, map->surf);
-
- if (pipenum == 1) {
- /* restore palette (gamma) */
- /*DRM_UDELAY(50000); */
- for (i = 0; i < 256; i++)
- PSB_WVDC32(pipe->palette[i], map->palette + (i << 2));
-
- PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL);
- PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
-
- /*TODO: resume HDMI port */
-
- /*TODO: resume pipe*/
-
- /*enable the plane*/
- PSB_WVDC32(pipe->cntr & ~DISPLAY_PLANE_ENABLE, map->cntr);
-
- return 0;
- }
-
- /*set up pipe related registers*/
- PSB_WVDC32(mipi_val, mipi_reg);
-
- /*setup MIPI adapter + MIPI IP registers*/
- if (dsi_config)
- mdfld_dsi_controller_init(dsi_config, pipenum);
-
- if (in_atomic() || in_interrupt())
- mdelay(20);
- else
- msleep(20);
-
- /*enable the plane*/
- PSB_WVDC32(pipe->cntr, map->cntr);
-
- if (in_atomic() || in_interrupt())
- mdelay(20);
- else
- msleep(20);
-
- /* LP Hold Release */
- temp = REG_READ(mipi_reg);
- temp |= LP_OUTPUT_HOLD_RELEASE;
- REG_WRITE(mipi_reg, temp);
- mdelay(1);
-
-
- /* Set DSI host to exit from Utra Low Power State */
- temp = REG_READ(device_ready_reg);
- temp &= ~ULPS_MASK;
- temp |= 0x3;
- temp |= EXIT_ULPS_DEV_READY;
- REG_WRITE(device_ready_reg, temp);
- mdelay(1);
-
- temp = REG_READ(device_ready_reg);
- temp &= ~ULPS_MASK;
- temp |= EXITING_ULPS;
- REG_WRITE(device_ready_reg, temp);
- mdelay(1);
-
- /*enable the pipe*/
- PSB_WVDC32(pipe->conf, map->conf);
-
- /* restore palette (gamma) */
- /*DRM_UDELAY(50000); */
- for (i = 0; i < 256; i++)
- PSB_WVDC32(pipe->palette[i], map->palette + (i << 2));
-
- return 0;
-}
-
-static int mdfld_save_registers(struct drm_device *dev)
-{
- /* mdfld_save_cursor_overlay_registers(dev); */
- mdfld_save_display_registers(dev, 0);
- mdfld_save_display_registers(dev, 2);
- mdfld_disable_crtc(dev, 0);
- mdfld_disable_crtc(dev, 2);
-
- return 0;
-}
-
-static int mdfld_restore_registers(struct drm_device *dev)
-{
- mdfld_restore_display_registers(dev, 2);
- mdfld_restore_display_registers(dev, 0);
- /* mdfld_restore_cursor_overlay_registers(dev); */
-
- return 0;
-}
-
-static int mdfld_power_down(struct drm_device *dev)
-{
- /* FIXME */
- return 0;
-}
-
-static int mdfld_power_up(struct drm_device *dev)
-{
- /* FIXME */
- return 0;
-}
-
-/* Medfield */
-static const struct psb_offset mdfld_regmap[3] = {
- {
- .fp0 = MRST_FPA0,
- .fp1 = MRST_FPA1,
- .cntr = DSPACNTR,
- .conf = PIPEACONF,
- .src = PIPEASRC,
- .dpll = MRST_DPLL_A,
- .htotal = HTOTAL_A,
- .hblank = HBLANK_A,
- .hsync = HSYNC_A,
- .vtotal = VTOTAL_A,
- .vblank = VBLANK_A,
- .vsync = VSYNC_A,
- .stride = DSPASTRIDE,
- .size = DSPASIZE,
- .pos = DSPAPOS,
- .surf = DSPASURF,
- .addr = MRST_DSPABASE,
- .status = PIPEASTAT,
- .linoff = DSPALINOFF,
- .tileoff = DSPATILEOFF,
- .palette = PALETTE_A,
- },
- {
- .fp0 = MDFLD_DPLL_DIV0,
- .cntr = DSPBCNTR,
- .conf = PIPEBCONF,
- .src = PIPEBSRC,
- .dpll = MDFLD_DPLL_B,
- .htotal = HTOTAL_B,
- .hblank = HBLANK_B,
- .hsync = HSYNC_B,
- .vtotal = VTOTAL_B,
- .vblank = VBLANK_B,
- .vsync = VSYNC_B,
- .stride = DSPBSTRIDE,
- .size = DSPBSIZE,
- .pos = DSPBPOS,
- .surf = DSPBSURF,
- .addr = MRST_DSPBBASE,
- .status = PIPEBSTAT,
- .linoff = DSPBLINOFF,
- .tileoff = DSPBTILEOFF,
- .palette = PALETTE_B,
- },
- {
- .fp0 = MRST_FPA0, /* This is what the old code did ?? */
- .cntr = DSPCCNTR,
- .conf = PIPECCONF,
- .src = PIPECSRC,
- /* No DPLL_C */
- .dpll = MRST_DPLL_A,
- .htotal = HTOTAL_C,
- .hblank = HBLANK_C,
- .hsync = HSYNC_C,
- .vtotal = VTOTAL_C,
- .vblank = VBLANK_C,
- .vsync = VSYNC_C,
- .stride = DSPCSTRIDE,
- .size = DSPBSIZE,
- .pos = DSPCPOS,
- .surf = DSPCSURF,
- .addr = MDFLD_DSPCBASE,
- .status = PIPECSTAT,
- .linoff = DSPCLINOFF,
- .tileoff = DSPCTILEOFF,
- .palette = PALETTE_C,
- },
-};
-
-static int mdfld_chip_setup(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- if (pci_enable_msi(dev->pdev))
- dev_warn(dev->dev, "Enabling MSI failed!\n");
- dev_priv->regmap = mdfld_regmap;
- return mid_chip_setup(dev);
-}
-
-const struct psb_ops mdfld_chip_ops = {
- .name = "mdfld",
- .accel_2d = 0,
- .pipes = 3,
- .crtcs = 3,
- .lvds_mask = (1 << 1),
- .hdmi_mask = (1 << 1),
- .cursor_needs_phys = 0,
- .sgx_offset = MRST_SGX_OFFSET,
-
- .chip_setup = mdfld_chip_setup,
- .crtc_helper = &mdfld_helper_funcs,
- .crtc_funcs = &psb_intel_crtc_funcs,
-
- .output_init = mdfld_output_init,
-
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- .backlight_init = mdfld_backlight_init,
-#endif
-
- .save_regs = mdfld_save_registers,
- .restore_regs = mdfld_restore_registers,
- .power_down = mdfld_power_down,
- .power_up = mdfld_power_up,
-};
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
deleted file mode 100644
index d4813e03f5ee..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
+++ /dev/null
@@ -1,1016 +0,0 @@
-/*
- * 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:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_pkg_sender.h"
-#include "psb_drv.h"
-#include "tc35876x-dsi-lvds.h"
-
-static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output,
- int pipe);
-
-static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe)
-{
- u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
- int timeout = 0;
-
- udelay(500);
-
- /* This will time out after approximately 2+ seconds */
- while ((timeout < 20000) &&
- (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) {
- udelay(100);
- timeout++;
- }
-
- if (timeout == 20000)
- DRM_INFO("MIPI: HS Data FIFO was never cleared!\n");
-}
-
-static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
-{
- u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
- int timeout = 0;
-
- udelay(500);
-
- /* This will time out after approximately 2+ seconds */
- while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg)
- & DSI_FIFO_GEN_HS_CTRL_FULL)) {
- udelay(100);
- timeout++;
- }
- if (timeout == 20000)
- DRM_INFO("MIPI: HS CMD FIFO was never cleared!\n");
-}
-
-static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
-{
- u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
- int timeout = 0;
-
- udelay(500);
-
- /* This will time out after approximately 2+ seconds */
- while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) &
- DPI_FIFO_EMPTY) != DPI_FIFO_EMPTY)) {
- udelay(100);
- timeout++;
- }
-
- if (timeout == 20000)
- DRM_ERROR("MIPI: DPI FIFO was never cleared\n");
-}
-
-static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
-{
- u32 intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
- int timeout = 0;
-
- udelay(500);
-
- /* This will time out after approximately 2+ seconds */
- while ((timeout < 20000) && (!(REG_READ(intr_stat_reg)
- & DSI_INTR_STATE_SPL_PKG_SENT))) {
- udelay(100);
- timeout++;
- }
-
- if (timeout == 20000)
- DRM_ERROR("MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
-}
-
-/* For TC35876X */
-
-static void dsi_set_device_ready_state(struct drm_device *dev, int state,
- int pipe)
-{
- REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), !!state, 0, 0);
-}
-
-static void dsi_set_pipe_plane_enable_state(struct drm_device *dev,
- int state, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- u32 pipeconf_reg = PIPEACONF;
- u32 dspcntr_reg = DSPACNTR;
-
- u32 dspcntr = dev_priv->dspcntr[pipe];
- u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
-
- if (pipe) {
- pipeconf_reg = PIPECCONF;
- dspcntr_reg = DSPCCNTR;
- } else
- mipi &= (~0x03);
-
- if (state) {
- /*Set up pipe */
- REG_WRITE(pipeconf_reg, BIT(31));
-
- if (REG_BIT_WAIT(pipeconf_reg, 1, 30))
- dev_err(&dev->pdev->dev, "%s: Pipe enable timeout\n",
- __func__);
-
- /*Set up display plane */
- REG_WRITE(dspcntr_reg, dspcntr);
- } else {
- u32 dspbase_reg = pipe ? MDFLD_DSPCBASE : MRST_DSPABASE;
-
- /* Put DSI lanes to ULPS to disable pipe */
- REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 2, 2, 1);
- REG_READ(MIPI_DEVICE_READY_REG(pipe)); /* posted write? */
-
- /* LP Hold */
- REG_FLD_MOD(MIPI_PORT_CONTROL(pipe), 0, 16, 16);
- REG_READ(MIPI_PORT_CONTROL(pipe)); /* posted write? */
-
- /* Disable display plane */
- REG_FLD_MOD(dspcntr_reg, 0, 31, 31);
-
- /* Flush the plane changes ??? posted write? */
- REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
- REG_READ(dspbase_reg);
-
- /* Disable PIPE */
- REG_FLD_MOD(pipeconf_reg, 0, 31, 31);
-
- if (REG_BIT_WAIT(pipeconf_reg, 0, 30))
- dev_err(&dev->pdev->dev, "%s: Pipe disable timeout\n",
- __func__);
-
- if (REG_BIT_WAIT(MIPI_GEN_FIFO_STAT_REG(pipe), 1, 28))
- dev_err(&dev->pdev->dev, "%s: FIFO not empty\n",
- __func__);
- }
-}
-
-static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder *dsi_encoder,
- int pipe)
-{
- struct mdfld_dsi_dpi_output *dpi_output =
- MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_encoder_get_config(dsi_encoder);
- struct drm_device *dev = dsi_config->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->dpi_panel_on[pipe]) {
- dev_err(dev->dev, "DPI panel is already off\n");
- return;
- }
- tc35876x_toshiba_bridge_panel_off(dev);
- tc35876x_set_bridge_reset_state(dev, 1);
- dsi_set_pipe_plane_enable_state(dev, 0, pipe);
- mdfld_dsi_dpi_shut_down(dpi_output, pipe);
- dsi_set_device_ready_state(dev, 0, pipe);
-}
-
-static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder *dsi_encoder,
- int pipe)
-{
- struct mdfld_dsi_dpi_output *dpi_output =
- MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_encoder_get_config(dsi_encoder);
- struct drm_device *dev = dsi_config->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (dev_priv->dpi_panel_on[pipe]) {
- dev_err(dev->dev, "DPI panel is already on\n");
- return;
- }
-
- /* For resume path sequence */
- mdfld_dsi_dpi_shut_down(dpi_output, pipe);
- dsi_set_device_ready_state(dev, 0, pipe);
-
- dsi_set_device_ready_state(dev, 1, pipe);
- tc35876x_set_bridge_reset_state(dev, 0);
- tc35876x_configure_lvds_bridge(dev);
- mdfld_dsi_dpi_turn_on(dpi_output, pipe); /* Send turn on command */
- dsi_set_pipe_plane_enable_state(dev, 1, pipe);
-}
-/* End for TC35876X */
-
-/* ************************************************************************* *\
- * FUNCTION: mdfld_dsi_tpo_ic_init
- *
- * 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 void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- u32 dcsChannelNumber = dsi_config->channel_num;
- u32 gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
- u32 gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
- u32 gen_ctrl_val = GEN_LONG_WRITE;
-
- DRM_INFO("Enter mrst init TPO MIPI display.\n");
-
- gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS;
-
- /* Flip page order */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00008036);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
-
- /* 0xF0 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x005a5af0);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
- /* Write protection key */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x005a5af1);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
- /* 0xFC */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x005a5afc);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
- /* 0xB7 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x770000b7);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000044);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS));
-
- /* 0xB6 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x000a0ab6);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-
- /* 0xF2 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x081010f2);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x4a070708);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x000000c5);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
-
- /* 0xF8 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x024003f8);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x01030a04);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x0e020220);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000004);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS));
-
- /* 0xE2 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x398fc3e2);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x0000916f);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS));
-
- /* 0xB0 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x000000b0);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
-
- /* 0xF4 */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x240242f4);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x78ee2002);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x2a071050);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x507fee10);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x10300710);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS));
-
- /* 0xBA */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x19fe07ba);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x101c0a31);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000010);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
-
- /* 0xBB */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x28ff07bb);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x24280a31);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000034);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
-
- /* 0xFB */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x535d05fb);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1b1a2130);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x221e180e);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x131d2120);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x535d0508);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1c1a2131);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x231f160d);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x111b2220);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x535c2008);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1f1d2433);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x2c251a10);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x2c34372d);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000023);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
-
- /* 0xFA */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x525c0bfa);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1c1c232f);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x2623190e);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x18212625);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x545d0d0e);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1e1d2333);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x26231a10);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x1a222725);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x545d280f);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x21202635);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x31292013);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x31393d33);
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x00000029);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
-
- /* Set DM */
- mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
- REG_WRITE(gen_data_reg, 0x000100f7);
- mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
- REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
-}
-
-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));
-}
-
-/*
- * Calculate the dpi time basing on a given drm mode @mode
- * return 0 on success.
- * FIXME: I was using proposed mode value for calculation, may need to
- * 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)
-{
- int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
- int pclk_vsync, pclk_vfp, pclk_vbp;
-
- pclk_hactive = mode->hdisplay;
- pclk_hfp = mode->hsync_start - mode->hdisplay;
- pclk_hsync = mode->hsync_end - mode->hsync_start;
- pclk_hbp = mode->htotal - mode->hsync_end;
-
- pclk_vfp = mode->vsync_start - mode->vdisplay;
- pclk_vsync = mode->vsync_end - mode->vsync_start;
- pclk_vbp = mode->vtotal - mode->vsync_end;
-
- /*
- * byte clock counts were calculated by following formula
- * bclock_count = pclk_count * bpp / num_lane / 8
- */
- dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(
- pclk_hsync, num_lane, bpp);
- dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(
- pclk_hbp, num_lane, bpp);
- dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(
- pclk_hfp, num_lane, bpp);
- dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(
- pclk_hactive, num_lane, bpp);
- dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(
- pclk_vsync, num_lane, bpp);
- dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(
- pclk_vbp, num_lane, bpp);
- dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(
- pclk_vfp, num_lane, bpp);
-
- return 0;
-}
-
-void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config,
- int pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- int lane_count = dsi_config->lane_count;
- struct mdfld_dsi_dpi_timing dpi_timing;
- struct drm_display_mode *mode = dsi_config->mode;
- u32 val;
-
- /*un-ready device*/
- REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 0, 0, 0);
-
- /*init dsi adapter before kicking off*/
- REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
-
- /*enable all interrupts*/
- REG_WRITE(MIPI_INTR_EN_REG(pipe), 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(MIPI_DSI_FUNC_PRG_REG(pipe), val);
-
- REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe),
- (mode->vtotal * mode->htotal * dsi_config->bpp /
- (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
- REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe),
- 0xffff & DSI_LP_RX_TIMEOUT_MASK);
-
- /*max value: 20 clock cycles of txclkesc*/
- REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe),
- 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
-
- /*min 21 txclkesc, max: ffffh*/
- REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe),
- 0xffff & DSI_RESET_TIMER_MASK);
-
- REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe),
- 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(MIPI_HSYNC_COUNT_REG(pipe),
- dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_HBP_COUNT_REG(pipe),
- dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_HFP_COUNT_REG(pipe),
- dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe),
- dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe),
- dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_VBP_COUNT_REG(pipe),
- dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_VFP_COUNT_REG(pipe),
- dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
-
- REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46);
-
- /*min: 7d0 max: 4e20*/
- REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0);
-
- /*set up video mode*/
- val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
- REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val);
-
- REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
-
- REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
-
- /*TODO: figure out how to setup these registers*/
- if (mdfld_get_panel_type(dev, pipe) == TC35876X)
- REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
- else
- REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408);
-
- REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
-
- if (mdfld_get_panel_type(dev, pipe) == TC35876X)
- tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */
-
- /*set device ready*/
- REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 1, 0, 0);
-}
-
-void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
-{
- struct drm_device *dev = output->dev;
-
- /* clear special packet sent bit */
- if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
- REG_WRITE(MIPI_INTR_STAT_REG(pipe),
- DSI_INTR_STATE_SPL_PKG_SENT);
-
- /*send turn on package*/
- REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON);
-
- /*wait for SPL_PKG_SENT interrupt*/
- mdfld_wait_for_SPL_PKG_SENT(dev, pipe);
-
- if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
- REG_WRITE(MIPI_INTR_STAT_REG(pipe),
- DSI_INTR_STATE_SPL_PKG_SENT);
-
- output->panel_on = 1;
-
- /* FIXME the following is disabled to WA the X slow start issue
- for TMD panel
- if (pipe == 2)
- dev_priv->dpi_panel_on2 = true;
- else if (pipe == 0)
- dev_priv->dpi_panel_on = true; */
-}
-
-static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output,
- int pipe)
-{
- struct drm_device *dev = output->dev;
-
- /*if output is on, or mode setting didn't happen, ignore this*/
- if ((!output->panel_on) || output->first_boot) {
- output->first_boot = 0;
- return;
- }
-
- /* Wait for dpi fifo to empty */
- mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
-
- /* Clear the special packet interrupt bit if set */
- if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
- REG_WRITE(MIPI_INTR_STAT_REG(pipe),
- DSI_INTR_STATE_SPL_PKG_SENT);
-
- if (REG_READ(MIPI_DPI_CONTROL_REG(pipe)) == DSI_DPI_CTRL_HS_SHUTDOWN)
- goto shutdown_out;
-
- REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN);
-
-shutdown_out:
- output->panel_on = 0;
- output->first_boot = 0;
-
- /* FIXME the following is disabled to WA the X slow start issue
- for TMD panel
- if (pipe == 2)
- dev_priv->dpi_panel_on2 = false;
- else if (pipe == 0)
- dev_priv->dpi_panel_on = false; */
-}
-
-static void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
-{
- struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder);
- struct mdfld_dsi_dpi_output *dpi_output =
- MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_encoder_get_config(dsi_encoder);
- int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
- struct drm_device *dev = dsi_config->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- /*start up display island if it was shutdown*/
- if (!gma_power_begin(dev, true))
- return;
-
- if (on) {
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
- mdfld_dsi_dpi_turn_on(dpi_output, pipe);
- else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
- mdfld_dsi_configure_up(dsi_encoder, pipe);
- else {
- /*enable mipi port*/
- REG_WRITE(MIPI_PORT_CONTROL(pipe),
- REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31));
- REG_READ(MIPI_PORT_CONTROL(pipe));
-
- mdfld_dsi_dpi_turn_on(dpi_output, pipe);
- mdfld_dsi_tpo_ic_init(dsi_config, pipe);
- }
- dev_priv->dpi_panel_on[pipe] = true;
- } else {
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
- mdfld_dsi_dpi_shut_down(dpi_output, pipe);
- else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
- mdfld_dsi_configure_down(dsi_encoder, pipe);
- else {
- mdfld_dsi_dpi_shut_down(dpi_output, pipe);
-
- /*disable mipi port*/
- REG_WRITE(MIPI_PORT_CONTROL(pipe),
- REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31));
- REG_READ(MIPI_PORT_CONTROL(pipe));
- }
- dev_priv->dpi_panel_on[pipe] = false;
- }
- gma_power_end(dev);
-}
-
-void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
-{
- mdfld_dsi_dpi_set_power(encoder, mode == DRM_MODE_DPMS_ON);
-}
-
-bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_encoder_get_config(dsi_encoder);
- struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
-
- if (fixed_mode) {
- adjusted_mode->hdisplay = fixed_mode->hdisplay;
- adjusted_mode->hsync_start = fixed_mode->hsync_start;
- adjusted_mode->hsync_end = fixed_mode->hsync_end;
- adjusted_mode->htotal = fixed_mode->htotal;
- adjusted_mode->vdisplay = fixed_mode->vdisplay;
- adjusted_mode->vsync_start = fixed_mode->vsync_start;
- adjusted_mode->vsync_end = fixed_mode->vsync_end;
- adjusted_mode->vtotal = fixed_mode->vtotal;
- adjusted_mode->clock = fixed_mode->clock;
- drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
- }
- return true;
-}
-
-void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder)
-{
- mdfld_dsi_dpi_set_power(encoder, false);
-}
-
-void mdfld_dsi_dpi_commit(struct drm_encoder *encoder)
-{
- mdfld_dsi_dpi_set_power(encoder, true);
-}
-
-/* For TC35876X */
-/* This functionality was implemented in FW in iCDK */
-/* But removed in DV0 and later. So need to add here. */
-static void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe)
-{
- struct drm_device *dev = dsi_config->dev;
-
- REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
- REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
- REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0xffffff);
- REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffffff);
- REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14);
- REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xff);
- REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x25);
- REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0xf0);
- REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
- REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
- REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000820);
- REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
-}
-
-static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config,
- int pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- struct mdfld_dsi_dpi_timing dpi_timing;
- struct drm_display_mode *mode = dsi_config->mode;
-
- mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing,
- dsi_config->lane_count,
- dsi_config->bpp);
-
- REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe),
- mode->vdisplay << 16 | mode->hdisplay);
- REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe),
- dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_HBP_COUNT_REG(pipe),
- dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_HFP_COUNT_REG(pipe),
- dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe),
- dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe),
- dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_VBP_COUNT_REG(pipe),
- dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
- REG_WRITE(MIPI_VFP_COUNT_REG(pipe),
- dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
-}
-
-static void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- int lane_count = dsi_config->lane_count;
-
- if (pipe) {
- REG_WRITE(MIPI_PORT_CONTROL(0), 0x00000002);
- REG_WRITE(MIPI_PORT_CONTROL(2), 0x80000000);
- } else {
- REG_WRITE(MIPI_PORT_CONTROL(0), 0x80010000);
- REG_WRITE(MIPI_PORT_CONTROL(2), 0x00);
- }
-
- REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150A600F);
- REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), 0x0000000F);
-
- /* lane_count = 3 */
- REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), 0x00000200 | lane_count);
-
- mdfld_mipi_set_video_timing(dsi_config, pipe);
-}
-
-static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config, int pipe)
-{
- struct drm_device *dev = dsi_config->dev;
- struct drm_display_mode *mode = dsi_config->mode;
-
- REG_WRITE(HTOTAL_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
- REG_WRITE(HBLANK_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
- REG_WRITE(HSYNC_A,
- ((mode->hsync_end - 1) << 16) | (mode->hsync_start - 1));
-
- REG_WRITE(VTOTAL_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
- REG_WRITE(VBLANK_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
- REG_WRITE(VSYNC_A,
- ((mode->vsync_end - 1) << 16) | (mode->vsync_start - 1));
-
- REG_WRITE(PIPEASRC,
- ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
-}
-/* End for TC35876X */
-
-void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder);
- struct mdfld_dsi_dpi_output *dpi_output =
- MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_encoder_get_config(dsi_encoder);
- struct drm_device *dev = dsi_config->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
-
- u32 pipeconf_reg = PIPEACONF;
- u32 dspcntr_reg = DSPACNTR;
-
- u32 pipeconf = dev_priv->pipeconf[pipe];
- u32 dspcntr = dev_priv->dspcntr[pipe];
- u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
-
- if (pipe) {
- pipeconf_reg = PIPECCONF;
- dspcntr_reg = DSPCCNTR;
- } else {
- if (mdfld_get_panel_type(dev, pipe) == TC35876X)
- mipi &= (~0x03); /* Use all four lanes */
- else
- mipi |= 2;
- }
-
- /*start up display island if it was shutdown*/
- if (!gma_power_begin(dev, true))
- return;
-
- if (mdfld_get_panel_type(dev, pipe) == TC35876X) {
- /*
- * The following logic is required to reset the bridge and
- * configure. This also starts the DSI clock at 200MHz.
- */
- tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */
- tc35876x_toshiba_bridge_panel_on(dev);
- udelay(100);
- /* Now start the DSI clock */
- REG_WRITE(MRST_DPLL_A, 0x00);
- REG_WRITE(MRST_FPA0, 0xC1);
- REG_WRITE(MRST_DPLL_A, 0x00800000);
- udelay(500);
- REG_WRITE(MRST_DPLL_A, 0x80800000);
-
- if (REG_BIT_WAIT(pipeconf_reg, 1, 29))
- dev_err(&dev->pdev->dev, "%s: DSI PLL lock timeout\n",
- __func__);
-
- REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
-
- mipi_set_properties(dsi_config, pipe);
- mdfld_mipi_config(dsi_config, pipe);
- mdfld_set_pipe_timing(dsi_config, pipe);
-
- REG_WRITE(DSPABASE, 0x00);
- REG_WRITE(DSPASIZE,
- ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
-
- REG_WRITE(DSPACNTR, 0x98000000);
- REG_WRITE(DSPASURF, 0x00);
-
- REG_WRITE(VGACNTRL, 0x80000000);
- REG_WRITE(DEVICE_READY_REG, 0x00000001);
-
- REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000);
- } else {
- /*set up mipi port FIXME: do at init time */
- REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi);
- }
- REG_READ(MIPI_PORT_CONTROL(pipe));
-
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
- /* NOP */
- } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) {
- /* set up DSI controller DPI interface */
- mdfld_dsi_dpi_controller_init(dsi_config, pipe);
-
- /* Configure MIPI Bridge and Panel */
- tc35876x_configure_lvds_bridge(dev);
- dev_priv->dpi_panel_on[pipe] = true;
- } else {
- /*turn on DPI interface*/
- mdfld_dsi_dpi_turn_on(dpi_output, pipe);
- }
-
- /*set up pipe*/
- REG_WRITE(pipeconf_reg, pipeconf);
- REG_READ(pipeconf_reg);
-
- /*set up display plane*/
- REG_WRITE(dspcntr_reg, dspcntr);
- REG_READ(dspcntr_reg);
-
- msleep(20); /* FIXME: this should wait for vblank */
-
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
- /* NOP */
- } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) {
- mdfld_dsi_dpi_turn_on(dpi_output, pipe);
- } else {
- /* init driver ic */
- mdfld_dsi_tpo_ic_init(dsi_config, pipe);
- /*init backlight*/
- mdfld_dsi_brightness_init(dsi_config, pipe);
- }
-
- gma_power_end(dev);
-}
-
-/*
- * Init DSI DPI encoder.
- * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
- * return pointer of newly allocated DPI encoder, NULL on error
- */
-struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
- struct mdfld_dsi_connector *dsi_connector,
- const struct panel_funcs *p_funcs)
-{
- struct mdfld_dsi_dpi_output *dpi_output = NULL;
- struct mdfld_dsi_config *dsi_config;
- struct drm_connector *connector = NULL;
- struct drm_encoder *encoder = NULL;
- int pipe;
- u32 data;
- int ret;
-
- pipe = dsi_connector->pipe;
-
- if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
- dsi_config = mdfld_dsi_get_config(dsi_connector);
-
- /* 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, false);
- 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) {
- DRM_ERROR("No memory\n");
- return NULL;
- }
-
- if (dsi_connector->pipe)
- dpi_output->panel_on = 0;
- else
- dpi_output->panel_on = 0;
-
- dpi_output->dev = dev;
- if (mdfld_get_panel_type(dev, pipe) != TC35876X)
- dpi_output->p_funcs = p_funcs;
- dpi_output->first_boot = 1;
-
- /*get fixed mode*/
- dsi_config = mdfld_dsi_get_config(dsi_connector);
-
- /*create drm encoder object*/
- connector = &dsi_connector->base.base;
- encoder = &dpi_output->base.base.base;
- drm_encoder_init(dev,
- encoder,
- p_funcs->encoder_funcs,
- DRM_MODE_ENCODER_LVDS);
- drm_encoder_helper_add(encoder,
- p_funcs->encoder_helper_funcs);
-
- /*attach to given connector*/
- drm_mode_connector_attach_encoder(connector, encoder);
-
- /*set possible crtcs and clones*/
- if (dsi_connector->pipe) {
- encoder->possible_crtcs = (1 << 2);
- encoder->possible_clones = (1 << 1);
- } else {
- encoder->possible_crtcs = (1 << 0);
- encoder->possible_clones = (1 << 0);
- }
-
- dsi_connector->base.encoder = &dpi_output->base.base;
-
- return &dpi_output->base;
-}
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h
deleted file mode 100644
index 2b40663e1696..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_DPI_H__
-#define __MDFLD_DSI_DPI_H__
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_output.h"
-
-struct mdfld_dsi_dpi_timing {
- u16 hsync_count;
- u16 hbp_count;
- u16 hfp_count;
- u16 hactive_count;
- u16 vsync_count;
- u16 vbp_count;
- u16 vfp_count;
-};
-
-struct mdfld_dsi_dpi_output {
- struct mdfld_dsi_encoder base;
- struct drm_device *dev;
-
- int panel_on;
- int first_boot;
-
- const struct panel_funcs *p_funcs;
-};
-
-#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder)\
- container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base)
-
-/* Export functions */
-extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
- struct mdfld_dsi_dpi_timing *dpi_timing,
- int num_lane, int bpp);
-extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
- struct mdfld_dsi_connector *dsi_connector,
- const struct panel_funcs *p_funcs);
-
-/* MDFLD DPI helper functions */
-extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
-extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
-extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder);
-extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder);
-extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
-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 *dsi_config,
- int pipe);
-#endif /*__MDFLD_DSI_DPI_H__*/
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
deleted file mode 100644
index 3abf8315f57c..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * 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:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include <linux/module.h>
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_pkg_sender.h"
-#include "tc35876x-dsi-lvds.h"
-#include <linux/pm_runtime.h>
-#include <asm/intel_scu_ipc.h>
-
-/* get the LABC from command line. */
-static int LABC_control = 1;
-
-#ifdef MODULE
-module_param(LABC_control, int, 0644);
-#else
-
-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
-
-/**
- * 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)
-{
- u32 GEN_BF_time_out_count;
-
- /* Check MIPI Adatper command registers */
- for (GEN_BF_time_out_count = 0;
- GEN_BF_time_out_count < GEN_FB_TIME_OUT;
- GEN_BF_time_out_count++) {
- if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
- break;
- udelay(100);
- }
-
- if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
- DRM_ERROR("mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x.\n",
- 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)
-{
- struct mdfld_dsi_pkg_sender *sender =
- mdfld_dsi_get_pkg_sender(dsi_config);
- struct drm_device *dev;
- struct drm_psb_private *dev_priv;
- u32 gen_ctrl_val;
-
- if (!sender) {
- DRM_ERROR("No sender found\n");
- return;
- }
-
- dev = sender->dev;
- dev_priv = dev->dev_private;
-
- /* Set default display backlight value to 85% (0xd8)*/
- mdfld_dsi_send_mcs_short(sender, write_display_brightness, 0xd8, 1,
- true);
-
- /* Set minimum brightness setting of CABC function to 20% (0x33)*/
- mdfld_dsi_send_mcs_short(sender, write_cabc_min_bright, 0x33, 1, true);
-
- /* Enable backlight or/and LABC */
- gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON |
- BACKLIGHT_ON;
- if (LABC_control == 1)
- gen_ctrl_val |= DISPLAY_DIMMING_ON | DISPLAY_BRIGHTNESS_AUTO
- | GAMMA_AUTO;
-
- if (LABC_control == 1)
- gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
-
- dev_priv->mipi_ctrl_display = gen_ctrl_val;
-
- mdfld_dsi_send_mcs_short(sender, write_ctrl_display, (u8)gen_ctrl_val,
- 1, true);
-
- mdfld_dsi_send_mcs_short(sender, write_ctrl_cabc, UI_IMAGE, 1, true);
-}
-
-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;
-
- if (!dev || (pipe != 0 && pipe != 2)) {
- DRM_ERROR("Invalid parameter\n");
- return;
- }
-
- p_type = mdfld_get_panel_type(dev, 0);
-
- dev_priv = dev->dev_private;
-
- if (pipe)
- dsi_config = dev_priv->dsi_configs[1];
- else
- dsi_config = dev_priv->dsi_configs[0];
-
- sender = mdfld_dsi_get_pkg_sender(dsi_config);
-
- if (!sender) {
- DRM_ERROR("No sender found\n");
- return;
- }
-
- gen_ctrl_val = (level * 0xff / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
-
- dev_dbg(sender->dev->dev, "pipe = %d, gen_ctrl_val = %d.\n",
- pipe, gen_ctrl_val);
-
- if (p_type == TMD_VID) {
- /* Set display backlight value */
- mdfld_dsi_send_mcs_short(sender, tmd_write_display_brightness,
- (u8)gen_ctrl_val, 1, true);
- } else {
- /* Set display backlight value */
- mdfld_dsi_send_mcs_short(sender, write_display_brightness,
- (u8)gen_ctrl_val, 1, true);
-
- /* Enable backlight control */
- if (level == 0)
- gen_ctrl_val = 0;
- else
- gen_ctrl_val = dev_priv->mipi_ctrl_display;
-
- mdfld_dsi_send_mcs_short(sender, write_ctrl_display,
- (u8)gen_ctrl_val, 1, true);
- }
-}
-
-static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
- u8 dcs, u32 *data, bool hs)
-{
- struct mdfld_dsi_pkg_sender *sender
- = mdfld_dsi_get_pkg_sender(dsi_config);
-
- if (!sender || !data) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- return mdfld_dsi_read_mcs(sender, dcs, data, 1, hs);
-}
-
-int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, u32 *mode,
- bool hs)
-{
- if (!dsi_config || !mode) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, hs);
-}
-
-/*
- * NOTE: this function was used by OSPM.
- * TODO: will be removed later, should work out display interfaces for OSPM
- */
-void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe)
-{
- if (!dsi_config || ((pipe != 0) && (pipe != 2))) {
- DRM_ERROR("Invalid parameters\n");
- return;
- }
-
- mdfld_dsi_dpi_controller_init(dsi_config, pipe);
-}
-
-static void mdfld_dsi_connector_save(struct drm_connector *connector)
-{
-}
-
-static void mdfld_dsi_connector_restore(struct drm_connector *connector)
-{
-}
-
-/* FIXME: start using the force parameter */
-static enum drm_connector_status
-mdfld_dsi_connector_detect(struct drm_connector *connector, bool force)
-{
- struct mdfld_dsi_connector *dsi_connector
- = mdfld_dsi_connector(connector);
-
- dsi_connector->status = connector_status_connected;
-
- return dsi_connector->status;
-}
-
-static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t value)
-{
- 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);
- bool centerechange;
- uint64_t val;
-
- if (!psb_crtc)
- goto set_prop_error;
-
- switch (value) {
- case DRM_MODE_SCALE_FULLSCREEN:
- break;
- case DRM_MODE_SCALE_NO_SCALE:
- break;
- case DRM_MODE_SCALE_ASPECT:
- break;
- default:
- goto set_prop_error;
- }
-
- if (drm_object_property_get_value(&connector->base, property, &val))
- goto set_prop_error;
-
- if (val == value)
- goto set_prop_done;
-
- if (drm_object_property_set_value(&connector->base,
- property, value))
- goto set_prop_error;
-
- centerechange = (val == DRM_MODE_SCALE_NO_SCALE) ||
- (value == DRM_MODE_SCALE_NO_SCALE);
-
- if (psb_crtc->saved_mode.hdisplay != 0 &&
- psb_crtc->saved_mode.vdisplay != 0) {
- if (centerechange) {
- if (!drm_crtc_helper_set_mode(encoder->crtc,
- &psb_crtc->saved_mode,
- encoder->crtc->x,
- encoder->crtc->y,
- encoder->crtc->fb))
- goto set_prop_error;
- } else {
- struct drm_encoder_helper_funcs *funcs =
- encoder->helper_private;
- funcs->mode_set(encoder,
- &psb_crtc->saved_mode,
- &psb_crtc->saved_adjusted_mode);
- }
- }
- } else if (!strcmp(property->name, "backlight") && encoder) {
- if (drm_object_property_set_value(&connector->base, property,
- value))
- goto set_prop_error;
- else
- gma_backlight_set(encoder->dev, value);
- }
-set_prop_done:
- return 0;
-set_prop_error:
- return -1;
-}
-
-static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
-{
- struct mdfld_dsi_connector *dsi_connector =
- mdfld_dsi_connector(connector);
- struct mdfld_dsi_pkg_sender *sender;
-
- if (!dsi_connector)
- return;
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- sender = dsi_connector->pkg_sender;
- mdfld_dsi_pkg_sender_destroy(sender);
- kfree(dsi_connector);
-}
-
-static int mdfld_dsi_connector_get_modes(struct drm_connector *connector)
-{
- struct mdfld_dsi_connector *dsi_connector =
- mdfld_dsi_connector(connector);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_get_config(dsi_connector);
- struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
- struct drm_display_mode *dup_mode = NULL;
- struct drm_device *dev = connector->dev;
-
- connector->display_info.min_vfreq = 0;
- connector->display_info.max_vfreq = 200;
- connector->display_info.min_hfreq = 0;
- connector->display_info.max_hfreq = 200;
-
- if (fixed_mode) {
- dev_dbg(dev->dev, "fixed_mode %dx%d\n",
- fixed_mode->hdisplay, fixed_mode->vdisplay);
- dup_mode = drm_mode_duplicate(dev, fixed_mode);
- drm_mode_probed_add(connector, dup_mode);
- return 1;
- }
- DRM_ERROR("Didn't get any modes!\n");
- return 0;
-}
-
-static int mdfld_dsi_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct mdfld_dsi_connector *dsi_connector =
- mdfld_dsi_connector(connector);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_get_config(dsi_connector);
- struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
-
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- return MODE_NO_INTERLACE;
-
- /**
- * FIXME: current DC has no fitting unit, reject any mode setting
- * request
- * Will figure out a way to do up-scaling(pannel fitting) later.
- **/
- if (fixed_mode) {
- if (mode->hdisplay != fixed_mode->hdisplay)
- return MODE_PANEL;
-
- if (mode->vdisplay != fixed_mode->vdisplay)
- return MODE_PANEL;
- }
-
- return MODE_OK;
-}
-
-static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
-{
- if (mode == connector->dpms)
- return;
-
- /*first, execute dpms*/
-
- drm_helper_connector_dpms(connector, mode);
-}
-
-static struct drm_encoder *mdfld_dsi_connector_best_encoder(
- struct drm_connector *connector)
-{
- struct mdfld_dsi_connector *dsi_connector =
- mdfld_dsi_connector(connector);
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_get_config(dsi_connector);
- return &dsi_config->encoder->base.base;
-}
-
-/*DSI connector funcs*/
-static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
- .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
- .save = mdfld_dsi_connector_save,
- .restore = mdfld_dsi_connector_restore,
- .detect = mdfld_dsi_connector_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .set_property = mdfld_dsi_connector_set_property,
- .destroy = mdfld_dsi_connector_destroy,
-};
-
-/*DSI connector helper funcs*/
-static const struct drm_connector_helper_funcs
- mdfld_dsi_connector_helper_funcs = {
- .get_modes = mdfld_dsi_connector_get_modes,
- .mode_valid = mdfld_dsi_connector_mode_valid,
- .best_encoder = mdfld_dsi_connector_best_encoder,
-};
-
-static int mdfld_dsi_get_default_config(struct drm_device *dev,
- struct mdfld_dsi_config *config, int pipe)
-{
- if (!dev || !config) {
- DRM_ERROR("Invalid parameters");
- return -EINVAL;
- }
-
- config->bpp = 24;
- if (mdfld_get_panel_type(dev, pipe) == TC35876X)
- config->lane_count = 4;
- else
- config->lane_count = 2;
- config->channel_num = 0;
-
- if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
- config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
- else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
- config->video_mode =
- MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS;
- else
- config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
-
- return 0;
-}
-
-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
- * @pipe pipe number. 0 or 2
- * @config
- *
- * 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,
- int pipe,
- const struct panel_funcs *p_vid_funcs)
-{
- struct mdfld_dsi_config *dsi_config;
- struct mdfld_dsi_connector *dsi_connector;
- struct drm_connector *connector;
- struct mdfld_dsi_encoder *encoder;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct panel_info dsi_panel_info;
- u32 width_mm, height_mm;
-
- dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
-
- if (pipe != 0 && pipe != 2) {
- DRM_ERROR("Invalid parameter\n");
- return;
- }
-
- /*create a new connetor*/
- dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
- if (!dsi_connector) {
- DRM_ERROR("No memory");
- return;
- }
-
- dsi_connector->pipe = pipe;
-
- dsi_config = kzalloc(sizeof(struct mdfld_dsi_config),
- GFP_KERNEL);
- if (!dsi_config) {
- DRM_ERROR("cannot allocate memory for DSI config\n");
- goto dsi_init_err0;
- }
- mdfld_dsi_get_default_config(dev, dsi_config, pipe);
-
- dsi_connector->private = dsi_config;
-
- dsi_config->changed = 1;
- dsi_config->dev = dev;
-
- dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
- if (p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
- goto dsi_init_err0;
-
- width_mm = dsi_panel_info.width_mm;
- height_mm = dsi_panel_info.height_mm;
-
- dsi_config->mode = dsi_config->fixed_mode;
- dsi_config->connector = dsi_connector;
-
- if (!dsi_config->fixed_mode) {
- DRM_ERROR("No pannel fixed mode was found\n");
- goto dsi_init_err0;
- }
-
- if (pipe && dev_priv->dsi_configs[0]) {
- dsi_config->dvr_ic_inited = 0;
- dev_priv->dsi_configs[1] = dsi_config;
- } else if (pipe == 0) {
- dsi_config->dvr_ic_inited = 1;
- dev_priv->dsi_configs[0] = dsi_config;
- } else {
- DRM_ERROR("Trying to init MIPI1 before MIPI0\n");
- goto dsi_init_err0;
- }
-
-
- connector = &dsi_connector->base.base;
- drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
- drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
-
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->display_info.width_mm = width_mm;
- connector->display_info.height_mm = height_mm;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
-
- /*attach properties*/
- drm_object_attach_property(&connector->base,
- dev->mode_config.scaling_mode_property,
- DRM_MODE_SCALE_FULLSCREEN);
- drm_object_attach_property(&connector->base,
- dev_priv->backlight_property,
- MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
-
- /*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;
- }
-
- encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
- if (!encoder) {
- DRM_ERROR("Create DPI encoder failed\n");
- goto dsi_init_err1;
- }
- encoder->private = dsi_config;
- dsi_config->encoder = encoder;
- encoder->base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI :
- INTEL_OUTPUT_MIPI2;
- drm_sysfs_connector_add(connector);
- return;
-
- /*TODO: add code to destroy outputs on error*/
-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);
-dsi_init_err0:
- kfree(dsi_connector);
-}
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.h b/drivers/gpu/drm/gma500/mdfld_dsi_output.h
deleted file mode 100644
index 36eb0744841c..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.h
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * 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:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#ifndef __MDFLD_DSI_OUTPUT_H__
-#define __MDFLD_DSI_OUTPUT_H__
-
-#include <linux/backlight.h>
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_edid.h>
-
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "mdfld_output.h"
-
-#include <asm/mrst.h>
-
-#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
-#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
-#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
-#define FLD_MOD(orig, val, start, end) \
- (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
-
-#define REG_FLD_MOD(reg, val, start, end) \
- REG_WRITE(reg, FLD_MOD(REG_READ(reg), val, start, end))
-
-static inline int REGISTER_FLD_WAIT(struct drm_device *dev, u32 reg,
- u32 val, int start, int end)
-{
- int t = 100000;
-
- while (FLD_GET(REG_READ(reg), start, end) != val) {
- if (--t == 0)
- return 1;
- }
-
- return 0;
-}
-
-#define REG_FLD_WAIT(reg, val, start, end) \
- REGISTER_FLD_WAIT(dev, reg, val, start, end)
-
-#define REG_BIT_WAIT(reg, val, bitnum) \
- REGISTER_FLD_WAIT(dev, reg, val, bitnum, bitnum)
-
-#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
-
-#ifdef DEBUG
-#define CHECK_PIPE(pipe) ({ \
- const typeof(pipe) __pipe = (pipe); \
- BUG_ON(__pipe != 0 && __pipe != 2); \
- __pipe; })
-#else
-#define CHECK_PIPE(pipe) (pipe)
-#endif
-
-/*
- * Actual MIPIA->MIPIC reg offset is 0x800, value 0x400 is valid for 0 and 2
- */
-#define REG_OFFSET(pipe) (CHECK_PIPE(pipe) * 0x400)
-
-/* mdfld DSI controller registers */
-#define MIPI_DEVICE_READY_REG(pipe) (0xb000 + REG_OFFSET(pipe))
-#define MIPI_INTR_STAT_REG(pipe) (0xb004 + REG_OFFSET(pipe))
-#define MIPI_INTR_EN_REG(pipe) (0xb008 + REG_OFFSET(pipe))
-#define MIPI_DSI_FUNC_PRG_REG(pipe) (0xb00c + REG_OFFSET(pipe))
-#define MIPI_HS_TX_TIMEOUT_REG(pipe) (0xb010 + REG_OFFSET(pipe))
-#define MIPI_LP_RX_TIMEOUT_REG(pipe) (0xb014 + REG_OFFSET(pipe))
-#define MIPI_TURN_AROUND_TIMEOUT_REG(pipe) (0xb018 + REG_OFFSET(pipe))
-#define MIPI_DEVICE_RESET_TIMER_REG(pipe) (0xb01c + REG_OFFSET(pipe))
-#define MIPI_DPI_RESOLUTION_REG(pipe) (0xb020 + REG_OFFSET(pipe))
-#define MIPI_DBI_FIFO_THROTTLE_REG(pipe) (0xb024 + REG_OFFSET(pipe))
-#define MIPI_HSYNC_COUNT_REG(pipe) (0xb028 + REG_OFFSET(pipe))
-#define MIPI_HBP_COUNT_REG(pipe) (0xb02c + REG_OFFSET(pipe))
-#define MIPI_HFP_COUNT_REG(pipe) (0xb030 + REG_OFFSET(pipe))
-#define MIPI_HACTIVE_COUNT_REG(pipe) (0xb034 + REG_OFFSET(pipe))
-#define MIPI_VSYNC_COUNT_REG(pipe) (0xb038 + REG_OFFSET(pipe))
-#define MIPI_VBP_COUNT_REG(pipe) (0xb03c + REG_OFFSET(pipe))
-#define MIPI_VFP_COUNT_REG(pipe) (0xb040 + REG_OFFSET(pipe))
-#define MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe) (0xb044 + REG_OFFSET(pipe))
-#define MIPI_DPI_CONTROL_REG(pipe) (0xb048 + REG_OFFSET(pipe))
-#define MIPI_DPI_DATA_REG(pipe) (0xb04c + REG_OFFSET(pipe))
-#define MIPI_INIT_COUNT_REG(pipe) (0xb050 + REG_OFFSET(pipe))
-#define MIPI_MAX_RETURN_PACK_SIZE_REG(pipe) (0xb054 + REG_OFFSET(pipe))
-#define MIPI_VIDEO_MODE_FORMAT_REG(pipe) (0xb058 + REG_OFFSET(pipe))
-#define MIPI_EOT_DISABLE_REG(pipe) (0xb05c + REG_OFFSET(pipe))
-#define MIPI_LP_BYTECLK_REG(pipe) (0xb060 + REG_OFFSET(pipe))
-#define MIPI_LP_GEN_DATA_REG(pipe) (0xb064 + REG_OFFSET(pipe))
-#define MIPI_HS_GEN_DATA_REG(pipe) (0xb068 + REG_OFFSET(pipe))
-#define MIPI_LP_GEN_CTRL_REG(pipe) (0xb06c + REG_OFFSET(pipe))
-#define MIPI_HS_GEN_CTRL_REG(pipe) (0xb070 + REG_OFFSET(pipe))
-#define MIPI_GEN_FIFO_STAT_REG(pipe) (0xb074 + REG_OFFSET(pipe))
-#define MIPI_HS_LS_DBI_ENABLE_REG(pipe) (0xb078 + REG_OFFSET(pipe))
-#define MIPI_DPHY_PARAM_REG(pipe) (0xb080 + REG_OFFSET(pipe))
-#define MIPI_DBI_BW_CTRL_REG(pipe) (0xb084 + REG_OFFSET(pipe))
-#define MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe) (0xb088 + REG_OFFSET(pipe))
-
-#define MIPI_CTRL_REG(pipe) (0xb104 + REG_OFFSET(pipe))
-#define MIPI_DATA_ADD_REG(pipe) (0xb108 + REG_OFFSET(pipe))
-#define MIPI_DATA_LEN_REG(pipe) (0xb10c + REG_OFFSET(pipe))
-#define MIPI_CMD_ADD_REG(pipe) (0xb110 + REG_OFFSET(pipe))
-#define MIPI_CMD_LEN_REG(pipe) (0xb114 + REG_OFFSET(pipe))
-
-/* non-uniform reg offset */
-#define MIPI_PORT_CONTROL(pipe) (CHECK_PIPE(pipe) ? MIPI_C : MIPI)
-
-#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 BIT(0)
-
-#define DSI_INTR_STATE_SPL_PKG_SENT BIT(30)
-#define DSI_INTR_STATE_TE BIT(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 BIT(0)
-#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY BIT(1)
-#define DSI_FIFO_GEN_HS_DATA_EMPTY BIT(2)
-#define DSI_FIFO_GEN_LP_DATA_FULL BIT(8)
-#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY BIT(9)
-#define DSI_FIFO_GEN_LP_DATA_EMPTY BIT(10)
-#define DSI_FIFO_GEN_HS_CTRL_FULL BIT(16)
-#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY BIT(17)
-#define DSI_FIFO_GEN_HS_CTRL_EMPTY BIT(18)
-#define DSI_FIFO_GEN_LP_CTRL_FULL BIT(24)
-#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY BIT(25)
-#define DSI_FIFO_GEN_LP_CTRL_EMPTY BIT(26)
-#define DSI_FIFO_DBI_EMPTY BIT(27)
-#define DSI_FIFO_DPI_EMPTY BIT(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)
-
-/*dsi power modes*/
-#define DSI_POWER_MODE_DISPLAY_ON BIT(2)
-#define DSI_POWER_MODE_NORMAL_ON BIT(3)
-#define DSI_POWER_MODE_SLEEP_OUT BIT(4)
-#define DSI_POWER_MODE_PARTIAL_ON BIT(5)
-#define DSI_POWER_MODE_IDLE_ON BIT(6)
-
-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 BIT(2)
-#define DSI_DPI_DISABLE_BTA BIT(3)
-
-struct mdfld_dsi_connector {
- struct psb_intel_connector base;
-
- int pipe;
- void *private;
- void *pkg_sender;
-
- /* Connection status */
- enum drm_connector_status status;
-};
-
-struct mdfld_dsi_encoder {
- struct psb_intel_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 *encoder;
-
- int changed;
-
- int bpp;
- int lane_count;
- /*Virtual channel number for this encoder*/
- int channel_num;
- /*video mode configure*/
- int video_mode;
-
- int dvr_ic_inited;
-};
-
-static inline struct mdfld_dsi_connector *mdfld_dsi_connector(
- struct drm_connector *connector)
-{
- struct psb_intel_connector *psb_connector;
-
- psb_connector = to_psb_intel_connector(connector);
-
- return container_of(psb_connector, struct mdfld_dsi_connector, base);
-}
-
-static inline struct mdfld_dsi_encoder *mdfld_dsi_encoder(
- struct drm_encoder *encoder)
-{
- struct psb_intel_encoder *psb_encoder;
-
- psb_encoder = to_psb_intel_encoder(encoder);
-
- return container_of(psb_encoder, struct mdfld_dsi_encoder, base);
-}
-
-static inline struct mdfld_dsi_config *
- mdfld_dsi_get_config(struct mdfld_dsi_connector *connector)
-{
- if (!connector)
- return NULL;
- return (struct mdfld_dsi_config *)connector->private;
-}
-
-static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config)
-{
- struct mdfld_dsi_connector *dsi_connector;
-
- if (!config)
- return NULL;
-
- dsi_connector = config->connector;
-
- if (!dsi_connector)
- return NULL;
-
- return dsi_connector->pkg_sender;
-}
-
-static inline struct mdfld_dsi_config *
- mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder)
-{
- if (!encoder)
- return NULL;
- return (struct mdfld_dsi_config *)encoder->private;
-}
-
-static inline struct mdfld_dsi_connector *
- mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder)
-{
- struct mdfld_dsi_config *config;
-
- if (!encoder)
- return NULL;
-
- config = mdfld_dsi_encoder_get_config(encoder);
- if (!config)
- return NULL;
-
- return config->connector;
-}
-
-static inline void *mdfld_dsi_encoder_get_pkg_sender(
- struct mdfld_dsi_encoder *encoder)
-{
- struct mdfld_dsi_config *dsi_config;
-
- dsi_config = mdfld_dsi_encoder_get_config(encoder);
- if (!dsi_config)
- return NULL;
-
- return mdfld_dsi_get_pkg_sender(dsi_config);
-}
-
-static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder)
-{
- struct mdfld_dsi_connector *connector;
-
- if (!encoder)
- return -1;
-
- connector = mdfld_dsi_encoder_get_connector(encoder);
- if (!connector)
- return -1;
- return connector->pipe;
-}
-
-/* Export functions */
-extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev,
- u32 gen_fifo_stat_reg, u32 fifo_stat);
-extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config,
- int pipe);
-extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe,
- int level);
-extern void mdfld_dsi_output_init(struct drm_device *dev,
- int pipe,
- const 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, bool hs);
-extern int mdfld_dsi_panel_reset(int pipe);
-
-#endif /*__MDFLD_DSI_OUTPUT_H__*/
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
deleted file mode 100644
index 489ffd2c66e5..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
+++ /dev/null
@@ -1,688 +0,0 @@
-/*
- * 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:
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include <linux/freezer.h>
-
-#include "mdfld_dsi_output.h"
-#include "mdfld_dsi_pkg_sender.h"
-#include "mdfld_dsi_dpi.h"
-
-#define MDFLD_DSI_READ_MAX_COUNT 5000
-
-enum data_type {
- DSI_DT_GENERIC_SHORT_WRITE_0 = 0x03,
- DSI_DT_GENERIC_SHORT_WRITE_1 = 0x13,
- DSI_DT_GENERIC_SHORT_WRITE_2 = 0x23,
- DSI_DT_GENERIC_READ_0 = 0x04,
- DSI_DT_GENERIC_READ_1 = 0x14,
- DSI_DT_GENERIC_READ_2 = 0x24,
- DSI_DT_GENERIC_LONG_WRITE = 0x29,
- DSI_DT_DCS_SHORT_WRITE_0 = 0x05,
- DSI_DT_DCS_SHORT_WRITE_1 = 0x15,
- DSI_DT_DCS_READ = 0x06,
- DSI_DT_DCS_LONG_WRITE = 0x39,
-};
-
-enum {
- MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
-};
-
-enum {
- MDFLD_DSI_PKG_SENDER_FREE = 0x0,
- MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
-};
-
-static const char *const dsi_errors[] = {
- "RX SOT Error",
- "RX SOT Sync Error",
- "RX EOT Sync Error",
- "RX Escape Mode Entry Error",
- "RX LP TX Sync Error",
- "RX HS Receive Timeout Error",
- "RX False Control Error",
- "RX ECC Single Bit Error",
- "RX ECC Multibit Error",
- "RX Checksum Error",
- "RX DSI Data Type Not Recognised",
- "RX DSI VC ID Invalid",
- "TX False Control Error",
- "TX ECC Single Bit Error",
- "TX ECC Multibit Error",
- "TX Checksum Error",
- "TX DSI Data Type Not Recognised",
- "TX DSI VC ID invalid",
- "High Contention",
- "Low contention",
- "DPI FIFO Under run",
- "HS TX Timeout",
- "LP RX Timeout",
- "Turn Around ACK Timeout",
- "ACK With No Error",
- "RX Invalid TX Length",
- "RX Prot Violation",
- "HS Generic Write FIFO Full",
- "LP Generic Write FIFO Full",
- "Generic Read Data Avail"
- "Special Packet Sent",
- "Tearing Effect",
-};
-
-static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
- u32 mask)
-{
- struct drm_device *dev = sender->dev;
- u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
- int retry = 0xffff;
-
- while (retry--) {
- if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
- return 0;
- udelay(100);
- }
- DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg));
- return -EIO;
-}
-
-static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
-{
- return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) |
- BIT(26) | BIT(27) | BIT(28)));
-}
-
-static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
-{
- return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26)));
-}
-
-static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
-{
- return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18)));
-}
-
-static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
-{
- u32 intr_stat_reg = sender->mipi_intr_stat_reg;
- struct drm_device *dev = sender->dev;
-
- dev_dbg(sender->dev->dev, "Handling error 0x%08x\n", mask);
-
- switch (mask) {
- case BIT(0):
- case BIT(1):
- case BIT(2):
- case BIT(3):
- case BIT(4):
- case BIT(5):
- case BIT(6):
- case BIT(7):
- case BIT(8):
- case BIT(9):
- case BIT(10):
- case BIT(11):
- case BIT(12):
- case BIT(13):
- dev_dbg(sender->dev->dev, "No Action required\n");
- break;
- case BIT(14):
- /*wait for all fifo empty*/
- /*wait_for_all_fifos_empty(sender)*/;
- break;
- case BIT(15):
- dev_dbg(sender->dev->dev, "No Action required\n");
- break;
- case BIT(16):
- break;
- case BIT(17):
- break;
- case BIT(18):
- case BIT(19):
- dev_dbg(sender->dev->dev, "High/Low contention detected\n");
- /*wait for contention recovery time*/
- /*mdelay(10);*/
- /*wait for all fifo empty*/
- if (0)
- wait_for_all_fifos_empty(sender);
- break;
- case BIT(20):
- dev_dbg(sender->dev->dev, "No Action required\n");
- break;
- case BIT(21):
- /*wait for all fifo empty*/
- /*wait_for_all_fifos_empty(sender);*/
- break;
- case BIT(22):
- break;
- case BIT(23):
- case BIT(24):
- case BIT(25):
- case BIT(26):
- case BIT(27):
- dev_dbg(sender->dev->dev, "HS Gen fifo full\n");
- REG_WRITE(intr_stat_reg, mask);
- wait_for_hs_fifos_empty(sender);
- break;
- case BIT(28):
- dev_dbg(sender->dev->dev, "LP Gen fifo full\n");
- REG_WRITE(intr_stat_reg, mask);
- wait_for_lp_fifos_empty(sender);
- break;
- case BIT(29):
- case BIT(30):
- case BIT(31):
- dev_dbg(sender->dev->dev, "No Action required\n");
- break;
- }
-
- if (mask & REG_READ(intr_stat_reg))
- dev_dbg(sender->dev->dev,
- "Cannot clean interrupt 0x%08x\n", mask);
- return 0;
-}
-
-static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
-{
- struct drm_device *dev = sender->dev;
- u32 intr_stat_reg = sender->mipi_intr_stat_reg;
- u32 mask;
- u32 intr_stat;
- int i;
- int err = 0;
-
- intr_stat = REG_READ(intr_stat_reg);
-
- for (i = 0; i < 32; i++) {
- mask = (0x00000001UL) << i;
- if (intr_stat & mask) {
- dev_dbg(sender->dev->dev, "[DSI]: %s\n", dsi_errors[i]);
- err = handle_dsi_error(sender, mask);
- if (err)
- DRM_ERROR("Cannot handle error\n");
- }
- }
- return err;
-}
-
-static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
- u8 cmd, u8 param, bool hs)
-{
- struct drm_device *dev = sender->dev;
- u32 ctrl_reg;
- u32 val;
- u8 virtual_channel = 0;
-
- if (hs) {
- ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
-
- /* FIXME: wait_for_hs_fifos_empty(sender); */
- } else {
- ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
-
- /* FIXME: wait_for_lp_fifos_empty(sender); */
- }
-
- val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) |
- FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0);
-
- REG_WRITE(ctrl_reg, val);
-
- return 0;
-}
-
-static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
- u8 *data, int len, bool hs)
-{
- struct drm_device *dev = sender->dev;
- u32 ctrl_reg;
- u32 data_reg;
- u32 val;
- u8 *p;
- u8 b1, b2, b3, b4;
- u8 virtual_channel = 0;
- int i;
-
- if (hs) {
- ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
- data_reg = sender->mipi_hs_gen_data_reg;
-
- /* FIXME: wait_for_hs_fifos_empty(sender); */
- } else {
- ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
- data_reg = sender->mipi_lp_gen_data_reg;
-
- /* FIXME: wait_for_lp_fifos_empty(sender); */
- }
-
- p = data;
- for (i = 0; i < len / 4; i++) {
- b1 = *p++;
- b2 = *p++;
- b3 = *p++;
- b4 = *p++;
-
- REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1);
- }
-
- i = len % 4;
- if (i) {
- b1 = 0; b2 = 0; b3 = 0;
-
- switch (i) {
- case 3:
- b1 = *p++;
- b2 = *p++;
- b3 = *p++;
- break;
- case 2:
- b1 = *p++;
- b2 = *p++;
- break;
- case 1:
- b1 = *p++;
- break;
- }
-
- REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1);
- }
-
- val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) |
- FLD_VAL(data_type, 5, 0);
-
- REG_WRITE(ctrl_reg, val);
-
- return 0;
-}
-
-static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
- u8 *data, u16 len)
-{
- u8 cmd;
-
- switch (data_type) {
- case DSI_DT_DCS_SHORT_WRITE_0:
- case DSI_DT_DCS_SHORT_WRITE_1:
- case DSI_DT_DCS_LONG_WRITE:
- cmd = *data;
- break;
- default:
- return 0;
- }
-
- /*this prevents other package sending while doing msleep*/
- sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
-
- /*wait for 120 milliseconds in case exit_sleep_mode just be sent*/
- if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
- /*TODO: replace it with msleep later*/
- mdelay(120);
- }
-
- if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) {
- /*TODO: replace it with msleep later*/
- mdelay(120);
- }
- return 0;
-}
-
-static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
- u8 *data, u16 len)
-{
- u8 cmd;
-
- switch (data_type) {
- case DSI_DT_DCS_SHORT_WRITE_0:
- case DSI_DT_DCS_SHORT_WRITE_1:
- case DSI_DT_DCS_LONG_WRITE:
- cmd = *data;
- break;
- default:
- return 0;
- }
-
- /*update panel status*/
- if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
- sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
- /*TODO: replace it with msleep later*/
- mdelay(120);
- } else if (unlikely(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;
-}
-
-static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
- u8 *data, u16 len, bool hs)
-{
- int ret;
-
- /*handle DSI error*/
- ret = dsi_error_handler(sender);
- if (ret) {
- DRM_ERROR("Error handling failed\n");
- return -EAGAIN;
- }
-
- /* send pkg */
- if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
- DRM_ERROR("sender is busy\n");
- return -EAGAIN;
- }
-
- ret = send_pkg_prepare(sender, data_type, data, len);
- if (ret) {
- DRM_ERROR("send_pkg_prepare error\n");
- return ret;
- }
-
- switch (data_type) {
- case DSI_DT_GENERIC_SHORT_WRITE_0:
- case DSI_DT_GENERIC_SHORT_WRITE_1:
- case DSI_DT_GENERIC_SHORT_WRITE_2:
- case DSI_DT_GENERIC_READ_0:
- case DSI_DT_GENERIC_READ_1:
- case DSI_DT_GENERIC_READ_2:
- case DSI_DT_DCS_SHORT_WRITE_0:
- case DSI_DT_DCS_SHORT_WRITE_1:
- case DSI_DT_DCS_READ:
- ret = send_short_pkg(sender, data_type, data[0], data[1], hs);
- break;
- case DSI_DT_GENERIC_LONG_WRITE:
- case DSI_DT_DCS_LONG_WRITE:
- ret = send_long_pkg(sender, data_type, data, len, hs);
- break;
- }
-
- send_pkg_done(sender, data_type, data, len);
-
- /*FIXME: should I query complete and fifo empty here?*/
-
- return ret;
-}
-
-int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
- u32 len, bool hs)
-{
- unsigned long flags;
-
- if (!sender || !data || !len) {
- DRM_ERROR("Invalid parameters\n");
- return -EINVAL;
- }
-
- spin_lock_irqsave(&sender->lock, flags);
- send_pkg(sender, DSI_DT_DCS_LONG_WRITE, data, len, hs);
- spin_unlock_irqrestore(&sender->lock, flags);
-
- return 0;
-}
-
-int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
- u8 param, u8 param_num, bool hs)
-{
- u8 data[2];
- unsigned long flags;
- u8 data_type;
-
- if (!sender) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- data[0] = cmd;
-
- if (param_num) {
- data_type = DSI_DT_DCS_SHORT_WRITE_1;
- data[1] = param;
- } else {
- data_type = DSI_DT_DCS_SHORT_WRITE_0;
- data[1] = 0;
- }
-
- spin_lock_irqsave(&sender->lock, flags);
- send_pkg(sender, data_type, data, sizeof(data), hs);
- spin_unlock_irqrestore(&sender->lock, flags);
-
- return 0;
-}
-
-int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
- u8 param1, u8 param_num, bool hs)
-{
- u8 data[2];
- unsigned long flags;
- u8 data_type;
-
- if (!sender || param_num > 2) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- switch (param_num) {
- case 0:
- data_type = DSI_DT_GENERIC_SHORT_WRITE_0;
- data[0] = 0;
- data[1] = 0;
- break;
- case 1:
- data_type = DSI_DT_GENERIC_SHORT_WRITE_1;
- data[0] = param0;
- data[1] = 0;
- break;
- case 2:
- data_type = DSI_DT_GENERIC_SHORT_WRITE_2;
- data[0] = param0;
- data[1] = param1;
- break;
- }
-
- spin_lock_irqsave(&sender->lock, flags);
- send_pkg(sender, data_type, data, sizeof(data), hs);
- spin_unlock_irqrestore(&sender->lock, flags);
-
- return 0;
-}
-
-int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
- u32 len, bool hs)
-{
- unsigned long flags;
-
- if (!sender || !data || !len) {
- DRM_ERROR("Invalid parameters\n");
- return -EINVAL;
- }
-
- spin_lock_irqsave(&sender->lock, flags);
- send_pkg(sender, DSI_DT_GENERIC_LONG_WRITE, data, len, hs);
- spin_unlock_irqrestore(&sender->lock, flags);
-
- return 0;
-}
-
-static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
- u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs)
-{
- unsigned long flags;
- struct drm_device *dev = sender->dev;
- int i;
- u32 gen_data_reg;
- int retry = MDFLD_DSI_READ_MAX_COUNT;
-
- if (!sender || !data_out || !len_out) {
- DRM_ERROR("Invalid parameters\n");
- return -EINVAL;
- }
-
- /**
- * 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, BIT(29));
-
- if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29)))
- DRM_ERROR("Can NOT clean read data valid interrupt\n");
-
- /*send out read request*/
- send_pkg(sender, data_type, data, len, hs);
-
- /*polling read data avail interrupt*/
- while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) {
- udelay(100);
- retry--;
- }
-
- if (!retry) {
- spin_unlock_irqrestore(&sender->lock, flags);
- return -ETIMEDOUT;
- }
-
- REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
-
- /*read data*/
- if (hs)
- gen_data_reg = sender->mipi_hs_gen_data_reg;
- else
- gen_data_reg = sender->mipi_lp_gen_data_reg;
-
- for (i = 0; i < len_out; i++)
- *(data_out + i) = REG_READ(gen_data_reg);
-
- spin_unlock_irqrestore(&sender->lock, flags);
-
- return 0;
-}
-
-int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
- u32 *data, u16 len, bool hs)
-{
- if (!sender || !data || !len) {
- DRM_ERROR("Invalid parameters\n");
- return -EINVAL;
- }
-
- return __read_panel_data(sender, DSI_DT_DCS_READ, &cmd, 1,
- data, len, hs);
-}
-
-int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
- int pipe)
-{
- struct mdfld_dsi_pkg_sender *pkg_sender;
- struct mdfld_dsi_config *dsi_config =
- mdfld_dsi_get_config(dsi_connector);
- struct drm_device *dev = dsi_config->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- u32 mipi_val = 0;
-
- if (!dsi_connector) {
- DRM_ERROR("Invalid parameter\n");
- return -EINVAL;
- }
-
- pkg_sender = dsi_connector->pkg_sender;
-
- if (!pkg_sender || IS_ERR(pkg_sender)) {
- pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
- GFP_KERNEL);
- if (!pkg_sender) {
- DRM_ERROR("Create DSI pkg sender failed\n");
- return -ENOMEM;
- }
- dsi_connector->pkg_sender = (void *)pkg_sender;
- }
-
- pkg_sender->dev = dev;
- pkg_sender->dsi_connector = dsi_connector;
- pkg_sender->pipe = pipe;
- pkg_sender->pkg_num = 0;
- pkg_sender->panel_mode = 0;
- pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
-
- /*init regs*/
- /* FIXME: should just copy the regmap ptr ? */
- pkg_sender->dpll_reg = map->dpll;
- pkg_sender->dspcntr_reg = map->cntr;
- pkg_sender->pipeconf_reg = map->conf;
- pkg_sender->dsplinoff_reg = map->linoff;
- pkg_sender->dspsurf_reg = map->surf;
- pkg_sender->pipestat_reg = map->status;
-
- pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
- pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
- pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
- pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe);
- pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
- pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
- pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe);
- pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe);
- pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe);
- pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe);
-
- /*init lock*/
- spin_lock_init(&pkg_sender->lock);
-
- if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
- /**
- * For video mode, don't enable DPI timing output here,
- * will init the DPI timing output during mode setting.
- */
- mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
-
- if (pipe == 0)
- mipi_val |= 0x2;
-
- REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val);
- REG_READ(MIPI_PORT_CONTROL(pipe));
-
- /* do dsi controller init */
- mdfld_dsi_controller_init(dsi_config, pipe);
- }
-
- return 0;
-}
-
-void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
-{
- if (!sender || IS_ERR(sender))
- return;
-
- /*free*/
- kfree(sender);
-}
-
-
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h
deleted file mode 100644
index 459cd7ea8b81..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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:
- * Jackie Li<yaodong.li@intel.com>
- */
-#ifndef __MDFLD_DSI_PKG_SENDER_H__
-#define __MDFLD_DSI_PKG_SENDER_H__
-
-#include <linux/kthread.h>
-
-#define MDFLD_MAX_DCS_PARAM 8
-
-struct mdfld_dsi_pkg_sender {
- struct drm_device *dev;
- struct mdfld_dsi_connector *dsi_connector;
- u32 status;
- u32 panel_mode;
-
- int pipe;
-
- spinlock_t lock;
-
- u32 pkg_num;
-
- /* Registers */
- u32 dpll_reg;
- u32 dspcntr_reg;
- u32 pipeconf_reg;
- u32 pipestat_reg;
- u32 dsplinoff_reg;
- u32 dspsurf_reg;
-
- u32 mipi_intr_stat_reg;
- u32 mipi_lp_gen_data_reg;
- u32 mipi_hs_gen_data_reg;
- u32 mipi_lp_gen_ctrl_reg;
- u32 mipi_hs_gen_ctrl_reg;
- u32 mipi_gen_fifo_stat_reg;
- u32 mipi_data_addr_reg;
- u32 mipi_data_len_reg;
- u32 mipi_cmd_addr_reg;
- 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);
-int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
- u8 param, u8 param_num, bool hs);
-int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
- u32 len, bool hs);
-int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
- u8 param1, u8 param_num, bool hs);
-int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
- u32 len, bool hs);
-/* Read interfaces */
-int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
- u32 *data, u16 len, bool hs);
-
-#endif
diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c
deleted file mode 100644
index 74485dc43945..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_intel_display.c
+++ /dev/null
@@ -1,1054 +0,0 @@
-/*
- * Copyright © 2006-2007 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-
-#include <drm/drmP.h>
-#include "psb_intel_reg.h"
-#include "psb_intel_display.h"
-#include "framebuffer.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_output.h"
-
-/* Hardcoded currently */
-static int ksel = KSEL_CRYSTAL_19;
-
-struct psb_intel_range_t {
- int min, max;
-};
-
-struct mrst_limit_t {
- struct psb_intel_range_t dot, m, p1;
-};
-
-struct mrst_clock_t {
- /* derived values */
- int dot;
- int m;
- int p1;
-};
-
-#define COUNT_MAX 0x10000000
-
-void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- int count, temp;
-
- switch (pipe) {
- case 0:
- case 1:
- case 2:
- break;
- default:
- DRM_ERROR("Illegal Pipe Number.\n");
- return;
- }
-
- /* FIXME JLIU7_PO */
- psb_intel_wait_for_vblank(dev);
- return;
-
- /* Wait for for the pipe disable to take effect. */
- for (count = 0; count < COUNT_MAX; count++) {
- temp = REG_READ(map->conf);
- if ((temp & PIPEACONF_PIPE_STATE) == 0)
- break;
- }
-}
-
-void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- int count, temp;
-
- switch (pipe) {
- case 0:
- case 1:
- case 2:
- break;
- default:
- DRM_ERROR("Illegal Pipe Number.\n");
- return;
- }
-
- /* FIXME JLIU7_PO */
- psb_intel_wait_for_vblank(dev);
- return;
-
- /* Wait for for the pipe enable to take effect. */
- for (count = 0; count < COUNT_MAX; count++) {
- temp = REG_READ(map->conf);
- if ((temp & PIPEACONF_PIPE_STATE) == 1)
- break;
- }
-}
-
-static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void psb_intel_crtc_commit(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-/**
- * Return the pipe currently connected to the panel fitter,
- * or -1 if the panel fitter is not present or not in use
- */
-static int psb_intel_panel_fitter_pipe(struct drm_device *dev)
-{
- u32 pfit_control;
-
- pfit_control = REG_READ(PFIT_CONTROL);
-
- /* See if the panel fitter is in use */
- if ((pfit_control & PFIT_ENABLE) == 0)
- return -1;
-
- /* 965 can place panel fitter on either pipe */
- return (pfit_control >> 29) & 0x3;
-}
-
-static struct drm_device globle_dev;
-
-void mdfld__intel_plane_set_alpha(int enable)
-{
- struct drm_device *dev = &globle_dev;
- int dspcntr_reg = DSPACNTR;
- u32 dspcntr;
-
- dspcntr = REG_READ(dspcntr_reg);
-
- if (enable) {
- dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
- dspcntr |= DISPPLANE_32BPP;
- } else {
- dspcntr &= ~DISPPLANE_32BPP;
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
- }
-
- REG_WRITE(dspcntr_reg, dspcntr);
-}
-
-static int check_fb(struct drm_framebuffer *fb)
-{
- if (!fb)
- return 0;
-
- switch (fb->bits_per_pixel) {
- case 8:
- case 16:
- case 24:
- case 32:
- return 0;
- default:
- DRM_ERROR("Unknown color depth\n");
- return -EINVAL;
- }
-}
-
-static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, 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 psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- int pipe = psb_intel_crtc->pipe;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- unsigned long start, offset;
- u32 dspcntr;
- int ret;
-
- memcpy(&globle_dev, dev, sizeof(struct drm_device));
-
- dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe);
-
- /* no fb bound */
- if (!crtc->fb) {
- dev_dbg(dev->dev, "No FB bound\n");
- return 0;
- }
-
- ret = check_fb(crtc->fb);
- if (ret)
- return ret;
-
- if (pipe > 2) {
- DRM_ERROR("Illegal Pipe Number.\n");
- return -EINVAL;
- }
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
- REG_WRITE(map->stride, crtc->fb->pitches[0]);
- dspcntr = REG_READ(map->cntr);
- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
- switch (crtc->fb->bits_per_pixel) {
- case 8:
- dspcntr |= DISPPLANE_8BPP;
- break;
- case 16:
- if (crtc->fb->depth == 15)
- dspcntr |= DISPPLANE_15_16BPP;
- else
- dspcntr |= DISPPLANE_16BPP;
- break;
- case 24:
- case 32:
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
- break;
- }
- REG_WRITE(map->cntr, dspcntr);
-
- dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n",
- start, offset, x, y);
- REG_WRITE(map->linoff, offset);
- REG_READ(map->linoff);
- REG_WRITE(map->surf, start);
- REG_READ(map->surf);
-
- gma_power_end(dev);
-
- return 0;
-}
-
-/*
- * Disable the pipe, plane and pll.
- *
- */
-void mdfld_disable_crtc(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- u32 temp;
-
- dev_dbg(dev->dev, "pipe = %d\n", pipe);
-
-
- if (pipe != 1)
- mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe),
- HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-
- /* 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);
- }
-
- /* FIXME_JLIU7 MDFLD_PO revisit */
-
- /* Next, disable display pipes */
- temp = REG_READ(map->conf);
- if ((temp & PIPEACONF_ENABLE) != 0) {
- temp &= ~PIPEACONF_ENABLE;
- temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
- REG_WRITE(map->conf, temp);
- REG_READ(map->conf);
-
- /* Wait for for the pipe disable to take effect. */
- mdfldWaitForPipeDisable(dev, pipe);
- }
-
- temp = REG_READ(map->dpll);
- if (temp & DPLL_VCO_ENABLE) {
- if ((pipe != 1 &&
- !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF))
- & PIPEACONF_ENABLE)) || pipe == 1) {
- temp &= ~(DPLL_VCO_ENABLE);
- REG_WRITE(map->dpll, temp);
- REG_READ(map->dpll);
- /* Wait for the clocks to turn off. */
- /* FIXME_MDFLD PO may need more delay */
- udelay(500);
-
- if (!(temp & MDFLD_PWR_GATE_EN)) {
- /* gating power of DPLL */
- REG_WRITE(map->dpll, temp | MDFLD_PWR_GATE_EN);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(5000);
- }
- }
- }
-
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- u32 pipeconf = dev_priv->pipeconf[pipe];
- u32 temp;
- int timeout = 0;
-
- dev_dbg(dev->dev, "mode = %d, pipe = %d\n", mode, pipe);
-
- /* Note: Old code uses pipe a stat for pipe b but that appears
- to be a bug */
-
- if (!gma_power_begin(dev, true))
- return;
-
- /* XXX: When our outputs are all unaware of DPMS modes other than off
- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
- */
- switch (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) {
- /* When ungating power of DPLL, needs to wait 0.5us
- before enable the VCO */
- if (temp & MDFLD_PWR_GATE_EN) {
- temp &= ~MDFLD_PWR_GATE_EN;
- REG_WRITE(map->dpll, temp);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
- }
-
- REG_WRITE(map->dpll, temp);
- REG_READ(map->dpll);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
-
- REG_WRITE(map->dpll, temp | DPLL_VCO_ENABLE);
- REG_READ(map->dpll);
-
- /**
- * wait for DSI PLL to lock
- * NOTE: only need to poll status of pipe 0 and pipe 1,
- * since both MIPI pipes share the same PLL.
- */
- while ((pipe != 2) && (timeout < 20000) &&
- !(REG_READ(map->conf) & PIPECONF_DSIPLL_LOCK)) {
- udelay(150);
- timeout++;
- }
- }
-
- /* 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));
- }
-
- /* Enable the pipe */
- temp = REG_READ(map->conf);
- if ((temp & PIPEACONF_ENABLE) == 0) {
- REG_WRITE(map->conf, pipeconf);
-
- /* Wait for for the pipe enable to take effect. */
- mdfldWaitForPipeEnable(dev, pipe);
- }
-
- /*workaround for sighting 3741701 Random X blank display*/
- /*perform w/a in video mode only on pipe A or C*/
- if (pipe == 0 || pipe == 2) {
- REG_WRITE(map->status, REG_READ(map->status));
- msleep(100);
- if (PIPE_VBLANK_STATUS & REG_READ(map->status))
- dev_dbg(dev->dev, "OK");
- else {
- dev_dbg(dev->dev, "STUCK!!!!");
- /*shutdown controller*/
- temp = REG_READ(map->cntr);
- REG_WRITE(map->cntr,
- temp & ~DISPLAY_PLANE_ENABLE);
- REG_WRITE(map->base, REG_READ(map->base));
- /*mdfld_dsi_dpi_shut_down(dev, pipe);*/
- REG_WRITE(0xb048, 1);
- msleep(100);
- temp = REG_READ(map->conf);
- temp &= ~PIPEACONF_ENABLE;
- REG_WRITE(map->conf, temp);
- msleep(100); /*wait for pipe disable*/
- REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0);
- msleep(100);
- REG_WRITE(0xb004, REG_READ(0xb004));
- /* try to bring the controller back up again*/
- REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 1);
- temp = REG_READ(map->cntr);
- REG_WRITE(map->cntr,
- temp | DISPLAY_PLANE_ENABLE);
- REG_WRITE(map->base, REG_READ(map->base));
- /*mdfld_dsi_dpi_turn_on(dev, pipe);*/
- REG_WRITE(0xb048, 2);
- msleep(100);
- temp = REG_READ(map->conf);
- temp |= PIPEACONF_ENABLE;
- REG_WRITE(map->conf, temp);
- }
- }
-
- psb_intel_crtc_load_lut(crtc);
-
- /* Give the overlay scaler a chance to enable
- if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, true); TODO */
-
- break;
- case DRM_MODE_DPMS_OFF:
- /* Give the overlay scaler a chance to disable
- * if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
- if (pipe != 1)
- mdfld_dsi_gen_fifo_ready(dev,
- MIPI_GEN_FIFO_STAT_REG(pipe),
- HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
-
- /* 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);
- }
-
- /* Next, disable display pipes */
- temp = REG_READ(map->conf);
- if ((temp & PIPEACONF_ENABLE) != 0) {
- temp &= ~PIPEACONF_ENABLE;
- temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
- REG_WRITE(map->conf, temp);
- REG_READ(map->conf);
-
- /* Wait for for the pipe disable to take effect. */
- mdfldWaitForPipeDisable(dev, pipe);
- }
-
- temp = REG_READ(map->dpll);
- if (temp & DPLL_VCO_ENABLE) {
- if ((pipe != 1 && !((REG_READ(PIPEACONF)
- | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
- || pipe == 1) {
- temp &= ~(DPLL_VCO_ENABLE);
- REG_WRITE(map->dpll, temp);
- REG_READ(map->dpll);
- /* Wait for the clocks to turn off. */
- /* FIXME_MDFLD PO may need more delay */
- udelay(500);
- }
- }
- break;
- }
- gma_power_end(dev);
-}
-
-
-#define MDFLD_LIMT_DPLL_19 0
-#define MDFLD_LIMT_DPLL_25 1
-#define MDFLD_LIMT_DPLL_83 2
-#define MDFLD_LIMT_DPLL_100 3
-#define MDFLD_LIMT_DSIPLL_19 4
-#define MDFLD_LIMT_DSIPLL_25 5
-#define MDFLD_LIMT_DSIPLL_83 6
-#define MDFLD_LIMT_DSIPLL_100 7
-
-#define MDFLD_DOT_MIN 19750
-#define MDFLD_DOT_MAX 120000
-#define MDFLD_DPLL_M_MIN_19 113
-#define MDFLD_DPLL_M_MAX_19 155
-#define MDFLD_DPLL_P1_MIN_19 2
-#define MDFLD_DPLL_P1_MAX_19 10
-#define MDFLD_DPLL_M_MIN_25 101
-#define MDFLD_DPLL_M_MAX_25 130
-#define MDFLD_DPLL_P1_MIN_25 2
-#define MDFLD_DPLL_P1_MAX_25 10
-#define MDFLD_DPLL_M_MIN_83 64
-#define MDFLD_DPLL_M_MAX_83 64
-#define MDFLD_DPLL_P1_MIN_83 2
-#define MDFLD_DPLL_P1_MAX_83 2
-#define MDFLD_DPLL_M_MIN_100 64
-#define MDFLD_DPLL_M_MAX_100 64
-#define MDFLD_DPLL_P1_MIN_100 2
-#define MDFLD_DPLL_P1_MAX_100 2
-#define MDFLD_DSIPLL_M_MIN_19 131
-#define MDFLD_DSIPLL_M_MAX_19 175
-#define MDFLD_DSIPLL_P1_MIN_19 3
-#define MDFLD_DSIPLL_P1_MAX_19 8
-#define MDFLD_DSIPLL_M_MIN_25 97
-#define MDFLD_DSIPLL_M_MAX_25 140
-#define MDFLD_DSIPLL_P1_MIN_25 3
-#define MDFLD_DSIPLL_P1_MAX_25 9
-#define MDFLD_DSIPLL_M_MIN_83 33
-#define MDFLD_DSIPLL_M_MAX_83 92
-#define MDFLD_DSIPLL_P1_MIN_83 2
-#define MDFLD_DSIPLL_P1_MAX_83 3
-#define MDFLD_DSIPLL_M_MIN_100 97
-#define MDFLD_DSIPLL_M_MAX_100 140
-#define MDFLD_DSIPLL_P1_MIN_100 3
-#define MDFLD_DSIPLL_P1_MAX_100 9
-
-static const struct mrst_limit_t mdfld_limits[] = {
- { /* MDFLD_LIMT_DPLL_19 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
- .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
- },
- { /* MDFLD_LIMT_DPLL_25 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
- .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
- },
- { /* MDFLD_LIMT_DPLL_83 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
- .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
- },
- { /* MDFLD_LIMT_DPLL_100 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
- .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
- },
- { /* MDFLD_LIMT_DSIPLL_19 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
- },
- { /* MDFLD_LIMT_DSIPLL_25 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
- },
- { /* MDFLD_LIMT_DSIPLL_83 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
- },
- { /* MDFLD_LIMT_DSIPLL_100 */
- .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
- .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
- .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
- },
-};
-
-#define MDFLD_M_MIN 21
-#define MDFLD_M_MAX 180
-static const u32 mdfld_m_converts[] = {
-/* M configuration table from 9-bit LFSR table */
- 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
- 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */
- 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
- 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
- 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
- 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
- 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
- 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
- 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
- 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
- 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
- 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
- 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
- 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
- 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
- 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
-};
-
-static const struct mrst_limit_t *mdfld_limit(struct drm_crtc *crtc)
-{
- const struct mrst_limit_t *limit = NULL;
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
- || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
- else if (ksel == KSEL_BYPASS_25)
- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
- else if ((ksel == KSEL_BYPASS_83_100) &&
- (dev_priv->core_freq == 166))
- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
- else if ((ksel == KSEL_BYPASS_83_100) &&
- (dev_priv->core_freq == 100 ||
- dev_priv->core_freq == 200))
- limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
- } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
- limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
- else if (ksel == KSEL_BYPASS_25)
- limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
- else if ((ksel == KSEL_BYPASS_83_100) &&
- (dev_priv->core_freq == 166))
- limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
- else if ((ksel == KSEL_BYPASS_83_100) &&
- (dev_priv->core_freq == 100 ||
- dev_priv->core_freq == 200))
- limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
- } else {
- limit = NULL;
- dev_dbg(dev->dev, "mdfld_limit Wrong display type.\n");
- }
-
- return limit;
-}
-
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-static void mdfld_clock(int refclk, struct mrst_clock_t *clock)
-{
- clock->dot = (refclk * clock->m) / clock->p1;
-}
-
-/**
- * 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
-mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
- struct mrst_clock_t *best_clock)
-{
- struct mrst_clock_t clock;
- const struct mrst_limit_t *limit = mdfld_limit(crtc);
- int err = target;
-
- memset(best_clock, 0, sizeof(*best_clock));
-
- for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
- for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
- clock.p1++) {
- int this_err;
-
- mdfld_clock(refclk, &clock);
-
- this_err = abs(clock.dot - target);
- if (this_err < err) {
- *best_clock = clock;
- err = this_err;
- }
- }
- }
- return err != target;
-}
-
-static int mdfld_crtc_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 psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int pipe = psb_intel_crtc->pipe;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- int refclk = 0;
- int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0,
- clk_tmp = 0;
- struct mrst_clock_t clock;
- bool ok;
- u32 dpll = 0, fp = 0;
- bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct psb_intel_encoder *psb_intel_encoder = NULL;
- uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
- struct drm_encoder *encoder;
- struct drm_connector *connector;
- int timeout = 0;
- int ret;
-
- dev_dbg(dev->dev, "pipe = 0x%x\n", pipe);
-
-#if 0
- if (pipe == 1) {
- if (!gma_power_begin(dev, true))
- return 0;
- android_hdmi_crtc_mode_set(crtc, mode, adjusted_mode,
- x, y, old_fb);
- goto mrst_crtc_mode_set_exit;
- }
-#endif
-
- ret = check_fb(crtc->fb);
- if (ret)
- return ret;
-
- dev_dbg(dev->dev, "adjusted_hdisplay = %d\n",
- adjusted_mode->hdisplay);
- dev_dbg(dev->dev, "adjusted_vdisplay = %d\n",
- adjusted_mode->vdisplay);
- dev_dbg(dev->dev, "adjusted_hsync_start = %d\n",
- adjusted_mode->hsync_start);
- dev_dbg(dev->dev, "adjusted_hsync_end = %d\n",
- adjusted_mode->hsync_end);
- dev_dbg(dev->dev, "adjusted_htotal = %d\n",
- adjusted_mode->htotal);
- dev_dbg(dev->dev, "adjusted_vsync_start = %d\n",
- adjusted_mode->vsync_start);
- dev_dbg(dev->dev, "adjusted_vsync_end = %d\n",
- adjusted_mode->vsync_end);
- dev_dbg(dev->dev, "adjusted_vtotal = %d\n",
- adjusted_mode->vtotal);
- dev_dbg(dev->dev, "adjusted_clock = %d\n",
- adjusted_mode->clock);
- dev_dbg(dev->dev, "hdisplay = %d\n",
- mode->hdisplay);
- dev_dbg(dev->dev, "vdisplay = %d\n",
- mode->vdisplay);
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- memcpy(&psb_intel_crtc->saved_mode, mode,
- sizeof(struct drm_display_mode));
- memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode,
- sizeof(struct drm_display_mode));
-
- list_for_each_entry(connector, &mode_config->connector_list, head) {
- if (!connector)
- continue;
-
- encoder = connector->encoder;
-
- if (!encoder)
- continue;
-
- if (encoder->crtc != crtc)
- continue;
-
- psb_intel_encoder = psb_intel_attached_encoder(connector);
-
- switch (psb_intel_encoder->type) {
- case INTEL_OUTPUT_MIPI:
- is_mipi = true;
- break;
- case INTEL_OUTPUT_MIPI2:
- is_mipi2 = true;
- break;
- case INTEL_OUTPUT_HDMI:
- is_hdmi = true;
- break;
- }
- }
-
- /* Disable the VGA plane that we never use */
- REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
-
- /* Disable the panel fitter if it was on our pipe */
- if (psb_intel_panel_fitter_pipe(dev) == pipe)
- REG_WRITE(PFIT_CONTROL, 0);
-
- /* pipesrc and dspsize control the size that is scaled from,
- * which should always be the user's requested size.
- */
- if (pipe == 1) {
- /* FIXME: To make HDMI display with 864x480 (TPO), 480x864
- * (PYR) or 480x854 (TMD), set the sprite width/height and
- * souce image size registers with the adjusted mode for
- * pipe B.
- */
-
- /*
- * The defined sprite rectangle must always be completely
- * contained within the displayable area of the screen image
- * (frame buffer).
- */
- REG_WRITE(map->size, ((min(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
- | (min(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
- /* Set the CRTC with encoder mode. */
- REG_WRITE(map->src, ((mode->crtc_hdisplay - 1) << 16)
- | (mode->crtc_vdisplay - 1));
- } else {
- REG_WRITE(map->size,
- ((mode->crtc_vdisplay - 1) << 16) |
- (mode->crtc_hdisplay - 1));
- REG_WRITE(map->src,
- ((mode->crtc_hdisplay - 1) << 16) |
- (mode->crtc_vdisplay - 1));
- }
-
- REG_WRITE(map->pos, 0);
-
- if (psb_intel_encoder)
- drm_object_property_get_value(&connector->base,
- dev->mode_config.scaling_mode_property, &scalingType);
-
- if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
- /* Medfield doesn't have register support for centering so we
- * need to mess with the h/vblank and h/vsync start and ends
- * to get centering
- */
- int offsetX = 0, offsetY = 0;
-
- offsetX = (adjusted_mode->crtc_hdisplay -
- mode->crtc_hdisplay) / 2;
- 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));
- } 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));
- }
-
- /* Flush the plane changes */
- {
- struct drm_crtc_helper_funcs *crtc_funcs =
- crtc->helper_private;
- crtc_funcs->mode_set_base(crtc, x, y, old_fb);
- }
-
- /* setup pipeconf */
- dev_priv->pipeconf[pipe] = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
-
- /* Set up the display plane register */
- dev_priv->dspcntr[pipe] = REG_READ(map->cntr);
- dev_priv->dspcntr[pipe] |= pipe << DISPPLANE_SEL_PIPE_POS;
- dev_priv->dspcntr[pipe] |= DISPLAY_PLANE_ENABLE;
-
- if (is_mipi2)
- goto mrst_crtc_mode_set_exit;
- clk = adjusted_mode->clock;
-
- if (is_hdmi) {
- if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) {
- refclk = 19200;
-
- if (is_mipi || is_mipi2)
- clk_n = 1, clk_p2 = 8;
- else if (is_hdmi)
- clk_n = 1, clk_p2 = 10;
- } else if (ksel == KSEL_BYPASS_25) {
- refclk = 25000;
-
- if (is_mipi || is_mipi2)
- clk_n = 1, clk_p2 = 8;
- else if (is_hdmi)
- clk_n = 1, clk_p2 = 10;
- } else if ((ksel == KSEL_BYPASS_83_100) &&
- dev_priv->core_freq == 166) {
- refclk = 83000;
-
- if (is_mipi || is_mipi2)
- clk_n = 4, clk_p2 = 8;
- else if (is_hdmi)
- clk_n = 4, clk_p2 = 10;
- } else if ((ksel == KSEL_BYPASS_83_100) &&
- (dev_priv->core_freq == 100 ||
- dev_priv->core_freq == 200)) {
- refclk = 100000;
- if (is_mipi || is_mipi2)
- clk_n = 4, clk_p2 = 8;
- else if (is_hdmi)
- clk_n = 4, clk_p2 = 10;
- }
-
- if (is_mipi)
- clk_byte = dev_priv->bpp / 8;
- else if (is_mipi2)
- clk_byte = dev_priv->bpp2 / 8;
-
- clk_tmp = clk * clk_n * clk_p2 * clk_byte;
-
- dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d.\n",
- clk, clk_n, clk_p2);
- dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d.\n",
- adjusted_mode->clock, clk_tmp);
-
- ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
-
- if (!ok) {
- DRM_ERROR
- ("mdfldFindBestPLL fail in mdfld_crtc_mode_set.\n");
- } else {
- m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
-
- dev_dbg(dev->dev, "dot clock = %d,"
- "m = %d, p1 = %d, m_conv = %d.\n",
- clock.dot, clock.m,
- clock.p1, m_conv);
- }
-
- dpll = REG_READ(map->dpll);
-
- if (dpll & DPLL_VCO_ENABLE) {
- dpll &= ~DPLL_VCO_ENABLE;
- REG_WRITE(map->dpll, dpll);
- REG_READ(map->dpll);
-
- /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
-
- /* reset M1, N1 & P1 */
- REG_WRITE(map->fp0, 0);
- dpll &= ~MDFLD_P1_MASK;
- REG_WRITE(map->dpll, dpll);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
- }
-
- /* When ungating power of DPLL, needs to wait 0.5us before
- * enable the VCO */
- if (dpll & MDFLD_PWR_GATE_EN) {
- dpll &= ~MDFLD_PWR_GATE_EN;
- REG_WRITE(map->dpll, dpll);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
- }
- dpll = 0;
-
-#if 0 /* FIXME revisit later */
- if (ksel == KSEL_CRYSTAL_19 || ksel == KSEL_BYPASS_19 ||
- ksel == KSEL_BYPASS_25)
- dpll &= ~MDFLD_INPUT_REF_SEL;
- else if (ksel == KSEL_BYPASS_83_100)
- dpll |= MDFLD_INPUT_REF_SEL;
-#endif /* FIXME revisit later */
-
- if (is_hdmi)
- dpll |= MDFLD_VCO_SEL;
-
- fp = (clk_n / 2) << 16;
- fp |= m_conv;
-
- /* compute bitmask from p1 value */
- dpll |= (1 << (clock.p1 - 2)) << 17;
-
-#if 0 /* 1080p30 & 720p */
- dpll = 0x00050000;
- fp = 0x000001be;
-#endif
-#if 0 /* 480p */
- dpll = 0x02010000;
- fp = 0x000000d2;
-#endif
- } else {
-#if 0 /*DBI_TPO_480x864*/
- dpll = 0x00020000;
- fp = 0x00000156;
-#endif /* DBI_TPO_480x864 */ /* get from spec. */
-
- dpll = 0x00800000;
- fp = 0x000000c1;
- }
-
- REG_WRITE(map->fp0, fp);
- REG_WRITE(map->dpll, dpll);
- /* FIXME_MDFLD PO - change 500 to 1 after PO */
- udelay(500);
-
- dpll |= DPLL_VCO_ENABLE;
- REG_WRITE(map->dpll, dpll);
- REG_READ(map->dpll);
-
- /* wait for DSI PLL to lock */
- while (timeout < 20000 &&
- !(REG_READ(map->conf) & PIPECONF_DSIPLL_LOCK)) {
- udelay(150);
- timeout++;
- }
-
- if (is_mipi)
- goto mrst_crtc_mode_set_exit;
-
- dev_dbg(dev->dev, "is_mipi = 0x%x\n", is_mipi);
-
- REG_WRITE(map->conf, dev_priv->pipeconf[pipe]);
- REG_READ(map->conf);
-
- /* Wait for for the pipe enable to take effect. */
- REG_WRITE(map->cntr, dev_priv->dspcntr[pipe]);
- psb_intel_wait_for_vblank(dev);
-
-mrst_crtc_mode_set_exit:
-
- gma_power_end(dev);
-
- return 0;
-}
-
-const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
- .dpms = mdfld_crtc_dpms,
- .mode_fixup = psb_intel_crtc_mode_fixup,
- .mode_set = mdfld_crtc_mode_set,
- .mode_set_base = mdfld__intel_pipe_set_base,
- .prepare = psb_intel_crtc_prepare,
- .commit = psb_intel_crtc_commit,
-};
-
diff --git a/drivers/gpu/drm/gma500/mdfld_output.c b/drivers/gpu/drm/gma500/mdfld_output.c
deleted file mode 100644
index c95966bb0c96..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_output.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 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, sublicensen
- * 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:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#include "mdfld_output.h"
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_output.h"
-
-#include "tc35876x-dsi-lvds.h"
-
-int mdfld_get_panel_type(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- return dev_priv->mdfld_panel_id;
-}
-
-static void mdfld_init_panel(struct drm_device *dev, int mipi_pipe,
- int p_type)
-{
- switch (p_type) {
- case TPO_VID:
- mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tpo_vid_funcs);
- break;
- case TC35876X:
- tc35876x_init(dev);
- mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tc35876x_funcs);
- break;
- case TMD_VID:
- mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tmd_vid_funcs);
- break;
- case HDMI:
-/* if (dev_priv->mdfld_hdmi_present)
- mdfld_hdmi_init(dev, &dev_priv->mode_dev); */
- break;
- }
-}
-
-
-int mdfld_output_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- /* FIXME: hardcoded for now */
- dev_priv->mdfld_panel_id = TC35876X;
- /* MIPI panel 1 */
- mdfld_init_panel(dev, 0, dev_priv->mdfld_panel_id);
- /* HDMI panel */
- mdfld_init_panel(dev, 1, HDMI);
- return 0;
-}
-
diff --git a/drivers/gpu/drm/gma500/mdfld_output.h b/drivers/gpu/drm/gma500/mdfld_output.h
deleted file mode 100644
index ab2b27c0f037..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_output.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 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, sublicensen
- * 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:
- * Thomas Eaton <thomas.g.eaton@intel.com>
- * Scott Rowe <scott.m.rowe@intel.com>
-*/
-
-#ifndef MDFLD_OUTPUT_H
-#define MDFLD_OUTPUT_H
-
-#include "psb_drv.h"
-
-#define TPO_PANEL_WIDTH 84
-#define TPO_PANEL_HEIGHT 46
-#define TMD_PANEL_WIDTH 39
-#define TMD_PANEL_HEIGHT 71
-
-struct mdfld_dsi_config;
-
-enum panel_type {
- TPO_VID,
- TMD_VID,
- HDMI,
- TC35876X,
-};
-
-struct panel_info {
- u32 width_mm;
- u32 height_mm;
- /* Other info */
-};
-
-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 *);
- int (*get_panel_info)(struct drm_device *, int, struct panel_info *);
- int (*reset)(int pipe);
- void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe);
-};
-
-int mdfld_output_init(struct drm_device *dev);
-
-struct backlight_device *mdfld_get_backlight_device(void);
-int mdfld_set_brightness(struct backlight_device *bd);
-
-int mdfld_get_panel_type(struct drm_device *dev, int pipe);
-
-extern const struct drm_crtc_helper_funcs mdfld_helper_funcs;
-
-extern const struct panel_funcs mdfld_tmd_vid_funcs;
-extern const struct panel_funcs mdfld_tpo_vid_funcs;
-
-extern void mdfld_disable_crtc(struct drm_device *dev, int pipe);
-extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe);
-extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
-#endif
diff --git a/drivers/gpu/drm/gma500/mdfld_tmd_vid.c b/drivers/gpu/drm/gma500/mdfld_tmd_vid.c
deleted file mode 100644
index dc0c6c3d3d29..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_tmd_vid.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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:
- * Jim Liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- * Gideon Eaton <eaton.
- * Scott Rowe <scott.m.rowe@intel.com>
- */
-
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_dsi_pkg_sender.h"
-
-static struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev)
-{
- struct drm_display_mode *mode;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
- bool use_gct = false; /*Disable GCT for now*/
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode)
- return NULL;
-
- if (use_gct) {
- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
- mode->hsync_start = mode->hdisplay + \
- ((ti->hsync_offset_hi << 8) | \
- ti->hsync_offset_lo);
- mode->hsync_end = mode->hsync_start + \
- ((ti->hsync_pulse_width_hi << 8) | \
- ti->hsync_pulse_width_lo);
- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
- ti->hblank_lo);
- mode->vsync_start = \
- mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
- ti->vsync_offset_lo);
- mode->vsync_end = \
- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
- ti->vsync_pulse_width_lo);
- 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 {
- mode->hdisplay = 480;
- mode->vdisplay = 854;
- mode->hsync_start = 487;
- mode->hsync_end = 490;
- mode->htotal = 499;
- mode->vsync_start = 861;
- mode->vsync_end = 865;
- mode->vtotal = 873;
- mode->clock = 33264;
- }
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- return mode;
-}
-
-static int tmd_vid_get_panel_info(struct drm_device *dev,
- int pipe,
- struct panel_info *pi)
-{
- if (!dev || !pi)
- return -EINVAL;
-
- pi->width_mm = TMD_PANEL_WIDTH;
- pi->height_mm = TMD_PANEL_HEIGHT;
-
- return 0;
-}
-
-/* ************************************************************************* *\
- * 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!
-\* ************************************************************************* */
-
-/* FIXME: make the below data u8 instead of u32; note byte order! */
-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};
-
-static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config,
- int pipe)
-{
- 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);
-
- /* FIXME: make the below data u8 instead of u32; note byte order! */
-
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_mcap_off,
- sizeof(tmd_cmd_mcap_off), false);
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_lane_switch,
- sizeof(tmd_cmd_enable_lane_switch), false);
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_lane_num,
- sizeof(tmd_cmd_set_lane_num), false);
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock0,
- sizeof(tmd_cmd_pushing_clock0), false);
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock1,
- sizeof(tmd_cmd_pushing_clock1), false);
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_mode,
- sizeof(tmd_cmd_set_mode), false);
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_sync_pulse_mode,
- sizeof(tmd_cmd_set_sync_pulse_mode), false);
- mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_column,
- sizeof(tmd_cmd_set_column), false);
- mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_page,
- sizeof(tmd_cmd_set_page), false);
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_video_mode,
- sizeof(tmd_cmd_set_video_mode), false);
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_backlight,
- sizeof(tmd_cmd_enable_backlight), false);
- mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_backlight_dimming,
- sizeof(tmd_cmd_set_backlight_dimming), false);
-
- dsi_config->dvr_ic_inited = 1;
-}
-
-/*TPO DPI encoder helper funcs*/
-static const struct drm_encoder_helper_funcs
- mdfld_tpo_dpi_encoder_helper_funcs = {
- .dpms = mdfld_dsi_dpi_dpms,
- .mode_fixup = mdfld_dsi_dpi_mode_fixup,
- .prepare = mdfld_dsi_dpi_prepare,
- .mode_set = mdfld_dsi_dpi_mode_set,
- .commit = mdfld_dsi_dpi_commit,
-};
-
-/*TPO DPI encoder funcs*/
-static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-const struct panel_funcs mdfld_tmd_vid_funcs = {
- .encoder_funcs = &mdfld_tpo_dpi_encoder_funcs,
- .encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs,
- .get_config_mode = &tmd_vid_get_config_mode,
- .get_panel_info = tmd_vid_get_panel_info,
- .reset = mdfld_dsi_panel_reset,
- .drv_ic_init = mdfld_dsi_tmd_drv_ic_init,
-};
diff --git a/drivers/gpu/drm/gma500/mdfld_tpo_vid.c b/drivers/gpu/drm/gma500/mdfld_tpo_vid.c
deleted file mode 100644
index d8d4170725b2..000000000000
--- a/drivers/gpu/drm/gma500/mdfld_tpo_vid.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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:
- * jim liu <jim.liu@intel.com>
- * Jackie Li<yaodong.li@intel.com>
- */
-
-#include "mdfld_dsi_dpi.h"
-
-static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev)
-{
- struct drm_display_mode *mode;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
- bool use_gct = false;
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode)
- return NULL;
-
- if (use_gct) {
- mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
- mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
- mode->hsync_start = mode->hdisplay +
- ((ti->hsync_offset_hi << 8) |
- ti->hsync_offset_lo);
- mode->hsync_end = mode->hsync_start +
- ((ti->hsync_pulse_width_hi << 8) |
- ti->hsync_pulse_width_lo);
- mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) |
- ti->hblank_lo);
- mode->vsync_start =
- mode->vdisplay + ((ti->vsync_offset_hi << 8) |
- ti->vsync_offset_lo);
- mode->vsync_end =
- mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) |
- ti->vsync_pulse_width_lo);
- 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 {
- mode->hdisplay = 864;
- mode->vdisplay = 480;
- mode->hsync_start = 873;
- mode->hsync_end = 876;
- mode->htotal = 887;
- mode->vsync_start = 487;
- mode->vsync_end = 490;
- mode->vtotal = 499;
- mode->clock = 33264;
- }
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- return mode;
-}
-
-static int tpo_vid_get_panel_info(struct drm_device *dev,
- int pipe,
- struct panel_info *pi)
-{
- if (!dev || !pi)
- return -EINVAL;
-
- pi->width_mm = TPO_PANEL_WIDTH;
- pi->height_mm = TPO_PANEL_HEIGHT;
-
- return 0;
-}
-
-/*TPO DPI encoder helper funcs*/
-static const struct drm_encoder_helper_funcs
- mdfld_tpo_dpi_encoder_helper_funcs = {
- .dpms = mdfld_dsi_dpi_dpms,
- .mode_fixup = mdfld_dsi_dpi_mode_fixup,
- .prepare = mdfld_dsi_dpi_prepare,
- .mode_set = mdfld_dsi_dpi_mode_set,
- .commit = mdfld_dsi_dpi_commit,
-};
-
-/*TPO DPI encoder funcs*/
-static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-const struct panel_funcs mdfld_tpo_vid_funcs = {
- .encoder_funcs = &mdfld_tpo_dpi_encoder_funcs,
- .encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs,
- .get_config_mode = &tpo_vid_get_config_mode,
- .get_panel_info = tpo_vid_get_panel_info,
-};
diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c
index a97e38e284fa..0326f3ddc621 100644
--- a/drivers/gpu/drm/gma500/mid_bios.c
+++ b/drivers/gpu/drm/gma500/mid_bios.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/**************************************************************************
* Copyright (c) 2011, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
/* TODO
@@ -23,23 +11,25 @@
* - Check ioremap failures
*/
-#include <drm/drmP.h>
#include <drm/drm.h>
-#include <drm/gma_drm.h>
-#include "psb_drv.h"
+#include <drm/drm_print.h>
+
#include "mid_bios.h"
+#include "psb_drv.h"
static void mid_get_fuse_settings(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ struct pci_dev *pci_root =
+ pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
+ 0, 0);
uint32_t fuse_value = 0;
uint32_t fuse_value_tmp = 0;
#define FB_REG06 0xD0810600
#define FB_MIPI_DISABLE (1 << 11)
#define FB_REG09 0xD0810900
-#define FB_REG09 0xD0810900
#define FB_SKU_MASK 0x7000
#define FB_SKU_SHIFT 12
#define FB_SKU_100 0
@@ -105,7 +95,10 @@ static void mid_get_fuse_settings(struct drm_device *dev)
static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
{
uint32_t platform_rev_id = 0;
- struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+ struct pci_dev *pdev = to_pci_dev(dev_priv->dev.dev);
+ int domain = pci_domain_nr(pdev->bus);
+ struct pci_dev *pci_gfx_root =
+ pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(2, 0));
if (pci_gfx_root == NULL) {
WARN_ON(1);
@@ -114,8 +107,7 @@ static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
pci_dev_put(pci_gfx_root);
- dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n",
- dev_priv->platform_rev_id);
+ dev_dbg(dev_priv->dev.dev, "platform_rev_id is %x\n", dev_priv->platform_rev_id);
}
struct mid_vbt_header {
@@ -236,9 +228,9 @@ static int mid_get_vbt_data_r10(struct drm_psb_private *dev_priv, u32 addr)
if (read_vbt_r10(addr, &vbt))
return -1;
- gct = kmalloc(sizeof(*gct) * vbt.panel_count, GFP_KERNEL);
+ gct = kmalloc_array(vbt.panel_count, sizeof(*gct), GFP_KERNEL);
if (!gct)
- return -1;
+ return -ENOMEM;
gct_virtual = ioremap(addr + sizeof(vbt),
sizeof(*gct) * vbt.panel_count);
@@ -278,13 +270,21 @@ out:
static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
{
- struct drm_device *dev = dev_priv->dev;
+ struct drm_device *dev = &dev_priv->dev;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
u32 addr;
u8 __iomem *vbt_virtual;
struct mid_vbt_header vbt_header;
- struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+ struct pci_dev *pci_gfx_root =
+ pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
+ 0, PCI_DEVFN(2, 0));
int ret = -1;
+ if (pci_gfx_root == NULL) {
+ WARN_ON(1);
+ return;
+ }
+
/* Get the address of the platform config vbt */
pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
pci_dev_put(pci_gfx_root);
@@ -330,7 +330,7 @@ out:
int mid_chip_setup(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
mid_get_fuse_settings(dev);
mid_get_vbt_data(dev_priv);
mid_get_pci_revID(dev_priv);
diff --git a/drivers/gpu/drm/gma500/mid_bios.h b/drivers/gpu/drm/gma500/mid_bios.h
index 00e7d564b7eb..8707f7c893a7 100644
--- a/drivers/gpu/drm/gma500/mid_bios.h
+++ b/drivers/gpu/drm/gma500/mid_bios.h
@@ -1,21 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/**************************************************************************
* Copyright (c) 2011, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
+struct drm_device;
extern int mid_chip_setup(struct drm_device *dev);
diff --git a/drivers/gpu/drm/gma500/mmu.c b/drivers/gpu/drm/gma500/mmu.c
index 49bac41beefb..e6753282e70e 100644
--- a/drivers/gpu/drm/gma500/mmu.c
+++ b/drivers/gpu/drm/gma500/mmu.c
@@ -1,21 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
/**************************************************************************
* Copyright (c) 2007, Intel Corporation.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
-#include <drm/drmP.h>
+
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+
+#include "mmu.h"
#include "psb_drv.h"
#include "psb_reg.h"
@@ -47,51 +39,6 @@
* but on average it should be fast.
*/
-struct psb_mmu_driver {
- /* protects driver- and pd structures. Always take in read mode
- * before taking the page table spinlock.
- */
- struct rw_semaphore sem;
-
- /* protects page tables, directory tables and pt tables.
- * and pt structures.
- */
- spinlock_t lock;
-
- atomic_t needs_tlbflush;
-
- uint8_t __iomem *register_map;
- struct psb_mmu_pd *default_pd;
- /*uint32_t bif_ctrl;*/
- int has_clflush;
- int clflush_add;
- unsigned long clflush_mask;
-
- struct drm_psb_private *dev_priv;
-};
-
-struct psb_mmu_pd;
-
-struct psb_mmu_pt {
- struct psb_mmu_pd *pd;
- uint32_t index;
- uint32_t count;
- struct page *p;
- uint32_t *v;
-};
-
-struct psb_mmu_pd {
- struct psb_mmu_driver *driver;
- int hw_context;
- struct psb_mmu_pt **tables;
- struct page *p;
- struct page *dummy_pt;
- struct page *dummy_page;
- uint32_t pd_mask;
- uint32_t invalid_pde;
- uint32_t invalid_pte;
-};
-
static inline uint32_t psb_mmu_pt_index(uint32_t offset)
{
return (offset >> PSB_PTE_SHIFT) & 0x3FF;
@@ -107,8 +54,7 @@ static inline void psb_clflush(void *addr)
__asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
}
-static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
- void *addr)
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, void *addr)
{
if (!driver->has_clflush)
return;
@@ -118,61 +64,69 @@ static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
mb();
}
-static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
+static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver, int force)
{
- uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
- uint32_t clflush_count = PAGE_SIZE / clflush_add;
- int i;
- uint8_t *clf;
-
- clf = kmap_atomic(page);
- mb();
- for (i = 0; i < clflush_count; ++i) {
- psb_clflush(clf);
- clf += clflush_add;
+ struct drm_device *dev = driver->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
+ if (atomic_read(&driver->needs_tlbflush) || force) {
+ uint32_t val = PSB_RSGX32(PSB_CR_BIF_CTRL);
+ PSB_WSGX32(val | _PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL);
+
+ /* Make sure data cache is turned off before enabling it */
+ wmb();
+ PSB_WSGX32(val & ~_PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL);
+ (void)PSB_RSGX32(PSB_CR_BIF_CTRL);
+ if (driver->msvdx_mmu_invaldc)
+ atomic_set(driver->msvdx_mmu_invaldc, 1);
}
- mb();
- kunmap_atomic(clf);
-}
-
-static void psb_pages_clflush(struct psb_mmu_driver *driver,
- struct page *page[], unsigned long num_pages)
-{
- int i;
-
- if (!driver->has_clflush)
- return ;
-
- for (i = 0; i < num_pages; i++)
- psb_page_clflush(driver, *page++);
-}
-
-static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
- int force)
-{
atomic_set(&driver->needs_tlbflush, 0);
}
+#if 0
static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
{
down_write(&driver->sem);
psb_mmu_flush_pd_locked(driver, force);
up_write(&driver->sem);
}
+#endif
-void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
+void psb_mmu_flush(struct psb_mmu_driver *driver)
{
- if (rc_prot)
- down_write(&driver->sem);
- if (rc_prot)
- up_write(&driver->sem);
+ struct drm_device *dev = driver->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ uint32_t val;
+
+ down_write(&driver->sem);
+ val = PSB_RSGX32(PSB_CR_BIF_CTRL);
+ if (atomic_read(&driver->needs_tlbflush))
+ PSB_WSGX32(val | _PSB_CB_CTRL_INVALDC, PSB_CR_BIF_CTRL);
+ else
+ PSB_WSGX32(val | _PSB_CB_CTRL_FLUSH, PSB_CR_BIF_CTRL);
+
+ /* Make sure data cache is turned off and MMU is flushed before
+ restoring bank interface control register */
+ wmb();
+ PSB_WSGX32(val & ~(_PSB_CB_CTRL_FLUSH | _PSB_CB_CTRL_INVALDC),
+ PSB_CR_BIF_CTRL);
+ (void)PSB_RSGX32(PSB_CR_BIF_CTRL);
+
+ atomic_set(&driver->needs_tlbflush, 0);
+ if (driver->msvdx_mmu_invaldc)
+ atomic_set(driver->msvdx_mmu_invaldc, 1);
+ up_write(&driver->sem);
}
void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
{
- /*ttm_tt_cache_flush(&pd->p, 1);*/
- psb_pages_clflush(pd->driver, &pd->p, 1);
+ struct drm_device *dev = pd->driver->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ uint32_t offset = (hw_context == 0) ? PSB_CR_BIF_DIR_LIST_BASE0 :
+ PSB_CR_BIF_DIR_LIST_BASE1 + hw_context * 4;
+
down_write(&pd->driver->sem);
+ PSB_WSGX32(page_to_pfn(pd->p) << PAGE_SHIFT, offset);
wmb();
psb_mmu_flush_pd_locked(pd->driver, 1);
pd->hw_context = hw_context;
@@ -183,7 +137,6 @@ void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
static inline unsigned long psb_pd_addr_end(unsigned long addr,
unsigned long end)
{
-
addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
return (addr < end) ? addr : end;
}
@@ -223,28 +176,26 @@ struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
goto out_err3;
if (!trap_pagefaults) {
- pd->invalid_pde =
- psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
- invalid_type);
- pd->invalid_pte =
- psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
- invalid_type);
+ pd->invalid_pde = psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
+ invalid_type);
+ pd->invalid_pte = psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
+ invalid_type);
} else {
pd->invalid_pde = 0;
pd->invalid_pte = 0;
}
- v = kmap(pd->dummy_pt);
+ v = kmap_local_page(pd->dummy_pt);
for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
v[i] = pd->invalid_pte;
- kunmap(pd->dummy_pt);
+ kunmap_local(v);
- v = kmap(pd->p);
+ v = kmap_local_page(pd->p);
for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
v[i] = pd->invalid_pde;
- kunmap(pd->p);
+ kunmap_local(v);
clear_page(kmap(pd->dummy_page));
kunmap(pd->dummy_page);
@@ -279,12 +230,16 @@ static void psb_mmu_free_pt(struct psb_mmu_pt *pt)
void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
{
struct psb_mmu_driver *driver = pd->driver;
+ struct drm_device *dev = driver->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_mmu_pt *pt;
int i;
down_write(&driver->sem);
- if (pd->hw_context != -1)
+ if (pd->hw_context != -1) {
+ PSB_WSGX32(0, PSB_CR_BIF_DIR_LIST_BASE0 + pd->hw_context * 4);
psb_mmu_flush_pd_locked(driver, 1);
+ }
/* Should take the spinlock here, but we don't need to do that
since we have the semaphore in write mode. */
@@ -331,7 +286,6 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
*ptes++ = pd->invalid_pte;
-
if (pd->driver->has_clflush && pd->hw_context != -1) {
mb();
for (i = 0; i < clflush_count; ++i) {
@@ -340,7 +294,6 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
}
mb();
}
-
kunmap_atomic(v);
spin_unlock(lock);
@@ -352,7 +305,7 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
}
static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
- unsigned long addr)
+ unsigned long addr)
{
uint32_t index = psb_mmu_pd_index(addr);
struct psb_mmu_pt *pt;
@@ -383,7 +336,7 @@ static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
kunmap_atomic((void *) v);
if (pd->hw_context != -1) {
- psb_mmu_clflush(pd->driver, (void *) &v[index]);
+ psb_mmu_clflush(pd->driver, (void *)&v[index]);
atomic_set(&pd->driver->needs_tlbflush, 1);
}
}
@@ -420,11 +373,10 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
pd->tables[pt->index] = NULL;
if (pd->hw_context != -1) {
- psb_mmu_clflush(pd->driver,
- (void *) &v[pt->index]);
+ psb_mmu_clflush(pd->driver, (void *)&v[pt->index]);
atomic_set(&pd->driver->needs_tlbflush, 1);
}
- kunmap_atomic(pt->v);
+ kunmap_atomic(v);
spin_unlock(&pd->driver->lock);
psb_mmu_free_pt(pt);
return;
@@ -432,8 +384,8 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
spin_unlock(&pd->driver->lock);
}
-static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
- unsigned long addr, uint32_t pte)
+static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, unsigned long addr,
+ uint32_t pte)
{
pt->v[psb_mmu_pt_index(addr)] = pte;
}
@@ -444,69 +396,41 @@ static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
}
-
-void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
- uint32_t mmu_offset, uint32_t gtt_start,
- uint32_t gtt_pages)
-{
- uint32_t *v;
- uint32_t start = psb_mmu_pd_index(mmu_offset);
- struct psb_mmu_driver *driver = pd->driver;
- int num_pages = gtt_pages;
-
- down_read(&driver->sem);
- spin_lock(&driver->lock);
-
- v = kmap_atomic(pd->p);
- v += start;
-
- while (gtt_pages--) {
- *v++ = gtt_start | pd->pd_mask;
- gtt_start += PAGE_SIZE;
- }
-
- /*ttm_tt_cache_flush(&pd->p, num_pages);*/
- psb_pages_clflush(pd->driver, &pd->p, num_pages);
- kunmap_atomic(v);
- spin_unlock(&driver->lock);
-
- if (pd->hw_context != -1)
- atomic_set(&pd->driver->needs_tlbflush, 1);
-
- up_read(&pd->driver->sem);
- psb_mmu_flush_pd(pd->driver, 0);
-}
-
struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
{
struct psb_mmu_pd *pd;
- /* down_read(&driver->sem); */
+ down_read(&driver->sem);
pd = driver->default_pd;
- /* up_read(&driver->sem); */
+ up_read(&driver->sem);
return pd;
}
void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
{
+ struct drm_device *dev = driver->dev;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
+ PSB_WSGX32(driver->bif_ctrl, PSB_CR_BIF_CTRL);
psb_mmu_free_pagedir(driver->default_pd);
kfree(driver);
}
-struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
- int trap_pagefaults,
- int invalid_type,
- struct drm_psb_private *dev_priv)
+struct psb_mmu_driver *psb_mmu_driver_init(struct drm_device *dev,
+ int trap_pagefaults,
+ int invalid_type,
+ atomic_t *msvdx_mmu_invaldc)
{
struct psb_mmu_driver *driver;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
driver = kmalloc(sizeof(*driver), GFP_KERNEL);
if (!driver)
return NULL;
- driver->dev_priv = dev_priv;
+ driver->dev = dev;
driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
invalid_type);
if (!driver->default_pd)
@@ -515,17 +439,23 @@ struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
spin_lock_init(&driver->lock);
init_rwsem(&driver->sem);
down_write(&driver->sem);
- driver->register_map = registers;
atomic_set(&driver->needs_tlbflush, 1);
+ driver->msvdx_mmu_invaldc = msvdx_mmu_invaldc;
+
+ driver->bif_ctrl = PSB_RSGX32(PSB_CR_BIF_CTRL);
+ PSB_WSGX32(driver->bif_ctrl | _PSB_CB_CTRL_CLEAR_FAULT,
+ PSB_CR_BIF_CTRL);
+ PSB_WSGX32(driver->bif_ctrl & ~_PSB_CB_CTRL_CLEAR_FAULT,
+ PSB_CR_BIF_CTRL);
driver->has_clflush = 0;
- if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
+ if (boot_cpu_has(X86_FEATURE_CLFLUSH)) {
uint32_t tfms, misc, cap0, cap4, clflush_size;
/*
- * clflush size is determined at kernel setup for x86_64
- * but not for i386. We have to do it here.
+ * clflush size is determined at kernel setup for x86_64 but not
+ * for i386. We have to do it here.
*/
cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
@@ -545,9 +475,8 @@ out_err1:
return NULL;
}
-static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
- unsigned long address, uint32_t num_pages,
- uint32_t desired_tile_stride,
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, unsigned long address,
+ uint32_t num_pages, uint32_t desired_tile_stride,
uint32_t hw_tile_stride)
{
struct psb_mmu_pt *pt;
@@ -561,11 +490,8 @@ static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
unsigned long clflush_add = pd->driver->clflush_add;
unsigned long clflush_mask = pd->driver->clflush_mask;
- if (!pd->driver->has_clflush) {
- /*ttm_tt_cache_flush(&pd->p, num_pages);*/
- psb_pages_clflush(pd->driver, &pd->p, num_pages);
+ if (!pd->driver->has_clflush)
return;
- }
if (hw_tile_stride)
rows = num_pages / desired_tile_stride;
@@ -586,10 +512,8 @@ static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
if (!pt)
continue;
do {
- psb_clflush(&pt->v
- [psb_mmu_pt_index(addr)]);
- } while (addr +=
- clflush_add,
+ psb_clflush(&pt->v[psb_mmu_pt_index(addr)]);
+ } while (addr += clflush_add,
(addr & clflush_mask) < next);
psb_mmu_pt_unmap_unlock(pt);
@@ -633,7 +557,7 @@ out:
up_read(&pd->driver->sem);
if (pd->hw_context != -1)
- psb_mmu_flush(pd->driver, 0);
+ psb_mmu_flush(pd->driver);
return;
}
@@ -660,7 +584,7 @@ void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
add = desired_tile_stride << PAGE_SHIFT;
row_add = hw_tile_stride << PAGE_SHIFT;
- /* down_read(&pd->driver->sem); */
+ down_read(&pd->driver->sem);
/* Make sure we only need to flush this processor's cache */
@@ -688,10 +612,10 @@ void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
psb_mmu_flush_ptes(pd, f_address, num_pages,
desired_tile_stride, hw_tile_stride);
- /* up_read(&pd->driver->sem); */
+ up_read(&pd->driver->sem);
if (pd->hw_context != -1)
- psb_mmu_flush(pd->driver, 0);
+ psb_mmu_flush(pd->driver);
}
int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
@@ -704,7 +628,7 @@ int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
unsigned long end;
unsigned long next;
unsigned long f_address = address;
- int ret = 0;
+ int ret = -ENOMEM;
down_read(&pd->driver->sem);
@@ -726,6 +650,7 @@ int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
psb_mmu_pt_unmap_unlock(pt);
} while (addr = next, next != end);
+ ret = 0;
out:
if (pd->hw_context != -1)
@@ -734,15 +659,15 @@ out:
up_read(&pd->driver->sem);
if (pd->hw_context != -1)
- psb_mmu_flush(pd->driver, 1);
+ psb_mmu_flush(pd->driver);
return ret;
}
int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
unsigned long address, uint32_t num_pages,
- uint32_t desired_tile_stride,
- uint32_t hw_tile_stride, int type)
+ uint32_t desired_tile_stride, uint32_t hw_tile_stride,
+ int type)
{
struct psb_mmu_pt *pt;
uint32_t rows = 1;
@@ -754,7 +679,7 @@ int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
unsigned long add;
unsigned long row_add;
unsigned long f_address = address;
- int ret = 0;
+ int ret = -ENOMEM;
if (hw_tile_stride) {
if (num_pages % desired_tile_stride != 0)
@@ -777,14 +702,11 @@ int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
do {
next = psb_pd_addr_end(addr, end);
pt = psb_mmu_pt_alloc_map_lock(pd, addr);
- if (!pt) {
- ret = -ENOMEM;
+ if (!pt)
goto out;
- }
do {
- pte =
- psb_mmu_mask_pte(page_to_pfn(*pages++),
- type);
+ pte = psb_mmu_mask_pte(page_to_pfn(*pages++),
+ type);
psb_mmu_set_pte(pt, addr, pte);
pt->count++;
} while (addr += PAGE_SIZE, addr < next);
@@ -794,6 +716,8 @@ int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
address += row_add;
}
+
+ ret = 0;
out:
if (pd->hw_context != -1)
psb_mmu_flush_ptes(pd, f_address, num_pages,
@@ -802,48 +726,7 @@ out:
up_read(&pd->driver->sem);
if (pd->hw_context != -1)
- psb_mmu_flush(pd->driver, 1);
-
- return ret;
-}
-
-int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
- unsigned long *pfn)
-{
- int ret;
- struct psb_mmu_pt *pt;
- uint32_t tmp;
- spinlock_t *lock = &pd->driver->lock;
-
- down_read(&pd->driver->sem);
- pt = psb_mmu_pt_map_lock(pd, virtual);
- if (!pt) {
- uint32_t *v;
+ psb_mmu_flush(pd->driver);
- spin_lock(lock);
- v = kmap_atomic(pd->p);
- tmp = v[psb_mmu_pd_index(virtual)];
- kunmap_atomic(v);
- spin_unlock(lock);
-
- if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
- !(pd->invalid_pte & PSB_PTE_VALID)) {
- ret = -EINVAL;
- goto out;
- }
- ret = 0;
- *pfn = pd->invalid_pte >> PAGE_SHIFT;
- goto out;
- }
- tmp = pt->v[psb_mmu_pt_index(virtual)];
- if (!(tmp & PSB_PTE_VALID)) {
- ret = -EINVAL;
- } else {
- ret = 0;
- *pfn = tmp >> PAGE_SHIFT;
- }
- psb_mmu_pt_unmap_unlock(pt);
-out:
- up_read(&pd->driver->sem);
return ret;
}
diff --git a/drivers/gpu/drm/gma500/mmu.h b/drivers/gpu/drm/gma500/mmu.h
new file mode 100644
index 000000000000..e6d39703718c
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mmu.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/**************************************************************************
+ * Copyright (c) 2007-2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+#ifndef __MMU_H
+#define __MMU_H
+
+struct psb_mmu_driver {
+ /* protects driver- and pd structures. Always take in read mode
+ * before taking the page table spinlock.
+ */
+ struct rw_semaphore sem;
+
+ /* protects page tables, directory tables and pt tables.
+ * and pt structures.
+ */
+ spinlock_t lock;
+
+ atomic_t needs_tlbflush;
+ atomic_t *msvdx_mmu_invaldc;
+ struct psb_mmu_pd *default_pd;
+ uint32_t bif_ctrl;
+ int has_clflush;
+ int clflush_add;
+ unsigned long clflush_mask;
+
+ struct drm_device *dev;
+};
+
+struct psb_mmu_pd;
+
+struct psb_mmu_pt {
+ struct psb_mmu_pd *pd;
+ uint32_t index;
+ uint32_t count;
+ struct page *p;
+ uint32_t *v;
+};
+
+struct psb_mmu_pd {
+ struct psb_mmu_driver *driver;
+ int hw_context;
+ struct psb_mmu_pt **tables;
+ struct page *p;
+ struct page *dummy_pt;
+ struct page *dummy_page;
+ uint32_t pd_mask;
+ uint32_t invalid_pde;
+ uint32_t invalid_pte;
+};
+
+extern struct psb_mmu_driver *psb_mmu_driver_init(struct drm_device *dev,
+ int trap_pagefaults,
+ int invalid_type,
+ atomic_t *msvdx_mmu_invaldc);
+extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
+extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
+ *driver);
+extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+ int trap_pagefaults,
+ int invalid_type);
+extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
+extern void psb_mmu_flush(struct psb_mmu_driver *driver);
+extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+ unsigned long address,
+ uint32_t num_pages);
+extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
+ uint32_t start_pfn,
+ unsigned long address,
+ uint32_t num_pages, int type);
+extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
+extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+ unsigned long address, uint32_t num_pages,
+ uint32_t desired_tile_stride,
+ uint32_t hw_tile_stride, int type);
+extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
+ unsigned long address, uint32_t num_pages,
+ uint32_t desired_tile_stride,
+ uint32_t hw_tile_stride);
+
+#endif
diff --git a/drivers/gpu/drm/gma500/oaktrail.h b/drivers/gpu/drm/gma500/oaktrail.h
index 30adbbe23024..8d20fa2ee286 100644
--- a/drivers/gpu/drm/gma500/oaktrail.h
+++ b/drivers/gpu/drm/gma500/oaktrail.h
@@ -1,22 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/**************************************************************************
* Copyright (c) 2007-2011, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
+struct psb_intel_mode_device;
+
/* MID device specific descriptors */
struct oaktrail_timing_info {
diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c
index 3071526bc3c1..086d14678a8e 100644
--- a/drivers/gpu/drm/gma500/oaktrail_crtc.c
+++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c
@@ -1,49 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright © 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/pm_runtime.h>
-#include <drm/drmP.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+
#include "framebuffer.h"
+#include "gem.h"
+#include "gma_display.h"
+#include "power.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "psb_intel_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 +37,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,65 +81,123 @@ 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;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
- || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) {
+ if (gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
+ || 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));
+ memset(&clock, 0, sizeof(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));
+ memset(&clock, 0, sizeof(clock));
for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
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,11 +206,10 @@ mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
}
}
}
- dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err);
return err != target;
}
-/**
+/*
* Sets the power management mode of the pipe and plane.
*
* This code should probably grow support for turning the cursor off and back
@@ -162,13 +218,15 @@ mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ 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) {
+ if (gma_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
oaktrail_crtc_hdmi_dpms(crtc, mode);
return;
}
@@ -183,36 +241,46 @@ 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);
+ }
- psb_intel_crtc_load_lut(crtc);
+ }
+ gma_crtc_load_lut(crtc);
/* Give the overlay scaler a chance to enable
if it's on this pipe */
@@ -223,53 +291,57 @@ 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. */
- psb_intel_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 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;
}
- /*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);
}
-/**
+/*
* Return the pipe currently connected to the panel fitter,
* or -1 if the panel fitter is not present or not in use
*/
@@ -292,41 +364,41 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
struct drm_framebuffer *old_fb)
{
struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int pipe = psb_intel_crtc->pipe;
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ 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;
bool is_mipi = false;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct psb_intel_encoder *psb_intel_encoder = NULL;
+ struct gma_encoder *gma_encoder = NULL;
uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
+ 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))
return 0;
- memcpy(&psb_intel_crtc->saved_mode,
- mode,
- sizeof(struct drm_display_mode));
- memcpy(&psb_intel_crtc->saved_adjusted_mode,
- adjusted_mode,
- sizeof(struct drm_display_mode));
+ drm_mode_copy(&gma_crtc->saved_mode, mode);
+ drm_mode_copy(&gma_crtc->saved_adjusted_mode, adjusted_mode);
- list_for_each_entry(connector, &mode_config->connector_list, head) {
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
if (!connector->encoder || connector->encoder->crtc != crtc)
continue;
- psb_intel_encoder = psb_intel_attached_encoder(connector);
+ gma_encoder = gma_attached_encoder(connector);
- switch (psb_intel_encoder->type) {
+ switch (gma_encoder->type) {
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
@@ -337,22 +409,28 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
is_mipi = true;
break;
}
+
+ break;
}
+ if (gma_encoder)
+ drm_object_property_get_value(&connector->base,
+ dev->mode_config.scaling_mode_property, &scalingType);
+
+ drm_connector_list_iter_end(&conn_iter);
+
/* 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));
-
- if (psb_intel_encoder)
- drm_object_property_get_value(&connector->base,
- dev->mode_config.scaling_mode_property, &scalingType);
+ for (i = 0; i <= need_aux; i++) {
+ REG_WRITE_WITH_AUX(map->src, ((mode->crtc_hdisplay - 1) << 16) |
+ (mode->crtc_vdisplay - 1), i);
+ }
if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
/* Moorestown doesn't have register support for centering so
@@ -365,40 +443,44 @@ 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 */
{
- struct drm_crtc_helper_funcs *crtc_funcs =
+ const struct drm_crtc_helper_funcs *crtc_funcs =
crtc->helper_private;
crtc_funcs->mode_set_base(crtc, x, y, old_fb);
}
@@ -418,21 +500,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,59 +547,57 @@ 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);
- 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);
- psb_intel_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);
- psb_intel_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);
return 0;
}
-static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
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 psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- int pipe = psb_intel_crtc->pipe;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ struct drm_framebuffer *fb = crtc->primary->fb;
+ int pipe = gma_crtc->pipe;
const struct psb_offset *map = &dev_priv->regmap[pipe];
unsigned long start, offset;
@@ -516,7 +605,7 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
int ret = 0;
/* no fb bound */
- if (!crtc->fb) {
+ if (!fb) {
dev_dbg(dev->dev, "No FB bound\n");
return 0;
}
@@ -524,20 +613,20 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
if (!gma_power_begin(dev, true))
return 0;
- start = psbfb->gtt->offset;
- offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
+ start = to_psb_gem_object(fb->obj[0])->offset;
+ offset = y * fb->pitches[0] + x * fb->format->cpp[0];
- REG_WRITE(map->stride, crtc->fb->pitches[0]);
+ REG_WRITE(map->stride, fb->pitches[0]);
dspcntr = REG_READ(map->cntr);
dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
- switch (crtc->fb->bits_per_pixel) {
+ switch (fb->format->cpp[0] * 8) {
case 8:
dspcntr |= DISPPLANE_8BPP;
break;
case 16:
- if (crtc->fb->depth == 15)
+ if (fb->format->depth == 15)
dspcntr |= DISPPLANE_15_16BPP;
else
dspcntr |= DISPPLANE_16BPP;
@@ -563,24 +652,10 @@ pipe_set_base_exit:
return ret;
}
-static void oaktrail_crtc_prepare(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void oaktrail_crtc_commit(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
const struct drm_crtc_helper_funcs oaktrail_helper_funcs = {
.dpms = oaktrail_crtc_dpms,
- .mode_fixup = oaktrail_crtc_mode_fixup,
.mode_set = oaktrail_crtc_mode_set,
.mode_set_base = oaktrail_pipe_set_base,
- .prepare = oaktrail_crtc_prepare,
- .commit = oaktrail_crtc_commit,
+ .prepare = gma_crtc_prepare,
+ .commit = gma_crtc_commit,
};
-
diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c
index 08747fd7105c..2531959d3d77 100644
--- a/drivers/gpu/drm/gma500/oaktrail_device.c
+++ b/drivers/gpu/drm/gma500/oaktrail_device.c
@@ -1,45 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0-only
/**************************************************************************
* Copyright (c) 2011, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
-#include <linux/backlight.h>
-#include <linux/module.h>
+#include <linux/delay.h>
#include <linux/dmi.h>
-#include <drm/drmP.h>
+#include <linux/module.h>
+
#include <drm/drm.h>
-#include <drm/gma_drm.h>
+
+#include "intel_bios.h"
+#include "mid_bios.h"
#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"
-#include "intel_bios.h"
+#include "psb_reg.h"
static int oaktrail_output_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
if (dev_priv->iLVDS_enable)
oaktrail_lvds_init(dev, &dev_priv->mode_dev);
else
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;
}
@@ -47,29 +36,18 @@ static int oaktrail_output_init(struct drm_device *dev)
* Provide the low level interfaces for the Moorestown backlight
*/
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
#define BLC_PWM_FREQ_CALC_CONSTANT 32
#define MHz 1000000
#define BLC_ADJUSTMENT_MAX 100
-static struct backlight_device *oaktrail_backlight_device;
-static int oaktrail_brightness;
-
-static int oaktrail_set_brightness(struct backlight_device *bd)
+static void oaktrail_set_brightness(struct drm_device *dev, int level)
{
- struct drm_device *dev = bl_get_data(oaktrail_backlight_device);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int level = bd->props.brightness;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 blc_pwm_ctl;
u32 max_pwm_blc;
- /* Percentage 1-100% being valid */
- if (level < 1)
- level = 1;
-
if (gma_power_begin(dev, 0)) {
/* Calculate and set the brightness value */
max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
@@ -92,21 +70,11 @@ static int oaktrail_set_brightness(struct backlight_device *bd)
REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
gma_power_end(dev);
}
- oaktrail_brightness = level;
- return 0;
}
-static int oaktrail_get_brightness(struct backlight_device *bd)
-{
- /* return locally cached var instead of HW read (due to DPST etc.) */
- /* FIXME: ideally return actual value in case firmware fiddled with
- it */
- return oaktrail_brightness;
-}
-
-static int device_backlight_init(struct drm_device *dev)
+static int oaktrail_backlight_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
unsigned long core_clock;
u16 bl_max_freq;
uint32_t value;
@@ -133,44 +101,11 @@ static int device_backlight_init(struct drm_device *dev)
REG_WRITE(BLC_PWM_CTL, value | (value << 16));
gma_power_end(dev);
}
- return 0;
-}
-
-static const struct backlight_ops oaktrail_ops = {
- .get_brightness = oaktrail_get_brightness,
- .update_status = oaktrail_set_brightness,
-};
-
-static int oaktrail_backlight_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int ret;
- struct backlight_properties props;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = 100;
- props.type = BACKLIGHT_PLATFORM;
-
- oaktrail_backlight_device = backlight_device_register("oaktrail-bl",
- NULL, (void *)dev, &oaktrail_ops, &props);
- if (IS_ERR(oaktrail_backlight_device))
- return PTR_ERR(oaktrail_backlight_device);
-
- ret = device_backlight_init(dev);
- if (ret < 0) {
- backlight_device_unregister(oaktrail_backlight_device);
- return ret;
- }
- oaktrail_backlight_device->props.brightness = 100;
- oaktrail_backlight_device->props.max_brightness = 100;
- backlight_update_status(oaktrail_backlight_device);
- dev_priv->backlight_device = oaktrail_backlight_device;
+ oaktrail_set_brightness(dev, PSB_MAX_BRIGHTNESS);
return 0;
}
-#endif
-
/*
* Provide the Moorestown specific chip logic and low level methods
* for power management
@@ -185,7 +120,7 @@ static int oaktrail_backlight_init(struct drm_device *dev)
*/
static int oaktrail_save_display_registers(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_save_area *regs = &dev_priv->regs;
struct psb_pipe *p = &regs->pipe[0];
int i;
@@ -299,7 +234,7 @@ static int oaktrail_save_display_registers(struct drm_device *dev)
*/
static int oaktrail_restore_display_registers(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_save_area *regs = &dev_priv->regs;
struct psb_pipe *p = &regs->pipe[0];
u32 pp_stat;
@@ -324,7 +259,7 @@ static int oaktrail_restore_display_registers(struct drm_device *dev)
/* Actually enable it */
PSB_WVDC32(p->dpll, MRST_DPLL_A);
- DRM_UDELAY(150);
+ udelay(150);
/* Restore mode */
PSB_WVDC32(p->htotal, HTOTAL_A);
@@ -414,7 +349,7 @@ static int oaktrail_restore_display_registers(struct drm_device *dev)
*/
static int oaktrail_power_down(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 pwr_mask ;
u32 pwr_sts;
@@ -438,7 +373,7 @@ static int oaktrail_power_down(struct drm_device *dev)
*/
static int oaktrail_power_up(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
u32 pwr_sts, pwr_cnt;
@@ -510,12 +445,10 @@ static const struct psb_offset oaktrail_regmap[2] = {
static int oaktrail_chip_setup(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
int ret;
-
- if (pci_enable_msi(dev->pdev))
- dev_warn(dev->dev, "Enabling MSI failed!\n");
+ dev_priv->use_msi = true;
dev_priv->regmap = oaktrail_regmap;
ret = mid_chip_setup(dev);
@@ -526,14 +459,16 @@ 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;
}
static void oaktrail_teardown(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ gma_intel_teardown_gmbus(dev);
oaktrail_hdmi_teardown(dev);
if (!dev_priv->has_gct)
psb_intel_destroy_bios(dev);
@@ -541,27 +476,28 @@ static void oaktrail_teardown(struct drm_device *dev)
const struct psb_ops oaktrail_chip_ops = {
.name = "Oaktrail",
- .accel_2d = 1,
.pipes = 2,
.crtcs = 2,
.hdmi_mask = (1 << 1),
.lvds_mask = (1 << 0),
+ .sdvo_mask = (1 << 1),
.cursor_needs_phys = 0,
.sgx_offset = MRST_SGX_OFFSET,
.chip_setup = oaktrail_chip_setup,
.chip_teardown = oaktrail_teardown,
.crtc_helper = &oaktrail_helper_funcs,
- .crtc_funcs = &psb_intel_crtc_funcs,
.output_init = oaktrail_output_init,
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
.backlight_init = oaktrail_backlight_init,
-#endif
+ .backlight_set = oaktrail_set_brightness,
+ .backlight_name = "oaktrail-bl",
.save_regs = oaktrail_save_display_registers,
.restore_regs = oaktrail_restore_display_registers,
+ .save_crtc = gma_crtc_save,
+ .restore_crtc = gma_crtc_restore,
.power_down = oaktrail_power_down,
.power_up = oaktrail_power_up,
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index f036f1fc161e..20d027d552c7 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
@@ -24,11 +24,18 @@
* Li Peng <peng.li@intel.com>
*/
-#include <drm/drmP.h>
+#include <linux/delay.h>
+
#include <drm/drm.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include "psb_drv.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))
@@ -127,7 +134,7 @@ static const struct oaktrail_hdmi_limit oaktrail_hdmi_limit = {
static void oaktrail_hdmi_audio_enable(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
HDMI_WRITE(HDMI_HCR, 0x67);
@@ -142,7 +149,7 @@ static void oaktrail_hdmi_audio_enable(struct drm_device *dev)
static void oaktrail_hdmi_audio_disable(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
HDMI_WRITE(0x51a8, 0x0);
@@ -155,17 +162,9 @@ static void oaktrail_hdmi_audio_disable(struct drm_device *dev)
HDMI_READ(HDMI_HCR);
}
-static void wait_for_vblank(struct drm_device *dev)
-{
- /* Wait for 20ms, i.e. one cycle at 50hz. */
- mdelay(20);
-}
-
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);
+ u32 new_crtc_htotal;
/*
* 1024 x 768 new_crtc_htotal = 0x1024;
@@ -269,7 +268,7 @@ int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc,
struct drm_framebuffer *old_fb)
{
struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
int pipe = 1;
int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
@@ -353,7 +352,7 @@ int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc,
/* Flush the plane changes */
{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
crtc_funcs->mode_set_base(crtc, x, y, old_fb);
}
@@ -372,10 +371,10 @@ int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc,
REG_WRITE(PCH_PIPEBCONF, pipeconf);
REG_READ(PCH_PIPEBCONF);
- wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
REG_WRITE(dspcntr_reg, dspcntr);
- wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
gma_power_end(dev);
@@ -459,7 +458,7 @@ void oaktrail_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
REG_READ(PCH_PIPEBCONF);
}
- wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
/* Enable plane */
temp = REG_READ(DSPBCNTR);
@@ -470,7 +469,7 @@ void oaktrail_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
REG_READ(DSPBSURF);
}
- psb_intel_crtc_load_lut(crtc);
+ gma_crtc_load_lut(crtc);
}
/* DSPARB */
@@ -499,7 +498,7 @@ static void oaktrail_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 drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
u32 temp;
@@ -515,8 +514,8 @@ static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode)
HDMI_WRITE(HDMI_VIDEO_REG, temp);
}
-static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+static enum drm_mode_status oaktrail_hdmi_mode_valid(struct drm_connector *connector,
+ const struct drm_display_mode *mode)
{
if (mode->clock > 165000)
return MODE_CLOCK_HIGH;
@@ -529,19 +528,12 @@ static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
return MODE_OK;
}
-static bool oaktrail_hdmi_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
static enum drm_connector_status
oaktrail_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 drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
u32 temp;
@@ -591,7 +583,7 @@ static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
}
if (edid) {
- drm_mode_connector_update_edid_property(connector, edid);
+ drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
}
return ret;
@@ -614,17 +606,16 @@ static void oaktrail_hdmi_destroy(struct drm_connector *connector)
static const struct drm_encoder_helper_funcs oaktrail_hdmi_helper_funcs = {
.dpms = oaktrail_hdmi_dpms,
- .mode_fixup = oaktrail_hdmi_mode_fixup,
- .prepare = psb_intel_encoder_prepare,
+ .prepare = gma_encoder_prepare,
.mode_set = oaktrail_hdmi_mode_set,
- .commit = psb_intel_encoder_commit,
+ .commit = gma_encoder_commit,
};
static const struct drm_connector_helper_funcs
oaktrail_hdmi_connector_helper_funcs = {
.get_modes = oaktrail_hdmi_get_modes,
.mode_valid = oaktrail_hdmi_mode_valid,
- .best_encoder = psb_intel_best_encoder,
+ .best_encoder = gma_best_encoder,
};
static const struct drm_connector_funcs oaktrail_hdmi_connector_funcs = {
@@ -634,68 +625,50 @@ static const struct drm_connector_funcs oaktrail_hdmi_connector_funcs = {
.destroy = oaktrail_hdmi_destroy,
};
-static void oaktrail_hdmi_enc_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs oaktrail_hdmi_enc_funcs = {
- .destroy = oaktrail_hdmi_enc_destroy,
-};
-
void oaktrail_hdmi_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev)
{
- struct psb_intel_encoder *psb_intel_encoder;
- struct psb_intel_connector *psb_intel_connector;
+ struct gma_encoder *gma_encoder;
+ struct gma_connector *gma_connector;
struct drm_connector *connector;
struct drm_encoder *encoder;
- psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
- if (!psb_intel_encoder)
+ gma_encoder = kzalloc(sizeof(struct gma_encoder), GFP_KERNEL);
+ if (!gma_encoder)
return;
- psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
- if (!psb_intel_connector)
+ gma_connector = kzalloc(sizeof(struct gma_connector), GFP_KERNEL);
+ if (!gma_connector)
goto failed_connector;
- connector = &psb_intel_connector->base;
- encoder = &psb_intel_encoder->base;
+ connector = &gma_connector->base;
+ encoder = &gma_encoder->base;
drm_connector_init(dev, connector,
&oaktrail_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_DVID);
- drm_encoder_init(dev, encoder,
- &oaktrail_hdmi_enc_funcs,
- DRM_MODE_ENCODER_TMDS);
+ drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
- psb_intel_connector_attach_encoder(psb_intel_connector,
- psb_intel_encoder);
+ gma_connector_attach_encoder(gma_connector, gma_encoder);
- psb_intel_encoder->type = INTEL_OUTPUT_HDMI;
+ gma_encoder->type = INTEL_OUTPUT_HDMI;
drm_encoder_helper_add(encoder, &oaktrail_hdmi_helper_funcs);
drm_connector_helper_add(connector, &oaktrail_hdmi_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
- drm_sysfs_connector_add(connector);
dev_info(dev->dev, "HDMI initialised.\n");
return;
failed_connector:
- kfree(psb_intel_encoder);
+ kfree(gma_encoder);
}
-static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
- { 0 }
-};
-
void oaktrail_hdmi_setup(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct pci_dev *pdev;
struct oaktrail_hdmi_dev *hdmi_dev;
int ret;
@@ -748,14 +721,14 @@ out:
void oaktrail_hdmi_teardown(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
struct pci_dev *pdev;
if (hdmi_dev) {
pdev = hdmi_dev->dev;
- pci_set_drvdata(pdev, NULL);
oaktrail_hdmi_i2c_exit(pdev);
+ pci_set_drvdata(pdev, NULL);
iounmap(hdmi_dev->regs);
kfree(hdmi_dev);
pci_dev_put(pdev);
@@ -765,7 +738,7 @@ void oaktrail_hdmi_teardown(struct drm_device *dev)
/* save HDMI register state */
void oaktrail_hdmi_save(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
struct psb_state *regs = &dev_priv->regs.psb;
struct psb_pipe *pipeb = &dev_priv->regs.pipe[1];
@@ -818,7 +791,7 @@ void oaktrail_hdmi_save(struct drm_device *dev)
/* restore HDMI register state */
void oaktrail_hdmi_restore(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
struct psb_state *regs = &dev_priv->regs.psb;
struct psb_pipe *pipeb = &dev_priv->regs.pipe[1];
@@ -830,7 +803,7 @@ void oaktrail_hdmi_restore(struct drm_device *dev)
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);
+ udelay(150);
/* pipe */
PSB_WVDC32(pipeb->src, PIPEBSRC);
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
index 1eb86c79523e..48e8ac560a2a 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
@@ -30,6 +30,9 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+
+#include <drm/drm_print.h>
+
#include "psb_drv.h"
#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
@@ -99,7 +102,7 @@ static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
i2c_dev->status = I2C_STAT_INIT;
i2c_dev->msg = pmsg;
i2c_dev->buf_offset = 0;
- INIT_COMPLETION(i2c_dev->complete);
+ reinit_completion(&i2c_dev->complete);
/* Enable I2C transaction */
temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION;
@@ -168,7 +171,6 @@ static struct i2c_adapter oaktrail_hdmi_i2c_adapter = {
.name = "oaktrail_hdmi_i2c",
.nr = 3,
.owner = THIS_MODULE,
- .class = I2C_CLASS_DDC,
.algo = &oaktrail_hdmi_i2c_algorithm,
};
@@ -279,11 +281,8 @@ int oaktrail_hdmi_i2c_init(struct pci_dev *dev)
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;
- }
+ if (!i2c_dev)
+ return -ENOMEM;
i2c_dev->adap = &oaktrail_hdmi_i2c_adapter;
i2c_dev->status = I2C_STAT_INIT;
@@ -300,16 +299,23 @@ int oaktrail_hdmi_i2c_init(struct pci_dev *dev)
oaktrail_hdmi_i2c_adapter.name, hdmi_dev);
if (ret) {
DRM_ERROR("Failed to request IRQ for I2C controller\n");
- goto err;
+ goto free_dev;
}
/* Adapter registration */
ret = i2c_add_numbered_adapter(&oaktrail_hdmi_i2c_adapter);
- return ret;
+ if (ret) {
+ DRM_ERROR("Failed to add I2C adapter\n");
+ goto free_irq;
+ }
+
+ return 0;
-err:
+free_irq:
+ free_irq(dev->irq, hdmi_dev);
+free_dev:
kfree(i2c_dev);
-exit:
+
return ret;
}
diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c
index 325013a9c48c..0705ba3813e6 100644
--- a/drivers/gpu/drm/gma500/oaktrail_lvds.c
+++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright © 2006-2009 Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Eric Anholt <eric@anholt.net>
* Dave Airlie <airlied@linux.ie>
@@ -21,15 +9,18 @@
*/
#include <linux/i2c.h>
-#include <drm/drmP.h>
-#include <asm/mrst.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drm_edid.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_simple_kms_helper.h>
#include "intel_bios.h"
+#include "power.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
/* The max/min PWM frequency in BPCR[31:17] - */
/* The smallest number is 1 (not 0) that can fit in the
@@ -39,15 +30,15 @@
#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
#define BRIGHTNESS_MAX_LEVEL 100
-/**
+/*
* Sets the power state for the panel.
*/
static void oaktrail_lvds_set_power(struct drm_device *dev,
- struct psb_intel_encoder *psb_intel_encoder,
+ struct gma_encoder *gma_encoder,
bool on)
{
u32 pp_status;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
if (!gma_power_begin(dev, true))
return;
@@ -70,7 +61,6 @@ static void oaktrail_lvds_set_power(struct drm_device *dev,
pp_status = REG_READ(PP_STATUS);
} while (pp_status & PP_ON);
dev_priv->is_lvds_on = false;
- pm_request_idle(&dev->pdev->dev);
}
gma_power_end(dev);
}
@@ -78,13 +68,12 @@ static void oaktrail_lvds_set_power(struct drm_device *dev,
static void oaktrail_lvds_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
- struct psb_intel_encoder *psb_intel_encoder =
- to_psb_intel_encoder(encoder);
+ struct gma_encoder *gma_encoder = to_gma_encoder(encoder);
if (mode == DRM_MODE_DPMS_ON)
- oaktrail_lvds_set_power(dev, psb_intel_encoder, true);
+ oaktrail_lvds_set_power(dev, gma_encoder, true);
else
- oaktrail_lvds_set_power(dev, psb_intel_encoder, false);
+ oaktrail_lvds_set_power(dev, gma_encoder, false);
/* XXX: We never power down the LVDS pairs. */
}
@@ -94,9 +83,9 @@ static void oaktrail_lvds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
- struct drm_mode_config *mode_config = &dev->mode_config;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector = NULL;
struct drm_crtc *crtc = encoder->crtc;
u32 lvds_port;
@@ -123,20 +112,22 @@ static void oaktrail_lvds_mode_set(struct drm_encoder *encoder,
REG_WRITE(LVDS, lvds_port);
/* Find the connector we're trying to set up */
- list_for_each_entry(connector, &mode_config->connector_list, head) {
- if (!connector->encoder || connector->encoder->crtc != crtc)
- continue;
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ if (connector->encoder && connector->encoder->crtc == crtc)
+ break;
}
if (!connector) {
+ drm_connector_list_iter_end(&conn_iter);
DRM_ERROR("Couldn't find connector when setting mode");
+ gma_power_end(dev);
return;
}
- drm_object_property_get_value(
- &connector->base,
- dev->mode_config.scaling_mode_property,
- &v);
+ drm_object_property_get_value( &connector->base,
+ dev->mode_config.scaling_mode_property, &v);
+ drm_connector_list_iter_end(&conn_iter);
if (v == DRM_MODE_SCALE_NO_SCALE)
REG_WRITE(PFIT_CONTROL, 0);
@@ -165,9 +156,8 @@ static void oaktrail_lvds_mode_set(struct drm_encoder *encoder,
static void oaktrail_lvds_prepare(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_encoder *psb_intel_encoder =
- to_psb_intel_encoder(encoder);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_encoder *gma_encoder = to_gma_encoder(encoder);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
if (!gma_power_begin(dev, true))
@@ -176,13 +166,13 @@ static void oaktrail_lvds_prepare(struct drm_encoder *encoder)
mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
BACKLIGHT_DUTY_CYCLE_MASK);
- oaktrail_lvds_set_power(dev, psb_intel_encoder, false);
+ oaktrail_lvds_set_power(dev, gma_encoder, false);
gma_power_end(dev);
}
static u32 oaktrail_lvds_get_max_backlight(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 ret;
if (gma_power_begin(dev, false)) {
@@ -202,15 +192,14 @@ static u32 oaktrail_lvds_get_max_backlight(struct drm_device *dev)
static void oaktrail_lvds_commit(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_encoder *psb_intel_encoder =
- to_psb_intel_encoder(encoder);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_encoder *gma_encoder = to_gma_encoder(encoder);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
if (mode_dev->backlight_duty_cycle == 0)
mode_dev->backlight_duty_cycle =
oaktrail_lvds_get_max_backlight(dev);
- oaktrail_lvds_set_power(dev, psb_intel_encoder, true);
+ oaktrail_lvds_set_power(dev, gma_encoder, true);
}
static const struct drm_encoder_helper_funcs oaktrail_lvds_helper_funcs = {
@@ -221,37 +210,13 @@ 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,
struct psb_intel_mode_device *mode_dev)
{
struct drm_display_mode *mode = NULL;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
mode_dev->panel_fixed_mode = NULL;
@@ -282,15 +247,15 @@ static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev,
((ti->vblank_hi << 8) | ti->vblank_lo);
mode->clock = ti->pixel_clock * 10;
#if 0
- printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay);
- printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay);
- printk(KERN_INFO "HSS is %d\n", mode->hsync_start);
- printk(KERN_INFO "HSE is %d\n", mode->hsync_end);
- printk(KERN_INFO "htotal is %d\n", mode->htotal);
- printk(KERN_INFO "VSS is %d\n", mode->vsync_start);
- printk(KERN_INFO "VSE is %d\n", mode->vsync_end);
- printk(KERN_INFO "vtotal is %d\n", mode->vtotal);
- printk(KERN_INFO "clock is %d\n", mode->clock);
+ pr_info("hdisplay is %d\n", mode->hdisplay);
+ pr_info("vdisplay is %d\n", mode->vdisplay);
+ pr_info("HSS is %d\n", mode->hsync_start);
+ pr_info("HSE is %d\n", mode->hsync_end);
+ pr_info("htotal is %d\n", mode->htotal);
+ pr_info("VSS is %d\n", mode->vsync_start);
+ pr_info("VSE is %d\n", mode->vsync_end);
+ pr_info("vtotal is %d\n", mode->vtotal);
+ pr_info("clock is %d\n", mode->clock);
#endif
mode_dev->panel_fixed_mode = mode;
}
@@ -306,10 +271,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);
@@ -318,6 +283,7 @@ static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev,
/**
* oaktrail_lvds_init - setup LVDS connectors on this device
* @dev: drm device
+ * @mode_dev: PSB mode device
*
* Create the connector, register the LVDS DDC bus, and try to figure out what
* modes we can display on the LVDS panel (if present).
@@ -325,36 +291,40 @@ static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev,
void oaktrail_lvds_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev)
{
- struct psb_intel_encoder *psb_intel_encoder;
- struct psb_intel_connector *psb_intel_connector;
+ struct gma_encoder *gma_encoder;
+ struct gma_connector *gma_connector;
+ struct gma_i2c_chan *ddc_bus;
struct drm_connector *connector;
struct drm_encoder *encoder;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct edid *edid;
struct i2c_adapter *i2c_adap;
struct drm_display_mode *scan; /* *modes, *bios_mode; */
+ int ret;
- psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
- if (!psb_intel_encoder)
+ gma_encoder = kzalloc(sizeof(struct gma_encoder), GFP_KERNEL);
+ if (!gma_encoder)
return;
- psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
- if (!psb_intel_connector)
- goto failed_connector;
+ gma_connector = kzalloc(sizeof(struct gma_connector), GFP_KERNEL);
+ if (!gma_connector)
+ goto err_free_encoder;
- connector = &psb_intel_connector->base;
- encoder = &psb_intel_encoder->base;
+ connector = &gma_connector->base;
+ encoder = &gma_encoder->base;
dev_priv->is_lvds_on = true;
- drm_connector_init(dev, connector,
- &psb_intel_lvds_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
+ ret = drm_connector_init(dev, connector,
+ &psb_intel_lvds_connector_funcs,
+ DRM_MODE_CONNECTOR_LVDS);
+ if (ret)
+ goto err_free_connector;
- drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs,
- DRM_MODE_ENCODER_LVDS);
+ ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS);
+ if (ret)
+ goto err_connector_cleanup;
- psb_intel_connector_attach_encoder(psb_intel_connector,
- psb_intel_encoder);
- psb_intel_encoder->type = INTEL_OUTPUT_LVDS;
+ gma_connector_attach_encoder(gma_connector, gma_encoder);
+ gma_encoder->type = INTEL_OUTPUT_LVDS;
drm_encoder_helper_add(encoder, &oaktrail_lvds_helper_funcs);
drm_connector_helper_add(connector,
@@ -387,21 +357,36 @@ void oaktrail_lvds_init(struct drm_device *dev,
* if closed, act like it's not there for now
*/
+ edid = NULL;
+ mutex_lock(&dev->mode_config.mutex);
+
i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus);
- if (i2c_adap == NULL)
- dev_err(dev->dev, "No ddc adapter available!\n");
+ if (i2c_adap)
+ edid = drm_get_edid(connector, i2c_adap);
+
+ if (edid == NULL && dev_priv->lpc_gpio_base) {
+ ddc_bus = oaktrail_lvds_i2c_init(dev);
+ if (!IS_ERR(ddc_bus)) {
+ i2c_adap = &ddc_bus->base;
+ edid = drm_get_edid(connector, i2c_adap);
+ }
+ }
+
+ /*
+ * Due to the logic in probing for i2c buses above we do not know the
+ * i2c_adap until now. Hence we cannot use drm_connector_init_with_ddc()
+ * but must instead set connector->ddc manually here.
+ */
+ connector->ddc = i2c_adap;
+
/*
* Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one.
*/
- if (i2c_adap) {
- edid = drm_get_edid(connector, i2c_adap);
- if (edid) {
- drm_mode_connector_update_edid_property(connector,
- edid);
- drm_add_edid_modes(connector, edid);
- kfree(edid);
- }
+ if (edid) {
+ drm_connector_update_edid_property(connector, edid);
+ drm_add_edid_modes(connector, edid);
+ kfree(edid);
list_for_each_entry(scan, &connector->probed_modes, head) {
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
@@ -410,7 +395,8 @@ void oaktrail_lvds_init(struct drm_device *dev,
goto out; /* FIXME: check for quirks */
}
}
- }
+ } else
+ dev_err(dev->dev, "No ddc adapter available!\n");
/*
* If we didn't get EDID, try geting panel timing
* from configuration data
@@ -425,24 +411,23 @@ void oaktrail_lvds_init(struct drm_device *dev,
/* If we still don't have a mode after all that, give up. */
if (!mode_dev->panel_fixed_mode) {
dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
- goto failed_find;
+ goto err_unlock;
}
out:
- drm_sysfs_connector_add(connector);
- return;
+ mutex_unlock(&dev->mode_config.mutex);
-failed_find:
- dev_dbg(dev->dev, "No LVDS modes found, disabling.\n");
- if (psb_intel_encoder->ddc_bus)
- psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus);
-
-/* failed_ddc: */
+ return;
+err_unlock:
+ mutex_unlock(&dev->mode_config.mutex);
+ gma_i2c_destroy(to_gma_i2c_chan(connector->ddc));
drm_encoder_cleanup(encoder);
+err_connector_cleanup:
drm_connector_cleanup(connector);
- kfree(psb_intel_connector);
-failed_connector:
- kfree(psb_intel_encoder);
+err_free_connector:
+ kfree(gma_connector);
+err_free_encoder:
+ kfree(gma_encoder);
}
diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds_i2c.c b/drivers/gpu/drm/gma500/oaktrail_lvds_i2c.c
new file mode 100644
index 000000000000..939c53fd09e8
--- /dev/null
+++ b/drivers/gpu/drm/gma500/oaktrail_lvds_i2c.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2002-2010, Intel Corporation.
+ * Copyright (c) 2014 ATRON electronic GmbH
+ * Author: Jan Safrata <jan.nikitenko@gmail.com>
+ *
+ * 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 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.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+
+
+/*
+ * LPC GPIO based I2C bus for LVDS of Atom E6xx
+ */
+
+/*-----------------------------------------------------------------------------
+ * LPC Register Offsets. Used for LVDS GPIO Bit Bashing. Registers are part
+ * Atom E6xx [D31:F0]
+ ----------------------------------------------------------------------------*/
+#define RGEN 0x20
+#define RGIO 0x24
+#define RGLVL 0x28
+#define RGTPE 0x2C
+#define RGTNE 0x30
+#define RGGPE 0x34
+#define RGSMI 0x38
+#define RGTS 0x3C
+
+/* The LVDS GPIO clock lines are GPIOSUS[3]
+ * The LVDS GPIO data lines are GPIOSUS[4]
+ */
+#define GPIO_CLOCK 0x08
+#define GPIO_DATA 0x10
+
+#define LPC_READ_REG(chan, r) inl((chan)->reg + (r))
+#define LPC_WRITE_REG(chan, r, val) outl((val), (chan)->reg + (r))
+
+static int get_clock(void *data)
+{
+ struct gma_i2c_chan *chan = data;
+ u32 val;
+
+ val = LPC_READ_REG(chan, RGIO);
+ val |= GPIO_CLOCK;
+ LPC_WRITE_REG(chan, RGIO, val);
+ LPC_READ_REG(chan, RGLVL);
+ val = (LPC_READ_REG(chan, RGLVL) & GPIO_CLOCK) ? 1 : 0;
+
+ return val;
+}
+
+static int get_data(void *data)
+{
+ struct gma_i2c_chan *chan = data;
+ u32 val;
+
+ val = LPC_READ_REG(chan, RGIO);
+ val |= GPIO_DATA;
+ LPC_WRITE_REG(chan, RGIO, val);
+ LPC_READ_REG(chan, RGLVL);
+ val = (LPC_READ_REG(chan, RGLVL) & GPIO_DATA) ? 1 : 0;
+
+ return val;
+}
+
+static void set_clock(void *data, int state_high)
+{
+ struct gma_i2c_chan *chan = data;
+ u32 val;
+
+ if (state_high) {
+ val = LPC_READ_REG(chan, RGIO);
+ val |= GPIO_CLOCK;
+ LPC_WRITE_REG(chan, RGIO, val);
+ } else {
+ val = LPC_READ_REG(chan, RGIO);
+ val &= ~GPIO_CLOCK;
+ LPC_WRITE_REG(chan, RGIO, val);
+ val = LPC_READ_REG(chan, RGLVL);
+ val &= ~GPIO_CLOCK;
+ LPC_WRITE_REG(chan, RGLVL, val);
+ }
+}
+
+static void set_data(void *data, int state_high)
+{
+ struct gma_i2c_chan *chan = data;
+ u32 val;
+
+ if (state_high) {
+ val = LPC_READ_REG(chan, RGIO);
+ val |= GPIO_DATA;
+ LPC_WRITE_REG(chan, RGIO, val);
+ } else {
+ val = LPC_READ_REG(chan, RGIO);
+ val &= ~GPIO_DATA;
+ LPC_WRITE_REG(chan, RGIO, val);
+ val = LPC_READ_REG(chan, RGLVL);
+ val &= ~GPIO_DATA;
+ LPC_WRITE_REG(chan, RGLVL, val);
+ }
+}
+
+struct gma_i2c_chan *oaktrail_lvds_i2c_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_i2c_chan *chan;
+ int ret;
+
+ chan = kzalloc(sizeof(struct gma_i2c_chan), GFP_KERNEL);
+ if (!chan)
+ return ERR_PTR(-ENOMEM);
+
+ chan->drm_dev = dev;
+ chan->reg = dev_priv->lpc_gpio_base;
+ strscpy(chan->base.name, "gma500 LPC", sizeof(chan->base.name));
+ chan->base.owner = THIS_MODULE;
+ chan->base.algo_data = &chan->algo;
+ chan->base.dev.parent = dev->dev;
+ chan->algo.setsda = set_data;
+ chan->algo.setscl = set_clock;
+ chan->algo.getsda = get_data;
+ chan->algo.getscl = get_clock;
+ chan->algo.udelay = 100;
+ chan->algo.timeout = usecs_to_jiffies(2200);
+ chan->algo.data = chan;
+
+ i2c_set_adapdata(&chan->base, chan);
+
+ set_data(chan, 1);
+ set_clock(chan, 1);
+ udelay(50);
+
+ ret = i2c_bit_add_bus(&chan->base);
+ if (ret < 0) {
+ kfree(chan);
+ return ERR_PTR(ret);
+ }
+
+ return chan;
+}
diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c
index ad0d6de938f3..5f0daa25b86d 100644
--- a/drivers/gpu/drm/gma500/opregion.c
+++ b/drivers/gpu/drm/gma500/opregion.c
@@ -22,8 +22,11 @@
*
*/
#include <linux/acpi.h>
-#include <linux/acpi_io.h>
+
+#include <drm/drm_print.h>
+
#include "psb_drv.h"
+#include "psb_irq.h"
#include "psb_intel_reg.h"
#define PCI_ASLE 0xe4
@@ -148,36 +151,32 @@ static struct psb_intel_opregion *system_opregion;
static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct opregion_asle *asle = dev_priv->opregion.asle;
- struct backlight_device *bd = dev_priv->backlight_device;
DRM_DEBUG_DRIVER("asle set backlight %x\n", bclp);
if (!(bclp & ASLE_BCLP_VALID))
return ASLE_BACKLIGHT_FAILED;
- if (bd == NULL)
- return ASLE_BACKLIGHT_FAILED;
-
bclp &= ASLE_BCLP_MSK;
if (bclp > 255)
return ASLE_BACKLIGHT_FAILED;
- if (config_enabled(CONFIG_BACKLIGHT_CLASS_DEVICE)) {
- int max = bd->props.max_brightness;
- gma_backlight_set(dev, bclp * max / 255);
- }
+ gma_backlight_set(dev, bclp * PSB_MAX_BRIGHTNESS / 255);
asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID;
return 0;
}
-void psb_intel_opregion_asle_intr(struct drm_device *dev)
+static void psb_intel_opregion_asle_work(struct work_struct *work)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct opregion_asle *asle = dev_priv->opregion.asle;
+ struct psb_intel_opregion *opregion =
+ container_of(work, struct psb_intel_opregion, asle_work);
+ struct drm_psb_private *dev_priv =
+ container_of(opregion, struct drm_psb_private, opregion);
+ struct opregion_asle *asle = opregion->asle;
u32 asle_stat = 0;
u32 asle_req;
@@ -191,9 +190,18 @@ void psb_intel_opregion_asle_intr(struct drm_device *dev)
}
if (asle_req & ASLE_SET_BACKLIGHT)
- asle_stat |= asle_set_backlight(dev, asle->bclp);
+ asle_stat |= asle_set_backlight(&dev_priv->dev, asle->bclp);
asle->aslc = asle_stat;
+
+}
+
+void psb_intel_opregion_asle_intr(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
+ if (dev_priv->opregion.asle)
+ schedule_work(&dev_priv->opregion.asle_work);
}
#define ASLE_ALS_EN (1<<0)
@@ -203,14 +211,14 @@ void psb_intel_opregion_asle_intr(struct drm_device *dev)
void psb_intel_opregion_enable_asle(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct opregion_asle *asle = dev_priv->opregion.asle;
if (asle && system_opregion ) {
/* Don't do this on Medfield or other non PC like devices, they
use the bit for something different altogether */
- psb_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE);
- psb_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE);
+ gma_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE);
+ gma_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE);
asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN
| ASLE_PFMB_EN;
@@ -250,7 +258,7 @@ static struct notifier_block psb_intel_opregion_notifier = {
void psb_intel_opregion_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_opregion *opregion = &dev_priv->opregion;
if (!opregion->header)
@@ -270,7 +278,7 @@ void psb_intel_opregion_init(struct drm_device *dev)
void psb_intel_opregion_fini(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_opregion *opregion = &dev_priv->opregion;
if (!opregion->header)
@@ -283,6 +291,8 @@ void psb_intel_opregion_fini(struct drm_device *dev)
unregister_acpi_notifier(&psb_intel_opregion_notifier);
}
+ cancel_work_sync(&opregion->asle_work);
+
/* just clear all opregion memory pointers now */
iounmap(opregion->header);
opregion->header = NULL;
@@ -294,17 +304,21 @@ void psb_intel_opregion_fini(struct drm_device *dev)
int psb_intel_opregion_setup(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
struct psb_intel_opregion *opregion = &dev_priv->opregion;
u32 opregion_phy, mboxes;
void __iomem *base;
int err = 0;
- pci_read_config_dword(dev->pdev, PCI_ASLS, &opregion_phy);
+ pci_read_config_dword(pdev, PCI_ASLS, &opregion_phy);
if (opregion_phy == 0) {
DRM_DEBUG_DRIVER("ACPI Opregion not supported\n");
return -ENOTSUPP;
}
+
+ INIT_WORK(&opregion->asle_work, psb_intel_opregion_asle_work);
+
DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
base = acpi_os_ioremap(opregion_phy, 8*1024);
if (!base)
diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c
index b6b135fcd59c..186af29bea6f 100644
--- a/drivers/gpu/drm/gma500/power.c
+++ b/drivers/gpu/drm/gma500/power.c
@@ -28,16 +28,15 @@
* Alan Cox <alan@linux.intel.com>
*/
+#include "gem.h"
#include "power.h"
#include "psb_drv.h"
#include "psb_reg.h"
#include "psb_intel_reg.h"
+#include "psb_irq.h"
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
-static struct mutex power_mutex; /* Serialize power ops */
-static spinlock_t power_ctrl_lock; /* Serialize power claim */
-
/**
* gma_power_init - initialise power manager
* @dev: our device
@@ -46,20 +45,29 @@ static spinlock_t power_ctrl_lock; /* Serialize power claim */
*/
void gma_power_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
/* FIXME: Move APM/OSPM base into relevant device code */
dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
dev_priv->ospm_base &= 0xffff;
- dev_priv->display_power = true; /* We start active */
- dev_priv->display_count = 0; /* Currently no users */
- dev_priv->suspended = false; /* And not suspended */
- spin_lock_init(&power_ctrl_lock);
- mutex_init(&power_mutex);
-
if (dev_priv->ops->init_pm)
dev_priv->ops->init_pm(dev);
+
+ /*
+ * Runtime pm support is broken atm. So for now unconditionally
+ * call pm_runtime_get() here and put it again in psb_driver_unload()
+ *
+ * To fix this we need to call pm_runtime_get() once for each active
+ * pipe at boot and then put() / get() for each pipe disable / enable
+ * so that the device gets runtime suspended when no pipes are active.
+ * Once this is in place the pm_runtime_get() below should be replaced
+ * by a pm_runtime_allow() call to undo the pm_runtime_forbid() from
+ * pci_pm_init().
+ */
+ pm_runtime_get(dev->dev);
+
+ dev_priv->pm_initialized = true;
}
/**
@@ -70,8 +78,12 @@ void gma_power_init(struct drm_device *dev)
*/
void gma_power_uninit(struct drm_device *dev)
{
- pm_runtime_disable(&dev->pdev->dev);
- pm_runtime_set_suspended(&dev->pdev->dev);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+
+ if (!dev_priv->pm_initialized)
+ return;
+
+ pm_runtime_put_noidle(dev->dev);
}
/**
@@ -82,17 +94,15 @@ void gma_power_uninit(struct drm_device *dev)
*/
static void gma_suspend_display(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
- if (dev_priv->suspended)
- return;
dev_priv->ops->save_regs(dev);
dev_priv->ops->power_down(dev);
- dev_priv->display_power = false;
}
/**
* gma_resume_display - resume display side logic
+ * @pdev: PCI device
*
* Resume the display hardware restoring state and enabling
* as necessary.
@@ -100,18 +110,18 @@ static void gma_suspend_display(struct drm_device *dev)
static void gma_resume_display(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
/* turn on the display power island */
dev_priv->ops->power_up(dev);
- dev_priv->suspended = false;
- dev_priv->display_power = true;
PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
pci_write_config_word(pdev, PSB_GMCH_CTRL,
dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
- psb_gtt_restore(dev); /* Rebuild our GTT mappings */
+ /* Rebuild our GTT mappings */
+ psb_gtt_resume(dev);
+ psb_gem_mm_resume(dev);
dev_priv->ops->restore_regs(dev);
}
@@ -124,62 +134,42 @@ static void gma_resume_display(struct pci_dev *pdev)
static void gma_suspend_pci(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
int bsm, vbt;
- if (dev_priv->suspended)
- return;
-
pci_save_state(pdev);
pci_read_config_dword(pdev, 0x5C, &bsm);
dev_priv->regs.saveBSM = bsm;
pci_read_config_dword(pdev, 0xFC, &vbt);
dev_priv->regs.saveVBT = vbt;
- pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
- pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
-
- dev_priv->suspended = true;
}
/**
* gma_resume_pci - resume helper
- * @dev: our PCI device
+ * @pdev: our PCI device
*
* Perform the resume processing on our PCI device state - rewrite
* register state and re-enable the PCI device
*/
-static bool gma_resume_pci(struct pci_dev *pdev)
+static int gma_resume_pci(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int ret;
-
- if (!dev_priv->suspended)
- return true;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
pci_write_config_dword(pdev, 0x5c, dev_priv->regs.saveBSM);
pci_write_config_dword(pdev, 0xFC, dev_priv->regs.saveVBT);
- /* restoring MSI address and data in PCIx space */
- pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
- pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
- ret = pci_enable_device(pdev);
- if (ret != 0)
- dev_err(&pdev->dev, "pci_enable failed: %d\n", ret);
- else
- dev_priv->suspended = false;
- return !dev_priv->suspended;
+ return pci_enable_device(pdev);
}
/**
* gma_power_suspend - bus callback for suspend
- * @pdev: our PCI device
- * @state: suspend type
+ * @_dev: our device
*
* Called back by the PCI layer during a suspend of the system. We
* perform the necessary shut down steps and save enough state that
@@ -187,58 +177,33 @@ static bool gma_resume_pci(struct pci_dev *pdev)
*/
int gma_power_suspend(struct device *_dev)
{
- struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
+ struct pci_dev *pdev = to_pci_dev(_dev);
struct drm_device *dev = pci_get_drvdata(pdev);
- struct drm_psb_private *dev_priv = dev->dev_private;
- mutex_lock(&power_mutex);
- if (!dev_priv->suspended) {
- if (dev_priv->display_count) {
- mutex_unlock(&power_mutex);
- dev_err(dev->dev, "GPU hardware busy, cannot suspend\n");
- return -EBUSY;
- }
- psb_irq_uninstall(dev);
- gma_suspend_display(dev);
- gma_suspend_pci(pdev);
- }
- mutex_unlock(&power_mutex);
+ gma_irq_uninstall(dev);
+ gma_suspend_display(dev);
+ gma_suspend_pci(pdev);
return 0;
}
/**
* gma_power_resume - resume power
- * @pdev: PCI device
+ * @_dev: our device
*
* Resume the PCI side of the graphics and then the displays
*/
int gma_power_resume(struct device *_dev)
{
- struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev);
+ struct pci_dev *pdev = to_pci_dev(_dev);
struct drm_device *dev = pci_get_drvdata(pdev);
- mutex_lock(&power_mutex);
gma_resume_pci(pdev);
gma_resume_display(pdev);
- psb_irq_preinstall(dev);
- psb_irq_postinstall(dev);
- mutex_unlock(&power_mutex);
+ gma_irq_install(dev);
return 0;
}
/**
- * gma_power_is_on - returne true if power is on
- * @dev: our DRM device
- *
- * Returns true if the display island power is on at this moment
- */
-bool gma_power_is_on(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- return dev_priv->display_power;
-}
-
-/**
* gma_power_begin - begin requiring power
* @dev: our DRM device
* @force_on: true to force power on
@@ -248,34 +213,10 @@ bool gma_power_is_on(struct drm_device *dev)
*/
bool gma_power_begin(struct drm_device *dev, bool force_on)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&power_ctrl_lock, flags);
- /* Power already on ? */
- if (dev_priv->display_power) {
- dev_priv->display_count++;
- pm_runtime_get(&dev->pdev->dev);
- spin_unlock_irqrestore(&power_ctrl_lock, flags);
- return true;
- }
- if (force_on == false)
- goto out_false;
-
- /* Ok power up needed */
- ret = gma_resume_pci(dev->pdev);
- if (ret == 0) {
- psb_irq_preinstall(dev);
- psb_irq_postinstall(dev);
- pm_runtime_get(&dev->pdev->dev);
- dev_priv->display_count++;
- spin_unlock_irqrestore(&power_ctrl_lock, flags);
- return true;
- }
-out_false:
- spin_unlock_irqrestore(&power_ctrl_lock, flags);
- return false;
+ if (force_on)
+ return pm_runtime_resume_and_get(dev->dev) == 0;
+ else
+ return pm_runtime_get_if_in_use(dev->dev) == 1;
}
/**
@@ -287,46 +228,5 @@ out_false:
*/
void gma_power_end(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- unsigned long flags;
- spin_lock_irqsave(&power_ctrl_lock, flags);
- dev_priv->display_count--;
- WARN_ON(dev_priv->display_count < 0);
- spin_unlock_irqrestore(&power_ctrl_lock, flags);
- pm_runtime_put(&dev->pdev->dev);
-}
-
-int psb_runtime_suspend(struct device *dev)
-{
- return gma_power_suspend(dev);
-}
-
-int psb_runtime_resume(struct device *dev)
-{
- return gma_power_resume(dev);
-}
-
-int psb_runtime_idle(struct device *dev)
-{
- struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev));
- struct drm_psb_private *dev_priv = drmdev->dev_private;
- if (dev_priv->display_count)
- return 0;
- else
- return 1;
-}
-
-int gma_power_thaw(struct device *_dev)
-{
- return gma_power_resume(_dev);
-}
-
-int gma_power_freeze(struct device *_dev)
-{
- return gma_power_suspend(_dev);
-}
-
-int gma_power_restore(struct device *_dev)
-{
- return gma_power_resume(_dev);
+ pm_runtime_put(dev->dev);
}
diff --git a/drivers/gpu/drm/gma500/power.h b/drivers/gpu/drm/gma500/power.h
index 56d8708bd41c..063328d66652 100644
--- a/drivers/gpu/drm/gma500/power.h
+++ b/drivers/gpu/drm/gma500/power.h
@@ -31,7 +31,9 @@
#define _PSB_POWERMGMT_H_
#include <linux/pci.h>
-#include <drm/drmP.h>
+
+struct device;
+struct drm_device;
void gma_power_init(struct drm_device *dev);
void gma_power_uninit(struct drm_device *dev);
@@ -41,9 +43,6 @@ void gma_power_uninit(struct drm_device *dev);
*/
int gma_power_suspend(struct device *dev);
int gma_power_resume(struct device *dev);
-int gma_power_thaw(struct device *dev);
-int gma_power_freeze(struct device *dev);
-int gma_power_restore(struct device *_dev);
/*
* These are the functions the driver should use to wrap all hw access
@@ -52,19 +51,4 @@ int gma_power_restore(struct device *_dev);
bool gma_power_begin(struct drm_device *dev, bool force);
void gma_power_end(struct drm_device *dev);
-/*
- * Use this function to do an instantaneous check for if the hw is on.
- * Only use this in cases where you know the mutex is already held such
- * as in irq install/uninstall and you need to
- * prevent a deadlock situation. Otherwise use gma_power_begin().
- */
-bool gma_power_is_on(struct drm_device *dev);
-
-/*
- * GFX-Runtime PM callbacks
- */
-int psb_runtime_suspend(struct device *dev);
-int psb_runtime_resume(struct device *dev);
-int psb_runtime_idle(struct device *dev);
-
#endif /*_PSB_POWERMGMT_H_*/
diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c
index f6f534b4197e..6dece8f0e380 100644
--- a/drivers/gpu/drm/gma500/psb_device.c
+++ b/drivers/gpu/drm/gma500/psb_device.c
@@ -1,42 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
/**************************************************************************
* Copyright (c) 2011, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
-#include <linux/backlight.h>
-#include <drm/drmP.h>
#include <drm/drm.h>
-#include <drm/gma_drm.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "gma_device.h"
+#include "intel_bios.h"
+#include "psb_device.h"
#include "psb_drv.h"
-#include "psb_reg.h"
#include "psb_intel_reg.h"
-#include "intel_bios.h"
-
+#include "psb_reg.h"
static int psb_output_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
psb_intel_lvds_init(dev, &dev_priv->mode_dev);
psb_intel_sdvo_init(dev, SDVOB);
return 0;
}
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-
/*
* Poulsbo Backlight Interfaces
*/
@@ -52,21 +38,9 @@ static int psb_output_init(struct drm_device *dev)
#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
-static int psb_brightness;
-static struct backlight_device *psb_backlight_device;
-
-static int psb_get_brightness(struct backlight_device *bd)
-{
- /* return locally cached var instead of HW read (due to DPST etc.) */
- /* FIXME: ideally return actual value in case firmware fiddled with
- it */
- return psb_brightness;
-}
-
-
static int psb_backlight_setup(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
unsigned long core_clock;
/* u32 bl_max_freq; */
/* unsigned long value; */
@@ -97,62 +71,12 @@ static int psb_backlight_setup(struct drm_device *dev)
REG_WRITE(BLC_PWM_CTL,
(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value));
}
- return 0;
-}
-static int psb_set_brightness(struct backlight_device *bd)
-{
- struct drm_device *dev = bl_get_data(psb_backlight_device);
- int level = bd->props.brightness;
+ psb_intel_lvds_set_brightness(dev, PSB_MAX_BRIGHTNESS);
- /* Percentage 1-100% being valid */
- if (level < 1)
- level = 1;
-
- psb_intel_lvds_set_brightness(dev, level);
- psb_brightness = level;
return 0;
}
-static const struct backlight_ops psb_ops = {
- .get_brightness = psb_get_brightness,
- .update_status = psb_set_brightness,
-};
-
-static int psb_backlight_init(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- int ret;
- struct backlight_properties props;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = 100;
- props.type = BACKLIGHT_PLATFORM;
-
- psb_backlight_device = backlight_device_register("psb-bl",
- NULL, (void *)dev, &psb_ops, &props);
- if (IS_ERR(psb_backlight_device))
- return PTR_ERR(psb_backlight_device);
-
- ret = psb_backlight_setup(dev);
- if (ret < 0) {
- backlight_device_unregister(psb_backlight_device);
- psb_backlight_device = NULL;
- return ret;
- }
- psb_backlight_device->props.brightness = 100;
- psb_backlight_device->props.max_brightness = 100;
- backlight_update_status(psb_backlight_device);
- dev_priv->backlight_device = psb_backlight_device;
-
- /* This must occur after the backlight is properly initialised */
- psb_lid_timer_init(dev_priv);
-
- return 0;
-}
-
-#endif
-
/*
* Provide the Poulsbo specific chip logic and low level methods
* for power management
@@ -160,7 +84,7 @@ static int psb_backlight_init(struct drm_device *dev)
static void psb_init_pm(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
gating &= ~3; /* Disable 2D clock gating */
@@ -178,8 +102,10 @@ static void psb_init_pm(struct drm_device *dev)
*/
static int psb_save_display_registers(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_connector *gma_connector;
struct drm_crtc *crtc;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
struct psb_state *regs = &dev_priv->regs.psb;
@@ -197,12 +123,16 @@ static int psb_save_display_registers(struct drm_device *dev)
drm_modeset_lock_all(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
if (drm_helper_crtc_in_use(crtc))
- crtc->funcs->save(crtc);
+ dev_priv->ops->save_crtc(crtc);
}
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- if (connector->funcs->save)
- connector->funcs->save(connector);
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ gma_connector = to_gma_connector(connector);
+ if (gma_connector->save)
+ gma_connector->save(connector);
+ }
+ drm_connector_list_iter_end(&conn_iter);
drm_modeset_unlock_all(dev);
return 0;
@@ -216,8 +146,10 @@ static int psb_save_display_registers(struct drm_device *dev)
*/
static int psb_restore_display_registers(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_connector *gma_connector;
struct drm_crtc *crtc;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
struct psb_state *regs = &dev_priv->regs.psb;
@@ -237,11 +169,15 @@ static int psb_restore_display_registers(struct drm_device *dev)
drm_modeset_lock_all(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
if (drm_helper_crtc_in_use(crtc))
- crtc->funcs->restore(crtc);
+ dev_priv->ops->restore_crtc(crtc);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
- if (connector->funcs->restore)
- connector->funcs->restore(connector);
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ gma_connector = to_gma_connector(connector);
+ if (gma_connector->restore)
+ gma_connector->restore(connector);
+ }
+ drm_connector_list_iter_end(&conn_iter);
drm_modeset_unlock_all(dev);
return 0;
@@ -257,45 +193,6 @@ static int psb_power_up(struct drm_device *dev)
return 0;
}
-static void psb_get_core_freq(struct drm_device *dev)
-{
- uint32_t clock;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
- /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
-
- pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
- pci_read_config_dword(pci_root, 0xD4, &clock);
- pci_dev_put(pci_root);
-
- switch (clock & 0x07) {
- case 0:
- dev_priv->core_freq = 100;
- break;
- case 1:
- dev_priv->core_freq = 133;
- break;
- case 2:
- dev_priv->core_freq = 150;
- break;
- case 3:
- dev_priv->core_freq = 178;
- break;
- case 4:
- dev_priv->core_freq = 200;
- break;
- case 5:
- case 6:
- case 7:
- dev_priv->core_freq = 266;
- break;
- default:
- dev_priv->core_freq = 0;
- }
-}
-
/* Poulsbo */
static const struct psb_offset psb_regmap[2] = {
{
@@ -350,9 +247,9 @@ static const struct psb_offset psb_regmap[2] = {
static int psb_chip_setup(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
dev_priv->regmap = psb_regmap;
- psb_get_core_freq(dev);
+ gma_get_core_freq(dev);
gma_intel_setup_gmbus(dev);
psb_intel_opregion_init(dev);
psb_intel_init_bios(dev);
@@ -361,35 +258,35 @@ static int psb_chip_setup(struct drm_device *dev)
static void psb_chip_teardown(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- psb_lid_timer_takedown(dev_priv);
gma_intel_teardown_gmbus(dev);
}
const struct psb_ops psb_chip_ops = {
.name = "Poulsbo",
- .accel_2d = 1,
.pipes = 2,
.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,
.chip_teardown = psb_chip_teardown,
.crtc_helper = &psb_intel_helper_funcs,
- .crtc_funcs = &psb_intel_crtc_funcs,
+ .clock_funcs = &psb_clock_funcs,
.output_init = psb_output_init,
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
- .backlight_init = psb_backlight_init,
-#endif
+ .backlight_init = psb_backlight_setup,
+ .backlight_set = psb_intel_lvds_set_brightness,
+ .backlight_name = "psb-bl",
.init_pm = psb_init_pm,
.save_regs = psb_save_display_registers,
.restore_regs = psb_restore_display_registers,
+ .save_crtc = gma_crtc_save,
+ .restore_crtc = gma_crtc_restore,
.power_down = psb_power_down,
.power_up = psb_power_up,
};
diff --git a/drivers/gpu/drm/gma500/psb_device.h b/drivers/gpu/drm/gma500/psb_device.h
new file mode 100644
index 000000000000..3f11179562c9
--- /dev/null
+++ b/drivers/gpu/drm/gma500/psb_device.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2013 Patrik Jakobsson
+ * Copyright © 2011 Intel Corporation
+ */
+
+#ifndef _PSB_DEVICE_H_
+#define _PSB_DEVICE_H_
+
+extern const struct gma_clock_funcs psb_clock_funcs;
+
+#endif
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index bddea5807442..005ab7f5355f 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -1,93 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0-only
/**************************************************************************
* Copyright (c) 2007-2011, Intel Corporation.
* All Rights Reserved.
* Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/gma_drm.h>
-#include "psb_drv.h"
-#include "framebuffer.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "intel_bios.h"
-#include "mid_bios.h"
-#include <drm/drm_pciids.h>
-#include "power.h"
+#include <linux/aperture.h>
#include <linux/cpu.h>
+#include <linux/module.h>
#include <linux/notifier.h>
-#include <linux/spinlock.h>
#include <linux/pm_runtime.h>
-#include <acpi/video.h>
-#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
-static int drm_psb_trap_pagefaults;
+#include <asm/set_memory.h>
-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+#include <acpi/video.h>
-MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
-module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
+#include <drm/clients/drm_client_setup.h>
+#include <drm/drm.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_pciids.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
+
+#include "framebuffer.h"
+#include "gem.h"
+#include "intel_bios.h"
+#include "mid_bios.h"
+#include "power.h"
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_irq.h"
+#include "psb_reg.h"
+static const struct drm_driver driver;
+static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
+/*
+ * The table below contains a mapping of the PCI vendor ID and the PCI Device ID
+ * to the different groups of PowerVR 5-series chip designs
+ *
+ * 0x8086 = Intel Corporation
+ *
+ * PowerVR SGX535 - Poulsbo - Intel GMA 500, Intel Atom Z5xx
+ * PowerVR SGX535 - Moorestown - Intel GMA 600
+ * PowerVR SGX535 - Oaktrail - Intel GMA 600, Intel Atom Z6xx, E6xx
+ * PowerVR SGX545 - Cedartrail - Intel GMA 3600, Intel Atom D2500, N2600
+ * PowerVR SGX545 - Cedartrail - Intel GMA 3650, Intel Atom D2550, D2700,
+ * N2800
+ */
+static const struct pci_device_id pciidlist[] = {
+ /* Poulsbo */
{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
-#if defined(CONFIG_DRM_GMA600)
- { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
- { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
- { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
- { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
- { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
- { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
- { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
- { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
- /* Atom E620 */
- { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
-#endif
-#if defined(CONFIG_DRM_MEDFIELD)
- {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
- {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
-#endif
-#if defined(CONFIG_DRM_GMA3600)
- { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0be9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0bea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0beb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0bec, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0bed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0bee, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
- { 0x8086, 0x0bef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
-#endif
+ /* Oak Trail */
+ { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+ { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+ { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+ { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+ { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+ { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+ { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+ { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+ { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops },
+ /* Cedar Trail */
+ { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0be8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0be9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0bea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0beb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0bec, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0bed, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0bee, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
+ { 0x8086, 0x0bef, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, pciidlist);
@@ -95,196 +92,167 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
/*
* Standard IOCTLs.
*/
-
-#define DRM_IOCTL_GMA_ADB \
- DRM_IOWR(DRM_GMA_ADB + DRM_COMMAND_BASE, uint32_t)
-#define DRM_IOCTL_GMA_MODE_OPERATION \
- DRM_IOWR(DRM_GMA_MODE_OPERATION + DRM_COMMAND_BASE, \
- struct drm_psb_mode_operation_arg)
-#define DRM_IOCTL_GMA_STOLEN_MEMORY \
- DRM_IOWR(DRM_GMA_STOLEN_MEMORY + DRM_COMMAND_BASE, \
- struct drm_psb_stolen_memory_arg)
-#define DRM_IOCTL_GMA_GAMMA \
- DRM_IOWR(DRM_GMA_GAMMA + DRM_COMMAND_BASE, \
- struct drm_psb_dpst_lut_arg)
-#define DRM_IOCTL_GMA_DPST_BL \
- DRM_IOWR(DRM_GMA_DPST_BL + DRM_COMMAND_BASE, \
- uint32_t)
-#define DRM_IOCTL_GMA_GET_PIPE_FROM_CRTC_ID \
- DRM_IOWR(DRM_GMA_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
- struct drm_psb_get_pipe_from_crtc_id_arg)
-#define DRM_IOCTL_GMA_GEM_CREATE \
- DRM_IOWR(DRM_GMA_GEM_CREATE + DRM_COMMAND_BASE, \
- struct drm_psb_gem_create)
-#define DRM_IOCTL_GMA_GEM_MMAP \
- DRM_IOWR(DRM_GMA_GEM_MMAP + DRM_COMMAND_BASE, \
- struct drm_psb_gem_mmap)
-
-static int psb_adb_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_gamma_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
-
-static struct drm_ioctl_desc psb_ioctls[] = {
- DRM_IOCTL_DEF_DRV(GMA_ADB, psb_adb_ioctl, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(GMA_MODE_OPERATION, psb_mode_operation_ioctl,
- DRM_AUTH),
- DRM_IOCTL_DEF_DRV(GMA_STOLEN_MEMORY, psb_stolen_memory_ioctl,
- DRM_AUTH),
- DRM_IOCTL_DEF_DRV(GMA_GAMMA, psb_gamma_ioctl, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(GMA_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
- DRM_IOCTL_DEF_DRV(GMA_GET_PIPE_FROM_CRTC_ID,
- psb_intel_get_pipe_from_crtc_id, 0),
- DRM_IOCTL_DEF_DRV(GMA_GEM_CREATE, psb_gem_create_ioctl,
- DRM_UNLOCKED | DRM_AUTH),
- DRM_IOCTL_DEF_DRV(GMA_GEM_MMAP, psb_gem_mmap_ioctl,
- DRM_UNLOCKED | DRM_AUTH),
+static const struct drm_ioctl_desc psb_ioctls[] = {
};
-static void psb_lastclose(struct drm_device *dev)
+/**
+ * psb_spank - reset the 2D engine
+ * @dev_priv: our PSB DRM device
+ *
+ * Soft reset the graphics engine and then reload the necessary registers.
+ */
+static void psb_spank(struct drm_psb_private *dev_priv)
{
- int ret;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_fbdev *fbdev = dev_priv->fbdev;
-
- drm_modeset_lock_all(dev);
- ret = drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
- if (ret)
- DRM_DEBUG("failed to restore crtc mode\n");
- drm_modeset_unlock_all(dev);
-
- return;
+ PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
+ _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
+ _PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
+ _PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
+ PSB_RSGX32(PSB_CR_SOFT_RESET);
+
+ msleep(1);
+
+ PSB_WSGX32(0, PSB_CR_SOFT_RESET);
+ wmb();
+ PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT,
+ PSB_CR_BIF_CTRL);
+ wmb();
+ (void) PSB_RSGX32(PSB_CR_BIF_CTRL);
+
+ msleep(1);
+ PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT,
+ PSB_CR_BIF_CTRL);
+ (void) PSB_RSGX32(PSB_CR_BIF_CTRL);
+ PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
}
static int psb_do_init(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_gtt *pg = &dev_priv->gtt;
uint32_t stolen_gtt;
- int ret = -ENOMEM;
-
if (pg->mmu_gatt_start & 0x0FFFFFFF) {
dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n");
- ret = -EINVAL;
- goto out_err;
+ return -EINVAL;
}
-
stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4;
stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT;
- stolen_gtt =
- (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
+ stolen_gtt = (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
dev_priv->gatt_free_offset = pg->mmu_gatt_start +
(stolen_gtt << PAGE_SHIFT) * 1024;
spin_lock_init(&dev_priv->irqmask_lock);
- spin_lock_init(&dev_priv->lock_2d);
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
PSB_RSGX32(PSB_CR_BIF_BANK1);
- PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK,
- PSB_CR_BIF_CTRL);
+
+ /* Do not bypass any MMU access, let them pagefault instead */
+ PSB_WSGX32((PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_MMU_ER_MASK),
+ PSB_CR_BIF_CTRL);
+ PSB_RSGX32(PSB_CR_BIF_CTRL);
+
psb_spank(dev_priv);
/* mmu_gatt ?? */
PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
+ PSB_RSGX32(PSB_CR_BIF_TWOD_REQ_BASE); /* Post */
+
return 0;
-out_err:
- return ret;
}
-static int psb_driver_unload(struct drm_device *dev)
+static void psb_driver_unload(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
- /* Kill vblank etc here */
+ /* TODO: Kill vblank etc here */
+ gma_backlight_exit(dev);
+ psb_modeset_cleanup(dev);
- if (dev_priv) {
- if (dev_priv->backlight_device)
- gma_backlight_exit(dev);
- psb_modeset_cleanup(dev);
+ gma_irq_uninstall(dev);
- if (dev_priv->ops->chip_teardown)
- dev_priv->ops->chip_teardown(dev);
+ if (dev_priv->ops->chip_teardown)
+ dev_priv->ops->chip_teardown(dev);
- psb_intel_opregion_fini(dev);
+ psb_intel_opregion_fini(dev);
- if (dev_priv->pf_pd) {
- psb_mmu_free_pagedir(dev_priv->pf_pd);
- dev_priv->pf_pd = NULL;
- }
- if (dev_priv->mmu) {
- struct psb_gtt *pg = &dev_priv->gtt;
-
- down_read(&pg->sem);
- psb_mmu_remove_pfn_sequence(
- psb_mmu_get_default_pd
- (dev_priv->mmu),
- pg->mmu_gatt_start,
- dev_priv->vram_stolen_size >> PAGE_SHIFT);
- up_read(&pg->sem);
- psb_mmu_driver_takedown(dev_priv->mmu);
- dev_priv->mmu = NULL;
- }
- psb_gtt_takedown(dev);
- if (dev_priv->scratch_page) {
- set_pages_wb(dev_priv->scratch_page, 1);
- __free_page(dev_priv->scratch_page);
- dev_priv->scratch_page = NULL;
- }
- if (dev_priv->vdc_reg) {
- iounmap(dev_priv->vdc_reg);
- dev_priv->vdc_reg = NULL;
- }
- if (dev_priv->sgx_reg) {
- iounmap(dev_priv->sgx_reg);
- dev_priv->sgx_reg = NULL;
- }
+ if (dev_priv->pf_pd) {
+ psb_mmu_free_pagedir(dev_priv->pf_pd);
+ dev_priv->pf_pd = NULL;
+ }
+ if (dev_priv->mmu) {
+ struct psb_gtt *pg = &dev_priv->gtt;
+
+ psb_mmu_remove_pfn_sequence(
+ psb_mmu_get_default_pd
+ (dev_priv->mmu),
+ pg->mmu_gatt_start,
+ dev_priv->vram_stolen_size >> PAGE_SHIFT);
+ psb_mmu_driver_takedown(dev_priv->mmu);
+ dev_priv->mmu = NULL;
+ }
+ psb_gem_mm_fini(dev);
+ psb_gtt_fini(dev);
+ if (dev_priv->scratch_page) {
+ set_pages_wb(dev_priv->scratch_page, 1);
+ __free_page(dev_priv->scratch_page);
+ dev_priv->scratch_page = NULL;
+ }
+ if (dev_priv->vdc_reg) {
+ iounmap(dev_priv->vdc_reg);
+ dev_priv->vdc_reg = NULL;
+ }
+ if (dev_priv->sgx_reg) {
+ 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;
+ }
+ pci_dev_put(dev_priv->aux_pdev);
+ pci_dev_put(dev_priv->lpc_pdev);
- /* Destroy VBT data */
- psb_intel_destroy_bios(dev);
+ /* Destroy VBT data */
+ psb_intel_destroy_bios(dev);
- kfree(dev_priv);
- dev->dev_private = NULL;
- }
gma_power_uninit(dev);
- return 0;
}
+static void psb_device_release(void *data)
+{
+ struct drm_device *dev = data;
+
+ psb_driver_unload(dev);
+}
-static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
+static int psb_driver_load(struct drm_device *dev, unsigned long flags)
{
- struct drm_psb_private *dev_priv;
- unsigned long resource_start;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ unsigned long resource_start, resource_len;
unsigned long irqflags;
- int ret = -ENOMEM;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
- struct psb_intel_encoder *psb_intel_encoder;
+ struct gma_encoder *gma_encoder;
+ struct psb_gtt *pg;
+ int ret = -ENOMEM;
- dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
- if (dev_priv == NULL)
- return -ENOMEM;
+ /* initializing driver private data */
- dev_priv->ops = (struct psb_ops *)chipset;
- dev_priv->dev = dev;
- dev->dev_private = (void *) dev_priv;
+ dev_priv->ops = (struct psb_ops *)flags;
- pci_set_master(dev->pdev);
+ pg = &dev_priv->gtt;
+
+ pci_set_master(pdev);
dev_priv->num_pipe = dev_priv->ops->pipes;
- resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
+ resource_start = pci_resource_start(pdev, PSB_MMIO_RESOURCE);
dev_priv->vdc_reg =
ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE);
@@ -296,6 +264,54 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
if (!dev_priv->sgx_reg)
goto out_err;
+ if (IS_MRST(dev)) {
+ int domain = pci_domain_nr(pdev->bus);
+
+ dev_priv->aux_pdev =
+ pci_get_domain_bus_and_slot(domain, 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(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;
+
+ dev_priv->lpc_pdev =
+ pci_get_domain_bus_and_slot(domain, 0,
+ PCI_DEVFN(31, 0));
+ if (dev_priv->lpc_pdev) {
+ pci_read_config_word(dev_priv->lpc_pdev, PSB_LPC_GBA,
+ &dev_priv->lpc_gpio_base);
+ pci_write_config_dword(dev_priv->lpc_pdev, PSB_LPC_GBA,
+ (u32)dev_priv->lpc_gpio_base | (1L<<31));
+ pci_read_config_word(dev_priv->lpc_pdev, PSB_LPC_GBA,
+ &dev_priv->lpc_gpio_base);
+ dev_priv->lpc_gpio_base &= 0xffc0;
+ if (dev_priv->lpc_gpio_base)
+ DRM_DEBUG_KMS("Found LPC GPIO at 0x%04x\n",
+ dev_priv->lpc_gpio_base);
+ else {
+ pci_dev_put(dev_priv->lpc_pdev);
+ dev_priv->lpc_pdev = NULL;
+ }
+ }
+ } else {
+ dev_priv->gmbus_reg = dev_priv->vdc_reg;
+ }
+
psb_intel_opregion_setup(dev);
ret = dev_priv->ops->chip_setup(dev);
@@ -313,13 +329,16 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
set_pages_uc(dev_priv->scratch_page, 1);
- ret = psb_gtt_init(dev, 0);
+ ret = psb_gtt_init(dev);
+ if (ret)
+ goto out_err;
+ ret = psb_gem_mm_init(dev);
if (ret)
goto out_err;
- dev_priv->mmu = psb_mmu_driver_init((void *)0,
- drm_psb_trap_pagefaults, 0,
- dev_priv);
+ ret = -ENOMEM;
+
+ dev_priv->mmu = psb_mmu_driver_init(dev, 1, 0, NULL);
if (!dev_priv->mmu)
goto out_err;
@@ -327,18 +346,25 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
if (!dev_priv->pf_pd)
goto out_err;
- psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
- psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
-
ret = psb_do_init(dev);
if (ret)
return ret;
+ /* Add stolen memory to SGX MMU */
+ ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd(dev_priv->mmu),
+ dev_priv->stolen_base >> PAGE_SHIFT,
+ pg->gatt_start,
+ pg->stolen_size >> PAGE_SHIFT, 0);
+
+ psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
+ psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
+
PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE);
PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE);
acpi_video_register();
+ /* Setup vertical blanking handling */
ret = drm_vblank_init(dev, dev_priv->num_pipe);
if (ret)
goto out_err;
@@ -357,339 +383,166 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
- drm_irq_install(dev);
-
- dev->vblank_disable_allowed = 1;
+ gma_irq_install(dev);
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
- dev->driver->get_vblank_counter = psb_get_vblank_counter;
-
psb_modeset_init(dev);
- psb_fbdev_init(dev);
drm_kms_helper_poll_init(dev);
- /* Only add backlight support if we have LVDS output */
- list_for_each_entry(connector, &dev->mode_config.connector_list,
- head) {
- psb_intel_encoder = psb_intel_attached_encoder(connector);
+ /* Only add backlight support if we have LVDS or MIPI output */
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ gma_encoder = gma_attached_encoder(connector);
- switch (psb_intel_encoder->type) {
- case INTEL_OUTPUT_LVDS:
- case INTEL_OUTPUT_MIPI:
+ if (gma_encoder->type == INTEL_OUTPUT_LVDS ||
+ gma_encoder->type == INTEL_OUTPUT_MIPI) {
ret = gma_backlight_init(dev);
+ if (ret == 0)
+ acpi_video_register_backlight();
break;
}
}
+ drm_connector_list_iter_end(&conn_iter);
if (ret)
return ret;
psb_intel_opregion_enable_asle(dev);
-#if 0
- /*enable runtime pm at last*/
- pm_runtime_enable(&dev->pdev->dev);
- pm_runtime_set_active(&dev->pdev->dev);
-#endif
- /*Intel drm driver load is done, continue doing pvr load*/
- return 0;
+
+ return devm_add_action_or_reset(dev->dev, psb_device_release, dev);
+
out_err:
psb_driver_unload(dev);
return ret;
}
-static int psb_driver_device_is_agp(struct drm_device *dev)
-{
- return 0;
-}
-
-static inline void get_brightness(struct backlight_device *bd)
-{
-#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;
-}
-
-static int psb_adb_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_adj1 = *arg;
- get_brightness(dev_priv->backlight_device);
- return 0;
-}
-
-static int psb_gamma_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+/*
+ * Hardware for gma500 is a hybrid device, which both acts as a PCI
+ * device (for legacy vga functionality) but also more like an
+ * integrated display on a SoC where the framebuffer simply
+ * resides in main memory and not in a special PCI bar (that
+ * internally redirects to a stolen range of main memory) like all
+ * other integrated PCI display devices implement it.
+ *
+ * To catch all cases we need to remove conflicting firmware devices
+ * for the stolen system memory and for the VGA functionality. As we
+ * currently cannot easily find the framebuffer's location in stolen
+ * memory, we remove all framebuffers here.
+ *
+ * TODO: Refactor psb_driver_load() to map vdc_reg earlier. Then
+ * we might be able to read the framebuffer range from the
+ * device.
+ */
+static int gma_remove_conflicting_framebuffers(struct pci_dev *pdev,
+ const struct drm_driver *req_driver)
{
- struct drm_psb_dpst_lut_arg *lut_arg = data;
- struct drm_mode_object *obj;
- struct drm_crtc *crtc;
- struct drm_connector *connector;
- struct psb_intel_crtc *psb_intel_crtc;
- int i = 0;
- int32_t obj_id;
-
- obj_id = lut_arg->output_id;
- obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- dev_dbg(dev->dev, "Invalid Connector object.\n");
- return -EINVAL;
- }
-
- connector = obj_to_connector(obj);
- crtc = connector->encoder->crtc;
- psb_intel_crtc = to_psb_intel_crtc(crtc);
-
- for (i = 0; i < 256; i++)
- psb_intel_crtc->lut_adj[i] = lut_arg->lut[i];
+ resource_size_t base = 0;
+ resource_size_t size = U32_MAX; /* 4 GiB HW limit */
+ const char *name = req_driver->name;
+ int ret;
- psb_intel_crtc_load_lut(crtc);
+ ret = aperture_remove_conflicting_devices(base, size, name);
+ if (ret)
+ return ret;
- return 0;
+ return __aperture_remove_legacy_vga_devices(pdev);
}
-static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- uint32_t obj_id;
- uint16_t op;
- struct drm_mode_modeinfo *umode;
- struct drm_display_mode *mode = NULL;
- struct drm_psb_mode_operation_arg *arg;
- struct drm_mode_object *obj;
- struct drm_connector *connector;
- struct drm_connector_helper_funcs *connector_funcs;
- int ret = 0;
- int resp = MODE_OK;
-
- arg = (struct drm_psb_mode_operation_arg *)data;
- obj_id = arg->obj_id;
- op = arg->operation;
-
- switch (op) {
- case PSB_MODE_OPERATION_MODE_VALID:
- umode = &arg->mode;
-
- drm_modeset_lock_all(dev);
-
- obj = drm_mode_object_find(dev, obj_id,
- DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
- ret = -EINVAL;
- goto mode_op_out;
- }
-
- connector = obj_to_connector(obj);
-
- mode = drm_mode_create(dev);
- if (!mode) {
- ret = -ENOMEM;
- goto mode_op_out;
- }
-
- /* drm_crtc_convert_umode(mode, umode); */
- {
- mode->clock = umode->clock;
- mode->hdisplay = umode->hdisplay;
- mode->hsync_start = umode->hsync_start;
- mode->hsync_end = umode->hsync_end;
- mode->htotal = umode->htotal;
- mode->hskew = umode->hskew;
- mode->vdisplay = umode->vdisplay;
- mode->vsync_start = umode->vsync_start;
- mode->vsync_end = umode->vsync_end;
- mode->vtotal = umode->vtotal;
- mode->vscan = umode->vscan;
- mode->vrefresh = umode->vrefresh;
- mode->flags = umode->flags;
- mode->type = umode->type;
- strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN);
- mode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
- }
-
- connector_funcs = (struct drm_connector_helper_funcs *)
- connector->helper_private;
+ struct drm_psb_private *dev_priv;
+ struct drm_device *dev;
+ int ret;
- if (connector_funcs->mode_valid) {
- resp = connector_funcs->mode_valid(connector, mode);
- arg->data = resp;
- }
+ ret = gma_remove_conflicting_framebuffers(pdev, &driver);
+ if (ret)
+ return ret;
- /*do some clean up work*/
- if (mode)
- drm_mode_destroy(dev, mode);
-mode_op_out:
- drm_modeset_unlock_all(dev);
+ ret = pcim_enable_device(pdev);
+ if (ret)
return ret;
- default:
- dev_dbg(dev->dev, "Unsupported psb mode operation\n");
- return -EOPNOTSUPP;
- }
+ dev_priv = devm_drm_dev_alloc(&pdev->dev, &driver, struct drm_psb_private, dev);
+ if (IS_ERR(dev_priv))
+ return PTR_ERR(dev_priv);
+ dev = &dev_priv->dev;
- return 0;
-}
+ pci_set_drvdata(pdev, dev);
-static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_private *dev_priv = psb_priv(dev);
- struct drm_psb_stolen_memory_arg *arg = data;
+ ret = psb_driver_load(dev, ent->driver_data);
+ if (ret)
+ return ret;
- arg->base = dev_priv->stolen_base;
- arg->size = dev_priv->vram_stolen_size;
+ ret = drm_dev_register(dev, ent->driver_data);
+ if (ret)
+ return ret;
- return 0;
-}
+ drm_client_setup(dev, NULL);
-static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
-{
return 0;
}
-static void psb_driver_close(struct drm_device *dev, struct drm_file *priv)
-{
-}
-
-static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- struct drm_file *file_priv = filp->private_data;
- struct drm_device *dev = file_priv->minor->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- static unsigned int runtime_allowed;
-
- if (runtime_allowed == 1 && dev_priv->is_lvds_on) {
- runtime_allowed++;
- pm_runtime_allow(&dev->pdev->dev);
- dev_priv->rpm_enabled = 1;
- }
- return drm_ioctl(filp, cmd, arg);
- /* FIXME: do we need to wrap the other side of this */
-}
-
-
-/* When a client dies:
- * - Check for and clean up flipped page state
- */
-static void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
-{
-}
-
-static void psb_remove(struct pci_dev *pdev)
+static void psb_pci_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
- drm_put_dev(dev);
-}
-static const struct dev_pm_ops psb_pm_ops = {
- .resume = gma_power_resume,
- .suspend = gma_power_suspend,
- .thaw = gma_power_thaw,
- .freeze = gma_power_freeze,
- .restore = gma_power_restore,
- .runtime_suspend = psb_runtime_suspend,
- .runtime_resume = psb_runtime_resume,
- .runtime_idle = psb_runtime_idle,
-};
+ drm_dev_unregister(dev);
+}
-static const struct vm_operations_struct psb_gem_vm_ops = {
- .fault = psb_gem_fault,
- .open = drm_gem_vm_open,
- .close = drm_gem_vm_close,
-};
+static DEFINE_RUNTIME_DEV_PM_OPS(psb_pm_ops, gma_power_suspend, gma_power_resume, NULL);
static const struct file_operations psb_gem_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
- .unlocked_ioctl = psb_unlocked_ioctl,
+ .unlocked_ioctl = drm_ioctl,
+ .compat_ioctl = drm_compat_ioctl,
.mmap = drm_gem_mmap,
.poll = drm_poll,
- .fasync = drm_fasync,
.read = drm_read,
+ .fop_flags = FOP_UNSIGNED_OFFSET,
};
-static struct drm_driver driver = {
- .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
- DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM ,
- .load = psb_driver_load,
- .unload = psb_driver_unload,
+static const struct drm_driver driver = {
+ .driver_features = DRIVER_MODESET | DRIVER_GEM,
+
+ .num_ioctls = ARRAY_SIZE(psb_ioctls),
- .ioctls = psb_ioctls,
- .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
- .device_is_agp = psb_driver_device_is_agp,
- .irq_preinstall = psb_irq_preinstall,
- .irq_postinstall = psb_irq_postinstall,
- .irq_uninstall = psb_irq_uninstall,
- .irq_handler = psb_irq_handler,
- .enable_vblank = psb_enable_vblank,
- .disable_vblank = psb_disable_vblank,
- .get_vblank_counter = psb_get_vblank_counter,
- .lastclose = psb_lastclose,
- .open = psb_driver_open,
- .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,
- .dumb_map_offset = psb_gem_dumb_map_gtt,
- .dumb_destroy = psb_gem_dumb_destroy,
+ PSB_FBDEV_DRIVER_OPS,
+ .ioctls = psb_ioctls,
.fops = &psb_gem_fops,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
- .date = PSB_DRM_DRIVER_DATE,
- .major = PSB_DRM_DRIVER_MAJOR,
- .minor = PSB_DRM_DRIVER_MINOR,
- .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL
};
static struct pci_driver psb_pci_driver = {
.name = DRIVER_NAME,
.id_table = pciidlist,
- .probe = psb_probe,
- .remove = psb_remove,
- .driver = {
- .pm = &psb_pm_ops,
- }
+ .probe = psb_pci_probe,
+ .remove = psb_pci_remove,
+ .driver.pm = &psb_pm_ops,
};
-static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- return drm_get_pci_dev(pdev, ent, &driver);
-}
-
static int __init psb_init(void)
{
- return drm_pci_init(&driver, &psb_pci_driver);
+ if (drm_firmware_drivers_only())
+ return -ENODEV;
+
+ return pci_register_driver(&psb_pci_driver);
}
static void __exit psb_exit(void)
{
- drm_pci_exit(&driver, &psb_pci_driver);
+ pci_unregister_driver(&psb_pci_driver);
}
late_initcall(psb_init);
module_exit(psb_exit);
-MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others");
+MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 6053b8abcd12..0b27112ec46f 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -1,121 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/**************************************************************************
* Copyright (c) 2007-2011, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
**************************************************************************/
#ifndef _PSB_DRV_H_
#define _PSB_DRV_H_
#include <linux/kref.h>
+#include <linux/mm_types.h>
+
+#include <drm/drm_device.h>
-#include <drm/drmP.h>
-#include <drm/drm_global.h>
-#include <drm/gma_drm.h>
-#include "psb_reg.h"
-#include "psb_intel_drv.h"
-#include "intel_bios.h"
#include "gtt.h"
-#include "power.h"
-#include "opregion.h"
+#include "intel_bios.h"
+#include "mmu.h"
#include "oaktrail.h"
+#include "opregion.h"
+#include "power.h"
+#include "psb_intel_drv.h"
+#include "psb_reg.h"
-/* Append new drm mode definition here, align with libdrm definition */
-#define DRM_MODE_SCALE_NO_SCALE 2
-
-enum {
- CHIP_PSB_8108 = 0, /* Poulsbo */
- CHIP_PSB_8109 = 1, /* Poulsbo */
- CHIP_MRST_4100 = 2, /* Moorestown/Oaktrail */
- CHIP_MFLD_0130 = 3, /* Medfield */
-};
+#define DRIVER_AUTHOR "Alan Cox <alan@linux.intel.com> and others"
-#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 DRIVER_NAME "gma500"
+#define DRIVER_DESC "DRM driver for the Intel GMA500, GMA600, GMA3600, GMA3650"
-/*
- * Driver definitions
- */
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+#define DRIVER_PATCHLEVEL 0
-#define DRIVER_NAME "gma500"
-#define DRIVER_DESC "DRM driver for the Intel GMA500"
+/* Append new drm mode definition here, align with libdrm definition */
+#define DRM_MODE_SCALE_NO_SCALE 2
-#define PSB_DRM_DRIVER_DATE "2011-06-06"
-#define PSB_DRM_DRIVER_MAJOR 1
-#define PSB_DRM_DRIVER_MINOR 0
-#define PSB_DRM_DRIVER_PATCHLEVEL 0
+#define IS_PSB(drm) ((to_pci_dev((drm)->dev)->device & 0xfffe) == 0x8108)
+#define IS_MRST(drm) ((to_pci_dev((drm)->dev)->device & 0xfff0) == 0x4100)
+#define IS_CDV(drm) ((to_pci_dev((drm)->dev)->device & 0xfff0) == 0x0be0)
-/*
- * Hardware offsets
- */
+/* Hardware offsets */
#define PSB_VDC_OFFSET 0x00000000
#define PSB_VDC_SIZE 0x000080000
#define MRST_MMIO_SIZE 0x0000C0000
-#define MDFLD_MMIO_SIZE 0x000100000
#define PSB_SGX_SIZE 0x8000
#define PSB_SGX_OFFSET 0x00040000
#define MRST_SGX_OFFSET 0x00080000
-/*
- * PCI resource identifiers
- */
+
+/* PCI resource identifiers */
#define PSB_MMIO_RESOURCE 0
+#define PSB_AUX_RESOURCE 0
#define PSB_GATT_RESOURCE 2
#define PSB_GTT_RESOURCE 3
-/*
- * PCI configuration
- */
+
+/* PCI configuration */
#define PSB_GMCH_CTRL 0x52
#define PSB_BSM 0x5C
#define _PSB_GMCH_ENABLED 0x4
#define PSB_PGETBL_CTL 0x2020
#define _PSB_PGETBL_ENABLED 0x00000001
#define PSB_SGX_2D_SLAVE_PORT 0x4000
+#define PSB_LPC_GBA 0x44
-/* To get rid of */
+/* TODO: To get rid of */
#define PSB_TT_PRIV0_LIMIT (256*1024*1024)
#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
-/*
- * SGX side MMU definitions (these can probably go)
- */
+/* SGX side MMU definitions (these can probably go) */
-/*
- * Flags for external memory type field.
- */
+/* Flags for external memory type field */
#define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */
#define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */
#define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */
-/*
- * PTE's and PDE's
- */
+
+/* PTE's and PDE's */
#define PSB_PDE_MASK 0x003FFFFF
#define PSB_PDE_SHIFT 22
#define PSB_PTE_SHIFT 12
-/*
- * Cache control
- */
+
+/* Cache control */
#define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */
#define PSB_PTE_WO 0x0002 /* Write only */
#define PSB_PTE_RO 0x0004 /* Read only */
#define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */
-/*
- * VDC registers and bits
- */
+/* VDC registers and bits */
#define PSB_MSVDX_CLOCKGATING 0x2064
#define PSB_TOPAZ_CLOCKGATING 0x2068
#define PSB_HWSTAM 0x2098
@@ -130,8 +98,6 @@ enum {
#define _PSB_DPST_PIPEA_FLAG (1<<6)
#define _PSB_PIPEA_EVENT_FLAG (1<<6)
#define _PSB_VSYNC_PIPEA_FLAG (1<<7)
-#define _MDFLD_MIPIA_FLAG (1<<16)
-#define _MDFLD_MIPIC_FLAG (1<<17)
#define _PSB_IRQ_DISP_HOTSYNC (1<<17)
#define _PSB_IRQ_SGX_FLAG (1<<18)
#define _PSB_IRQ_MSVDX_FLAG (1<<19)
@@ -140,13 +106,6 @@ enum {
#define _PSB_PIPE_EVENT_FLAG (_PSB_VSYNC_PIPEA_FLAG | \
_PSB_VSYNC_PIPEB_FLAG)
-/* This flag includes all the display IRQ bits excepts the vblank irqs. */
-#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \
- _MDFLD_PIPEB_EVENT_FLAG | \
- _PSB_PIPEA_EVENT_FLAG | \
- _PSB_VSYNC_PIPEA_FLAG | \
- _MDFLD_MIPIA_FLAG | \
- _MDFLD_MIPIC_FLAG)
#define PSB_INT_IDENTITY_R 0x20A4
#define PSB_INT_MASK_R 0x20A8
#define PSB_INT_ENABLE_R 0x20A0
@@ -201,35 +160,9 @@ enum {
#define PSB_NUM_VBLANKS 2
+#define PSB_WATCHDOG_DELAY (HZ * 2)
-#define PSB_2D_SIZE (256*1024*1024)
-#define PSB_MAX_RELOC_PAGES 1024
-
-#define PSB_LOW_REG_OFFS 0x0204
-#define PSB_HIGH_REG_OFFS 0x0600
-
-#define PSB_NUM_VBLANKS 2
-#define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
-#define PSB_LID_DELAY (DRM_HZ / 10)
-
-#define MDFLD_PNW_B0 0x04
-#define MDFLD_PNW_C0 0x08
-
-#define MDFLD_DSR_2D_3D_0 (1 << 0)
-#define MDFLD_DSR_2D_3D_2 (1 << 1)
-#define MDFLD_DSR_CURSOR_0 (1 << 2)
-#define MDFLD_DSR_CURSOR_2 (1 << 3)
-#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_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
-
-#define MDFLD_DSR_RR 45
-#define MDFLD_DPU_ENABLE (1 << 31)
-#define MDFLD_DSR_FULLSCREEN (1 << 30)
-#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR)
+#define PSB_MAX_BRIGHTNESS 100
#define PSB_PWR_STATE_ON 1
#define PSB_PWR_STATE_OFF 2
@@ -250,6 +183,9 @@ enum {
#define KSEL_BYPASS_25 6
#define KSEL_BYPASS_83_100 7
+struct drm_fb_helper;
+struct drm_fb_helper_surface_size;
+
struct opregion_header;
struct opregion_acpi;
struct opregion_swsci;
@@ -262,12 +198,13 @@ struct psb_intel_opregion {
struct opregion_asle *asle;
void *vbt;
u32 __iomem *lid_state;
+ struct work_struct asle_work;
};
struct sdvo_device_mapping {
u8 initialized;
u8 dvo_port;
- u8 slave_addr;
+ u8 target_addr;
u8 dvo_wiring;
u8 i2c_pin;
u8 i2c_speed;
@@ -280,10 +217,7 @@ struct intel_gmbus {
u32 reg0;
};
-/*
- * Register offset maps
- */
-
+/* Register offset maps */
struct psb_offset {
u32 fp0;
u32 fp1;
@@ -317,9 +251,7 @@ struct psb_offset {
* update the register cache instead.
*/
-/*
- * Common status for pipes.
- */
+/* Common status for pipes */
struct psb_pipe {
u32 fp0;
u32 fp1;
@@ -405,16 +337,6 @@ struct psb_state {
uint32_t savePWM_CONTROL_LOGIC;
};
-struct medfield_state {
- uint32_t saveMIPI;
- uint32_t saveMIPI_C;
-
- uint32_t savePFIT_CONTROL;
- uint32_t savePFIT_PGM_RATIOS;
- uint32_t saveHDMIPHYMISCCTL;
- uint32_t saveHDMIB_CONTROL;
-};
-
struct cdv_state {
uint32_t saveDSPCLK_GATE_D;
uint32_t saveRAMCLK_GATE_D;
@@ -440,7 +362,6 @@ struct psb_save_area {
uint32_t saveVBT;
union {
struct psb_state psb;
- struct medfield_state mdfld;
struct cdv_state cdv;
};
uint32_t saveBLC_PWM_CTL2;
@@ -451,11 +372,16 @@ struct psb_ops;
#define PSB_NUM_PIPE 3
+struct intel_scu_ipc_dev;
+
struct drm_psb_private {
- struct drm_device *dev;
+ struct drm_device dev;
+
+ struct pci_dev *aux_pdev; /* Currently only used by mrst */
+ struct pci_dev *lpc_pdev; /* Currently only used by mrst */
const struct psb_ops *ops;
const struct psb_offset *regmap;
-
+
struct child_device_config *child_dev;
int child_dev_num;
@@ -468,44 +394,35 @@ struct drm_psb_private {
uint32_t stolen_base;
u8 __iomem *vram_addr;
unsigned long vram_stolen_size;
- int gtt_initialized;
u16 gmch_ctrl; /* Saved GTT setup */
u32 pge_ctl;
struct mutex gtt_mutex;
struct resource *gtt_mem; /* Our PCI resource */
+ struct mutex mmap_mutex;
+
struct psb_mmu_driver *mmu;
struct psb_mmu_pd *pf_pd;
- /*
- * Register base
- */
-
+ /* Register base */
uint8_t __iomem *sgx_reg;
uint8_t __iomem *vdc_reg;
+ uint8_t __iomem *aux_reg; /* Auxillary vdc pipe regs */
+ uint16_t lpc_gpio_base;
uint32_t gatt_free_offset;
- /*
- * Fencing / irq.
- */
-
+ /* Fencing / irq */
uint32_t vdc_irq_mask;
uint32_t pipestat[PSB_NUM_PIPE];
spinlock_t irqmask_lock;
+ bool irq_enabled;
- /*
- * Power
- */
-
- bool suspended;
- bool display_power;
- int display_count;
+ /* Power */
+ bool pm_initialized;
- /*
- * Modesetting
- */
+ /* Modesetting */
struct psb_intel_mode_device mode_dev;
bool modeset; /* true if we have done the mode_device setup */
@@ -513,15 +430,10 @@ struct drm_psb_private {
struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
uint32_t num_pipe;
- /*
- * OSPM info (Power management base) (can go ?)
- */
+ /* OSPM info (Power management base) (TODO: can go ?) */
uint32_t ospm_base;
- /*
- * Sizes info
- */
-
+ /* Sizes info */
u32 fuse_reg_value;
u32 video_device_fuse;
@@ -530,6 +442,7 @@ struct drm_psb_private {
/* gmbus */
struct intel_gmbus *gmbus;
+ uint8_t __iomem *gmbus_reg;
/* Used by SDVO */
int crt_ddc_pin;
@@ -540,9 +453,7 @@ struct drm_psb_private {
struct drm_property *broadcast_rgb_property;
struct drm_property *force_audio_property;
- /*
- * LVDS info
- */
+ /* LVDS info */
int backlight_duty_cycle; /* restore backlight to this value */
bool panel_wants_dither;
struct drm_display_mode *panel_fixed_mode;
@@ -550,7 +461,7 @@ struct drm_psb_private {
struct drm_display_mode *sdvo_lvds_vbt_mode;
struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */
- struct psb_intel_i2c_chan *lvds_i2c_bus; /* FIXME: Remove this? */
+ struct gma_i2c_chan *lvds_i2c_bus; /* FIXME: Remove this? */
/* Feature bits from the VBIOS */
unsigned int int_tv_support:1;
@@ -561,49 +472,29 @@ struct drm_psb_private {
int lvds_ssc_freq;
bool is_lvds_on;
bool is_mipi_on;
+ bool lvds_enabled_in_vbt;
u32 mipi_ctrl_display;
unsigned int core_freq;
uint32_t iLVDS_enable;
- /* Runtime PM state */
- int rpm_enabled;
-
/* MID specific */
+ bool use_msi;
bool has_gct;
struct oaktrail_gct_data gct_data;
/* Oaktrail HDMI state */
struct oaktrail_hdmi_dev *hdmi_priv;
-
- /*
- * Register state
- */
+ /* Register state */
struct psb_save_area regs;
- /* MSI reg save */
- uint32_t msi_addr;
- uint32_t msi_data;
-
- /*
- * Hotplug handling
- */
-
+ /* Hotplug handling */
struct work_struct hotplug_work;
- /*
- * LID-Switch
- */
- spinlock_t lid_lock;
- struct timer_list lid_timer;
struct psb_intel_opregion opregion;
- u32 lid_last_state;
-
- /*
- * Watchdog
- */
+ /* Watchdog */
uint32_t apm_reg;
uint16_t apm_base;
@@ -611,6 +502,7 @@ struct drm_psb_private {
* Used for modifying backlight from
* xrandr -- consider removing and using HAL instead
*/
+ struct intel_scu_ipc_dev *scu;
struct backlight_device *backlight_device;
struct drm_property *backlight_property;
bool backlight_enabled;
@@ -618,17 +510,6 @@ struct drm_psb_private {
uint32_t blc_adj1;
uint32_t blc_adj2;
- void *fbdev;
-
- /* 2D acceleration */
- spinlock_t lock_2d;
-
- /*
- * Panel brightness
- */
- int brightness;
- int brightness_adjusted;
-
bool dsr_enable;
u32 dsr_fb_update;
bool dpi_panel_on[3];
@@ -639,8 +520,6 @@ struct drm_psb_private {
u32 pipeconf[3];
u32 dspcntr[3];
- int mdfld_panel_id;
-
bool dplla_96mhz; /* DPLL data from the VBT */
struct {
@@ -657,24 +536,25 @@ struct drm_psb_private {
uint8_t panel_type;
};
+static inline struct drm_psb_private *to_drm_psb_private(struct drm_device *dev)
+{
+ return container_of(dev, struct drm_psb_private, dev);
+}
-/*
- * Operations for each board type
- */
-
+/* Operations for each board type */
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 */
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 */
struct drm_crtc_helper_funcs const *crtc_helper;
- struct drm_crtc_funcs const *crtc_funcs;
+ const struct gma_clock_funcs *clock_funcs;
/* Setup hooks */
int (*chip_setup)(struct drm_device *dev);
@@ -690,123 +570,44 @@ struct psb_ops {
void (*init_pm)(struct drm_device *dev);
int (*save_regs)(struct drm_device *dev);
int (*restore_regs)(struct drm_device *dev);
+ void (*save_crtc)(struct drm_crtc *crtc);
+ void (*restore_crtc)(struct drm_crtc *crtc);
int (*power_up)(struct drm_device *dev);
int (*power_down)(struct drm_device *dev);
+ void (*update_wm)(struct drm_device *dev, struct drm_crtc *crtc);
+ void (*disable_sr)(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
+ void (*backlight_set)(struct drm_device *dev, int level);
+ int (*backlight_get)(struct drm_device *dev);
+ const char *backlight_name;
+
int i2c_bus; /* I2C bus identifier for Moorestown */
};
-
-
-struct psb_mmu_driver;
-
-extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
-extern int drm_pick_crtcs(struct drm_device *dev);
-
-static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
-{
- return (struct drm_psb_private *) dev->dev_private;
-}
-
-/*
- * MMU stuff.
- */
-
-extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
- int trap_pagefaults,
- int invalid_type,
- struct drm_psb_private *dev_priv);
-extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
-extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
- *driver);
-extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
- uint32_t gtt_start, uint32_t gtt_pages);
-extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
- int trap_pagefaults,
- int invalid_type);
-extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
-extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
-extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
- unsigned long address,
- uint32_t num_pages);
-extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
- uint32_t start_pfn,
- unsigned long address,
- uint32_t num_pages, int type);
-extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
- unsigned long *pfn);
-
-/*
- * Enable / disable MMU for different requestors.
- */
-
-
-extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
-extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
- unsigned long address, uint32_t num_pages,
- uint32_t desired_tile_stride,
- uint32_t hw_tile_stride, int type);
-extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
- unsigned long address, uint32_t num_pages,
- uint32_t desired_tile_stride,
- uint32_t hw_tile_stride);
-/*
- *psb_irq.c
- */
-
-extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
-extern int psb_irq_enable_dpst(struct drm_device *dev);
-extern int psb_irq_disable_dpst(struct drm_device *dev);
-extern void psb_irq_preinstall(struct drm_device *dev);
-extern int psb_irq_postinstall(struct drm_device *dev);
-extern void psb_irq_uninstall(struct drm_device *dev);
-extern void psb_irq_turn_on_dpst(struct drm_device *dev);
-extern void psb_irq_turn_off_dpst(struct drm_device *dev);
-
-extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
-extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
-extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern int psb_enable_vblank(struct drm_device *dev, int crtc);
-extern void psb_disable_vblank(struct drm_device *dev, int crtc);
-void
-psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
-
-void
-psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
-
-extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
-
-/*
- * framebuffer.c
- */
-extern int psbfb_probed(struct drm_device *dev);
-extern int psbfb_remove(struct drm_device *dev,
- struct drm_framebuffer *fb);
-/*
- * accel_2d.c
- */
-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);
-
-/*
- * psb_reset.c
- */
-
-extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
-extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
-extern void psb_print_pagefault(struct drm_psb_private *dev_priv);
-
/* modesetting */
extern void psb_modeset_init(struct drm_device *dev);
extern void psb_modeset_cleanup(struct drm_device *dev);
-extern int psb_fbdev_init(struct drm_device *dev);
+
+/* framebuffer */
+struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev,
+ const struct drm_format_info *info,
+ const struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_gem_object *obj);
+
+/* fbdev */
+#if defined(CONFIG_DRM_FBDEV_EMULATION)
+int psb_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes);
+#define PSB_FBDEV_DRIVER_OPS \
+ .fbdev_probe = psb_fbdev_driver_fbdev_probe
+#else
+#define PSB_FBDEV_DRIVER_OPS \
+ .fbdev_probe = NULL
+#endif
/* backlight.c */
int gma_backlight_init(struct drm_device *dev);
@@ -824,7 +625,6 @@ extern void oaktrail_lvds_init(struct drm_device *dev,
/* psb_intel_display.c */
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 const struct drm_connector_helper_funcs
@@ -832,21 +632,8 @@ 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);
extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args);
-extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
- uint32_t handle);
-extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
- uint32_t handle, uint64_t *offset);
-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;
@@ -854,92 +641,73 @@ extern const struct psb_ops psb_chip_ops;
/* oaktrail_device.c */
extern const struct psb_ops oaktrail_chip_ops;
-/* mdlfd_device.c */
-extern const struct psb_ops mdfld_chip_ops;
-
/* cdv_device.c */
extern const struct psb_ops cdv_chip_ops;
-/*
- * Debug print bits setting
- */
-#define PSB_D_GENERAL (1 << 0)
-#define PSB_D_INIT (1 << 1)
-#define PSB_D_IRQ (1 << 2)
-#define PSB_D_ENTRY (1 << 3)
-/* debug the get H/V BP/FP count */
-#define PSB_D_HV (1 << 4)
-#define PSB_D_DBI_BF (1 << 5)
-#define PSB_D_PM (1 << 6)
-#define PSB_D_RENDER (1 << 7)
-#define PSB_D_REG (1 << 8)
-#define PSB_D_MSVDX (1 << 9)
-#define PSB_D_TOPAZ (1 << 10)
-
-extern int drm_idle_check_interval;
-
-/*
- * Utilities
- */
-
-static inline u32 MRST_MSG_READ32(uint port, uint offset)
+/* Utilities */
+static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
{
- int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
- uint32_t ret_val = 0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_read_config_dword(pci_root, 0xD4, &ret_val);
- pci_dev_put(pci_root);
- return ret_val;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ return ioread32(dev_priv->vdc_reg + reg);
}
-static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value)
+
+static inline uint32_t REGISTER_READ_AUX(struct drm_device *dev, uint32_t reg)
{
- int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD4, value);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_dev_put(pci_root);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ return ioread32(dev_priv->aux_reg + reg);
}
-static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
+
+#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)
{
- int mcr = (0x10<<24) | (port << 16) | (offset << 8);
- uint32_t ret_val = 0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_read_config_dword(pci_root, 0xD4, &ret_val);
- pci_dev_put(pci_root);
- return ret_val;
+ uint32_t val;
+
+ if (aux)
+ val = REG_READ_AUX(reg);
+ else
+ val = REG_READ(reg);
+
+ return val;
}
-static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
+
+#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)
{
- int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
- struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
- pci_write_config_dword(pci_root, 0xD4, value);
- pci_write_config_dword(pci_root, 0xD0, mcr);
- pci_dev_put(pci_root);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ iowrite32((val), dev_priv->vdc_reg + (reg));
}
-static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t 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;
- return ioread32(dev_priv->vdc_reg + reg);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ iowrite32((val), dev_priv->aux_reg + (reg));
}
-#define REG_READ(reg) REGISTER_READ(dev, (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(struct drm_device *dev, uint32_t reg,
- uint32_t val)
+static inline void REGISTER_WRITE_WITH_AUX(struct drm_device *dev, uint32_t reg,
+ uint32_t val, int aux)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- iowrite32((val), dev_priv->vdc_reg + (reg));
+ if (aux)
+ REG_WRITE_AUX(reg, val);
+ else
+ REG_WRITE(reg, val);
}
-#define REG_WRITE(reg, val) REGISTER_WRITE(dev, (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)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
iowrite16((val), dev_priv->vdc_reg + (reg));
}
@@ -948,7 +716,7 @@ static inline void REGISTER_WRITE16(struct drm_device *dev,
static inline void REGISTER_WRITE8(struct drm_device *dev,
uint32_t reg, uint32_t val)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
iowrite8((val), dev_priv->vdc_reg + (reg));
}
@@ -957,25 +725,9 @@ static inline void REGISTER_WRITE8(struct drm_device *dev,
#define PSB_WVDC32(_val, _offs) iowrite32(_val, dev_priv->vdc_reg + (_offs))
#define PSB_RVDC32(_offs) ioread32(dev_priv->vdc_reg + (_offs))
-/* #define TRAP_SGX_PM_FAULT 1 */
-#ifdef TRAP_SGX_PM_FAULT
-#define PSB_RSGX32(_offs) \
-({ \
- if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) { \
- printk(KERN_ERR \
- "access sgx when it's off!! (READ) %s, %d\n", \
- __FILE__, __LINE__); \
- melay(1000); \
- } \
- ioread32(dev_priv->sgx_reg + (_offs)); \
-})
-#else
#define PSB_RSGX32(_offs) ioread32(dev_priv->sgx_reg + (_offs))
-#endif
#define PSB_WSGX32(_val, _offs) iowrite32(_val, dev_priv->sgx_reg + (_offs))
-#define MSVDX_REG_DUMP 0
-
#define PSB_WMSVDX32(_val, _offs) iowrite32(_val, dev_priv->msvdx_reg + (_offs))
#define PSB_RMSVDX32(_offs) ioread32(dev_priv->msvdx_reg + (_offs))
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c
index 6666493789d1..1ff2bd23db74 100644
--- a/drivers/gpu/drm/gma500/psb_intel_display.c
+++ b/drivers/gpu/drm/gma500/psb_intel_display.c
@@ -1,64 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright © 2006-2011 Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Eric Anholt <eric@anholt.net>
*/
+#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-#include <drm/drmP.h>
+#include <drm/drm_modeset_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+
#include "framebuffer.h"
+#include "gem.h"
+#include "gma_display.h"
+#include "power.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "psb_intel_display.h"
-#include "power.h"
-
-struct psb_intel_clock_t {
- /* given values */
- int n;
- int m1, m2;
- int p1, p2;
- /* derived values */
- int dot;
- int vco;
- int m;
- int p;
-};
-
-struct psb_intel_range_t {
- int min, max;
-};
-
-struct psb_intel_p2_t {
- int dot_limit;
- int p2_slow, p2_fast;
-};
-
-struct psb_intel_limit_t {
- struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1;
- struct psb_intel_p2_t p2;
-};
#define INTEL_LIMIT_I9XX_SDVO_DAC 0
#define INTEL_LIMIT_I9XX_LVDS 1
-static const struct psb_intel_limit_t psb_intel_limits[] = {
+static const struct gma_limit_t psb_intel_limits[] = {
{ /* INTEL_LIMIT_I9XX_SDVO_DAC */
.dot = {.min = 20000, .max = 400000},
.vco = {.min = 1400000, .max = 2800000},
@@ -68,8 +34,8 @@ static const struct psb_intel_limit_t psb_intel_limits[] = {
.m2 = {.min = 3, .max = 7},
.p = {.min = 5, .max = 80},
.p1 = {.min = 1, .max = 8},
- .p2 = {.dot_limit = 200000,
- .p2_slow = 10, .p2_fast = 5},
+ .p2 = {.dot_limit = 200000, .p2_slow = 10, .p2_fast = 5},
+ .find_pll = gma_find_best_pll,
},
{ /* INTEL_LIMIT_I9XX_LVDS */
.dot = {.min = 20000, .max = 400000},
@@ -83,23 +49,24 @@ static const struct psb_intel_limit_t psb_intel_limits[] = {
/* The single-channel range is 25-112Mhz, and dual-channel
* is 80-224Mhz. Prefer single channel as much as possible.
*/
- .p2 = {.dot_limit = 112000,
- .p2_slow = 14, .p2_fast = 7},
+ .p2 = {.dot_limit = 112000, .p2_slow = 14, .p2_fast = 7},
+ .find_pll = gma_find_best_pll,
},
};
-static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc)
+static const struct gma_limit_t *psb_intel_limit(struct drm_crtc *crtc,
+ int refclk)
{
- const struct psb_intel_limit_t *limit;
+ const struct gma_limit_t *limit;
- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
+ if (gma_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS];
else
limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
return limit;
}
-static void psb_intel_clock(int refclk, struct psb_intel_clock_t *clock)
+static void psb_intel_clock(int refclk, struct gma_clock_t *clock)
{
clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
clock->p = clock->p1 * clock->p2;
@@ -107,354 +74,7 @@ static void psb_intel_clock(int refclk, struct psb_intel_clock_t *clock)
clock->dot = clock->vco / clock->p;
}
-/**
- * Returns whether any output on the specified pipe is of the specified type
- */
-bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct drm_connector *l_entry;
-
- list_for_each_entry(l_entry, &mode_config->connector_list, head) {
- if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(l_entry);
- if (psb_intel_encoder->type == type)
- return true;
- }
- }
- return false;
-}
-
-#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; }
-/**
- * Returns whether the given set of divisors are valid for a given refclk with
- * the given connectors.
- */
-
-static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc,
- struct psb_intel_clock_t *clock)
-{
- const struct psb_intel_limit_t *limit = psb_intel_limit(crtc);
-
- if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
- INTELPllInvalid("p1 out of range\n");
- if (clock->p < limit->p.min || limit->p.max < clock->p)
- INTELPllInvalid("p out of range\n");
- if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
- INTELPllInvalid("m2 out of range\n");
- if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
- INTELPllInvalid("m1 out of range\n");
- if (clock->m1 <= clock->m2)
- INTELPllInvalid("m1 <= m2\n");
- if (clock->m < limit->m.min || limit->m.max < clock->m)
- INTELPllInvalid("m out of range\n");
- if (clock->n < limit->n.min || limit->n.max < clock->n)
- INTELPllInvalid("n out of range\n");
- if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
- INTELPllInvalid("vco out of range\n");
- /* XXX: We may need to be checking "Dot clock"
- * depending on the multiplier, connector, etc.,
- * rather than just a single range.
- */
- if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
- INTELPllInvalid("dot out of range\n");
-
- return true;
-}
-
-/**
- * Returns a set of divisors for the desired target clock with the given
- * refclk, or FALSE. The returned values represent the clock equation:
- * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
- */
-static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target,
- int refclk,
- struct psb_intel_clock_t *best_clock)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_clock_t clock;
- const struct psb_intel_limit_t *limit = psb_intel_limit(crtc);
- int err = target;
-
- if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
- (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
- /*
- * For LVDS, if the panel is on, just rely on its current
- * settings for dual-channel. We haven't figured out how to
- * reliably set up different single/dual channel state, if we
- * even can.
- */
- if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
- LVDS_CLKB_POWER_UP)
- clock.p2 = limit->p2.p2_fast;
- else
- clock.p2 = limit->p2.p2_slow;
- } else {
- if (target < limit->p2.dot_limit)
- clock.p2 = limit->p2.p2_slow;
- else
- clock.p2 = limit->p2.p2_fast;
- }
-
- memset(best_clock, 0, sizeof(*best_clock));
-
- for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
- clock.m1++) {
- for (clock.m2 = limit->m2.min;
- clock.m2 < clock.m1 && clock.m2 <= limit->m2.max;
- clock.m2++) {
- 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++) {
- int this_err;
-
- psb_intel_clock(refclk, &clock);
-
- if (!psb_intel_PLL_is_valid
- (crtc, &clock))
- continue;
-
- this_err = abs(clock.dot - target);
- if (this_err < err) {
- *best_clock = clock;
- err = this_err;
- }
- }
- }
- }
- }
-
- return err != target;
-}
-
-void psb_intel_wait_for_vblank(struct drm_device *dev)
-{
- /* Wait for 20ms, i.e. one cycle at 50hz. */
- mdelay(20);
-}
-
-static int psb_intel_pipe_set_base(struct drm_crtc *crtc,
- 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 psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
- int pipe = psb_intel_crtc->pipe;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- unsigned long start, offset;
- u32 dspcntr;
- int ret = 0;
-
- if (!gma_power_begin(dev, true))
- return 0;
-
- /* no fb bound */
- if (!crtc->fb) {
- dev_dbg(dev->dev, "No FB bound\n");
- goto psb_intel_pipe_cleaner;
- }
-
- /* We are displaying this buffer, make sure it is actually loaded
- into the GTT */
- ret = psb_gtt_pin(psbfb->gtt);
- if (ret < 0)
- goto psb_intel_pipe_set_base_exit;
- start = psbfb->gtt->offset;
-
- offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
-
- REG_WRITE(map->stride, crtc->fb->pitches[0]);
-
- dspcntr = REG_READ(map->cntr);
- dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
-
- switch (crtc->fb->bits_per_pixel) {
- case 8:
- dspcntr |= DISPPLANE_8BPP;
- break;
- case 16:
- if (crtc->fb->depth == 15)
- dspcntr |= DISPPLANE_15_16BPP;
- else
- dspcntr |= DISPPLANE_16BPP;
- break;
- case 24:
- case 32:
- dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
- break;
- default:
- dev_err(dev->dev, "Unknown color depth\n");
- ret = -EINVAL;
- psb_gtt_unpin(psbfb->gtt);
- goto psb_intel_pipe_set_base_exit;
- }
- REG_WRITE(map->cntr, dspcntr);
-
- REG_WRITE(map->base, start + offset);
- REG_READ(map->base);
-
-psb_intel_pipe_cleaner:
- /* If there was a previous display we can now unpin it */
- if (old_fb)
- psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
-
-psb_intel_pipe_set_base_exit:
- gma_power_end(dev);
- return ret;
-}
-
-/**
- * Sets the power management mode of the pipe and plane.
- *
- * This code should probably grow support for turning the cursor off and back
- * on appropriately at the same time as we're turning the pipe off/on.
- */
-static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- const struct psb_offset *map = &dev_priv->regmap[pipe];
- u32 temp;
-
- /* XXX: When our outputs are all unaware of DPMS modes other than off
- * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
- */
- switch (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));
- }
-
- psb_intel_crtc_load_lut(crtc);
-
- /* Give the overlay scaler a chance to enable
- * if it's on this pipe */
- /* psb_intel_crtc_dpms_video(crtc, true); TODO */
- break;
- case DRM_MODE_DPMS_OFF:
- /* Give the overlay scaler a chance to disable
- * 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);
- }
-
- /* 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 vblank for the disable to take effect. */
- psb_intel_wait_for_vblank(dev);
-
- 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);
- break;
- }
-
- /*Set FIFO Watermarks*/
- REG_WRITE(DSPARB, 0x3F3E);
-}
-
-static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void psb_intel_crtc_commit(struct drm_crtc *crtc)
-{
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-void psb_intel_encoder_prepare(struct drm_encoder *encoder)
-{
- struct drm_encoder_helper_funcs *encoder_funcs =
- encoder->helper_private;
- /* lvds has its own version of prepare see psb_intel_lvds_prepare */
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-
-void psb_intel_encoder_commit(struct drm_encoder *encoder)
-{
- struct drm_encoder_helper_funcs *encoder_funcs =
- encoder->helper_private;
- /* lvds has its own version of commit see psb_intel_lvds_commit */
- encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
-}
-
-void psb_intel_encoder_destroy(struct drm_encoder *encoder)
-{
- struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
-
- drm_encoder_cleanup(encoder);
- kfree(intel_encoder);
-}
-
-static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-
-/**
+/*
* Return the pipe currently connected to the panel fitter,
* or -1 if the panel fitter is not present or not in use
*/
@@ -478,34 +98,35 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
struct drm_framebuffer *old_fb)
{
struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
- int pipe = psb_intel_crtc->pipe;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ int pipe = gma_crtc->pipe;
const struct psb_offset *map = &dev_priv->regmap[pipe];
int refclk;
- struct psb_intel_clock_t clock;
+ struct gma_clock_t clock;
u32 dpll = 0, fp = 0, dspcntr, pipeconf;
bool ok, is_sdvo = false;
bool is_lvds = false, is_tv = false;
- struct drm_mode_config *mode_config = &dev->mode_config;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
+ const struct gma_limit_t *limit;
/* No scan out no play */
- if (crtc->fb == NULL) {
+ if (crtc->primary->fb == NULL) {
crtc_funcs->mode_set_base(crtc, x, y, old_fb);
return 0;
}
- list_for_each_entry(connector, &mode_config->connector_list, head) {
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
if (!connector->encoder
|| connector->encoder->crtc != crtc)
continue;
- switch (psb_intel_encoder->type) {
+ switch (gma_encoder->type) {
case INTEL_OUTPUT_LVDS:
is_lvds = true;
break;
@@ -516,14 +137,20 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
is_tv = true;
break;
}
+
+ break;
}
+ drm_connector_list_iter_end(&conn_iter);
refclk = 96000;
- ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
+ limit = gma_crtc->clock_funcs->limit(crtc, refclk);
+
+ ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk,
&clock);
if (!ok) {
- dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
+ DRM_ERROR("Couldn't find PLL settings for mode! target: %d, actual: %d",
+ adjusted_mode->clock, clock.dot);
return 0;
}
@@ -661,368 +288,29 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
REG_WRITE(map->conf, pipeconf);
REG_READ(map->conf);
- psb_intel_wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
REG_WRITE(map->cntr, dspcntr);
/* Flush the plane changes */
crtc_funcs->mode_set_base(crtc, x, y, old_fb);
- psb_intel_wait_for_vblank(dev);
-
- return 0;
-}
-
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
- int palreg = map->palette;
- int i;
-
- /* The clocks have to be on to load the palette. */
- if (!crtc->enabled)
- return;
-
- switch (psb_intel_crtc->pipe) {
- case 0:
- case 1:
- break;
- default:
- dev_err(dev->dev, "Illegal Pipe Number.\n");
- return;
- }
-
- if (gma_power_begin(dev, false)) {
- for (i = 0; i < 256; i++) {
- REG_WRITE(palreg + 4 * i,
- ((psb_intel_crtc->lut_r[i] +
- psb_intel_crtc->lut_adj[i]) << 16) |
- ((psb_intel_crtc->lut_g[i] +
- psb_intel_crtc->lut_adj[i]) << 8) |
- (psb_intel_crtc->lut_b[i] +
- psb_intel_crtc->lut_adj[i]));
- }
- gma_power_end(dev);
- } else {
- for (i = 0; i < 256; i++) {
- dev_priv->regs.pipe[0].palette[i] =
- ((psb_intel_crtc->lut_r[i] +
- psb_intel_crtc->lut_adj[i]) << 16) |
- ((psb_intel_crtc->lut_g[i] +
- psb_intel_crtc->lut_adj[i]) << 8) |
- (psb_intel_crtc->lut_b[i] +
- psb_intel_crtc->lut_adj[i]);
- }
-
- }
-}
-
-/**
- * Save HW states of giving crtc
- */
-static void psb_intel_crtc_save(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
- const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
- uint32_t paletteReg;
- int i;
-
- if (!crtc_state) {
- dev_err(dev->dev, "No CRTC state found\n");
- return;
- }
-
- crtc_state->saveDSPCNTR = REG_READ(map->cntr);
- crtc_state->savePIPECONF = REG_READ(map->conf);
- crtc_state->savePIPESRC = REG_READ(map->src);
- crtc_state->saveFP0 = REG_READ(map->fp0);
- crtc_state->saveFP1 = REG_READ(map->fp1);
- crtc_state->saveDPLL = REG_READ(map->dpll);
- crtc_state->saveHTOTAL = REG_READ(map->htotal);
- crtc_state->saveHBLANK = REG_READ(map->hblank);
- crtc_state->saveHSYNC = REG_READ(map->hsync);
- crtc_state->saveVTOTAL = REG_READ(map->vtotal);
- crtc_state->saveVBLANK = REG_READ(map->vblank);
- crtc_state->saveVSYNC = REG_READ(map->vsync);
- crtc_state->saveDSPSTRIDE = REG_READ(map->stride);
-
- /*NOTE: DSPSIZE DSPPOS only for psb*/
- crtc_state->saveDSPSIZE = REG_READ(map->size);
- crtc_state->saveDSPPOS = REG_READ(map->pos);
-
- crtc_state->saveDSPBASE = REG_READ(map->base);
-
- paletteReg = map->palette;
- for (i = 0; i < 256; ++i)
- crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
-}
-
-/**
- * Restore HW states of giving crtc
- */
-static void psb_intel_crtc_restore(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
- const struct psb_offset *map = &dev_priv->regmap[psb_intel_crtc->pipe];
- uint32_t paletteReg;
- int i;
-
- if (!crtc_state) {
- dev_err(dev->dev, "No crtc state\n");
- return;
- }
-
- if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
- REG_WRITE(map->dpll,
- crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
- REG_READ(map->dpll);
- udelay(150);
- }
-
- REG_WRITE(map->fp0, crtc_state->saveFP0);
- REG_READ(map->fp0);
-
- REG_WRITE(map->fp1, crtc_state->saveFP1);
- REG_READ(map->fp1);
-
- REG_WRITE(map->dpll, crtc_state->saveDPLL);
- REG_READ(map->dpll);
- udelay(150);
-
- REG_WRITE(map->htotal, crtc_state->saveHTOTAL);
- REG_WRITE(map->hblank, crtc_state->saveHBLANK);
- REG_WRITE(map->hsync, crtc_state->saveHSYNC);
- REG_WRITE(map->vtotal, crtc_state->saveVTOTAL);
- REG_WRITE(map->vblank, crtc_state->saveVBLANK);
- REG_WRITE(map->vsync, crtc_state->saveVSYNC);
- REG_WRITE(map->stride, crtc_state->saveDSPSTRIDE);
-
- REG_WRITE(map->size, crtc_state->saveDSPSIZE);
- REG_WRITE(map->pos, crtc_state->saveDSPPOS);
-
- REG_WRITE(map->src, crtc_state->savePIPESRC);
- REG_WRITE(map->base, crtc_state->saveDSPBASE);
- REG_WRITE(map->conf, crtc_state->savePIPECONF);
-
- psb_intel_wait_for_vblank(dev);
-
- REG_WRITE(map->cntr, crtc_state->saveDSPCNTR);
- REG_WRITE(map->base, crtc_state->saveDSPBASE);
-
- psb_intel_wait_for_vblank(dev);
-
- paletteReg = map->palette;
- for (i = 0; i < 256; ++i)
- REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
-}
-
-static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
- struct drm_file *file_priv,
- uint32_t handle,
- uint32_t width, uint32_t height)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
- uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
- uint32_t temp;
- size_t addr = 0;
- struct gtt_range *gt;
- struct gtt_range *cursor_gt = psb_intel_crtc->cursor_gt;
- struct drm_gem_object *obj;
- void *tmp_dst, *tmp_src;
- int ret = 0, i, cursor_pages;
-
- /* if we want to turn of the cursor ignore width and height */
- if (!handle) {
- /* turn off the cursor */
- temp = CURSOR_MODE_DISABLE;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, 0);
- gma_power_end(dev);
- }
-
- /* 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 = NULL;
- }
-
- return 0;
- }
-
- /* Currently we only support 64x64 cursors */
- if (width != 64 || height != 64) {
- dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
- return -EINVAL;
- }
-
- obj = drm_gem_object_lookup(dev, file_priv, handle);
- if (!obj)
- return -ENOENT;
-
- if (obj->size < width * height * 4) {
- dev_dbg(dev->dev, "buffer is to small\n");
- ret = -ENOMEM;
- goto unref_cursor;
- }
-
- gt = container_of(obj, struct gtt_range, gem);
-
- /* Pin the memory into the GTT */
- ret = psb_gtt_pin(gt);
- if (ret) {
- dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
- goto unref_cursor;
- }
-
- if (dev_priv->ops->cursor_needs_phys) {
- if (cursor_gt == NULL) {
- dev_err(dev->dev, "No hardware cursor mem available");
- ret = -ENOMEM;
- goto unref_cursor;
- }
-
- /* Prevent overflow */
- if (gt->npage > 4)
- cursor_pages = 4;
- else
- cursor_pages = gt->npage;
-
- /* Copy the cursor to cursor mem */
- tmp_dst = dev_priv->vram_addr + cursor_gt->offset;
- for (i = 0; i < cursor_pages; i++) {
- tmp_src = kmap(gt->pages[i]);
- memcpy(tmp_dst, tmp_src, PAGE_SIZE);
- kunmap(gt->pages[i]);
- tmp_dst += PAGE_SIZE;
- }
-
- addr = psb_intel_crtc->cursor_addr;
- } else {
- addr = gt->offset; /* Or resource.start ??? */
- psb_intel_crtc->cursor_addr = addr;
- }
-
- temp = 0;
- /* set the pipe for the cursor */
- temp |= (pipe << 28);
- temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE(control, temp);
- REG_WRITE(base, addr);
- gma_power_end(dev);
- }
+ gma_wait_for_vblank(dev);
- /* unpin the old bo */
- 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;
- return ret;
-
-unref_cursor:
- drm_gem_object_unreference(obj);
- return ret;
-}
-
-static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
- struct drm_device *dev = crtc->dev;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
- uint32_t temp = 0;
- uint32_t addr;
-
-
- if (x < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
- x = -x;
- }
- if (y < 0) {
- temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
- y = -y;
- }
-
- temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
- temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
-
- addr = psb_intel_crtc->cursor_addr;
-
- if (gma_power_begin(dev, false)) {
- REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
- REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr);
- gma_power_end(dev);
- }
return 0;
}
-static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
- u16 *green, u16 *blue, uint32_t type, uint32_t size)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int i;
-
- if (size != 256)
- return;
-
- for (i = 0; i < 256; i++) {
- psb_intel_crtc->lut_r[i] = red[i] >> 8;
- psb_intel_crtc->lut_g[i] = green[i] >> 8;
- psb_intel_crtc->lut_b[i] = blue[i] >> 8;
- }
-
- psb_intel_crtc_load_lut(crtc);
-}
-
-static int psb_crtc_set_config(struct drm_mode_set *set)
-{
- int ret;
- struct drm_device *dev = set->crtc->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (!dev_priv->rpm_enabled)
- return drm_crtc_helper_set_config(set);
-
- pm_runtime_forbid(&dev->pdev->dev);
- ret = drm_crtc_helper_set_config(set);
- pm_runtime_allow(&dev->pdev->dev);
- return ret;
-}
-
/* Returns the clock of the currently programmed mode of the given pipe. */
static int psb_intel_crtc_clock_get(struct drm_device *dev,
struct drm_crtc *crtc)
{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct drm_psb_private *dev_priv = dev->dev_private;
- int pipe = psb_intel_crtc->pipe;
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ int pipe = gma_crtc->pipe;
const struct psb_offset *map = &dev_priv->regmap[pipe];
u32 dpll;
u32 fp;
- struct psb_intel_clock_t clock;
+ struct gma_clock_t clock;
bool is_lvds;
struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
@@ -1092,14 +380,14 @@ static int psb_intel_crtc_clock_get(struct drm_device *dev,
struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
struct drm_crtc *crtc)
{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- int pipe = psb_intel_crtc->pipe;
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ int pipe = gma_crtc->pipe;
struct drm_display_mode *mode;
int htot;
int hsync;
int vtot;
int vsync;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_pipe *p = &dev_priv->regs.pipe[pipe];
const struct psb_offset *map = &dev_priv->regmap[pipe];
@@ -1136,58 +424,19 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
return mode;
}
-static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
-{
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- struct gtt_range *gt;
-
- /* 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 = NULL;
- }
-
- if (psb_intel_crtc->cursor_gt != NULL)
- psb_gtt_free_range(crtc->dev, psb_intel_crtc->cursor_gt);
- kfree(psb_intel_crtc->crtc_state);
- drm_crtc_cleanup(crtc);
- kfree(psb_intel_crtc);
-}
-
-static void psb_intel_crtc_disable(struct drm_crtc *crtc)
-{
- struct gtt_range *gt;
- struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-
- crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-
- if (crtc->fb) {
- gt = to_psb_fb(crtc->fb)->gtt;
- psb_gtt_unpin(gt);
- }
-}
-
const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
- .dpms = psb_intel_crtc_dpms,
- .mode_fixup = psb_intel_crtc_mode_fixup,
+ .dpms = gma_crtc_dpms,
.mode_set = psb_intel_crtc_mode_set,
- .mode_set_base = psb_intel_pipe_set_base,
- .prepare = psb_intel_crtc_prepare,
- .commit = psb_intel_crtc_commit,
- .disable = psb_intel_crtc_disable,
+ .mode_set_base = gma_pipe_set_base,
+ .prepare = gma_crtc_prepare,
+ .commit = gma_crtc_commit,
+ .disable = gma_crtc_disable,
};
-const struct drm_crtc_funcs psb_intel_crtc_funcs = {
- .save = psb_intel_crtc_save,
- .restore = psb_intel_crtc_restore,
- .cursor_set = psb_intel_crtc_cursor_set,
- .cursor_move = psb_intel_crtc_cursor_move,
- .gamma_set = psb_intel_crtc_gamma_set,
- .set_config = psb_crtc_set_config,
- .destroy = psb_intel_crtc_destroy,
+const struct gma_clock_funcs psb_clock_funcs = {
+ .clock = psb_intel_clock,
+ .limit = psb_intel_limit,
+ .pll_is_valid = gma_pll_is_valid,
};
/*
@@ -1195,174 +444,116 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = {
* to zero. This is a workaround for h/w defect on Oaktrail
*/
static void psb_intel_cursor_init(struct drm_device *dev,
- struct psb_intel_crtc *psb_intel_crtc)
+ struct gma_crtc *gma_crtc)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR };
u32 base[3] = { CURABASE, CURBBASE, CURCBASE };
- struct gtt_range *cursor_gt;
+ struct psb_gem_object *cursor_pobj;
if (dev_priv->ops->cursor_needs_phys) {
/* Allocate 4 pages of stolen mem for a hardware cursor. That
* is enough for the 64 x 64 ARGB cursors we support.
*/
- cursor_gt = psb_gtt_alloc_range(dev, 4 * PAGE_SIZE, "cursor", 1);
- if (!cursor_gt) {
- psb_intel_crtc->cursor_gt = NULL;
+ cursor_pobj = psb_gem_create(dev, 4 * PAGE_SIZE, "cursor", true, PAGE_SIZE);
+ if (IS_ERR(cursor_pobj)) {
+ gma_crtc->cursor_pobj = NULL;
goto out;
}
- psb_intel_crtc->cursor_gt = cursor_gt;
- psb_intel_crtc->cursor_addr = dev_priv->stolen_base +
- cursor_gt->offset;
+ gma_crtc->cursor_pobj = cursor_pobj;
+ gma_crtc->cursor_addr = dev_priv->stolen_base + cursor_pobj->offset;
} else {
- psb_intel_crtc->cursor_gt = NULL;
+ gma_crtc->cursor_pobj = NULL;
}
out:
- REG_WRITE(control[psb_intel_crtc->pipe], 0);
- REG_WRITE(base[psb_intel_crtc->pipe], 0);
+ REG_WRITE(control[gma_crtc->pipe], 0);
+ REG_WRITE(base[gma_crtc->pipe], 0);
}
void psb_intel_crtc_init(struct drm_device *dev, int pipe,
struct psb_intel_mode_device *mode_dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_crtc *psb_intel_crtc;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_crtc *gma_crtc;
int i;
- uint16_t *r_base, *g_base, *b_base;
/* We allocate a extra array of drm_connector pointers
* for fbdev after the crtc */
- psb_intel_crtc =
- kzalloc(sizeof(struct psb_intel_crtc) +
- (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
- GFP_KERNEL);
- if (psb_intel_crtc == NULL)
+ gma_crtc = kzalloc(sizeof(struct gma_crtc) +
+ (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
+ GFP_KERNEL);
+ if (gma_crtc == NULL)
return;
- psb_intel_crtc->crtc_state =
+ gma_crtc->crtc_state =
kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
- if (!psb_intel_crtc->crtc_state) {
+ if (!gma_crtc->crtc_state) {
dev_err(dev->dev, "Crtc state error: No memory\n");
- kfree(psb_intel_crtc);
+ kfree(gma_crtc);
return;
}
- /* Set the CRTC operations from the chip specific data */
- drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs);
-
- drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
- psb_intel_crtc->pipe = pipe;
- psb_intel_crtc->plane = pipe;
-
- r_base = psb_intel_crtc->base.gamma_store;
- g_base = r_base + 256;
- b_base = g_base + 256;
- for (i = 0; i < 256; i++) {
- psb_intel_crtc->lut_r[i] = i;
- psb_intel_crtc->lut_g[i] = i;
- psb_intel_crtc->lut_b[i] = i;
- r_base[i] = i << 8;
- g_base[i] = i << 8;
- b_base[i] = i << 8;
-
- psb_intel_crtc->lut_adj[i] = 0;
- }
+ drm_crtc_init(dev, &gma_crtc->base, &gma_crtc_funcs);
- psb_intel_crtc->mode_dev = mode_dev;
- psb_intel_crtc->cursor_addr = 0;
+ /* Set the CRTC clock functions from chip specific data */
+ gma_crtc->clock_funcs = dev_priv->ops->clock_funcs;
- drm_crtc_helper_add(&psb_intel_crtc->base,
+ drm_mode_crtc_set_gamma_size(&gma_crtc->base, 256);
+ gma_crtc->pipe = pipe;
+ gma_crtc->plane = pipe;
+
+ for (i = 0; i < 256; i++)
+ gma_crtc->lut_adj[i] = 0;
+
+ gma_crtc->mode_dev = mode_dev;
+ gma_crtc->cursor_addr = 0;
+
+ drm_crtc_helper_add(&gma_crtc->base,
dev_priv->ops->crtc_helper);
/* Setup the array of drm_connector pointer array */
- psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;
+ gma_crtc->mode_set.crtc = &gma_crtc->base;
BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
- dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL);
- dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] =
- &psb_intel_crtc->base;
- dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] =
- &psb_intel_crtc->base;
- psb_intel_crtc->mode_set.connectors =
- (struct drm_connector **) (psb_intel_crtc + 1);
- psb_intel_crtc->mode_set.num_connectors = 0;
- psb_intel_cursor_init(dev, psb_intel_crtc);
+ dev_priv->plane_to_crtc_mapping[gma_crtc->plane] != NULL);
+ dev_priv->plane_to_crtc_mapping[gma_crtc->plane] = &gma_crtc->base;
+ dev_priv->pipe_to_crtc_mapping[gma_crtc->pipe] = &gma_crtc->base;
+ gma_crtc->mode_set.connectors = (struct drm_connector **)(gma_crtc + 1);
+ gma_crtc->mode_set.num_connectors = 0;
+ psb_intel_cursor_init(dev, gma_crtc);
/* Set to true so that the pipe is forced off on initial config. */
- psb_intel_crtc->active = true;
-}
-
-int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data;
- struct drm_mode_object *drmmode_obj;
- struct psb_intel_crtc *crtc;
-
- if (!dev_priv) {
- dev_err(dev->dev, "called with no initialization\n");
- return -EINVAL;
- }
-
- drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
- DRM_MODE_OBJECT_CRTC);
-
- if (!drmmode_obj) {
- dev_err(dev->dev, "no such CRTC id\n");
- return -EINVAL;
- }
-
- crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj));
- pipe_from_crtc_id->pipe = crtc->pipe;
-
- return 0;
+ gma_crtc->active = true;
}
struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
{
- struct drm_crtc *crtc = NULL;
+ struct drm_crtc *crtc;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
- if (psb_intel_crtc->pipe == pipe)
- break;
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+
+ if (gma_crtc->pipe == pipe)
+ return crtc;
}
- return crtc;
+ return NULL;
}
-int psb_intel_connector_clones(struct drm_device *dev, int type_mask)
+int gma_connector_clones(struct drm_device *dev, int type_mask)
{
- int index_mask = 0;
+ struct drm_connector_list_iter conn_iter;
struct drm_connector *connector;
+ int index_mask = 0;
int entry = 0;
- list_for_each_entry(connector, &dev->mode_config.connector_list,
- head) {
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- if (type_mask & (1 << psb_intel_encoder->type))
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
+ if (type_mask & (1 << gma_encoder->type))
index_mask |= (1 << entry);
entry++;
}
- return index_mask;
-}
-
-/* current intel driver doesn't take advantage of encoders
- always give back the encoder for the connector
-*/
-struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector)
-{
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ drm_connector_list_iter_end(&conn_iter);
- return &psb_intel_encoder->base;
-}
-
-void psb_intel_connector_attach_encoder(struct psb_intel_connector *connector,
- struct psb_intel_encoder *encoder)
-{
- connector->encoder = encoder;
- drm_mode_connector_attach_encoder(&connector->base,
- &encoder->base);
+ return index_mask;
}
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.h b/drivers/gpu/drm/gma500/psb_intel_display.h
deleted file mode 100644
index 3724b971e91c..000000000000
--- a/drivers/gpu/drm/gma500/psb_intel_display.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* copyright (c) 2008, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- */
-
-#ifndef _INTEL_DISPLAY_H_
-#define _INTEL_DISPLAY_H_
-
-bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
-
-#endif
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
index 4dcae421a58d..979ea8ecf0d5 100644
--- a/drivers/gpu/drm/gma500/psb_intel_drv.h
+++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
@@ -1,19 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2009-2011, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#ifndef __INTEL_DRV_H__
@@ -22,8 +9,10 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <linux/gpio.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_vblank.h>
+#include "gma_display.h"
/*
* Display related stuff
@@ -65,25 +54,6 @@
#define INTEL_OUTPUT_DISPLAYPORT 9
#define INTEL_OUTPUT_EDP 10
-#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
-#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
-
-static inline void
-psb_intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
- int multiplier)
-{
- mode->clock *= multiplier;
- mode->private_flags |= multiplier;
-}
-
-static inline int
-psb_intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode)
-{
- return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK)
- >> INTEL_MODE_PIXEL_MULTIPLIER_SHIFT;
-}
-
-
/*
* Hold information useally put on the device driver privates here,
* since it needs to be shared across multiple of devices drivers privates.
@@ -107,20 +77,21 @@ struct psb_intel_mode_device {
uint32_t saveBLC_PWM_CTL;
};
-struct psb_intel_i2c_chan {
+struct gma_i2c_chan {
+ struct i2c_adapter base;
+ struct i2c_algo_bit_data algo;
+ u8 target_addr;
+
/* for getting at dev. private (mmio etc.) */
struct drm_device *drm_dev;
- u32 reg; /* GPIO reg */
- struct i2c_adapter adapter;
- struct i2c_algo_bit_data algo;
- u8 slave_addr;
+ u32 reg; /* GPIO reg */
};
-struct psb_intel_encoder {
+struct gma_encoder {
struct drm_encoder base;
int type;
bool needs_tv_clock;
- void (*hot_plug)(struct psb_intel_encoder *);
+ void (*hot_plug)(struct gma_encoder *);
int crtc_mask;
int clone_mask;
u32 ddi_select; /* Channel info */
@@ -132,13 +103,15 @@ struct psb_intel_encoder {
/* FIXME: Either make SDVO and LVDS store it's i2c here or give CDV it's
own set of output privates */
- struct psb_intel_i2c_chan *i2c_bus;
- struct psb_intel_i2c_chan *ddc_bus;
+ struct gma_i2c_chan *i2c_bus;
};
-struct psb_intel_connector {
+struct gma_connector {
struct drm_connector base;
- struct psb_intel_encoder *encoder;
+ struct gma_encoder *encoder;
+
+ void (*save)(struct drm_connector *connector);
+ void (*restore)(struct drm_connector *connector);
};
struct psb_intel_crtc_state {
@@ -161,13 +134,12 @@ struct psb_intel_crtc_state {
uint32_t savePalette[256];
};
-struct psb_intel_crtc {
+struct gma_crtc {
struct drm_crtc base;
int pipe;
int plane;
uint32_t cursor_addr;
- struct gtt_range *cursor_gt;
- u8 lut_r[256], lut_g[256], lut_b[256];
+ struct psb_gem_object *cursor_pobj;
u8 lut_adj[256];
struct psb_intel_framebuffer *fbdev_fb;
/* a mode_set for fbdev users on this crtc */
@@ -188,89 +160,62 @@ struct psb_intel_crtc {
/* Saved Crtc HW states */
struct psb_intel_crtc_state *crtc_state;
+
+ const struct gma_clock_funcs *clock_funcs;
+
+ struct drm_pending_vblank_event *page_flip_event;
};
-#define to_psb_intel_crtc(x) \
- container_of(x, struct psb_intel_crtc, base)
-#define to_psb_intel_connector(x) \
- container_of(x, struct psb_intel_connector, base)
-#define to_psb_intel_encoder(x) \
- container_of(x, struct psb_intel_encoder, base)
+#define to_gma_crtc(x) \
+ container_of(x, struct gma_crtc, base)
+#define to_gma_connector(x) \
+ container_of(x, struct gma_connector, base)
+#define to_gma_encoder(x) \
+ container_of(x, struct gma_encoder, base)
#define to_psb_intel_framebuffer(x) \
container_of(x, struct psb_intel_framebuffer, base)
+#define to_gma_i2c_chan(x) \
+ container_of(x, struct gma_i2c_chan, base)
-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
- const u32 reg, const char *name);
-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan);
+struct gma_i2c_chan *gma_i2c_create(struct drm_device *dev, const u32 reg,
+ const char *name);
+void gma_i2c_destroy(struct gma_i2c_chan *chan);
int psb_intel_ddc_get_modes(struct drm_connector *connector,
struct i2c_adapter *adapter);
-extern bool psb_intel_ddc_probe(struct i2c_adapter *adapter);
extern void psb_intel_crtc_init(struct drm_device *dev, int pipe,
struct psb_intel_mode_device *mode_dev);
-extern void psb_intel_crt_init(struct drm_device *dev);
extern bool psb_intel_sdvo_init(struct drm_device *dev, int output_device);
-extern void psb_intel_dvo_init(struct drm_device *dev);
-extern void psb_intel_tv_init(struct drm_device *dev);
extern void psb_intel_lvds_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev);
extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level);
extern void oaktrail_lvds_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev);
-extern void oaktrail_wait_for_INTR_PKT_SENT(struct drm_device *dev);
-extern void oaktrail_dsi_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev);
-extern void mid_dsi_init(struct drm_device *dev,
- struct psb_intel_mode_device *mode_dev, int dsi_num);
+struct gma_i2c_chan *oaktrail_lvds_i2c_init(struct drm_device *dev);
-extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc);
-extern void psb_intel_encoder_prepare(struct drm_encoder *encoder);
-extern void psb_intel_encoder_commit(struct drm_encoder *encoder);
-extern void psb_intel_encoder_destroy(struct drm_encoder *encoder);
+extern struct drm_encoder *gma_best_encoder(struct drm_connector *connector);
+extern void gma_connector_attach_encoder(struct gma_connector *connector,
+ struct gma_encoder *encoder);
-static inline struct psb_intel_encoder *psb_intel_attached_encoder(
+static inline struct gma_encoder *gma_attached_encoder(
struct drm_connector *connector)
{
- return to_psb_intel_connector(connector)->encoder;
+ return to_gma_connector(connector)->encoder;
}
-extern void psb_intel_connector_attach_encoder(
- struct psb_intel_connector *connector,
- struct psb_intel_encoder *encoder);
-
-extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector
- *connector);
-
extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
struct drm_crtc *crtc);
-extern void psb_intel_wait_for_vblank(struct drm_device *dev);
-extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev,
int pipe);
-extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev,
- int sdvoB);
-extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector);
-extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector,
- int enable);
-extern int intelfb_probe(struct drm_device *dev);
-extern int intelfb_remove(struct drm_device *dev,
- struct drm_framebuffer *fb);
-extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device
- *dev, struct
- drm_mode_fb_cmd
- *mode_cmd,
- void *mm_private);
extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
-extern int psb_intel_lvds_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode);
+extern enum drm_mode_status psb_intel_lvds_mode_valid(struct drm_connector *connector,
+ const struct drm_display_mode *mode);
extern int psb_intel_lvds_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t value);
extern void psb_intel_lvds_destroy(struct drm_connector *connector);
-extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
/* intel_gmbus.c */
extern void gma_intel_i2c_reset(struct drm_device *dev);
@@ -285,9 +230,6 @@ extern void cdv_intel_dp_set_m_n(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
-extern void psb_intel_attach_force_audio_property(struct drm_connector *connector);
-extern void psb_intel_attach_broadcast_rgb_property(struct drm_connector *connector);
-
extern int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val);
extern int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val);
extern void cdv_sb_reset(struct drm_device *dev);
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index 9fa5fa2e6192..f8f3c42e67a7 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright © 2006-2007 Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Eric Anholt <eric@anholt.net>
* Dave Airlie <airlied@linux.ie>
@@ -21,14 +9,18 @@
*/
#include <linux/i2c.h>
-#include <drm/drmP.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+#include <drm/drm_simple_kms_helper.h>
#include "intel_bios.h"
+#include "power.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
-#include "power.h"
-#include <linux/pm_runtime.h>
/*
* LVDS I2C backlight control macros
@@ -60,8 +52,7 @@ struct psb_intel_lvds_priv {
uint32_t savePFIT_PGM_RATIOS;
uint32_t saveBLC_PWM_CTL;
- struct psb_intel_i2c_chan *i2c_bus;
- struct psb_intel_i2c_chan *ddc_bus;
+ struct gma_i2c_chan *i2c_bus;
};
@@ -70,7 +61,7 @@ struct psb_intel_lvds_priv {
*/
static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 ret;
if (gma_power_begin(dev, false)) {
@@ -99,16 +90,15 @@ static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
unsigned int level)
{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
- struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
+ struct gma_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
u8 out_buf[2];
unsigned int blc_i2c_brightness;
struct i2c_msg msgs[] = {
{
- .addr = lvds_i2c_bus->slave_addr,
+ .addr = lvds_i2c_bus->target_addr,
.flags = 0,
.len = 2,
.buf = out_buf,
@@ -125,7 +115,7 @@ static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
out_buf[1] = (u8)blc_i2c_brightness;
- if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) {
+ if (i2c_transfer(&lvds_i2c_bus->base, msgs, 1) == 1) {
dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n",
dev_priv->lvds_bl->brightnesscmd,
blc_i2c_brightness);
@@ -139,8 +129,7 @@ static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 max_pwm_blc;
u32 blc_pwm_duty_cycle;
@@ -172,7 +161,7 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
*/
void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
dev_dbg(dev->dev, "backlight level is %d\n", level);
@@ -194,7 +183,7 @@ void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
*/
static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 blc_pwm_ctl;
if (gma_power_begin(dev, false)) {
@@ -219,7 +208,7 @@ static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
*/
static void psb_intel_lvds_set_power(struct drm_device *dev, bool on)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
u32 pp_status;
@@ -227,7 +216,7 @@ static void psb_intel_lvds_set_power(struct drm_device *dev, bool on)
dev_err(dev->dev, "set power, chip off!\n");
return;
}
-
+
if (on) {
REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
POWER_TARGET_ON);
@@ -265,12 +254,10 @@ static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
static void psb_intel_lvds_save(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *)dev->dev_private;
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
struct psb_intel_lvds_priv *lvds_priv =
- (struct psb_intel_lvds_priv *)psb_intel_encoder->dev_priv;
+ (struct psb_intel_lvds_priv *)gma_encoder->dev_priv;
lvds_priv->savePP_ON = REG_READ(LVDSPP_ON);
lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF);
@@ -307,10 +294,9 @@ static void psb_intel_lvds_restore(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
u32 pp_status;
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
struct psb_intel_lvds_priv *lvds_priv =
- (struct psb_intel_lvds_priv *)psb_intel_encoder->dev_priv;
+ (struct psb_intel_lvds_priv *)gma_encoder->dev_priv;
dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
lvds_priv->savePP_ON,
@@ -345,16 +331,15 @@ static void psb_intel_lvds_restore(struct drm_connector *connector)
}
}
-int psb_intel_lvds_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+enum drm_mode_status psb_intel_lvds_mode_valid(struct drm_connector *connector,
+ const struct drm_display_mode *mode)
{
- struct drm_psb_private *dev_priv = connector->dev->dev_private;
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
+ struct drm_psb_private *dev_priv = to_drm_psb_private(connector->dev);
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
struct drm_display_mode *fixed_mode =
dev_priv->mode_dev.panel_fixed_mode;
- if (psb_intel_encoder->type == INTEL_OUTPUT_MIPI2)
+ if (gma_encoder->type == INTEL_OUTPUT_MIPI2)
fixed_mode = dev_priv->mode_dev.panel_fixed_mode2;
/* just in case */
@@ -379,25 +364,23 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
- struct psb_intel_crtc *psb_intel_crtc =
- to_psb_intel_crtc(encoder->crtc);
+ struct gma_crtc *gma_crtc = to_gma_crtc(encoder->crtc);
struct drm_encoder *tmp_encoder;
struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
- struct psb_intel_encoder *psb_intel_encoder =
- to_psb_intel_encoder(encoder);
+ struct gma_encoder *gma_encoder = to_gma_encoder(encoder);
- if (psb_intel_encoder->type == INTEL_OUTPUT_MIPI2)
+ if (gma_encoder->type == INTEL_OUTPUT_MIPI2)
panel_fixed_mode = mode_dev->panel_fixed_mode2;
/* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */
- if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) {
- printk(KERN_ERR "Can't support LVDS on pipe A\n");
+ if (!IS_MRST(dev) && gma_crtc->pipe == 0) {
+ pr_err("Can't support LVDS on pipe A\n");
return false;
}
- if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) {
- printk(KERN_ERR "Must use PIPE A\n");
+ if (IS_MRST(dev) && gma_crtc->pipe != 0) {
+ pr_err("Must use PIPE A\n");
return false;
}
/* Should never happen!! */
@@ -405,8 +388,7 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
head) {
if (tmp_encoder != encoder
&& tmp_encoder->crtc == encoder->crtc) {
- printk(KERN_ERR "Can't enable LVDS and another "
- "encoder on the same pipe\n");
+ pr_err("Can't enable LVDS and another encoder on the same pipe\n");
return false;
}
}
@@ -443,7 +425,7 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
if (!gma_power_begin(dev, true))
@@ -461,7 +443,7 @@ static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
static void psb_intel_lvds_commit(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
if (mode_dev->backlight_duty_cycle == 0)
@@ -476,7 +458,7 @@ static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
u32 pfit_control;
/*
@@ -505,49 +487,27 @@ static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
}
/*
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector
- *connector, bool force)
-{
- return connector_status_connected;
-}
-
-/*
* Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
*/
static int psb_intel_lvds_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- struct psb_intel_lvds_priv *lvds_priv = psb_intel_encoder->dev_priv;
int ret = 0;
if (!IS_MRST(dev))
- ret = psb_intel_ddc_get_modes(connector, &lvds_priv->i2c_bus->adapter);
+ ret = psb_intel_ddc_get_modes(connector, connector->ddc);
if (ret)
return ret;
- /* Didn't get an EDID, so
- * Set wide sync ranges so we get all modes
- * handed to valid_mode for checking
- */
- connector->display_info.min_vfreq = 0;
- connector->display_info.max_vfreq = 200;
- connector->display_info.min_hfreq = 0;
- connector->display_info.max_hfreq = 200;
-
if (mode_dev->panel_fixed_mode != NULL) {
struct drm_display_mode *mode =
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+ if (!mode)
+ return 0;
+
drm_mode_probed_add(connector, mode);
return 1;
}
@@ -555,24 +515,14 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
return 0;
}
-/**
- * psb_intel_lvds_destroy - unregister and free LVDS structures
- * @connector: connector to free
- *
- * Unregister the DDC bus for this connector then free the driver private
- * structure.
- */
void psb_intel_lvds_destroy(struct drm_connector *connector)
{
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- struct psb_intel_lvds_priv *lvds_priv = psb_intel_encoder->dev_priv;
+ struct gma_connector *gma_connector = to_gma_connector(connector);
+ struct gma_i2c_chan *ddc_bus = to_gma_i2c_chan(connector->ddc);
- if (lvds_priv->ddc_bus)
- psb_intel_i2c_destroy(lvds_priv->ddc_bus);
- drm_sysfs_connector_remove(connector);
+ gma_i2c_destroy(ddc_bus);
drm_connector_cleanup(connector);
- kfree(connector);
+ kfree(gma_connector);
}
int psb_intel_lvds_set_property(struct drm_connector *connector,
@@ -585,8 +535,7 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
return -1;
if (!strcmp(property->name, "scaling mode")) {
- struct psb_intel_crtc *crtc =
- to_psb_intel_crtc(encoder->crtc);
+ struct gma_crtc *crtc = to_gma_crtc(encoder->crtc);
uint64_t curval;
if (!crtc)
@@ -622,7 +571,7 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
&crtc->saved_mode,
encoder->crtc->x,
encoder->crtc->y,
- encoder->crtc->fb))
+ encoder->crtc->primary->fb))
goto set_prop_error;
}
} else if (!strcmp(property->name, "backlight")) {
@@ -633,7 +582,7 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
else
gma_backlight_set(encoder->dev, value);
} else if (!strcmp(property->name, "DPMS")) {
- struct drm_encoder_helper_funcs *hfuncs
+ const struct drm_encoder_helper_funcs *hfuncs
= encoder->helper_private;
hfuncs->dpms(encoder, value);
}
@@ -656,34 +605,20 @@ const struct drm_connector_helper_funcs
psb_intel_lvds_connector_helper_funcs = {
.get_modes = psb_intel_lvds_get_modes,
.mode_valid = psb_intel_lvds_mode_valid,
- .best_encoder = psb_intel_best_encoder,
+ .best_encoder = gma_best_encoder,
};
const struct drm_connector_funcs psb_intel_lvds_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .save = psb_intel_lvds_save,
- .restore = psb_intel_lvds_restore,
- .detect = psb_intel_lvds_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = psb_intel_lvds_set_property,
.destroy = psb_intel_lvds_destroy,
};
-
-static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder)
-{
- drm_encoder_cleanup(encoder);
-}
-
-const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = {
- .destroy = psb_intel_lvds_enc_destroy,
-};
-
-
-
/**
* psb_intel_lvds_init - setup LVDS connectors on this device
* @dev: drm device
+ * @mode_dev: mode device
*
* Create the connector, register the LVDS DDC bus, and try to figure out what
* modes we can display on the LVDS panel (if present).
@@ -691,52 +626,65 @@ const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = {
void psb_intel_lvds_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev)
{
- struct psb_intel_encoder *psb_intel_encoder;
- struct psb_intel_connector *psb_intel_connector;
+ struct gma_encoder *gma_encoder;
+ struct gma_connector *gma_connector;
struct psb_intel_lvds_priv *lvds_priv;
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_display_mode *scan; /* *modes, *bios_mode; */
struct drm_crtc *crtc;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_i2c_chan *ddc_bus;
u32 lvds;
int pipe;
+ int ret;
- psb_intel_encoder =
- kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
- if (!psb_intel_encoder) {
- dev_err(dev->dev, "psb_intel_encoder allocation error\n");
+ gma_encoder = kzalloc(sizeof(struct gma_encoder), GFP_KERNEL);
+ if (!gma_encoder) {
+ dev_err(dev->dev, "gma_encoder allocation error\n");
return;
}
+ encoder = &gma_encoder->base;
- psb_intel_connector =
- kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
- if (!psb_intel_connector) {
- dev_err(dev->dev, "psb_intel_connector allocation error\n");
- goto failed_encoder;
+ gma_connector = kzalloc(sizeof(struct gma_connector), GFP_KERNEL);
+ if (!gma_connector) {
+ dev_err(dev->dev, "gma_connector allocation error\n");
+ goto err_free_encoder;
}
lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);
if (!lvds_priv) {
dev_err(dev->dev, "LVDS private allocation error\n");
- goto failed_connector;
+ goto err_free_connector;
}
- psb_intel_encoder->dev_priv = lvds_priv;
+ gma_encoder->dev_priv = lvds_priv;
- connector = &psb_intel_connector->base;
- encoder = &psb_intel_encoder->base;
- drm_connector_init(dev, connector,
- &psb_intel_lvds_connector_funcs,
- DRM_MODE_CONNECTOR_LVDS);
+ connector = &gma_connector->base;
+ gma_connector->save = psb_intel_lvds_save;
+ gma_connector->restore = psb_intel_lvds_restore;
- drm_encoder_init(dev, encoder,
- &psb_intel_lvds_enc_funcs,
- DRM_MODE_ENCODER_LVDS);
+ /* Set up the DDC bus. */
+ ddc_bus = gma_i2c_create(dev, GPIOC, "LVDSDDC_C");
+ if (!ddc_bus) {
+ dev_printk(KERN_ERR, dev->dev,
+ "DDC bus registration " "failed.\n");
+ goto err_free_lvds_priv;
+ }
- psb_intel_connector_attach_encoder(psb_intel_connector,
- psb_intel_encoder);
- psb_intel_encoder->type = INTEL_OUTPUT_LVDS;
+ ret = drm_connector_init_with_ddc(dev, connector,
+ &psb_intel_lvds_connector_funcs,
+ DRM_MODE_CONNECTOR_LVDS,
+ &ddc_bus->base);
+ if (ret)
+ goto err_ddc_destroy;
+
+ ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS);
+ if (ret)
+ goto err_connector_cleanup;
+
+ gma_connector_attach_encoder(gma_connector, gma_encoder);
+ gma_encoder->type = INTEL_OUTPUT_LVDS;
drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs);
drm_connector_helper_add(connector,
@@ -757,13 +705,13 @@ void psb_intel_lvds_init(struct drm_device *dev,
* Set up I2C bus
* FIXME: distroy i2c_bus when exit
*/
- lvds_priv->i2c_bus = psb_intel_i2c_create(dev, GPIOB, "LVDSBLC_B");
+ lvds_priv->i2c_bus = gma_i2c_create(dev, GPIOB, "LVDSBLC_B");
if (!lvds_priv->i2c_bus) {
dev_printk(KERN_ERR,
- &dev->pdev->dev, "I2C bus registration failed.\n");
- goto failed_blc_i2c;
+ dev->dev, "I2C bus registration failed.\n");
+ goto err_encoder_cleanup;
}
- lvds_priv->i2c_bus->slave_addr = 0x2C;
+ lvds_priv->i2c_bus->target_addr = 0x2C;
dev_priv->lvds_i2c_bus = lvds_priv->i2c_bus;
/*
@@ -776,37 +724,34 @@ void psb_intel_lvds_init(struct drm_device *dev,
* if closed, act like it's not there for now
*/
- /* Set up the DDC bus. */
- lvds_priv->ddc_bus = psb_intel_i2c_create(dev, GPIOC, "LVDSDDC_C");
- if (!lvds_priv->ddc_bus) {
- dev_printk(KERN_ERR, &dev->pdev->dev,
- "DDC bus registration " "failed.\n");
- goto failed_ddc;
- }
-
/*
* Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one.
*/
- psb_intel_ddc_get_modes(connector, &lvds_priv->ddc_bus->adapter);
+ mutex_lock(&dev->mode_config.mutex);
+ psb_intel_ddc_get_modes(connector, &ddc_bus->base);
+
list_for_each_entry(scan, &connector->probed_modes, head) {
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
mode_dev->panel_fixed_mode =
drm_mode_duplicate(dev, scan);
+ DRM_DEBUG_KMS("Using mode from DDC\n");
goto out; /* FIXME: check for quirks */
}
}
/* Failed to get EDID, what about VBT? do we need this? */
- if (mode_dev->vbt_mode)
+ if (dev_priv->lfp_lvds_vbt_mode) {
mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev, mode_dev->vbt_mode);
+ drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
- if (!mode_dev->panel_fixed_mode)
- if (dev_priv->lfp_lvds_vbt_mode)
- mode_dev->panel_fixed_mode =
- drm_mode_duplicate(dev,
- dev_priv->lfp_lvds_vbt_mode);
+ if (mode_dev->panel_fixed_mode) {
+ mode_dev->panel_fixed_mode->type |=
+ DRM_MODE_TYPE_PREFERRED;
+ DRM_DEBUG_KMS("Using mode from VBT\n");
+ goto out;
+ }
+ }
/*
* If we didn't get EDID, try checking if the panel is already turned
@@ -823,6 +768,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
if (mode_dev->panel_fixed_mode) {
mode_dev->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED;
+ DRM_DEBUG_KMS("Using pre-programmed mode\n");
goto out; /* FIXME: check for quirks */
}
}
@@ -830,7 +776,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
/* If we still don't have a mode after all that, give up. */
if (!mode_dev->panel_fixed_mode) {
dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
- goto failed_find;
+ goto err_unlock;
}
/*
@@ -838,21 +784,23 @@ void psb_intel_lvds_init(struct drm_device *dev,
* actually having one.
*/
out:
- drm_sysfs_connector_add(connector);
+ mutex_unlock(&dev->mode_config.mutex);
return;
-failed_find:
- if (lvds_priv->ddc_bus)
- psb_intel_i2c_destroy(lvds_priv->ddc_bus);
-failed_ddc:
- if (lvds_priv->i2c_bus)
- psb_intel_i2c_destroy(lvds_priv->i2c_bus);
-failed_blc_i2c:
+err_unlock:
+ mutex_unlock(&dev->mode_config.mutex);
+ gma_i2c_destroy(lvds_priv->i2c_bus);
+err_encoder_cleanup:
drm_encoder_cleanup(encoder);
+err_connector_cleanup:
drm_connector_cleanup(connector);
-failed_connector:
- kfree(psb_intel_connector);
-failed_encoder:
- kfree(psb_intel_encoder);
+err_ddc_destroy:
+ gma_i2c_destroy(ddc_bus);
+err_free_lvds_priv:
+ kfree(lvds_priv);
+err_free_connector:
+ kfree(gma_connector);
+err_free_encoder:
+ kfree(gma_encoder);
}
diff --git a/drivers/gpu/drm/gma500/psb_intel_modes.c b/drivers/gpu/drm/gma500/psb_intel_modes.c
index 4fca0d6feebe..45b10f30a2a9 100644
--- a/drivers/gpu/drm/gma500/psb_intel_modes.c
+++ b/drivers/gpu/drm/gma500/psb_intel_modes.c
@@ -1,61 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2007 Intel Corporation
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authers: Jesse Barnes <jesse.barnes@intel.com>
*/
#include <linux/i2c.h>
-#include <linux/fb.h>
-#include <drm/drmP.h>
-#include "psb_intel_drv.h"
-/**
- * psb_intel_ddc_probe
- *
- */
-bool psb_intel_ddc_probe(struct i2c_adapter *adapter)
-{
- u8 out_buf[] = { 0x0, 0x0 };
- u8 buf[2];
- int ret;
- struct i2c_msg msgs[] = {
- {
- .addr = 0x50,
- .flags = 0,
- .len = 1,
- .buf = out_buf,
- },
- {
- .addr = 0x50,
- .flags = I2C_M_RD,
- .len = 1,
- .buf = buf,
- }
- };
-
- ret = i2c_transfer(adapter, msgs, 2);
- if (ret == 2)
- return true;
+#include <drm/drm_edid.h>
- return false;
-}
+#include "psb_intel_drv.h"
/**
* psb_intel_ddc_get_modes - get modelist from monitor
* @connector: DRM connector device to use
+ * @adapter: Associated I2C adaptor
*
* Fetch the EDID information from @connector using the DDC bus.
*/
@@ -67,7 +26,7 @@ int psb_intel_ddc_get_modes(struct drm_connector *connector,
edid = drm_get_edid(connector, adapter);
if (edid) {
- drm_mode_connector_update_edid_property(connector, edid);
+ drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
}
diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h b/drivers/gpu/drm/gma500/psb_intel_reg.h
index 0be30e4d146d..ced7b433befb 100644
--- a/drivers/gpu/drm/gma500/psb_intel_reg.h
+++ b/drivers/gpu/drm/gma500/psb_intel_reg.h
@@ -1,18 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __PSB_INTEL_REG_H__
#define __PSB_INTEL_REG_H__
@@ -562,38 +550,6 @@
#define HISTOGRAM_INT_CTRL_CLEAR (1UL << 30)
#define DPST_YUV_LUMA_MODE 0
-struct dpst_ie_histogram_control {
- union {
- uint32_t data;
- struct {
- uint32_t bin_reg_index:7;
- uint32_t reserved:4;
- uint32_t bin_reg_func_select:1;
- uint32_t sync_to_phase_in:1;
- uint32_t alt_enhancement_mode:2;
- uint32_t reserved1:1;
- uint32_t sync_to_phase_in_count:8;
- uint32_t histogram_mode_select:1;
- uint32_t reserved2:4;
- uint32_t ie_pipe_assignment:1;
- uint32_t ie_mode_table_enabled:1;
- uint32_t ie_histogram_enable:1;
- };
- };
-};
-
-struct dpst_guardband {
- union {
- uint32_t data;
- struct {
- uint32_t guardband:22;
- uint32_t guardband_interrupt_delay:8;
- uint32_t interrupt_status:1;
- uint32_t interrupt_enable:1;
- };
- };
-};
-
#define PIPEAFRAMEHIGH 0x70040
#define PIPEAFRAMEPIXEL 0x70044
#define PIPEBFRAMEHIGH 0x71040
@@ -607,7 +563,7 @@ struct dpst_guardband {
#define PIPE_PIXEL_MASK 0x00ffffff
#define PIPE_PIXEL_SHIFT 0
-#define FW_BLC_SELF 0x20e0
+#define FW_BLC_SELF 0x20e0
#define FW_BLC_SELF_EN (1<<15)
#define DSPARB 0x70030
@@ -801,17 +757,9 @@ struct dpst_guardband {
* MOORESTOWN delta registers
*/
#define MRST_DPLL_A 0x0f014
-#define MDFLD_DPLL_B 0x0f018
-#define MDFLD_INPUT_REF_SEL (1 << 14)
-#define MDFLD_VCO_SEL (1 << 16)
#define DPLLA_MODE_LVDS (2 << 26) /* mrst */
-#define MDFLD_PLL_LATCHEN (1 << 28)
-#define MDFLD_PWR_GATE_EN (1 << 30)
-#define MDFLD_P1_MASK (0x1FF << 17)
#define MRST_FPA0 0x0f040
#define MRST_FPA1 0x0f044
-#define MDFLD_DPLL_DIV0 0x0f048
-#define MDFLD_DPLL_DIV1 0x0f04c
#define MRST_PERF_MODE 0x020f4
/*
@@ -860,7 +808,6 @@ struct dpst_guardband {
#define MRST_DSPABASE 0x7019c
#define MRST_DSPBBASE 0x7119c
-#define MDFLD_DSPCBASE 0x7219c
/*
* Moorestown registers.
@@ -942,7 +889,6 @@ struct dpst_guardband {
#define DEVICE_RESET_REG 0xb01C
#define DPI_RESOLUTION_REG 0xb020
#define RES_V_POS 0x10
-#define DBI_RESOLUTION_REG 0xb024 /* Reserved for MDFLD */
#define HORIZ_SYNC_PAD_COUNT_REG 0xb028
#define HORIZ_BACK_PORCH_COUNT_REG 0xb02C
#define HORIZ_FRONT_PORCH_COUNT_REG 0xb030
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index 19e36603b23b..553e7c7d9bb8 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -25,18 +25,23 @@
* Authors:
* Eric Anholt <eric@anholt.net>
*/
-#include <linux/module.h>
+
+#include <linux/delay.h>
#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/delay.h>
-#include <drm/drmP.h>
+
#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h>
-#include "psb_intel_drv.h"
-#include <drm/gma_drm.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_print.h>
+
#include "psb_drv.h"
-#include "psb_intel_sdvo_regs.h"
+#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
+#include "psb_intel_sdvo_regs.h"
#define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)
#define SDVO_RGB_MASK (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)
@@ -62,13 +67,11 @@ static const char *tv_format_names[] = {
"SECAM_60"
};
-#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names))
-
struct psb_intel_sdvo {
- struct psb_intel_encoder base;
+ struct gma_encoder base;
struct i2c_adapter *i2c;
- u8 slave_addr;
+ u8 target_addr;
struct i2c_adapter ddc;
@@ -125,13 +128,15 @@ struct psb_intel_sdvo {
bool is_lvds;
/**
- * This is sdvo fixed pannel mode pointer
+ * This is sdvo fixed panel mode pointer
*/
struct drm_display_mode *sdvo_lvds_fixed_mode;
/* DDC bus used by this SDVO encoder */
uint8_t ddc_bus;
+ u8 pixel_multiplier;
+
/* Input timings for adjusted_mode */
struct psb_intel_sdvo_dtd input_dtd;
@@ -140,7 +145,7 @@ struct psb_intel_sdvo {
};
struct psb_intel_sdvo_connector {
- struct psb_intel_connector base;
+ struct gma_connector base;
/* Mark the type of connector */
uint16_t output_flag;
@@ -148,7 +153,7 @@ struct psb_intel_sdvo_connector {
int force_audio;
/* This contains all current supported TV format */
- u8 tv_format_supported[TV_FORMAT_NUM];
+ u8 tv_format_supported[ARRAY_SIZE(tv_format_names)];
int format_supported_num;
struct drm_property *tv_format;
@@ -200,13 +205,13 @@ static struct psb_intel_sdvo *to_psb_intel_sdvo(struct drm_encoder *encoder)
static struct psb_intel_sdvo *intel_attached_sdvo(struct drm_connector *connector)
{
- return container_of(psb_intel_attached_encoder(connector),
+ return container_of(gma_attached_encoder(connector),
struct psb_intel_sdvo, base);
}
static struct psb_intel_sdvo_connector *to_psb_intel_sdvo_connector(struct drm_connector *connector)
{
- return container_of(to_psb_intel_connector(connector), struct psb_intel_sdvo_connector, base);
+ return container_of(to_gma_connector(connector), struct psb_intel_sdvo_connector, base);
}
static bool
@@ -219,7 +224,7 @@ static bool
psb_intel_sdvo_create_enhance_property(struct psb_intel_sdvo *psb_intel_sdvo,
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector);
-/**
+/*
* Writes the SDVOB or SDVOC with the given value, but always writes both
* SDVOB and SDVOC to work around apparent hardware issues (according to
* comments in the BIOS).
@@ -228,24 +233,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);
+ }
}
}
@@ -253,13 +260,13 @@ static bool psb_intel_sdvo_read_byte(struct psb_intel_sdvo *psb_intel_sdvo, u8 a
{
struct i2c_msg msgs[] = {
{
- .addr = psb_intel_sdvo->slave_addr,
+ .addr = psb_intel_sdvo->target_addr,
.flags = 0,
.len = 1,
.buf = &addr,
},
{
- .addr = psb_intel_sdvo->slave_addr,
+ .addr = psb_intel_sdvo->target_addr,
.flags = I2C_M_RD,
.len = 1,
.buf = ch,
@@ -396,26 +403,38 @@ static const struct _sdvo_cmd_name {
#define IS_SDVOB(reg) (reg == SDVOB)
#define SDVO_NAME(svdo) (IS_SDVOB((svdo)->sdvo_reg) ? "SDVOB" : "SDVOC")
-static void psb_intel_sdvo_debug_write(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd,
- const void *args, int args_len)
+static void psb_intel_sdvo_debug_write(struct psb_intel_sdvo *psb_intel_sdvo,
+ u8 cmd, const void *args, int args_len)
{
- int i;
+ struct drm_device *dev = psb_intel_sdvo->base.base.dev;
+ int i, pos = 0;
+ char buffer[73];
+
+#define BUF_PRINT(args...) \
+ pos += snprintf(buffer + pos, max_t(int, sizeof(buffer) - pos, 0), args)
+
+ for (i = 0; i < args_len; i++) {
+ BUF_PRINT("%02X ", ((u8 *)args)[i]);
+ }
+
+ for (; i < 8; i++) {
+ BUF_PRINT(" ");
+ }
- DRM_DEBUG_KMS("%s: W: %02X ",
- SDVO_NAME(psb_intel_sdvo), cmd);
- for (i = 0; i < args_len; i++)
- DRM_LOG_KMS("%02X ", ((u8 *)args)[i]);
- for (; i < 8; i++)
- DRM_LOG_KMS(" ");
for (i = 0; i < ARRAY_SIZE(sdvo_cmd_names); i++) {
if (cmd == sdvo_cmd_names[i].cmd) {
- DRM_LOG_KMS("(%s)", sdvo_cmd_names[i].name);
+ BUF_PRINT("(%s)", sdvo_cmd_names[i].name);
break;
}
}
+
if (i == ARRAY_SIZE(sdvo_cmd_names))
- DRM_LOG_KMS("(%02X)", cmd);
- DRM_LOG_KMS("\n");
+ BUF_PRINT("(%02X)", cmd);
+
+ drm_WARN_ON(dev, pos >= sizeof(buffer) - 1);
+#undef BUF_PRINT
+
+ DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(psb_intel_sdvo), cmd, buffer);
}
static const char *cmd_status_names[] = {
@@ -428,24 +447,31 @@ static const char *cmd_status_names[] = {
"Scaling not supported"
};
+#define MAX_ARG_LEN 32
+
static bool psb_intel_sdvo_write_cmd(struct psb_intel_sdvo *psb_intel_sdvo, u8 cmd,
const void *args, int args_len)
{
- u8 buf[args_len*2 + 2], status;
- struct i2c_msg msgs[args_len + 3];
+ u8 buf[MAX_ARG_LEN*2 + 2], status;
+ struct i2c_msg msgs[MAX_ARG_LEN + 3];
int i, ret;
+ if (args_len > MAX_ARG_LEN) {
+ DRM_ERROR("Need to increase arg length\n");
+ return false;
+ }
+
psb_intel_sdvo_debug_write(psb_intel_sdvo, cmd, args, args_len);
for (i = 0; i < args_len; i++) {
- msgs[i].addr = psb_intel_sdvo->slave_addr;
+ msgs[i].addr = psb_intel_sdvo->target_addr;
msgs[i].flags = 0;
msgs[i].len = 2;
msgs[i].buf = buf + 2 *i;
buf[2*i + 0] = SDVO_I2C_ARG_0 - i;
buf[2*i + 1] = ((u8*)args)[i];
}
- msgs[i].addr = psb_intel_sdvo->slave_addr;
+ msgs[i].addr = psb_intel_sdvo->target_addr;
msgs[i].flags = 0;
msgs[i].len = 2;
msgs[i].buf = buf + 2*i;
@@ -454,12 +480,12 @@ static bool psb_intel_sdvo_write_cmd(struct psb_intel_sdvo *psb_intel_sdvo, u8 c
/* the following two are to read the response */
status = SDVO_I2C_CMD_STATUS;
- msgs[i+1].addr = psb_intel_sdvo->slave_addr;
+ msgs[i+1].addr = psb_intel_sdvo->target_addr;
msgs[i+1].flags = 0;
msgs[i+1].len = 1;
msgs[i+1].buf = &status;
- msgs[i+2].addr = psb_intel_sdvo->slave_addr;
+ msgs[i+2].addr = psb_intel_sdvo->target_addr;
msgs[i+2].flags = I2C_M_RD;
msgs[i+2].len = 1;
msgs[i+2].buf = &status;
@@ -479,13 +505,13 @@ static bool psb_intel_sdvo_write_cmd(struct psb_intel_sdvo *psb_intel_sdvo, u8 c
}
static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
- void *response, int response_len)
+ void *response, int response_len)
{
+ struct drm_device *dev = psb_intel_sdvo->base.base.dev;
+ char buffer[73];
+ int i, pos = 0;
u8 retry = 5;
u8 status;
- int i;
-
- DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(psb_intel_sdvo));
/*
* The documentation states that all commands will be
@@ -500,7 +526,8 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
&status))
goto log_fail;
- while (status == SDVO_CMD_STATUS_PENDING && retry--) {
+ while ((status == SDVO_CMD_STATUS_PENDING ||
+ status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && retry--) {
udelay(15);
if (!psb_intel_sdvo_read_byte(psb_intel_sdvo,
SDVO_I2C_CMD_STATUS,
@@ -508,10 +535,13 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
goto log_fail;
}
+#define BUF_PRINT(args...) \
+ pos += snprintf(buffer + pos, max_t(int, sizeof(buffer) - pos, 0), args)
+
if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
- DRM_LOG_KMS("(%s)", cmd_status_names[status]);
+ BUF_PRINT("(%s)", cmd_status_names[status]);
else
- DRM_LOG_KMS("(??? %d)", status);
+ BUF_PRINT("(??? %d)", status);
if (status != SDVO_CMD_STATUS_SUCCESS)
goto log_fail;
@@ -522,13 +552,18 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
SDVO_I2C_RETURN_0 + i,
&((u8 *)response)[i]))
goto log_fail;
- DRM_LOG_KMS(" %02X", ((u8 *)response)[i]);
+ BUF_PRINT(" %02X", ((u8 *)response)[i]);
}
- DRM_LOG_KMS("\n");
+
+ drm_WARN_ON(dev, pos >= sizeof(buffer) - 1);
+#undef BUF_PRINT
+
+ DRM_DEBUG_KMS("%s: R: %s\n", SDVO_NAME(psb_intel_sdvo), buffer);
return true;
log_fail:
- DRM_LOG_KMS("... failed\n");
+ DRM_DEBUG_KMS("%s: R: ... failed %s\n",
+ SDVO_NAME(psb_intel_sdvo), buffer);
return false;
}
@@ -576,7 +611,7 @@ static bool psb_intel_sdvo_set_target_input(struct psb_intel_sdvo *psb_intel_sdv
&targets, sizeof(targets));
}
-/**
+/*
* Return whether each input is trained.
*
* This function is making an assumption about the layout of the response,
@@ -854,36 +889,6 @@ static bool psb_intel_sdvo_set_avi_infoframe(struct psb_intel_sdvo *psb_intel_sd
DRM_INFO("HDMI is not supported yet");
return false;
-#if 0
- struct dip_infoframe avi_if = {
- .type = DIP_TYPE_AVI,
- .ver = DIP_VERSION_AVI,
- .len = DIP_LEN_AVI,
- };
- uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
- uint8_t set_buf_index[2] = { 1, 0 };
- uint64_t *data = (uint64_t *)&avi_if;
- unsigned i;
-
- intel_dip_infoframe_csum(&avi_if);
-
- if (!psb_intel_sdvo_set_value(psb_intel_sdvo,
- SDVO_CMD_SET_HBUF_INDEX,
- set_buf_index, 2))
- return false;
-
- for (i = 0; i < sizeof(avi_if); i += 8) {
- if (!psb_intel_sdvo_set_value(psb_intel_sdvo,
- SDVO_CMD_SET_HBUF_DATA,
- data, 8))
- return false;
- data++;
- }
-
- return psb_intel_sdvo_set_value(psb_intel_sdvo,
- SDVO_CMD_SET_HBUF_TXRATE,
- &tx_rate, 1);
-#endif
}
static bool psb_intel_sdvo_set_tv_format(struct psb_intel_sdvo *psb_intel_sdvo)
@@ -948,7 +953,6 @@ static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder);
- int multiplier;
/* We need to construct preferred input timings based on our
* output timings. To do that, we have to set the output
@@ -975,8 +979,9 @@ static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder,
/* Make the CRTC code factor in the SDVO pixel multiplier. The
* SDVO device will factor out the multiplier during mode_set.
*/
- multiplier = psb_intel_sdvo_get_pixel_multiplier(adjusted_mode);
- psb_intel_mode_set_pixel_multiplier(adjusted_mode, multiplier);
+ psb_intel_sdvo->pixel_multiplier =
+ psb_intel_sdvo_get_pixel_multiplier(adjusted_mode);
+ adjusted_mode->clock *= psb_intel_sdvo->pixel_multiplier;
return true;
}
@@ -987,13 +992,13 @@ static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder,
{
struct drm_device *dev = encoder->dev;
struct drm_crtc *crtc = encoder->crtc;
- struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder);
u32 sdvox;
struct psb_intel_sdvo_in_out_map in_out;
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;
@@ -1049,7 +1054,7 @@ static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder,
(void) psb_intel_sdvo_set_input_timing(psb_intel_sdvo, &input_dtd);
- switch (pixel_multiplier) {
+ switch (psb_intel_sdvo->pixel_multiplier) {
default:
case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break;
case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break;
@@ -1059,7 +1064,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;
@@ -1070,7 +1079,7 @@ static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder,
}
sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
- if (psb_intel_crtc->pipe == 1)
+ if (gma_crtc->pipe == 1)
sdvox |= SDVO_PIPE_B_SELECT;
if (psb_intel_sdvo->has_hdmi_audio)
sdvox |= SDVO_AUDIO_ENABLE;
@@ -1089,6 +1098,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:
@@ -1107,21 +1118,29 @@ 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++)
- psb_intel_wait_for_vblank(dev);
+ gma_wait_for_vblank(dev);
status = psb_intel_sdvo_get_trained_inputs(psb_intel_sdvo, &input1, &input2);
/* Warn if the device reported failure to sync.
@@ -1140,8 +1159,8 @@ static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
return;
}
-static int psb_intel_sdvo_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+static enum drm_mode_status psb_intel_sdvo_mode_valid(struct drm_connector *connector,
+ const struct drm_display_mode *mode)
{
struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector);
@@ -1202,75 +1221,6 @@ static bool psb_intel_sdvo_get_capabilities(struct psb_intel_sdvo *psb_intel_sdv
return true;
}
-/* No use! */
-#if 0
-struct drm_connector* psb_intel_sdvo_find(struct drm_device *dev, int sdvoB)
-{
- struct drm_connector *connector = NULL;
- struct psb_intel_sdvo *iout = NULL;
- struct psb_intel_sdvo *sdvo;
-
- /* find the sdvo connector */
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- iout = to_psb_intel_sdvo(connector);
-
- if (iout->type != INTEL_OUTPUT_SDVO)
- continue;
-
- sdvo = iout->dev_priv;
-
- if (sdvo->sdvo_reg == SDVOB && sdvoB)
- return connector;
-
- if (sdvo->sdvo_reg == SDVOC && !sdvoB)
- return connector;
-
- }
-
- return NULL;
-}
-
-int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector)
-{
- u8 response[2];
- u8 status;
- struct psb_intel_sdvo *psb_intel_sdvo;
- DRM_DEBUG_KMS("\n");
-
- if (!connector)
- return 0;
-
- psb_intel_sdvo = to_psb_intel_sdvo(connector);
-
- return psb_intel_sdvo_get_value(psb_intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
- &response, 2) && response[0];
-}
-
-void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
-{
- u8 response[2];
- u8 status;
- struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(connector);
-
- psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
- psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2);
-
- if (on) {
- psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
- status = psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2);
-
- psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
- } else {
- response[0] = 0;
- response[1] = 0;
- psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
- }
-
- psb_intel_sdvo_write_cmd(psb_intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
- psb_intel_sdvo_read_response(psb_intel_sdvo, &response, 2);
-}
-#endif
-
static bool
psb_intel_sdvo_multifunc_encoder(struct psb_intel_sdvo *psb_intel_sdvo)
{
@@ -1290,7 +1240,7 @@ psb_intel_sdvo_get_edid(struct drm_connector *connector)
static struct edid *
psb_intel_sdvo_get_analog_edid(struct drm_connector *connector)
{
- struct drm_psb_private *dev_priv = connector->dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(connector->dev);
return drm_get_edid(connector,
&dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
@@ -1448,7 +1398,7 @@ static void psb_intel_sdvo_get_ddc_modes(struct drm_connector *connector)
bool connector_is_digital = !!IS_TMDS(psb_intel_sdvo_connector);
if (connector_is_digital == monitor_is_digital) {
- drm_mode_connector_update_edid_property(connector, edid);
+ drm_connector_update_edid_property(connector, edid);
drm_add_edid_modes(connector, edid);
}
@@ -1559,7 +1509,7 @@ static void psb_intel_sdvo_get_tv_modes(struct drm_connector *connector)
static void psb_intel_sdvo_get_lvds_modes(struct drm_connector *connector)
{
struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector);
- struct drm_psb_private *dev_priv = connector->dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(connector->dev);
struct drm_display_mode *newmode;
/*
@@ -1613,60 +1563,12 @@ static int psb_intel_sdvo_get_modes(struct drm_connector *connector)
return !list_empty(&connector->probed_modes);
}
-static void
-psb_intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
-{
- struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector);
- struct drm_device *dev = connector->dev;
-
- if (psb_intel_sdvo_connector->left)
- drm_property_destroy(dev, psb_intel_sdvo_connector->left);
- if (psb_intel_sdvo_connector->right)
- drm_property_destroy(dev, psb_intel_sdvo_connector->right);
- if (psb_intel_sdvo_connector->top)
- drm_property_destroy(dev, psb_intel_sdvo_connector->top);
- if (psb_intel_sdvo_connector->bottom)
- drm_property_destroy(dev, psb_intel_sdvo_connector->bottom);
- if (psb_intel_sdvo_connector->hpos)
- drm_property_destroy(dev, psb_intel_sdvo_connector->hpos);
- if (psb_intel_sdvo_connector->vpos)
- drm_property_destroy(dev, psb_intel_sdvo_connector->vpos);
- if (psb_intel_sdvo_connector->saturation)
- drm_property_destroy(dev, psb_intel_sdvo_connector->saturation);
- if (psb_intel_sdvo_connector->contrast)
- drm_property_destroy(dev, psb_intel_sdvo_connector->contrast);
- if (psb_intel_sdvo_connector->hue)
- drm_property_destroy(dev, psb_intel_sdvo_connector->hue);
- if (psb_intel_sdvo_connector->sharpness)
- drm_property_destroy(dev, psb_intel_sdvo_connector->sharpness);
- if (psb_intel_sdvo_connector->flicker_filter)
- drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter);
- if (psb_intel_sdvo_connector->flicker_filter_2d)
- drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_2d);
- if (psb_intel_sdvo_connector->flicker_filter_adaptive)
- drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_adaptive);
- if (psb_intel_sdvo_connector->tv_luma_filter)
- drm_property_destroy(dev, psb_intel_sdvo_connector->tv_luma_filter);
- if (psb_intel_sdvo_connector->tv_chroma_filter)
- drm_property_destroy(dev, psb_intel_sdvo_connector->tv_chroma_filter);
- if (psb_intel_sdvo_connector->dot_crawl)
- drm_property_destroy(dev, psb_intel_sdvo_connector->dot_crawl);
- if (psb_intel_sdvo_connector->brightness)
- drm_property_destroy(dev, psb_intel_sdvo_connector->brightness);
-}
-
static void psb_intel_sdvo_destroy(struct drm_connector *connector)
{
- struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector);
+ struct gma_connector *gma_connector = to_gma_connector(connector);
- if (psb_intel_sdvo_connector->tv_format)
- drm_property_destroy(connector->dev,
- psb_intel_sdvo_connector->tv_format);
-
- psb_intel_sdvo_destroy_enhance_property(connector);
- drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
- kfree(connector);
+ kfree(gma_connector);
}
static bool psb_intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)
@@ -1692,7 +1594,7 @@ psb_intel_sdvo_set_property(struct drm_connector *connector,
{
struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector);
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector);
- struct drm_psb_private *dev_priv = connector->dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(connector->dev);
uint16_t temp_value;
uint8_t cmd;
int ret;
@@ -1740,7 +1642,7 @@ psb_intel_sdvo_set_property(struct drm_connector *connector,
}
if (property == psb_intel_sdvo_connector->tv_format) {
- if (val >= TV_FORMAT_NUM)
+ if (val >= ARRAY_SIZE(tv_format_names))
return -EINVAL;
if (psb_intel_sdvo->tv_format_index ==
@@ -1826,7 +1728,7 @@ done:
if (psb_intel_sdvo->base.base.crtc) {
struct drm_crtc *crtc = psb_intel_sdvo->base.base.crtc;
drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
- crtc->y, crtc->fb);
+ crtc->y, crtc->primary->fb);
}
return 0;
@@ -1836,10 +1738,8 @@ done:
static void psb_intel_sdvo_save(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- struct psb_intel_encoder *psb_intel_encoder =
- psb_intel_attached_encoder(connector);
- struct psb_intel_sdvo *sdvo =
- to_psb_intel_sdvo(&psb_intel_encoder->base);
+ struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
+ struct psb_intel_sdvo *sdvo = to_psb_intel_sdvo(&gma_encoder->base);
sdvo->saveSDVO = REG_READ(sdvo->sdvo_reg);
}
@@ -1847,8 +1747,7 @@ static void psb_intel_sdvo_save(struct drm_connector *connector)
static void psb_intel_sdvo_restore(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
- struct drm_encoder *encoder =
- &psb_intel_attached_encoder(connector)->base;
+ struct drm_encoder *encoder = &gma_attached_encoder(connector)->base;
struct psb_intel_sdvo *sdvo = to_psb_intel_sdvo(encoder);
struct drm_crtc *crtc = encoder->crtc;
@@ -1864,15 +1763,13 @@ static void psb_intel_sdvo_restore(struct drm_connector *connector)
static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = {
.dpms = psb_intel_sdvo_dpms,
.mode_fixup = psb_intel_sdvo_mode_fixup,
- .prepare = psb_intel_encoder_prepare,
+ .prepare = gma_encoder_prepare,
.mode_set = psb_intel_sdvo_mode_set,
- .commit = psb_intel_encoder_commit,
+ .commit = gma_encoder_commit,
};
static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = {
.dpms = drm_helper_connector_dpms,
- .save = psb_intel_sdvo_save,
- .restore = psb_intel_sdvo_restore,
.detect = psb_intel_sdvo_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = psb_intel_sdvo_set_property,
@@ -1882,7 +1779,7 @@ static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = {
static const struct drm_connector_helper_funcs psb_intel_sdvo_connector_helper_funcs = {
.get_modes = psb_intel_sdvo_get_modes,
.mode_valid = psb_intel_sdvo_mode_valid,
- .best_encoder = psb_intel_best_encoder,
+ .best_encoder = gma_best_encoder,
};
static void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder)
@@ -1894,7 +1791,7 @@ static void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder)
psb_intel_sdvo->sdvo_lvds_fixed_mode);
i2c_del_adapter(&psb_intel_sdvo->ddc);
- psb_intel_encoder_destroy(encoder);
+ gma_encoder_destroy(encoder);
}
static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = {
@@ -1945,7 +1842,7 @@ psb_intel_sdvo_guess_ddc_bus(struct psb_intel_sdvo *sdvo)
#endif
}
-/**
+/*
* Choose the appropriate DDC bus for control bus switch command for this
* SDVO output based on the controlled output.
*
@@ -2003,9 +1900,9 @@ psb_intel_sdvo_is_hdmi_connector(struct psb_intel_sdvo *psb_intel_sdvo, int devi
}
static u8
-psb_intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg)
+psb_intel_sdvo_get_target_addr(struct drm_device *dev, int sdvo_reg)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct sdvo_device_mapping *my_mapping, *other_mapping;
if (IS_SDVOB(sdvo_reg)) {
@@ -2017,14 +1914,14 @@ psb_intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg)
}
/* If the BIOS described our SDVO device, take advantage of it. */
- if (my_mapping->slave_addr)
- return my_mapping->slave_addr;
+ if (my_mapping->target_addr)
+ return my_mapping->target_addr;
/* If the BIOS only described a different SDVO device, use the
* address that it isn't using.
*/
- if (other_mapping->slave_addr) {
- if (other_mapping->slave_addr == 0x70)
+ if (other_mapping->target_addr) {
+ if (other_mapping->target_addr == 0x70)
return 0x72;
else
return 0x70;
@@ -2055,8 +1952,10 @@ psb_intel_sdvo_connector_init(struct psb_intel_sdvo_connector *connector,
connector->base.base.doublescan_allowed = 0;
connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
- psb_intel_connector_attach_encoder(&connector->base, &encoder->base);
- drm_sysfs_connector_add(&connector->base.base);
+ connector->base.save = psb_intel_sdvo_save;
+ connector->base.restore = psb_intel_sdvo_restore;
+
+ gma_connector_attach_encoder(&connector->base, &encoder->base);
}
static void
@@ -2075,7 +1974,7 @@ psb_intel_sdvo_dvi_init(struct psb_intel_sdvo *psb_intel_sdvo, int device)
{
struct drm_encoder *encoder = &psb_intel_sdvo->base.base;
struct drm_connector *connector;
- struct psb_intel_connector *intel_connector;
+ struct gma_connector *intel_connector;
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector;
psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL);
@@ -2115,7 +2014,7 @@ psb_intel_sdvo_tv_init(struct psb_intel_sdvo *psb_intel_sdvo, int type)
{
struct drm_encoder *encoder = &psb_intel_sdvo->base.base;
struct drm_connector *connector;
- struct psb_intel_connector *intel_connector;
+ struct gma_connector *intel_connector;
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector;
psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL);
@@ -2154,7 +2053,7 @@ psb_intel_sdvo_analog_init(struct psb_intel_sdvo *psb_intel_sdvo, int device)
{
struct drm_encoder *encoder = &psb_intel_sdvo->base.base;
struct drm_connector *connector;
- struct psb_intel_connector *intel_connector;
+ struct gma_connector *intel_connector;
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector;
psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL);
@@ -2188,7 +2087,7 @@ psb_intel_sdvo_lvds_init(struct psb_intel_sdvo *psb_intel_sdvo, int device)
{
struct drm_encoder *encoder = &psb_intel_sdvo->base.base;
struct drm_connector *connector;
- struct psb_intel_connector *intel_connector;
+ struct gma_connector *intel_connector;
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector;
psb_intel_sdvo_connector = kzalloc(sizeof(struct psb_intel_sdvo_connector), GFP_KERNEL);
@@ -2302,7 +2201,7 @@ static bool psb_intel_sdvo_tv_create_property(struct psb_intel_sdvo *psb_intel_s
return false;
psb_intel_sdvo_connector->format_supported_num = 0;
- for (i = 0 ; i < TV_FORMAT_NUM; i++)
+ for (i = 0 ; i < ARRAY_SIZE(tv_format_names); i++)
if (format_map & (1 << i))
psb_intel_sdvo_connector->tv_format_supported[psb_intel_sdvo_connector->format_supported_num++] = i;
@@ -2315,7 +2214,7 @@ static bool psb_intel_sdvo_tv_create_property(struct psb_intel_sdvo *psb_intel_s
for (i = 0; i < psb_intel_sdvo_connector->format_supported_num; i++)
drm_property_add_enum(
- psb_intel_sdvo_connector->tv_format, i,
+ psb_intel_sdvo_connector->tv_format,
i, tv_format_names[psb_intel_sdvo_connector->tv_format_supported[i]]);
psb_intel_sdvo->tv_format_index = psb_intel_sdvo_connector->tv_format_supported[0];
@@ -2528,9 +2427,8 @@ psb_intel_sdvo_init_ddc_proxy(struct psb_intel_sdvo *sdvo,
struct drm_device *dev)
{
sdvo->ddc.owner = THIS_MODULE;
- sdvo->ddc.class = I2C_CLASS_DDC;
snprintf(sdvo->ddc.name, I2C_NAME_SIZE, "SDVO DDC proxy");
- sdvo->ddc.dev.parent = &dev->pdev->dev;
+ sdvo->ddc.dev.parent = dev->dev;
sdvo->ddc.algo_data = sdvo;
sdvo->ddc.algo = &psb_intel_sdvo_ddc_proxy;
@@ -2539,8 +2437,8 @@ psb_intel_sdvo_init_ddc_proxy(struct psb_intel_sdvo *sdvo,
bool psb_intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
- struct psb_intel_encoder *psb_intel_encoder;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct gma_encoder *gma_encoder;
struct psb_intel_sdvo *psb_intel_sdvo;
int i;
@@ -2549,7 +2447,7 @@ bool psb_intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
return false;
psb_intel_sdvo->sdvo_reg = sdvo_reg;
- psb_intel_sdvo->slave_addr = psb_intel_sdvo_get_slave_addr(dev, sdvo_reg) >> 1;
+ psb_intel_sdvo->target_addr = psb_intel_sdvo_get_target_addr(dev, sdvo_reg) >> 1;
psb_intel_sdvo_select_i2c_bus(dev_priv, psb_intel_sdvo, sdvo_reg);
if (!psb_intel_sdvo_init_ddc_proxy(psb_intel_sdvo, dev)) {
kfree(psb_intel_sdvo);
@@ -2557,9 +2455,10 @@ bool psb_intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
}
/* encoder type will be decided later */
- psb_intel_encoder = &psb_intel_sdvo->base;
- psb_intel_encoder->type = INTEL_OUTPUT_SDVO;
- drm_encoder_init(dev, &psb_intel_encoder->base, &psb_intel_sdvo_enc_funcs, 0);
+ gma_encoder = &psb_intel_sdvo->base;
+ gma_encoder->type = INTEL_OUTPUT_SDVO;
+ drm_encoder_init(dev, &gma_encoder->base, &psb_intel_sdvo_enc_funcs,
+ 0, NULL);
/* Read the regs to test if we can talk to the device */
for (i = 0; i < 0x40; i++) {
@@ -2577,7 +2476,7 @@ bool psb_intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
else
dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
- drm_encoder_helper_add(&psb_intel_encoder->base, &psb_intel_sdvo_helper_funcs);
+ drm_encoder_helper_add(&gma_encoder->base, &psb_intel_sdvo_helper_funcs);
/* In default case sdvo lvds is false */
if (!psb_intel_sdvo_get_capabilities(psb_intel_sdvo, &psb_intel_sdvo->caps))
@@ -2620,7 +2519,7 @@ bool psb_intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
return true;
err:
- drm_encoder_cleanup(&psb_intel_encoder->base);
+ drm_encoder_cleanup(&gma_encoder->base);
i2c_del_adapter(&psb_intel_sdvo->ddc);
kfree(psb_intel_sdvo);
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
index 029eccf30137..3a946b472064 100644
--- a/drivers/gpu/drm/gma500/psb_irq.c
+++ b/drivers/gpu/drm/gma500/psb_irq.c
@@ -1,41 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
/**************************************************************************
* Copyright (c) 2007, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
* develop this driver.
*
**************************************************************************/
-/*
- */
-#include <drm/drmP.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
+
+#include "power.h"
#include "psb_drv.h"
-#include "psb_reg.h"
#include "psb_intel_reg.h"
-#include "power.h"
#include "psb_irq.h"
-#include "mdfld_output.h"
+#include "psb_reg.h"
/*
* inline functions
*/
-static inline u32
-psb_pipestat(int pipe)
+static inline u32 gma_pipestat(int pipe)
{
if (pipe == 0)
return PIPEASTAT;
@@ -46,32 +33,7 @@ psb_pipestat(int pipe)
BUG();
}
-static inline u32
-mid_pipe_event(int pipe)
-{
- if (pipe == 0)
- return _PSB_PIPEA_EVENT_FLAG;
- if (pipe == 1)
- return _MDFLD_PIPEB_EVENT_FLAG;
- if (pipe == 2)
- return _MDFLD_PIPEC_EVENT_FLAG;
- BUG();
-}
-
-static inline u32
-mid_pipe_vsync(int pipe)
-{
- if (pipe == 0)
- return _PSB_VSYNC_PIPEA_FLAG;
- if (pipe == 1)
- return _PSB_VSYNC_PIPEB_FLAG;
- if (pipe == 2)
- return _MDFLD_PIPEC_VBLANK_FLAG;
- BUG();
-}
-
-static inline u32
-mid_pipeconf(int pipe)
+static inline u32 gma_pipeconf(int pipe)
{
if (pipe == 0)
return PIPEACONF;
@@ -82,74 +44,46 @@ mid_pipeconf(int pipe)
BUG();
}
-void
-psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+void gma_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
{
if ((dev_priv->pipestat[pipe] & mask) != mask) {
- u32 reg = psb_pipestat(pipe);
+ u32 reg = gma_pipestat(pipe);
dev_priv->pipestat[pipe] |= mask;
/* Enable the interrupt, clear any pending status */
- if (gma_power_begin(dev_priv->dev, false)) {
+ if (gma_power_begin(&dev_priv->dev, false)) {
u32 writeVal = PSB_RVDC32(reg);
writeVal |= (mask | (mask >> 16));
PSB_WVDC32(writeVal, reg);
(void) PSB_RVDC32(reg);
- gma_power_end(dev_priv->dev);
+ gma_power_end(&dev_priv->dev);
}
}
}
-void
-psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+void gma_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
{
if ((dev_priv->pipestat[pipe] & mask) != 0) {
- u32 reg = psb_pipestat(pipe);
+ u32 reg = gma_pipestat(pipe);
dev_priv->pipestat[pipe] &= ~mask;
- if (gma_power_begin(dev_priv->dev, false)) {
+ if (gma_power_begin(&dev_priv->dev, false)) {
u32 writeVal = PSB_RVDC32(reg);
writeVal &= ~mask;
PSB_WVDC32(writeVal, reg);
(void) PSB_RVDC32(reg);
- gma_power_end(dev_priv->dev);
+ gma_power_end(&dev_priv->dev);
}
}
}
-static void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
-{
- if (gma_power_begin(dev_priv->dev, false)) {
- u32 pipe_event = mid_pipe_event(pipe);
- dev_priv->vdc_irq_mask |= pipe_event;
- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
- gma_power_end(dev_priv->dev);
- }
-}
-
-static void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
-{
- if (dev_priv->pipestat[pipe] == 0) {
- if (gma_power_begin(dev_priv->dev, false)) {
- u32 pipe_event = mid_pipe_event(pipe);
- dev_priv->vdc_irq_mask &= ~pipe_event;
- PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
- PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
- gma_power_end(dev_priv->dev);
- }
- }
-}
-
-/**
+/*
* Display controller interrupt handler for pipe event.
- *
*/
-static void mid_pipe_event_handler(struct drm_device *dev, int pipe)
+static void gma_pipe_event_handler(struct drm_device *dev, int pipe)
{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
uint32_t pipe_stat_val = 0;
- uint32_t pipe_stat_reg = psb_pipestat(pipe);
+ uint32_t pipe_stat_reg = gma_pipestat(pipe);
uint32_t pipe_enable = dev_priv->pipestat[pipe];
uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
uint32_t pipe_clear;
@@ -178,33 +112,95 @@ static void mid_pipe_event_handler(struct drm_device *dev, int pipe)
"%s, can't clear status bits for pipe %d, its value = 0x%x.\n",
__func__, pipe, PSB_RVDC32(pipe_stat_reg));
- if (pipe_stat_val & PIPE_VBLANK_STATUS)
- drm_handle_vblank(dev, pipe);
+ if (pipe_stat_val & PIPE_VBLANK_STATUS) {
+ struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
+ struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+ unsigned long flags;
- if (pipe_stat_val & PIPE_TE_STATUS)
drm_handle_vblank(dev, pipe);
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ if (gma_crtc->page_flip_event) {
+ drm_crtc_send_vblank_event(crtc,
+ gma_crtc->page_flip_event);
+ gma_crtc->page_flip_event = NULL;
+ drm_crtc_vblank_put(crtc);
+ }
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
}
/*
* Display controller interrupt handler.
*/
-static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
+static void gma_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
{
if (vdc_stat & _PSB_IRQ_ASLE)
psb_intel_opregion_asle_intr(dev);
if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
- mid_pipe_event_handler(dev, 0);
+ gma_pipe_event_handler(dev, 0);
if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG)
- mid_pipe_event_handler(dev, 1);
+ gma_pipe_event_handler(dev, 1);
}
-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
+/*
+ * SGX interrupt handler
+ */
+static void gma_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2)
+{
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ u32 val, addr;
+
+ if (stat_1 & _PSB_CE_TWOD_COMPLETE)
+ val = PSB_RSGX32(PSB_CR_2D_BLIT_STATUS);
+
+ if (stat_2 & _PSB_CE2_BIF_REQUESTER_FAULT) {
+ val = PSB_RSGX32(PSB_CR_BIF_INT_STAT);
+ addr = PSB_RSGX32(PSB_CR_BIF_FAULT);
+ if (val) {
+ if (val & _PSB_CBI_STAT_PF_N_RW)
+ DRM_ERROR("SGX MMU page fault:");
+ else
+ DRM_ERROR("SGX MMU read / write protection fault:");
+
+ if (val & _PSB_CBI_STAT_FAULT_CACHE)
+ DRM_ERROR("\tCache requestor");
+ if (val & _PSB_CBI_STAT_FAULT_TA)
+ DRM_ERROR("\tTA requestor");
+ if (val & _PSB_CBI_STAT_FAULT_VDM)
+ DRM_ERROR("\tVDM requestor");
+ if (val & _PSB_CBI_STAT_FAULT_2D)
+ DRM_ERROR("\t2D requestor");
+ if (val & _PSB_CBI_STAT_FAULT_PBE)
+ DRM_ERROR("\tPBE requestor");
+ if (val & _PSB_CBI_STAT_FAULT_TSP)
+ DRM_ERROR("\tTSP requestor");
+ if (val & _PSB_CBI_STAT_FAULT_ISP)
+ DRM_ERROR("\tISP requestor");
+ if (val & _PSB_CBI_STAT_FAULT_USSEPDS)
+ DRM_ERROR("\tUSSEPDS requestor");
+ if (val & _PSB_CBI_STAT_FAULT_HOST)
+ DRM_ERROR("\tHost requestor");
+
+ DRM_ERROR("\tMMU failing address is 0x%08x.\n",
+ (unsigned int)addr);
+ }
+ }
+
+ /* Clear bits */
+ PSB_WSGX32(stat_1, PSB_CR_EVENT_HOST_CLEAR);
+ PSB_WSGX32(stat_2, PSB_CR_EVENT_HOST_CLEAR2);
+ PSB_RSGX32(PSB_CR_EVENT_HOST_CLEAR2);
+}
+
+static irqreturn_t gma_irq_handler(int irq, void *arg)
{
struct drm_device *dev = arg;
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, hotplug_int = 0;
+ u32 sgx_stat_1, sgx_stat_2;
int handled = 0;
spin_lock(&dev_priv->irqmask_lock);
@@ -214,11 +210,6 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
if (vdc_stat & (_PSB_PIPE_EVENT_FLAG|_PSB_IRQ_ASLE))
dsp_int = 1;
- /* FIXME: Handle Medfield
- if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)
- dsp_int = 1;
- */
-
if (vdc_stat & _PSB_IRQ_SGX_FLAG)
sgx_int = 1;
if (vdc_stat & _PSB_IRQ_DISP_HOTSYNC)
@@ -227,20 +218,15 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
vdc_stat &= dev_priv->vdc_irq_mask;
spin_unlock(&dev_priv->irqmask_lock);
- if (dsp_int && gma_power_is_on(dev)) {
- psb_vdc_interrupt(dev, vdc_stat);
+ if (dsp_int) {
+ gma_vdc_interrupt(dev, vdc_stat);
handled = 1;
}
if (sgx_int) {
- /* Not expected - we have it masked, shut it up */
- u32 s, s2;
- s = PSB_RSGX32(PSB_CR_EVENT_STATUS);
- s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
- PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR);
- PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2);
- /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but
- we may as well poll even if we add that ! */
+ sgx_stat_1 = PSB_RSGX32(PSB_CR_EVENT_STATUS);
+ sgx_stat_2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
+ gma_sgx_interrupt(dev, sgx_stat_1, sgx_stat_2);
handled = 1;
}
@@ -253,7 +239,7 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
(void) PSB_RVDC32(PSB_INT_IDENTITY_R);
- DRM_READMEMORYBARRIER();
+ rmb();
if (!handled)
return IRQ_NONE;
@@ -261,77 +247,110 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
return IRQ_HANDLED;
}
-void psb_irq_preinstall(struct drm_device *dev)
+void gma_irq_preinstall(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct drm_crtc *crtc;
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
- if (gma_power_is_on(dev))
- PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
- if (dev->vblank_enabled[0])
- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
- if (dev->vblank_enabled[1])
- dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
-
- /* FIXME: Handle Medfield irq mask
- if (dev->vblank_enabled[1])
- dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;
- if (dev->vblank_enabled[2])
- dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
- */
+ PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+ PSB_WVDC32(0x00000000, PSB_INT_MASK_R);
+ PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
+ PSB_WSGX32(0x00000000, PSB_CR_EVENT_HOST_ENABLE);
+ PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE);
+
+ drm_for_each_crtc(crtc, dev) {
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
+
+ if (vblank->enabled) {
+ u32 mask = drm_crtc_index(crtc) ? _PSB_VSYNC_PIPEB_FLAG :
+ _PSB_VSYNC_PIPEA_FLAG;
+ dev_priv->vdc_irq_mask |= mask;
+ }
+ }
/* Revisit this area - want per device masks ? */
if (dev_priv->ops->hotplug)
dev_priv->vdc_irq_mask |= _PSB_IRQ_DISP_HOTSYNC;
- dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE;
+ dev_priv->vdc_irq_mask |= _PSB_IRQ_ASLE | _PSB_IRQ_SGX_FLAG;
/* This register is safe even if display island is off */
PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
}
-int psb_irq_postinstall(struct drm_device *dev)
+void gma_irq_postinstall(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct drm_crtc *crtc;
unsigned long irqflags;
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+ /* Enable 2D and MMU fault interrupts */
+ PSB_WSGX32(_PSB_CE2_BIF_REQUESTER_FAULT, PSB_CR_EVENT_HOST_ENABLE2);
+ PSB_WSGX32(_PSB_CE_TWOD_COMPLETE, PSB_CR_EVENT_HOST_ENABLE);
+ PSB_RSGX32(PSB_CR_EVENT_HOST_ENABLE); /* Post */
+
/* This register is safe even if display island is off */
PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
- if (dev->vblank_enabled[0])
- 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])
- psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
- else
- psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
+ drm_for_each_crtc(crtc, dev) {
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
- if (dev->vblank_enabled[2])
- psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
- else
- psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
+ if (vblank->enabled)
+ gma_enable_pipestat(dev_priv, drm_crtc_index(crtc), PIPE_VBLANK_INTERRUPT_ENABLE);
+ else
+ gma_disable_pipestat(dev_priv, drm_crtc_index(crtc), PIPE_VBLANK_INTERRUPT_ENABLE);
+ }
if (dev_priv->ops->hotplug_enable)
dev_priv->ops->hotplug_enable(dev, true);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+int gma_irq_install(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ int ret;
+
+ if (dev_priv->use_msi && pci_enable_msi(pdev)) {
+ dev_warn(dev->dev, "Enabling MSI failed!\n");
+ dev_priv->use_msi = false;
+ }
+
+ if (pdev->irq == IRQ_NOTCONNECTED)
+ return -ENOTCONN;
+
+ gma_irq_preinstall(dev);
+
+ /* PCI devices require shared interrupts. */
+ ret = request_irq(pdev->irq, gma_irq_handler, IRQF_SHARED, dev->driver->name, dev);
+ if (ret)
+ return ret;
+
+ gma_irq_postinstall(dev);
+
+ dev_priv->irq_enabled = true;
+
return 0;
}
-void psb_irq_uninstall(struct drm_device *dev)
+void gma_irq_uninstall(struct drm_device *dev)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
+ struct drm_crtc *crtc;
unsigned long irqflags;
+ if (!dev_priv->irq_enabled)
+ return;
+
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
if (dev_priv->ops->hotplug_enable)
@@ -339,14 +358,12 @@ void psb_irq_uninstall(struct drm_device *dev)
PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
- if (dev->vblank_enabled[0])
- psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- if (dev->vblank_enabled[1])
- psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
+ drm_for_each_crtc(crtc, dev) {
+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
- if (dev->vblank_enabled[2])
- psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
+ if (vblank->enabled)
+ gma_disable_pipestat(dev_priv, drm_crtc_index(crtc), PIPE_VBLANK_INTERRUPT_ENABLE);
+ }
dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
_PSB_IRQ_MSVDX_FLAG |
@@ -361,124 +378,20 @@ void psb_irq_uninstall(struct drm_device *dev)
/* This register is safe even if display island is off */
PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-}
-
-void psb_irq_turn_on_dpst(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- u32 hist_reg;
- u32 pwm_reg;
-
- if (gma_power_begin(dev, false)) {
- PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL);
- hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
- PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL);
- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
-
- PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC);
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
- PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE
- | PWM_PHASEIN_INT_ENABLE,
- PWM_CONTROL_LOGIC);
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-
- psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
-
- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
- PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR,
- HISTOGRAM_INT_CONTROL);
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
- PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
- PWM_CONTROL_LOGIC);
- gma_power_end(dev);
- }
+ free_irq(pdev->irq, dev);
+ if (dev_priv->use_msi)
+ pci_disable_msi(pdev);
}
-int psb_irq_enable_dpst(struct drm_device *dev)
+int gma_crtc_enable_vblank(struct drm_crtc *crtc)
{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- /* enable DPST */
- mid_enable_pipe_event(dev_priv, 0);
- psb_irq_turn_on_dpst(dev);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
- return 0;
-}
-
-void psb_irq_turn_off_dpst(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- u32 hist_reg;
- u32 pwm_reg;
-
- if (gma_power_begin(dev, false)) {
- PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
-
- psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
-
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
- PSB_WVDC32(pwm_reg & ~PWM_PHASEIN_INT_ENABLE,
- PWM_CONTROL_LOGIC);
- pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
-
- gma_power_end(dev);
- }
-}
-
-int psb_irq_disable_dpst(struct drm_device *dev)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- unsigned long irqflags;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- mid_disable_pipe_event(dev_priv, 0);
- psb_irq_turn_off_dpst(dev);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-
- return 0;
-}
-
-#ifdef PSB_FIXME
-static int psb_vblank_do_wait(struct drm_device *dev,
- unsigned int *sequence, atomic_t *counter)
-{
- unsigned int cur_vblank;
- int ret = 0;
- DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
- (((cur_vblank = atomic_read(counter))
- - *sequence) <= (1 << 23)));
- *sequence = cur_vblank;
-
- return ret;
-}
-#endif
-
-/*
- * It is used to enable VBLANK interrupt
- */
-int psb_enable_vblank(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_device *dev = crtc->dev;
+ unsigned int pipe = crtc->index;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
unsigned long irqflags;
uint32_t reg_val = 0;
- uint32_t pipeconf_reg = mid_pipeconf(pipe);
-
- /* Medfield is different - we should perhaps extract out vblank
- and blacklight etc ops */
- if (IS_MFLD(dev))
- return mdfld_enable_te(dev, pipe);
+ uint32_t pipeconf_reg = gma_pipeconf(pipe);
if (gma_power_begin(dev, false)) {
reg_val = REG_READ(pipeconf_reg);
@@ -497,23 +410,20 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
- psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
+ gma_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
return 0;
}
-/*
- * It is used to disable VBLANK interrupt
- */
-void psb_disable_vblank(struct drm_device *dev, int pipe)
+void gma_crtc_disable_vblank(struct drm_crtc *crtc)
{
- struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_device *dev = crtc->dev;
+ unsigned int pipe = crtc->index;
+ struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
unsigned long irqflags;
- if (IS_MFLD(dev))
- mdfld_disable_te(dev, pipe);
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
if (pipe == 0)
@@ -523,56 +433,7 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
- psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-}
-
-/*
- * It is used to enable TE interrupt
- */
-int mdfld_enable_te(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- unsigned long irqflags;
- uint32_t reg_val = 0;
- uint32_t pipeconf_reg = mid_pipeconf(pipe);
-
- if (gma_power_begin(dev, false)) {
- reg_val = REG_READ(pipeconf_reg);
- gma_power_end(dev);
- }
-
- if (!(reg_val & PIPEACONF_ENABLE))
- return -EINVAL;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- mid_enable_pipe_event(dev_priv, pipe);
- psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
-
- spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-
- return 0;
-}
-
-/*
- * It is used to disable TE interrupt
- */
-void mdfld_disable_te(struct drm_device *dev, int pipe)
-{
- struct drm_psb_private *dev_priv =
- (struct drm_psb_private *) dev->dev_private;
- unsigned long irqflags;
-
- if (!dev_priv->dsr_enable)
- return;
-
- spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
-
- mid_disable_pipe_event(dev_priv, pipe);
- psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
+ gma_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
}
@@ -580,8 +441,10 @@ void mdfld_disable_te(struct drm_device *dev, int pipe)
/* Called from drm generic code, passed a 'crtc', which
* we use as a pipe index
*/
-u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
+u32 gma_crtc_get_vblank_counter(struct drm_crtc *crtc)
{
+ struct drm_device *dev = crtc->dev;
+ unsigned int pipe = crtc->index;
uint32_t high_frame = PIPEAFRAMEHIGH;
uint32_t low_frame = PIPEAFRAMEPIXEL;
uint32_t pipeconf_reg = PIPEACONF;
@@ -612,9 +475,9 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
reg_val = REG_READ(pipeconf_reg);
if (!(reg_val & PIPEACONF_ENABLE)) {
- dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n",
- pipe);
- goto psb_get_vblank_counter_exit;
+ dev_err(dev->dev, "trying to get vblank count for disabled pipe %u\n",
+ pipe);
+ goto err_gma_power_end;
}
/*
@@ -633,8 +496,7 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
count = (high1 << 8) | low;
-psb_get_vblank_counter_exit:
-
+err_gma_power_end:
gma_power_end(dev);
return count;
diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h
index debb7f190c06..7648f69824a5 100644
--- a/drivers/gpu/drm/gma500/psb_irq.h
+++ b/drivers/gpu/drm/gma500/psb_irq.h
@@ -1,20 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/**************************************************************************
* Copyright (c) 2009-2011, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
* Authors:
* Benjamin Defnet <benjamin.r.defnet@intel.com>
* Rajesh Poornachandran <rajesh.poornachandran@intel.com>
@@ -24,24 +12,18 @@
#ifndef _PSB_IRQ_H_
#define _PSB_IRQ_H_
-#include <drm/drmP.h>
-
-bool sysirq_init(struct drm_device *dev);
-void sysirq_uninit(struct drm_device *dev);
+struct drm_crtc;
+struct drm_device;
-void psb_irq_preinstall(struct drm_device *dev);
-int psb_irq_postinstall(struct drm_device *dev);
-void psb_irq_uninstall(struct drm_device *dev);
-irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
+void gma_irq_preinstall(struct drm_device *dev);
+void gma_irq_postinstall(struct drm_device *dev);
+int gma_irq_install(struct drm_device *dev);
+void gma_irq_uninstall(struct drm_device *dev);
-int psb_irq_enable_dpst(struct drm_device *dev);
-int psb_irq_disable_dpst(struct drm_device *dev);
-void psb_irq_turn_on_dpst(struct drm_device *dev);
-void psb_irq_turn_off_dpst(struct drm_device *dev);
-int psb_enable_vblank(struct drm_device *dev, int pipe);
-void psb_disable_vblank(struct drm_device *dev, int pipe);
-u32 psb_get_vblank_counter(struct drm_device *dev, int pipe);
+int gma_crtc_enable_vblank(struct drm_crtc *crtc);
+void gma_crtc_disable_vblank(struct drm_crtc *crtc);
+u32 gma_crtc_get_vblank_counter(struct drm_crtc *crtc);
+void gma_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
+void gma_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
-int mdfld_enable_te(struct drm_device *dev, int pipe);
-void mdfld_disable_te(struct drm_device *dev, int pipe);
#endif /* _PSB_IRQ_H_ */
diff --git a/drivers/gpu/drm/gma500/psb_lid.c b/drivers/gpu/drm/gma500/psb_lid.c
deleted file mode 100644
index 1d2ebb5e530f..000000000000
--- a/drivers/gpu/drm/gma500/psb_lid.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
- **************************************************************************/
-
-#include <drm/drmP.h>
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include <linux/spinlock.h>
-
-static void psb_lid_timer_func(unsigned long data)
-{
- struct drm_psb_private * dev_priv = (struct drm_psb_private *)data;
- struct drm_device *dev = (struct drm_device *)dev_priv->dev;
- struct timer_list *lid_timer = &dev_priv->lid_timer;
- unsigned long irq_flags;
- u32 __iomem *lid_state = dev_priv->opregion.lid_state;
- u32 pp_status;
-
- if (readl(lid_state) == dev_priv->lid_last_state)
- goto lid_timer_schedule;
-
- if ((readl(lid_state)) & 0x01) {
- /*lid state is open*/
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while ((pp_status & PP_ON) == 0 &&
- (pp_status & PP_SEQUENCE_MASK) != 0);
-
- if (REG_READ(PP_STATUS) & PP_ON) {
- /*FIXME: should be backlight level before*/
- psb_intel_lvds_set_brightness(dev, 100);
- } else {
- DRM_DEBUG("LVDS panel never powered up");
- return;
- }
- } else {
- psb_intel_lvds_set_brightness(dev, 0);
-
- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON);
- do {
- pp_status = REG_READ(PP_STATUS);
- } while ((pp_status & PP_ON) == 0);
- }
- dev_priv->lid_last_state = readl(lid_state);
-
-lid_timer_schedule:
- spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
- if (!timer_pending(lid_timer)) {
- lid_timer->expires = jiffies + PSB_LID_DELAY;
- add_timer(lid_timer);
- }
- spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_init(struct drm_psb_private *dev_priv)
-{
- struct timer_list *lid_timer = &dev_priv->lid_timer;
- unsigned long irq_flags;
-
- spin_lock_init(&dev_priv->lid_lock);
- spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
-
- init_timer(lid_timer);
-
- lid_timer->data = (unsigned long)dev_priv;
- lid_timer->function = psb_lid_timer_func;
- lid_timer->expires = jiffies + PSB_LID_DELAY;
-
- add_timer(lid_timer);
- spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
-}
-
-void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
-{
- del_timer_sync(&dev_priv->lid_timer);
-}
-
diff --git a/drivers/gpu/drm/gma500/psb_reg.h b/drivers/gpu/drm/gma500/psb_reg.h
index b81c7c1e9c2d..2a229a0ef36c 100644
--- a/drivers/gpu/drm/gma500/psb_reg.h
+++ b/drivers/gpu/drm/gma500/psb_reg.h
@@ -1,22 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/**************************************************************************
*
* Copyright (c) (2005-2007) Imagination Technologies Limited.
* Copyright (c) 2007, Intel Corporation.
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA..
- *
**************************************************************************/
#ifndef _PSB_REG_H_
@@ -562,21 +550,7 @@
#define PSB_PM_SSC 0x20
#define PSB_PM_SSS 0x30
#define PSB_PWRGT_DISPLAY_MASK 0xc /*on a different BA than video/gfx*/
-#define MDFLD_PWRGT_DISPLAY_A_CNTR 0x0000000c
-#define MDFLD_PWRGT_DISPLAY_B_CNTR 0x0000c000
-#define MDFLD_PWRGT_DISPLAY_C_CNTR 0x00030000
-#define MDFLD_PWRGT_DISP_MIPI_CNTR 0x000c0000
-#define MDFLD_PWRGT_DISPLAY_CNTR (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */
/* Display SSS register bits are different in A0 vs. B0 */
#define PSB_PWRGT_GFX_MASK 0x3
-#define MDFLD_PWRGT_DISPLAY_A_STS 0x000000c0
-#define MDFLD_PWRGT_DISPLAY_B_STS 0x00000300
-#define MDFLD_PWRGT_DISPLAY_C_STS 0x00000c00
#define PSB_PWRGT_GFX_MASK_B0 0xc3
-#define MDFLD_PWRGT_DISPLAY_A_STS_B0 0x0000000c
-#define MDFLD_PWRGT_DISPLAY_B_STS_B0 0x0000c000
-#define MDFLD_PWRGT_DISPLAY_C_STS_B0 0x00030000
-#define MDFLD_PWRGT_DISP_MIPI_STS 0x000c0000
-#define MDFLD_PWRGT_DISPLAY_STS_A0 (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
-#define MDFLD_PWRGT_DISPLAY_STS_B0 (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
#endif
diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
deleted file mode 100644
index 771ff66711af..000000000000
--- a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
+++ /dev/null
@@ -1,829 +0,0 @@
-/*
- * Copyright © 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.
- *
- */
-
-#include "mdfld_dsi_dpi.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_pkg_sender.h"
-#include "tc35876x-dsi-lvds.h"
-#include <linux/i2c/tc35876x.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/intel_scu_ipc.h>
-
-static struct i2c_client *tc35876x_client;
-static struct i2c_client *cmi_lcd_i2c_client;
-
-#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
-#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
-
-/* DSI D-PHY Layer Registers */
-#define D0W_DPHYCONTTX 0x0004
-#define CLW_DPHYCONTRX 0x0020
-#define D0W_DPHYCONTRX 0x0024
-#define D1W_DPHYCONTRX 0x0028
-#define D2W_DPHYCONTRX 0x002C
-#define D3W_DPHYCONTRX 0x0030
-#define COM_DPHYCONTRX 0x0038
-#define CLW_CNTRL 0x0040
-#define D0W_CNTRL 0x0044
-#define D1W_CNTRL 0x0048
-#define D2W_CNTRL 0x004C
-#define D3W_CNTRL 0x0050
-#define DFTMODE_CNTRL 0x0054
-
-/* DSI PPI Layer Registers */
-#define PPI_STARTPPI 0x0104
-#define PPI_BUSYPPI 0x0108
-#define PPI_LINEINITCNT 0x0110
-#define PPI_LPTXTIMECNT 0x0114
-#define PPI_LANEENABLE 0x0134
-#define PPI_TX_RX_TA 0x013C
-#define PPI_CLS_ATMR 0x0140
-#define PPI_D0S_ATMR 0x0144
-#define PPI_D1S_ATMR 0x0148
-#define PPI_D2S_ATMR 0x014C
-#define PPI_D3S_ATMR 0x0150
-#define PPI_D0S_CLRSIPOCOUNT 0x0164
-#define PPI_D1S_CLRSIPOCOUNT 0x0168
-#define PPI_D2S_CLRSIPOCOUNT 0x016C
-#define PPI_D3S_CLRSIPOCOUNT 0x0170
-#define CLS_PRE 0x0180
-#define D0S_PRE 0x0184
-#define D1S_PRE 0x0188
-#define D2S_PRE 0x018C
-#define D3S_PRE 0x0190
-#define CLS_PREP 0x01A0
-#define D0S_PREP 0x01A4
-#define D1S_PREP 0x01A8
-#define D2S_PREP 0x01AC
-#define D3S_PREP 0x01B0
-#define CLS_ZERO 0x01C0
-#define D0S_ZERO 0x01C4
-#define D1S_ZERO 0x01C8
-#define D2S_ZERO 0x01CC
-#define D3S_ZERO 0x01D0
-#define PPI_CLRFLG 0x01E0
-#define PPI_CLRSIPO 0x01E4
-#define HSTIMEOUT 0x01F0
-#define HSTIMEOUTENABLE 0x01F4
-
-/* DSI Protocol Layer Registers */
-#define DSI_STARTDSI 0x0204
-#define DSI_BUSYDSI 0x0208
-#define DSI_LANEENABLE 0x0210
-#define DSI_LANESTATUS0 0x0214
-#define DSI_LANESTATUS1 0x0218
-#define DSI_INTSTATUS 0x0220
-#define DSI_INTMASK 0x0224
-#define DSI_INTCLR 0x0228
-#define DSI_LPTXTO 0x0230
-
-/* DSI General Registers */
-#define DSIERRCNT 0x0300
-
-/* DSI Application Layer Registers */
-#define APLCTRL 0x0400
-#define RDPKTLN 0x0404
-
-/* Video Path Registers */
-#define VPCTRL 0x0450
-#define HTIM1 0x0454
-#define HTIM2 0x0458
-#define VTIM1 0x045C
-#define VTIM2 0x0460
-#define VFUEN 0x0464
-
-/* LVDS Registers */
-#define LVMX0003 0x0480
-#define LVMX0407 0x0484
-#define LVMX0811 0x0488
-#define LVMX1215 0x048C
-#define LVMX1619 0x0490
-#define LVMX2023 0x0494
-#define LVMX2427 0x0498
-#define LVCFG 0x049C
-#define LVPHY0 0x04A0
-#define LVPHY1 0x04A4
-
-/* System Registers */
-#define SYSSTAT 0x0500
-#define SYSRST 0x0504
-
-/* GPIO Registers */
-/*#define GPIOC 0x0520*/
-#define GPIOO 0x0524
-#define GPIOI 0x0528
-
-/* I2C Registers */
-#define I2CTIMCTRL 0x0540
-#define I2CMADDR 0x0544
-#define WDATAQ 0x0548
-#define RDATAQ 0x054C
-
-/* Chip/Rev Registers */
-#define IDREG 0x0580
-
-/* Debug Registers */
-#define DEBUG00 0x05A0
-#define DEBUG01 0x05A4
-
-/* Panel CABC registers */
-#define PANEL_PWM_CONTROL 0x90
-#define PANEL_FREQ_DIVIDER_HI 0x91
-#define PANEL_FREQ_DIVIDER_LO 0x92
-#define PANEL_DUTY_CONTROL 0x93
-#define PANEL_MODIFY_RGB 0x94
-#define PANEL_FRAMERATE_CONTROL 0x96
-#define PANEL_PWM_MIN 0x97
-#define PANEL_PWM_REF 0x98
-#define PANEL_PWM_MAX 0x99
-#define PANEL_ALLOW_DISTORT 0x9A
-#define PANEL_BYPASS_PWMI 0x9B
-
-/* Panel color management registers */
-#define PANEL_CM_ENABLE 0x700
-#define PANEL_CM_HUE 0x701
-#define PANEL_CM_SATURATION 0x702
-#define PANEL_CM_INTENSITY 0x703
-#define PANEL_CM_BRIGHTNESS 0x704
-#define PANEL_CM_CE_ENABLE 0x705
-#define PANEL_CM_PEAK_EN 0x710
-#define PANEL_CM_GAIN 0x711
-#define PANEL_CM_HUETABLE_START 0x730
-#define PANEL_CM_HUETABLE_END 0x747 /* inclusive */
-
-/* Input muxing for registers LVMX0003...LVMX2427 */
-enum {
- INPUT_R0, /* 0 */
- INPUT_R1,
- INPUT_R2,
- INPUT_R3,
- INPUT_R4,
- INPUT_R5,
- INPUT_R6,
- INPUT_R7,
- INPUT_G0, /* 8 */
- INPUT_G1,
- INPUT_G2,
- INPUT_G3,
- INPUT_G4,
- INPUT_G5,
- INPUT_G6,
- INPUT_G7,
- INPUT_B0, /* 16 */
- INPUT_B1,
- INPUT_B2,
- INPUT_B3,
- INPUT_B4,
- INPUT_B5,
- INPUT_B6,
- INPUT_B7,
- INPUT_HSYNC, /* 24 */
- INPUT_VSYNC,
- INPUT_DE,
- LOGIC_0,
- /* 28...31 undefined */
-};
-
-#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00) \
- (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) | \
- FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
-
-/**
- * tc35876x_regw - Write DSI-LVDS bridge register using I2C
- * @client: struct i2c_client to use
- * @reg: register address
- * @value: value to write
- *
- * Returns 0 on success, or a negative error value.
- */
-static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
-{
- int r;
- u8 tx_data[] = {
- /* NOTE: Register address big-endian, data little-endian. */
- (reg >> 8) & 0xff,
- reg & 0xff,
- value & 0xff,
- (value >> 8) & 0xff,
- (value >> 16) & 0xff,
- (value >> 24) & 0xff,
- };
- struct i2c_msg msgs[] = {
- {
- .addr = client->addr,
- .flags = 0,
- .buf = tx_data,
- .len = ARRAY_SIZE(tx_data),
- },
- };
-
- r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
- if (r < 0) {
- dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
- __func__, reg, value, r);
- return r;
- }
-
- if (r < ARRAY_SIZE(msgs)) {
- dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
- __func__, reg, value, r);
- return -EAGAIN;
- }
-
- dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n",
- __func__, reg, value);
-
- return 0;
-}
-
-/**
- * tc35876x_regr - Read DSI-LVDS bridge register using I2C
- * @client: struct i2c_client to use
- * @reg: register address
- * @value: pointer for storing the value
- *
- * Returns 0 on success, or a negative error value.
- */
-static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
-{
- int r;
- u8 tx_data[] = {
- (reg >> 8) & 0xff,
- reg & 0xff,
- };
- u8 rx_data[4];
- struct i2c_msg msgs[] = {
- {
- .addr = client->addr,
- .flags = 0,
- .buf = tx_data,
- .len = ARRAY_SIZE(tx_data),
- },
- {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .buf = rx_data,
- .len = ARRAY_SIZE(rx_data),
- },
- };
-
- r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
- if (r < 0) {
- dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
- reg, r);
- return r;
- }
-
- if (r < ARRAY_SIZE(msgs)) {
- dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
- reg, r);
- return -EAGAIN;
- }
-
- *value = rx_data[0] << 24 | rx_data[1] << 16 |
- rx_data[2] << 8 | rx_data[3];
-
- dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
- reg, *value);
-
- return 0;
-}
-
-void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state)
-{
- struct tc35876x_platform_data *pdata;
-
- if (WARN(!tc35876x_client, "%s called before probe", __func__))
- return;
-
- dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
-
- pdata = dev_get_platdata(&tc35876x_client->dev);
-
- if (pdata->gpio_bridge_reset == -1)
- return;
-
- if (state) {
- gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
- mdelay(10);
- } else {
- /* Pull MIPI Bridge reset pin to Low */
- gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
- mdelay(20);
- /* Pull MIPI Bridge reset pin to High */
- gpio_set_value_cansleep(pdata->gpio_bridge_reset, 1);
- mdelay(40);
- }
-}
-
-void tc35876x_configure_lvds_bridge(struct drm_device *dev)
-{
- struct i2c_client *i2c = tc35876x_client;
- u32 ppi_lptxtimecnt;
- u32 txtagocnt;
- u32 txtasurecnt;
- u32 id;
-
- if (WARN(!tc35876x_client, "%s called before probe", __func__))
- return;
-
- dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
-
- if (!tc35876x_regr(i2c, IDREG, &id))
- dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
- else
- dev_err(&tc35876x_client->dev, "Cannot read ID\n");
-
- ppi_lptxtimecnt = 4;
- txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
- txtasurecnt = 3 * ppi_lptxtimecnt / 2;
- tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
- FLD_VAL(txtasurecnt, 10, 0));
- tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
-
- tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
- tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
- tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
- tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
-
- /* Enabling MIPI & PPI lanes, Enable 4 lanes */
- tc35876x_regw(i2c, PPI_LANEENABLE,
- BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
- tc35876x_regw(i2c, DSI_LANEENABLE,
- BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
- tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
- tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
-
- /* Setting LVDS output frequency */
- tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
- FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
-
- /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
- tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
-
- /* Horizontal back porch and horizontal pulse width. 0x00280028 */
- tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
-
- /* Horizontal front porch and horizontal active video size. 0x00500500*/
- tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
-
- /* Vertical back porch and vertical sync pulse width. 0x000e000a */
- tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
-
- /* Vertical front porch and vertical display size. 0x000e0320 */
- tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
-
- /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
- tc35876x_regw(i2c, VFUEN, BIT(0));
-
- /* Soft reset LCD controller. */
- tc35876x_regw(i2c, SYSRST, BIT(2));
-
- /* LVDS-TX input muxing */
- tc35876x_regw(i2c, LVMX0003,
- INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2));
- tc35876x_regw(i2c, LVMX0407,
- INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6));
- tc35876x_regw(i2c, LVMX0811,
- INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3));
- tc35876x_regw(i2c, LVMX1215,
- INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5));
- tc35876x_regw(i2c, LVMX1619,
- INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0));
- tc35876x_regw(i2c, LVMX2023,
- INPUT_MUX(LOGIC_0, INPUT_B7, INPUT_B6, INPUT_B5));
- tc35876x_regw(i2c, LVMX2427,
- INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
-
- /* Enable LVDS transmitter. */
- tc35876x_regw(i2c, LVCFG, BIT(0));
-
- /* Clear notifications. Don't write reserved bits. Was write 0xffffffff
- * to 0x0288, must be in error?! */
- tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
-}
-
-#define GPIOPWMCTRL 0x38F
-#define PWM0CLKDIV0 0x62 /* low byte */
-#define PWM0CLKDIV1 0x61 /* high byte */
-
-#define SYSTEMCLK 19200000UL /* 19.2 MHz */
-#define PWM_FREQUENCY 9600 /* Hz */
-
-/* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */
-static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f)
-{
- return (baseclk - f) / f;
-}
-
-static void tc35876x_brightness_init(struct drm_device *dev)
-{
- int ret;
- u8 pwmctrl;
- u16 clkdiv;
-
- /* Make sure the PWM reference is the 19.2 MHz system clock. Read first
- * instead of setting directly to catch potential conflicts between PWM
- * users. */
- ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl);
- if (ret || pwmctrl != 0x01) {
- if (ret)
- dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n");
- else
- dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl);
-
- ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01);
- if (ret)
- dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n");
- }
-
- clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY);
-
- ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
- if (!ret)
- ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff);
-
- if (ret)
- dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n");
- else
- dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n",
- clkdiv, PWM_FREQUENCY);
-}
-
-#define PWM0DUTYCYCLE 0x67
-
-void tc35876x_brightness_control(struct drm_device *dev, int level)
-{
- int ret;
- u8 duty_val;
- u8 panel_duty_val;
-
- level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
-
- /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
- duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
-
- /* I won't pretend to understand this formula. The panel spec is quite
- * bad engrish.
- */
- panel_duty_val = (2 * level - 100) * 0xA9 /
- MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
-
- ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
- if (ret)
- dev_err(&tc35876x_client->dev, "%s: ipc write fail\n",
- __func__);
-
- if (cmi_lcd_i2c_client) {
- ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
- PANEL_PWM_MAX, panel_duty_val);
- if (ret < 0)
- dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n",
- __func__);
- }
-}
-
-void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
-{
- struct tc35876x_platform_data *pdata;
-
- if (WARN(!tc35876x_client, "%s called before probe", __func__))
- return;
-
- dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
-
- pdata = dev_get_platdata(&tc35876x_client->dev);
-
- if (pdata->gpio_panel_bl_en != -1)
- gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0);
-
- if (pdata->gpio_panel_vadd != -1)
- gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0);
-}
-
-void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
-{
- struct tc35876x_platform_data *pdata;
- struct drm_psb_private *dev_priv = dev->dev_private;
-
- if (WARN(!tc35876x_client, "%s called before probe", __func__))
- return;
-
- dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
-
- pdata = dev_get_platdata(&tc35876x_client->dev);
-
- if (pdata->gpio_panel_vadd != -1) {
- gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1);
- msleep(260);
- }
-
- if (cmi_lcd_i2c_client) {
- int ret;
- dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n");
- /* Bit 4 is average_saving. Setting it to 1, the brightness is
- * referenced to the average of the frame content. 0 means
- * reference to the maximum of frame contents. Bits 3:0 are
- * allow_distort. When set to a nonzero value, all color values
- * between 255-allow_distort*2 and 255 are mapped to the
- * 255-allow_distort*2 value.
- */
- ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
- PANEL_ALLOW_DISTORT, 0x10);
- if (ret < 0)
- dev_err(&cmi_lcd_i2c_client->dev,
- "i2c write failed (%d)\n", ret);
- ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
- PANEL_BYPASS_PWMI, 0);
- if (ret < 0)
- dev_err(&cmi_lcd_i2c_client->dev,
- "i2c write failed (%d)\n", ret);
- /* Set minimum brightness value - this is tunable */
- ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
- PANEL_PWM_MIN, 0x35);
- if (ret < 0)
- dev_err(&cmi_lcd_i2c_client->dev,
- "i2c write failed (%d)\n", ret);
- }
-
- if (pdata->gpio_panel_bl_en != -1)
- gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 1);
-
- tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
-}
-
-static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev)
-{
- struct drm_display_mode *mode;
-
- dev_dbg(&dev->pdev->dev, "%s\n", __func__);
-
- mode = kzalloc(sizeof(*mode), GFP_KERNEL);
- if (!mode)
- return NULL;
-
- /* FIXME: do this properly. */
- mode->hdisplay = 1280;
- mode->vdisplay = 800;
- mode->hsync_start = 1360;
- mode->hsync_end = 1400;
- mode->htotal = 1440;
- mode->vsync_start = 814;
- mode->vsync_end = 824;
- mode->vtotal = 838;
- mode->clock = 33324 << 1;
-
- dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay);
- dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay);
- dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start);
- dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end);
- dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal);
- dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start);
- dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end);
- dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal);
- dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock);
-
- drm_mode_set_name(mode);
- drm_mode_set_crtcinfo(mode, 0);
-
- mode->type |= DRM_MODE_TYPE_PREFERRED;
-
- return mode;
-}
-
-/* DV1 Active area 216.96 x 135.6 mm */
-#define DV1_PANEL_WIDTH 217
-#define DV1_PANEL_HEIGHT 136
-
-static int tc35876x_get_panel_info(struct drm_device *dev, int pipe,
- struct panel_info *pi)
-{
- if (!dev || !pi)
- return -EINVAL;
-
- pi->width_mm = DV1_PANEL_WIDTH;
- pi->height_mm = DV1_PANEL_HEIGHT;
-
- return 0;
-}
-
-static int tc35876x_bridge_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct tc35876x_platform_data *pdata;
-
- dev_info(&client->dev, "%s\n", __func__);
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
- __func__);
- return -ENODEV;
- }
-
- pdata = dev_get_platdata(&client->dev);
- if (!pdata) {
- dev_err(&client->dev, "%s: no platform data\n", __func__);
- return -ENODEV;
- }
-
- if (pdata->gpio_bridge_reset != -1) {
- gpio_request(pdata->gpio_bridge_reset, "tc35876x bridge reset");
- gpio_direction_output(pdata->gpio_bridge_reset, 0);
- }
-
- if (pdata->gpio_panel_bl_en != -1) {
- gpio_request(pdata->gpio_panel_bl_en, "tc35876x panel bl en");
- gpio_direction_output(pdata->gpio_panel_bl_en, 0);
- }
-
- if (pdata->gpio_panel_vadd != -1) {
- gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd");
- gpio_direction_output(pdata->gpio_panel_vadd, 0);
- }
-
- tc35876x_client = client;
-
- return 0;
-}
-
-static int tc35876x_bridge_remove(struct i2c_client *client)
-{
- struct tc35876x_platform_data *pdata = dev_get_platdata(&client->dev);
-
- dev_dbg(&client->dev, "%s\n", __func__);
-
- if (pdata->gpio_bridge_reset != -1)
- gpio_free(pdata->gpio_bridge_reset);
-
- if (pdata->gpio_panel_bl_en != -1)
- gpio_free(pdata->gpio_panel_bl_en);
-
- if (pdata->gpio_panel_vadd != -1)
- gpio_free(pdata->gpio_panel_vadd);
-
- tc35876x_client = NULL;
-
- return 0;
-}
-
-static const struct i2c_device_id tc35876x_bridge_id[] = {
- { "i2c_disp_brig", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
-
-static struct i2c_driver tc35876x_bridge_i2c_driver = {
- .driver = {
- .name = "i2c_disp_brig",
- },
- .id_table = tc35876x_bridge_id,
- .probe = tc35876x_bridge_probe,
- .remove = tc35876x_bridge_remove,
-};
-
-/* LCD panel I2C */
-static int cmi_lcd_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- dev_info(&client->dev, "%s\n", __func__);
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
- __func__);
- return -ENODEV;
- }
-
- cmi_lcd_i2c_client = client;
-
- return 0;
-}
-
-static int cmi_lcd_i2c_remove(struct i2c_client *client)
-{
- dev_dbg(&client->dev, "%s\n", __func__);
-
- cmi_lcd_i2c_client = NULL;
-
- return 0;
-}
-
-static const struct i2c_device_id cmi_lcd_i2c_id[] = {
- { "cmi-lcd", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id);
-
-static struct i2c_driver cmi_lcd_i2c_driver = {
- .driver = {
- .name = "cmi-lcd",
- },
- .id_table = cmi_lcd_i2c_id,
- .probe = cmi_lcd_i2c_probe,
- .remove = cmi_lcd_i2c_remove,
-};
-
-/* HACK to create I2C device while it's not created by platform code */
-#define CMI_LCD_I2C_ADAPTER 2
-#define CMI_LCD_I2C_ADDR 0x60
-
-static int cmi_lcd_hack_create_device(void)
-{
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- struct i2c_board_info info = {
- .type = "cmi-lcd",
- .addr = CMI_LCD_I2C_ADDR,
- };
-
- pr_debug("%s\n", __func__);
-
- adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER);
- if (!adapter) {
- pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
- CMI_LCD_I2C_ADAPTER);
- return -EINVAL;
- }
-
- client = i2c_new_device(adapter, &info);
- if (!client) {
- pr_err("%s: i2c_new_device() failed\n", __func__);
- i2c_put_adapter(adapter);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = {
- .dpms = mdfld_dsi_dpi_dpms,
- .mode_fixup = mdfld_dsi_dpi_mode_fixup,
- .prepare = mdfld_dsi_dpi_prepare,
- .mode_set = mdfld_dsi_dpi_mode_set,
- .commit = mdfld_dsi_dpi_commit,
-};
-
-static const struct drm_encoder_funcs tc35876x_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-const struct panel_funcs mdfld_tc35876x_funcs = {
- .encoder_funcs = &tc35876x_encoder_funcs,
- .encoder_helper_funcs = &tc35876x_encoder_helper_funcs,
- .get_config_mode = tc35876x_get_config_mode,
- .get_panel_info = tc35876x_get_panel_info,
-};
-
-void tc35876x_init(struct drm_device *dev)
-{
- int r;
-
- dev_dbg(&dev->pdev->dev, "%s\n", __func__);
-
- cmi_lcd_hack_create_device();
-
- r = i2c_add_driver(&cmi_lcd_i2c_driver);
- if (r < 0)
- dev_err(&dev->pdev->dev,
- "%s: i2c_add_driver() for %s failed (%d)\n",
- __func__, cmi_lcd_i2c_driver.driver.name, r);
-
- r = i2c_add_driver(&tc35876x_bridge_i2c_driver);
- if (r < 0)
- dev_err(&dev->pdev->dev,
- "%s: i2c_add_driver() for %s failed (%d)\n",
- __func__, tc35876x_bridge_i2c_driver.driver.name, r);
-
- tc35876x_brightness_init(dev);
-}
-
-void tc35876x_exit(void)
-{
- pr_debug("%s\n", __func__);
-
- i2c_del_driver(&tc35876x_bridge_i2c_driver);
-
- if (cmi_lcd_i2c_client)
- i2c_del_driver(&cmi_lcd_i2c_driver);
-}
diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h
deleted file mode 100644
index b14b7f9e7d1e..000000000000
--- a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright © 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.
- *
- */
-
-#ifndef __MDFLD_DSI_LVDS_BRIDGE_H__
-#define __MDFLD_DSI_LVDS_BRIDGE_H__
-
-void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state);
-void tc35876x_configure_lvds_bridge(struct drm_device *dev);
-void tc35876x_brightness_control(struct drm_device *dev, int level);
-void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev);
-void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev);
-void tc35876x_init(struct drm_device *dev);
-void tc35876x_exit(void);
-
-extern const struct panel_funcs mdfld_tc35876x_funcs;
-
-#endif /*__MDFLD_DSI_LVDS_BRIDGE_H__*/