Merge branch 'fbcon-locking-fixes' of ssh://people.freedesktop.org/~airlied/linux into drm-next
This pulls in most of Linus tree up to -rc6, this fixes the worst lockdep reported issues and re-enables fbcon lockdep. (not the fbcon maintainer) * 'fbcon-locking-fixes' of ssh://people.freedesktop.org/~airlied/linux: (529 commits) Revert "Revert "console: implement lockdep support for console_lock"" fbcon: fix locking harder fb: Yet another band-aid for fixing lockdep mess fb: rework locking to fix lock ordering on takeover
This commit is contained in:
@@ -24,7 +24,7 @@ config DRM_EXYNOS_DMABUF
|
||||
|
||||
config DRM_EXYNOS_FIMD
|
||||
bool "Exynos DRM FIMD"
|
||||
depends on DRM_EXYNOS && !FB_S3C
|
||||
depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
|
||||
help
|
||||
Choose this option if you want to use Exynos FIMD for DRM.
|
||||
|
||||
@@ -48,7 +48,7 @@ config DRM_EXYNOS_G2D
|
||||
|
||||
config DRM_EXYNOS_IPP
|
||||
bool "Exynos DRM IPP"
|
||||
depends on DRM_EXYNOS
|
||||
depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM
|
||||
help
|
||||
Choose this option if you want to use IPP feature for DRM.
|
||||
|
||||
|
@@ -18,7 +18,6 @@
|
||||
#include "exynos_drm_drv.h"
|
||||
#include "exynos_drm_encoder.h"
|
||||
|
||||
#define MAX_EDID 256
|
||||
#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
|
||||
drm_connector)
|
||||
|
||||
@@ -96,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
|
||||
to_exynos_connector(connector);
|
||||
struct exynos_drm_manager *manager = exynos_connector->manager;
|
||||
struct exynos_drm_display_ops *display_ops = manager->display_ops;
|
||||
unsigned int count;
|
||||
struct edid *edid = NULL;
|
||||
unsigned int count = 0;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
@@ -114,27 +115,21 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
|
||||
* because lcd panel has only one mode.
|
||||
*/
|
||||
if (display_ops->get_edid) {
|
||||
int ret;
|
||||
void *edid;
|
||||
|
||||
edid = kzalloc(MAX_EDID, GFP_KERNEL);
|
||||
if (!edid) {
|
||||
DRM_ERROR("failed to allocate edid\n");
|
||||
return 0;
|
||||
edid = display_ops->get_edid(manager->dev, connector);
|
||||
if (IS_ERR_OR_NULL(edid)) {
|
||||
ret = PTR_ERR(edid);
|
||||
edid = NULL;
|
||||
DRM_ERROR("Panel operation get_edid failed %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = display_ops->get_edid(manager->dev, connector,
|
||||
edid, MAX_EDID);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to get edid data.\n");
|
||||
kfree(edid);
|
||||
edid = NULL;
|
||||
return 0;
|
||||
count = drm_add_edid_modes(connector, edid);
|
||||
if (count < 0) {
|
||||
DRM_ERROR("Add edid modes failed %d\n", count);
|
||||
goto out;
|
||||
}
|
||||
|
||||
drm_mode_connector_update_edid_property(connector, edid);
|
||||
count = drm_add_edid_modes(connector, edid);
|
||||
kfree(edid);
|
||||
} else {
|
||||
struct exynos_drm_panel_info *panel;
|
||||
struct drm_display_mode *mode = drm_mode_create(connector->dev);
|
||||
@@ -161,6 +156,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
|
||||
count = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(edid);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,7 @@
|
||||
struct exynos_drm_dmabuf_attachment {
|
||||
struct sg_table sgt;
|
||||
enum dma_data_direction dir;
|
||||
bool is_mapped;
|
||||
};
|
||||
|
||||
static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf,
|
||||
@@ -72,17 +73,10 @@ static struct sg_table *
|
||||
|
||||
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||
|
||||
if (WARN_ON(dir == DMA_NONE))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* just return current sgt if already requested. */
|
||||
if (exynos_attach->dir == dir)
|
||||
if (exynos_attach->dir == dir && exynos_attach->is_mapped)
|
||||
return &exynos_attach->sgt;
|
||||
|
||||
/* reattaching is not allowed. */
|
||||
if (WARN_ON(exynos_attach->dir != DMA_NONE))
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
buf = gem_obj->buffer;
|
||||
if (!buf) {
|
||||
DRM_ERROR("buffer is null.\n");
|
||||
@@ -107,13 +101,17 @@ static struct sg_table *
|
||||
wr = sg_next(wr);
|
||||
}
|
||||
|
||||
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
|
||||
if (!nents) {
|
||||
DRM_ERROR("failed to map sgl with iommu.\n");
|
||||
sgt = ERR_PTR(-EIO);
|
||||
goto err_unlock;
|
||||
if (dir != DMA_NONE) {
|
||||
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
|
||||
if (!nents) {
|
||||
DRM_ERROR("failed to map sgl with iommu.\n");
|
||||
sg_free_table(sgt);
|
||||
sgt = ERR_PTR(-EIO);
|
||||
goto err_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
exynos_attach->is_mapped = true;
|
||||
exynos_attach->dir = dir;
|
||||
attach->priv = exynos_attach;
|
||||
|
||||
|
@@ -148,8 +148,8 @@ struct exynos_drm_overlay {
|
||||
struct exynos_drm_display_ops {
|
||||
enum exynos_drm_output_type type;
|
||||
bool (*is_connected)(struct device *dev);
|
||||
int (*get_edid)(struct device *dev, struct drm_connector *connector,
|
||||
u8 *edid, int len);
|
||||
struct edid *(*get_edid)(struct device *dev,
|
||||
struct drm_connector *connector);
|
||||
void *(*get_panel)(struct device *dev);
|
||||
int (*check_timing)(struct device *dev, void *timing);
|
||||
int (*power_on)(struct device *dev, int mode);
|
||||
|
@@ -324,7 +324,7 @@ out:
|
||||
g2d_userptr = NULL;
|
||||
}
|
||||
|
||||
dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
|
||||
static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
|
||||
unsigned long userptr,
|
||||
unsigned long size,
|
||||
struct drm_file *filp,
|
||||
|
@@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int drm_hdmi_get_edid(struct device *dev,
|
||||
struct drm_connector *connector, u8 *edid, int len)
|
||||
static struct edid *drm_hdmi_get_edid(struct device *dev,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (hdmi_ops && hdmi_ops->get_edid)
|
||||
return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid,
|
||||
len);
|
||||
return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int drm_hdmi_check_timing(struct device *dev, void *timing)
|
||||
|
@@ -30,8 +30,8 @@ struct exynos_drm_hdmi_context {
|
||||
struct exynos_hdmi_ops {
|
||||
/* display */
|
||||
bool (*is_connected)(void *ctx);
|
||||
int (*get_edid)(void *ctx, struct drm_connector *connector,
|
||||
u8 *edid, int len);
|
||||
struct edid *(*get_edid)(void *ctx,
|
||||
struct drm_connector *connector);
|
||||
int (*check_timing)(void *ctx, void *timing);
|
||||
int (*power_on)(void *ctx, int mode);
|
||||
|
||||
|
@@ -869,7 +869,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
|
||||
}
|
||||
}
|
||||
|
||||
void ipp_handle_cmd_work(struct device *dev,
|
||||
static void ipp_handle_cmd_work(struct device *dev,
|
||||
struct exynos_drm_ippdrv *ippdrv,
|
||||
struct drm_exynos_ipp_cmd_work *cmd_work,
|
||||
struct drm_exynos_ipp_cmd_node *c_node)
|
||||
|
@@ -734,7 +734,7 @@ static int rotator_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rot_limit_table rot_limit_tbl = {
|
||||
static struct rot_limit_table rot_limit_tbl = {
|
||||
.ycbcr420_2p = {
|
||||
.min_w = 32,
|
||||
.min_h = 32,
|
||||
@@ -751,7 +751,7 @@ struct rot_limit_table rot_limit_tbl = {
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device_id rotator_driver_ids[] = {
|
||||
static struct platform_device_id rotator_driver_ids[] = {
|
||||
{
|
||||
.name = "exynos-rot",
|
||||
.driver_data = (unsigned long)&rot_limit_tbl,
|
||||
|
@@ -98,10 +98,12 @@ static bool vidi_display_is_connected(struct device *dev)
|
||||
return ctx->connected ? true : false;
|
||||
}
|
||||
|
||||
static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
|
||||
u8 *edid, int len)
|
||||
static struct edid *vidi_get_edid(struct device *dev,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct vidi_context *ctx = get_vidi_context(dev);
|
||||
struct edid *edid;
|
||||
int edid_len;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
@@ -111,13 +113,18 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
|
||||
*/
|
||||
if (!ctx->raw_edid) {
|
||||
DRM_DEBUG_KMS("raw_edid is null.\n");
|
||||
return -EFAULT;
|
||||
return ERR_PTR(-EFAULT);
|
||||
}
|
||||
|
||||
memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions)
|
||||
* EDID_LENGTH, len));
|
||||
edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
|
||||
edid = kzalloc(edid_len, GFP_KERNEL);
|
||||
if (!edid) {
|
||||
DRM_DEBUG_KMS("failed to allocate edid\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
return 0;
|
||||
memcpy(edid, ctx->raw_edid, edid_len);
|
||||
return edid;
|
||||
}
|
||||
|
||||
static void *vidi_get_panel(struct device *dev)
|
||||
@@ -514,7 +521,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
|
||||
struct exynos_drm_manager *manager;
|
||||
struct exynos_drm_display_ops *display_ops;
|
||||
struct drm_exynos_vidi_connection *vidi = data;
|
||||
struct edid *raw_edid;
|
||||
int edid_len;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
@@ -551,11 +557,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
|
||||
}
|
||||
|
||||
if (vidi->connection) {
|
||||
if (!vidi->edid) {
|
||||
DRM_DEBUG_KMS("edid data is null.\n");
|
||||
struct edid *raw_edid = (struct edid *)(uint32_t)vidi->edid;
|
||||
if (!drm_edid_is_valid(raw_edid)) {
|
||||
DRM_DEBUG_KMS("edid data is invalid.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
raw_edid = (struct edid *)(uint32_t)vidi->edid;
|
||||
edid_len = (1 + raw_edid->extensions) * EDID_LENGTH;
|
||||
ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL);
|
||||
if (!ctx->raw_edid) {
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <plat/gpio-cfg.h>
|
||||
|
||||
#include <drm/exynos_drm.h>
|
||||
|
||||
@@ -98,8 +97,7 @@ struct hdmi_context {
|
||||
|
||||
void __iomem *regs;
|
||||
void *parent_ctx;
|
||||
int external_irq;
|
||||
int internal_irq;
|
||||
int irq;
|
||||
|
||||
struct i2c_client *ddc_port;
|
||||
struct i2c_client *hdmiphy_port;
|
||||
@@ -1391,8 +1389,7 @@ static bool hdmi_is_connected(void *ctx)
|
||||
return hdata->hpd;
|
||||
}
|
||||
|
||||
static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
|
||||
u8 *edid, int len)
|
||||
static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
|
||||
{
|
||||
struct edid *raw_edid;
|
||||
struct hdmi_context *hdata = ctx;
|
||||
@@ -1400,22 +1397,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (!hdata->ddc_port)
|
||||
return -ENODEV;
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
|
||||
if (raw_edid) {
|
||||
hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
|
||||
memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
|
||||
* EDID_LENGTH, len));
|
||||
DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
|
||||
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
|
||||
raw_edid->width_cm, raw_edid->height_cm);
|
||||
kfree(raw_edid);
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!raw_edid)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
return 0;
|
||||
hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
|
||||
DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
|
||||
(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
|
||||
raw_edid->width_cm, raw_edid->height_cm);
|
||||
|
||||
return raw_edid;
|
||||
}
|
||||
|
||||
static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
|
||||
@@ -1652,16 +1645,16 @@ static void hdmi_conf_reset(struct hdmi_context *hdata)
|
||||
|
||||
/* resetting HDMI core */
|
||||
hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
|
||||
mdelay(10);
|
||||
usleep_range(10000, 12000);
|
||||
hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
|
||||
mdelay(10);
|
||||
usleep_range(10000, 12000);
|
||||
}
|
||||
|
||||
static void hdmi_conf_init(struct hdmi_context *hdata)
|
||||
{
|
||||
struct hdmi_infoframe infoframe;
|
||||
|
||||
/* disable HPD interrupts */
|
||||
/* disable HPD interrupts from HDMI IP block, use GPIO instead */
|
||||
hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
|
||||
HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
|
||||
|
||||
@@ -1779,7 +1772,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
|
||||
u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
|
||||
if (val & HDMI_PHY_STATUS_READY)
|
||||
break;
|
||||
mdelay(1);
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
/* steady state not achieved */
|
||||
if (tries == 0) {
|
||||
@@ -1946,7 +1939,7 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
|
||||
u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
|
||||
if (val & HDMI_PHY_STATUS_READY)
|
||||
break;
|
||||
mdelay(1);
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
/* steady state not achieved */
|
||||
if (tries == 0) {
|
||||
@@ -1998,9 +1991,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
|
||||
|
||||
/* reset hdmiphy */
|
||||
hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
|
||||
mdelay(10);
|
||||
usleep_range(10000, 12000);
|
||||
hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
|
||||
mdelay(10);
|
||||
usleep_range(10000, 12000);
|
||||
}
|
||||
|
||||
static void hdmiphy_poweron(struct hdmi_context *hdata)
|
||||
@@ -2048,7 +2041,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
|
||||
return;
|
||||
}
|
||||
|
||||
mdelay(10);
|
||||
usleep_range(10000, 12000);
|
||||
|
||||
/* operation mode */
|
||||
operation[0] = 0x1f;
|
||||
@@ -2170,6 +2163,13 @@ static void hdmi_commit(void *ctx)
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mutex_lock(&hdata->hdmi_mutex);
|
||||
if (!hdata->powered) {
|
||||
mutex_unlock(&hdata->hdmi_mutex);
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&hdata->hdmi_mutex);
|
||||
|
||||
hdmi_conf_apply(hdata);
|
||||
}
|
||||
|
||||
@@ -2265,7 +2265,7 @@ static struct exynos_hdmi_ops hdmi_ops = {
|
||||
.dpms = hdmi_dpms,
|
||||
};
|
||||
|
||||
static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
|
||||
static irqreturn_t hdmi_irq_thread(int irq, void *arg)
|
||||
{
|
||||
struct exynos_drm_hdmi_context *ctx = arg;
|
||||
struct hdmi_context *hdata = ctx->ctx;
|
||||
@@ -2280,31 +2280,6 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
|
||||
{
|
||||
struct exynos_drm_hdmi_context *ctx = arg;
|
||||
struct hdmi_context *hdata = ctx->ctx;
|
||||
u32 intc_flag;
|
||||
|
||||
intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
|
||||
/* clearing flags for HPD plug/unplug */
|
||||
if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
|
||||
DRM_DEBUG_KMS("unplugged\n");
|
||||
hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
|
||||
HDMI_INTC_FLAG_HPD_UNPLUG);
|
||||
}
|
||||
if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
|
||||
DRM_DEBUG_KMS("plugged\n");
|
||||
hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
|
||||
HDMI_INTC_FLAG_HPD_PLUG);
|
||||
}
|
||||
|
||||
if (ctx->drm_dev)
|
||||
drm_helper_hpd_irq_event(ctx->drm_dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int hdmi_resources_init(struct hdmi_context *hdata)
|
||||
{
|
||||
struct device *dev = hdata->dev;
|
||||
@@ -2555,39 +2530,24 @@ static int hdmi_probe(struct platform_device *pdev)
|
||||
|
||||
hdata->hdmiphy_port = hdmi_hdmiphy;
|
||||
|
||||
hdata->external_irq = gpio_to_irq(hdata->hpd_gpio);
|
||||
if (hdata->external_irq < 0) {
|
||||
DRM_ERROR("failed to get GPIO external irq\n");
|
||||
ret = hdata->external_irq;
|
||||
goto err_hdmiphy;
|
||||
}
|
||||
|
||||
hdata->internal_irq = platform_get_irq(pdev, 0);
|
||||
if (hdata->internal_irq < 0) {
|
||||
DRM_ERROR("failed to get platform internal irq\n");
|
||||
ret = hdata->internal_irq;
|
||||
hdata->irq = gpio_to_irq(hdata->hpd_gpio);
|
||||
if (hdata->irq < 0) {
|
||||
DRM_ERROR("failed to get GPIO irq\n");
|
||||
ret = hdata->irq;
|
||||
goto err_hdmiphy;
|
||||
}
|
||||
|
||||
hdata->hpd = gpio_get_value(hdata->hpd_gpio);
|
||||
|
||||
ret = request_threaded_irq(hdata->external_irq, NULL,
|
||||
hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
|
||||
ret = request_threaded_irq(hdata->irq, NULL,
|
||||
hdmi_irq_thread, IRQF_TRIGGER_RISING |
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"hdmi_external", drm_hdmi_ctx);
|
||||
"hdmi", drm_hdmi_ctx);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to register hdmi external interrupt\n");
|
||||
DRM_ERROR("failed to register hdmi interrupt\n");
|
||||
goto err_hdmiphy;
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(hdata->internal_irq, NULL,
|
||||
hdmi_internal_irq_thread, IRQF_ONESHOT,
|
||||
"hdmi_internal", drm_hdmi_ctx);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to register hdmi internal interrupt\n");
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
/* Attach HDMI Driver to common hdmi. */
|
||||
exynos_hdmi_drv_attach(drm_hdmi_ctx);
|
||||
|
||||
@@ -2598,8 +2558,6 @@ static int hdmi_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(hdata->external_irq, drm_hdmi_ctx);
|
||||
err_hdmiphy:
|
||||
i2c_del_driver(&hdmiphy_driver);
|
||||
err_ddc:
|
||||
@@ -2617,8 +2575,7 @@ static int hdmi_remove(struct platform_device *pdev)
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
free_irq(hdata->internal_irq, hdata);
|
||||
free_irq(hdata->external_irq, hdata);
|
||||
free_irq(hdata->irq, hdata);
|
||||
|
||||
|
||||
/* hdmiphy i2c driver */
|
||||
@@ -2637,8 +2594,7 @@ static int hdmi_suspend(struct device *dev)
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
disable_irq(hdata->internal_irq);
|
||||
disable_irq(hdata->external_irq);
|
||||
disable_irq(hdata->irq);
|
||||
|
||||
hdata->hpd = false;
|
||||
if (ctx->drm_dev)
|
||||
@@ -2663,8 +2619,7 @@ static int hdmi_resume(struct device *dev)
|
||||
|
||||
hdata->hpd = gpio_get_value(hdata->hpd_gpio);
|
||||
|
||||
enable_irq(hdata->external_irq);
|
||||
enable_irq(hdata->internal_irq);
|
||||
enable_irq(hdata->irq);
|
||||
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
|
||||
|
@@ -600,7 +600,7 @@ static void vp_win_reset(struct mixer_context *ctx)
|
||||
/* waiting until VP_SRESET_PROCESSING is 0 */
|
||||
if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
|
||||
break;
|
||||
mdelay(10);
|
||||
usleep_range(10000, 12000);
|
||||
}
|
||||
WARN(tries == 0, "failed to reset Video Processor\n");
|
||||
}
|
||||
@@ -776,6 +776,13 @@ static void mixer_win_commit(void *ctx, int win)
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
|
||||
|
||||
mutex_lock(&mixer_ctx->mixer_mutex);
|
||||
if (!mixer_ctx->powered) {
|
||||
mutex_unlock(&mixer_ctx->mixer_mutex);
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&mixer_ctx->mixer_mutex);
|
||||
|
||||
if (win > 1 && mixer_ctx->vp_enabled)
|
||||
vp_video_buffer(mixer_ctx, win);
|
||||
else
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <generated/utsrelease.h>
|
||||
#include <drm/drmP.h>
|
||||
#include "intel_drv.h"
|
||||
#include "intel_ringbuffer.h"
|
||||
@@ -644,6 +645,7 @@ static void i915_ring_error_state(struct seq_file *m,
|
||||
seq_printf(m, "%s command stream:\n", ring_str(ring));
|
||||
seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]);
|
||||
seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]);
|
||||
seq_printf(m, " CTL: 0x%08x\n", error->ctl[ring]);
|
||||
seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]);
|
||||
seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]);
|
||||
seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]);
|
||||
@@ -692,10 +694,13 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
||||
|
||||
seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
|
||||
error->time.tv_usec);
|
||||
seq_printf(m, "Kernel: " UTS_RELEASE);
|
||||
seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
|
||||
seq_printf(m, "EIR: 0x%08x\n", error->eir);
|
||||
seq_printf(m, "IER: 0x%08x\n", error->ier);
|
||||
seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
|
||||
seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
|
||||
seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
|
||||
seq_printf(m, "CCID: 0x%08x\n", error->ccid);
|
||||
|
||||
for (i = 0; i < dev_priv->num_fence_regs; i++)
|
||||
|
@@ -209,10 +209,13 @@ struct drm_i915_error_state {
|
||||
u32 pgtbl_er;
|
||||
u32 ier;
|
||||
u32 ccid;
|
||||
u32 derrmr;
|
||||
u32 forcewake;
|
||||
bool waiting[I915_NUM_RINGS];
|
||||
u32 pipestat[I915_MAX_PIPES];
|
||||
u32 tail[I915_NUM_RINGS];
|
||||
u32 head[I915_NUM_RINGS];
|
||||
u32 ctl[I915_NUM_RINGS];
|
||||
u32 ipeir[I915_NUM_RINGS];
|
||||
u32 ipehr[I915_NUM_RINGS];
|
||||
u32 instdone[I915_NUM_RINGS];
|
||||
|
@@ -615,6 +615,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
|
||||
total = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
struct drm_i915_gem_relocation_entry __user *user_relocs;
|
||||
u64 invalid_offset = (u64)-1;
|
||||
int j;
|
||||
|
||||
user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr;
|
||||
|
||||
@@ -625,6 +627,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* As we do not update the known relocation offsets after
|
||||
* relocating (due to the complexities in lock handling),
|
||||
* we need to mark them as invalid now so that we force the
|
||||
* relocation processing next time. Just in case the target
|
||||
* object is evicted and then rebound into its old
|
||||
* presumed_offset before the next execbuffer - if that
|
||||
* happened we would make the mistake of assuming that the
|
||||
* relocations were valid.
|
||||
*/
|
||||
for (j = 0; j < exec[i].relocation_count; j++) {
|
||||
if (copy_to_user(&user_relocs[j].presumed_offset,
|
||||
&invalid_offset,
|
||||
sizeof(invalid_offset))) {
|
||||
ret = -EFAULT;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
reloc_offset[i] = total;
|
||||
total += exec[i].relocation_count;
|
||||
}
|
||||
|
@@ -1228,6 +1228,7 @@ static void i915_record_ring_state(struct drm_device *dev,
|
||||
error->acthd[ring->id] = intel_ring_get_active_head(ring);
|
||||
error->head[ring->id] = I915_READ_HEAD(ring);
|
||||
error->tail[ring->id] = I915_READ_TAIL(ring);
|
||||
error->ctl[ring->id] = I915_READ_CTL(ring);
|
||||
|
||||
error->cpu_ring_head[ring->id] = ring->head;
|
||||
error->cpu_ring_tail[ring->id] = ring->tail;
|
||||
@@ -1323,6 +1324,16 @@ static void i915_capture_error_state(struct drm_device *dev)
|
||||
else
|
||||
error->ier = I915_READ(IER);
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 6)
|
||||
error->derrmr = I915_READ(DERRMR);
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
error->forcewake = I915_READ(FORCEWAKE_VLV);
|
||||
else if (INTEL_INFO(dev)->gen >= 7)
|
||||
error->forcewake = I915_READ(FORCEWAKE_MT);
|
||||
else if (INTEL_INFO(dev)->gen == 6)
|
||||
error->forcewake = I915_READ(FORCEWAKE);
|
||||
|
||||
for_each_pipe(pipe)
|
||||
error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
|
||||
|
||||
|
@@ -521,6 +521,8 @@
|
||||
#define GEN7_ERR_INT 0x44040
|
||||
#define ERR_INT_MMIO_UNCLAIMED (1<<13)
|
||||
|
||||
#define DERRMR 0x44050
|
||||
|
||||
/* GM45+ chicken bits -- debug workaround bits that may be required
|
||||
* for various sorts of correct behavior. The top 16 bits of each are
|
||||
* the enables for writing to the corresponding low bit.
|
||||
@@ -540,6 +542,7 @@
|
||||
#define MI_MODE 0x0209c
|
||||
# define VS_TIMER_DISPATCH (1 << 6)
|
||||
# define MI_FLUSH_ENABLE (1 << 12)
|
||||
# define ASYNC_FLIP_PERF_DISABLE (1 << 14)
|
||||
|
||||
#define GEN6_GT_MODE 0x20d0
|
||||
#define GEN6_GT_MODE_HI (1 << 9)
|
||||
|
@@ -2650,7 +2650,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
|
||||
|
||||
static void
|
||||
intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
||||
struct intel_dp *intel_dp)
|
||||
struct intel_dp *intel_dp,
|
||||
struct edp_power_seq *out)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct edp_power_seq cur, vbt, spec, final;
|
||||
@@ -2721,16 +2722,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
||||
intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
|
||||
#undef get_delay
|
||||
|
||||
DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
|
||||
intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
|
||||
intel_dp->panel_power_cycle_delay);
|
||||
|
||||
DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
|
||||
intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
|
||||
|
||||
if (out)
|
||||
*out = final;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
|
||||
struct intel_dp *intel_dp,
|
||||
struct edp_power_seq *seq)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp_on, pp_off, pp_div;
|
||||
|
||||
/* And finally store the new values in the power sequencer. */
|
||||
pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
|
||||
(final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
|
||||
pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
|
||||
(final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
|
||||
pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
|
||||
(seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
|
||||
pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
|
||||
(seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
|
||||
/* Compute the divisor for the pp clock, simply match the Bspec
|
||||
* formula. */
|
||||
pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1)
|
||||
<< PP_REFERENCE_DIVIDER_SHIFT;
|
||||
pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000)
|
||||
pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
|
||||
<< PANEL_POWER_CYCLE_DELAY_SHIFT);
|
||||
|
||||
/* Haswell doesn't have any port selection bits for the panel
|
||||
@@ -2746,14 +2766,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
||||
I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
|
||||
I915_WRITE(PCH_PP_DIVISOR, pp_div);
|
||||
|
||||
|
||||
DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
|
||||
intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
|
||||
intel_dp->panel_power_cycle_delay);
|
||||
|
||||
DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
|
||||
intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
|
||||
|
||||
DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
|
||||
I915_READ(PCH_PP_ON_DELAYS),
|
||||
I915_READ(PCH_PP_OFF_DELAYS),
|
||||
@@ -2770,6 +2782,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
||||
struct drm_device *dev = intel_encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_display_mode *fixed_mode = NULL;
|
||||
struct edp_power_seq power_seq = { 0 };
|
||||
enum port port = intel_dig_port->port;
|
||||
const char *name = NULL;
|
||||
int type;
|
||||
@@ -2842,7 +2855,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
||||
}
|
||||
|
||||
if (is_edp(intel_dp))
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp);
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
|
||||
|
||||
intel_dp_i2c_init(intel_dp, intel_connector, name);
|
||||
|
||||
@@ -2869,6 +2882,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
||||
return;
|
||||
}
|
||||
|
||||
/* We now know it's not a ghost, init power sequence regs. */
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
|
||||
&power_seq);
|
||||
|
||||
ironlake_edp_panel_vdd_on(intel_dp);
|
||||
edid = drm_get_edid(connector, &intel_dp->adapter);
|
||||
if (edid) {
|
||||
|
@@ -4279,7 +4279,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
|
||||
static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
|
||||
POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
|
||||
/* something from same cacheline, but !FORCEWAKE_MT */
|
||||
POSTING_READ(ECOBUS);
|
||||
}
|
||||
|
||||
static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
|
||||
@@ -4296,7 +4297,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
|
||||
DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
|
||||
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
|
||||
POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
|
||||
/* something from same cacheline, but !FORCEWAKE_MT */
|
||||
POSTING_READ(ECOBUS);
|
||||
|
||||
if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
@@ -4333,14 +4335,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
|
||||
static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE, 0);
|
||||
/* gen6_gt_check_fifodbg doubles as the POSTING_READ */
|
||||
/* something from same cacheline, but !FORCEWAKE */
|
||||
POSTING_READ(ECOBUS);
|
||||
gen6_gt_check_fifodbg(dev_priv);
|
||||
}
|
||||
|
||||
static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
|
||||
/* gen6_gt_check_fifodbg doubles as the POSTING_READ */
|
||||
/* something from same cacheline, but !FORCEWAKE_MT */
|
||||
POSTING_READ(ECOBUS);
|
||||
gen6_gt_check_fifodbg(dev_priv);
|
||||
}
|
||||
|
||||
@@ -4380,6 +4384,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
|
||||
static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff));
|
||||
/* something from same cacheline, but !FORCEWAKE_VLV */
|
||||
POSTING_READ(FORCEWAKE_ACK_VLV);
|
||||
}
|
||||
|
||||
static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
|
||||
@@ -4400,7 +4406,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
|
||||
static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
|
||||
/* The below doubles as a POSTING_READ */
|
||||
/* something from same cacheline, but !FORCEWAKE_VLV */
|
||||
POSTING_READ(FORCEWAKE_ACK_VLV);
|
||||
gen6_gt_check_fifodbg(dev_priv);
|
||||
}
|
||||
|
||||
|
@@ -505,13 +505,25 @@ static int init_render_ring(struct intel_ring_buffer *ring)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret = init_ring_common(ring);
|
||||
|
||||
if (INTEL_INFO(dev)->gen > 3) {
|
||||
if (INTEL_INFO(dev)->gen > 3)
|
||||
I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
|
||||
if (IS_GEN7(dev))
|
||||
I915_WRITE(GFX_MODE_GEN7,
|
||||
_MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
|
||||
_MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
|
||||
}
|
||||
|
||||
/* We need to disable the AsyncFlip performance optimisations in order
|
||||
* to use MI_WAIT_FOR_EVENT within the CS. It should already be
|
||||
* programmed to '1' on all products.
|
||||
*/
|
||||
if (INTEL_INFO(dev)->gen >= 6)
|
||||
I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
|
||||
|
||||
/* Required for the hardware to program scanline values for waiting */
|
||||
if (INTEL_INFO(dev)->gen == 6)
|
||||
I915_WRITE(GFX_MODE,
|
||||
_MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS));
|
||||
|
||||
if (IS_GEN7(dev))
|
||||
I915_WRITE(GFX_MODE_GEN7,
|
||||
_MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
|
||||
_MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 5) {
|
||||
ret = init_pipe_control(ring);
|
||||
|
@@ -1313,14 +1313,18 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
|
||||
if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) {
|
||||
radeon_wait_for_vblank(rdev, i);
|
||||
tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
|
||||
WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
|
||||
}
|
||||
} else {
|
||||
tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
|
||||
if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) {
|
||||
radeon_wait_for_vblank(rdev, i);
|
||||
tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
|
||||
}
|
||||
}
|
||||
/* wait for the next frame */
|
||||
@@ -1345,6 +1349,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
|
||||
blackout &= ~BLACKOUT_MODE_MASK;
|
||||
WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1);
|
||||
}
|
||||
/* wait for the MC to settle */
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
|
||||
@@ -1378,11 +1384,15 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
|
||||
if (ASIC_IS_DCE6(rdev)) {
|
||||
tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
|
||||
tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
|
||||
WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
|
||||
} else {
|
||||
tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
|
||||
tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
|
||||
WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
|
||||
}
|
||||
/* wait for the next frame */
|
||||
frame_count = radeon_get_vblank_counter(rdev, i);
|
||||
@@ -2036,9 +2046,20 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
|
||||
WREG32(HDP_ADDR_CONFIG, gb_addr_config);
|
||||
WREG32(DMA_TILING_CONFIG, gb_addr_config);
|
||||
|
||||
tmp = gb_addr_config & NUM_PIPES_MASK;
|
||||
tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends,
|
||||
EVERGREEN_MAX_BACKENDS, disabled_rb_mask);
|
||||
if ((rdev->config.evergreen.max_backends == 1) &&
|
||||
(rdev->flags & RADEON_IS_IGP)) {
|
||||
if ((disabled_rb_mask & 3) == 1) {
|
||||
/* RB0 disabled, RB1 enabled */
|
||||
tmp = 0x11111111;
|
||||
} else {
|
||||
/* RB1 disabled, RB0 enabled */
|
||||
tmp = 0x00000000;
|
||||
}
|
||||
} else {
|
||||
tmp = gb_addr_config & NUM_PIPES_MASK;
|
||||
tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends,
|
||||
EVERGREEN_MAX_BACKENDS, disabled_rb_mask);
|
||||
}
|
||||
WREG32(GB_BACKEND_MAP, tmp);
|
||||
|
||||
WREG32(CGTS_SYS_TCC_DISABLE, 0);
|
||||
@@ -2401,6 +2422,12 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
|
||||
{
|
||||
struct evergreen_mc_save save;
|
||||
|
||||
if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
|
||||
reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
|
||||
|
||||
if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
|
||||
reset_mask &= ~RADEON_RESET_DMA;
|
||||
|
||||
if (reset_mask == 0)
|
||||
return 0;
|
||||
|
||||
|
@@ -1216,7 +1216,7 @@ void cayman_dma_stop(struct radeon_device *rdev)
|
||||
int cayman_dma_resume(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_ring *ring;
|
||||
u32 rb_cntl, dma_cntl;
|
||||
u32 rb_cntl, dma_cntl, ib_cntl;
|
||||
u32 rb_bufsz;
|
||||
u32 reg_offset, wb_offset;
|
||||
int i, r;
|
||||
@@ -1265,7 +1265,11 @@ int cayman_dma_resume(struct radeon_device *rdev)
|
||||
WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8);
|
||||
|
||||
/* enable DMA IBs */
|
||||
WREG32(DMA_IB_CNTL + reg_offset, DMA_IB_ENABLE | CMD_VMID_FORCE);
|
||||
ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE;
|
||||
#ifdef __BIG_ENDIAN
|
||||
ib_cntl |= DMA_IB_SWAP_ENABLE;
|
||||
#endif
|
||||
WREG32(DMA_IB_CNTL + reg_offset, ib_cntl);
|
||||
|
||||
dma_cntl = RREG32(DMA_CNTL + reg_offset);
|
||||
dma_cntl &= ~CTXEMPTY_INT_ENABLE;
|
||||
@@ -1409,6 +1413,12 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
|
||||
{
|
||||
struct evergreen_mc_save save;
|
||||
|
||||
if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
|
||||
reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
|
||||
|
||||
if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
|
||||
reset_mask &= ~RADEON_RESET_DMA;
|
||||
|
||||
if (reset_mask == 0)
|
||||
return 0;
|
||||
|
||||
|
@@ -1378,6 +1378,12 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
|
||||
{
|
||||
struct rv515_mc_save save;
|
||||
|
||||
if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
|
||||
reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
|
||||
|
||||
if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
|
||||
reset_mask &= ~RADEON_RESET_DMA;
|
||||
|
||||
if (reset_mask == 0)
|
||||
return 0;
|
||||
|
||||
@@ -1456,12 +1462,15 @@ u32 r6xx_remap_render_backend(struct radeon_device *rdev,
|
||||
u32 disabled_rb_mask)
|
||||
{
|
||||
u32 rendering_pipe_num, rb_num_width, req_rb_num;
|
||||
u32 pipe_rb_ratio, pipe_rb_remain;
|
||||
u32 pipe_rb_ratio, pipe_rb_remain, tmp;
|
||||
u32 data = 0, mask = 1 << (max_rb_num - 1);
|
||||
unsigned i, j;
|
||||
|
||||
/* mask out the RBs that don't exist on that asic */
|
||||
disabled_rb_mask |= (0xff << max_rb_num) & 0xff;
|
||||
tmp = disabled_rb_mask | ((0xff << max_rb_num) & 0xff);
|
||||
/* make sure at least one RB is available */
|
||||
if ((tmp & 0xff) != 0xff)
|
||||
disabled_rb_mask = tmp;
|
||||
|
||||
rendering_pipe_num = 1 << tiling_pipe_num;
|
||||
req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask);
|
||||
@@ -2307,7 +2316,7 @@ void r600_dma_stop(struct radeon_device *rdev)
|
||||
int r600_dma_resume(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
|
||||
u32 rb_cntl, dma_cntl;
|
||||
u32 rb_cntl, dma_cntl, ib_cntl;
|
||||
u32 rb_bufsz;
|
||||
int r;
|
||||
|
||||
@@ -2347,7 +2356,11 @@ int r600_dma_resume(struct radeon_device *rdev)
|
||||
WREG32(DMA_RB_BASE, ring->gpu_addr >> 8);
|
||||
|
||||
/* enable DMA IBs */
|
||||
WREG32(DMA_IB_CNTL, DMA_IB_ENABLE);
|
||||
ib_cntl = DMA_IB_ENABLE;
|
||||
#ifdef __BIG_ENDIAN
|
||||
ib_cntl |= DMA_IB_SWAP_ENABLE;
|
||||
#endif
|
||||
WREG32(DMA_IB_CNTL, ib_cntl);
|
||||
|
||||
dma_cntl = RREG32(DMA_CNTL);
|
||||
dma_cntl &= ~CTXEMPTY_INT_ENABLE;
|
||||
|
@@ -324,7 +324,6 @@ struct radeon_bo {
|
||||
struct list_head list;
|
||||
/* Protected by tbo.reserved */
|
||||
u32 placements[3];
|
||||
u32 busy_placements[3];
|
||||
struct ttm_placement placement;
|
||||
struct ttm_buffer_object tbo;
|
||||
struct ttm_bo_kmap_obj kmap;
|
||||
@@ -654,6 +653,8 @@ struct radeon_ring {
|
||||
u32 ptr_reg_mask;
|
||||
u32 nop;
|
||||
u32 idx;
|
||||
u64 last_semaphore_signal_addr;
|
||||
u64 last_semaphore_wait_addr;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -1445,7 +1445,7 @@ static struct radeon_asic cayman_asic = {
|
||||
.vm = {
|
||||
.init = &cayman_vm_init,
|
||||
.fini = &cayman_vm_fini,
|
||||
.pt_ring_index = R600_RING_TYPE_DMA_INDEX,
|
||||
.pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
|
||||
.set_page = &cayman_vm_set_page,
|
||||
},
|
||||
.ring = {
|
||||
@@ -1572,7 +1572,7 @@ static struct radeon_asic trinity_asic = {
|
||||
.vm = {
|
||||
.init = &cayman_vm_init,
|
||||
.fini = &cayman_vm_fini,
|
||||
.pt_ring_index = R600_RING_TYPE_DMA_INDEX,
|
||||
.pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
|
||||
.set_page = &cayman_vm_set_page,
|
||||
},
|
||||
.ring = {
|
||||
@@ -1699,7 +1699,7 @@ static struct radeon_asic si_asic = {
|
||||
.vm = {
|
||||
.init = &si_vm_init,
|
||||
.fini = &si_vm_fini,
|
||||
.pt_ring_index = R600_RING_TYPE_DMA_INDEX,
|
||||
.pt_ring_index = RADEON_RING_TYPE_GFX_INDEX,
|
||||
.set_page = &si_vm_set_page,
|
||||
},
|
||||
.ring = {
|
||||
|
@@ -2470,6 +2470,14 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
|
||||
1),
|
||||
ATOM_DEVICE_CRT1_SUPPORT);
|
||||
}
|
||||
/* RV100 board with external TDMS bit mis-set.
|
||||
* Actually uses internal TMDS, clear the bit.
|
||||
*/
|
||||
if (dev->pdev->device == 0x5159 &&
|
||||
dev->pdev->subsystem_vendor == 0x1014 &&
|
||||
dev->pdev->subsystem_device == 0x029A) {
|
||||
tmp &= ~(1 << 4);
|
||||
}
|
||||
if ((tmp >> 4) & 0x1) {
|
||||
devices |= ATOM_DEVICE_DFP2_SUPPORT;
|
||||
radeon_add_legacy_encoder(dev,
|
||||
|
@@ -286,6 +286,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
|
||||
p->chunks[p->chunk_ib_idx].kpage[1] == NULL) {
|
||||
kfree(p->chunks[p->chunk_ib_idx].kpage[0]);
|
||||
kfree(p->chunks[p->chunk_ib_idx].kpage[1]);
|
||||
p->chunks[p->chunk_ib_idx].kpage[0] = NULL;
|
||||
p->chunks[p->chunk_ib_idx].kpage[1] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
@@ -241,7 +241,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
/* fixed on DCE6 and newer */
|
||||
if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
|
||||
int i = 0;
|
||||
struct drm_crtc *crtc_p;
|
||||
|
||||
|
@@ -429,7 +429,8 @@ bool radeon_card_posted(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE)
|
||||
if (efi_enabled(EFI_BOOT) &&
|
||||
rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE)
|
||||
return false;
|
||||
|
||||
/* first check CRTCs */
|
||||
|
@@ -1115,14 +1115,16 @@ radeon_user_framebuffer_create(struct drm_device *dev,
|
||||
}
|
||||
|
||||
radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL);
|
||||
if (radeon_fb == NULL)
|
||||
if (radeon_fb == NULL) {
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj);
|
||||
if (ret) {
|
||||
kfree(radeon_fb);
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
return NULL;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return &radeon_fb->base;
|
||||
|
@@ -69,9 +69,10 @@
|
||||
* 2.26.0 - r600-eg: fix htile size computation
|
||||
* 2.27.0 - r600-SI: Add CS ioctl support for async DMA
|
||||
* 2.28.0 - r600-eg: Add MEM_WRITE packet support
|
||||
* 2.29.0 - R500 FP16 color clear registers
|
||||
*/
|
||||
#define KMS_DRIVER_MAJOR 2
|
||||
#define KMS_DRIVER_MINOR 28
|
||||
#define KMS_DRIVER_MINOR 29
|
||||
#define KMS_DRIVER_PATCHLEVEL 0
|
||||
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
|
||||
int radeon_driver_unload_kms(struct drm_device *dev);
|
||||
|
@@ -84,6 +84,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
|
||||
rbo->placement.fpfn = 0;
|
||||
rbo->placement.lpfn = 0;
|
||||
rbo->placement.placement = rbo->placements;
|
||||
rbo->placement.busy_placement = rbo->placements;
|
||||
if (domain & RADEON_GEM_DOMAIN_VRAM)
|
||||
rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
|
||||
TTM_PL_FLAG_VRAM;
|
||||
@@ -104,14 +105,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
|
||||
if (!c)
|
||||
rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
|
||||
rbo->placement.num_placement = c;
|
||||
|
||||
c = 0;
|
||||
rbo->placement.busy_placement = rbo->busy_placements;
|
||||
if (rbo->rdev->flags & RADEON_IS_AGP) {
|
||||
rbo->busy_placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT;
|
||||
} else {
|
||||
rbo->busy_placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT;
|
||||
}
|
||||
rbo->placement.num_busy_placement = c;
|
||||
}
|
||||
|
||||
@@ -357,6 +350,7 @@ int radeon_bo_list_validate(struct list_head *head)
|
||||
{
|
||||
struct radeon_bo_list *lobj;
|
||||
struct radeon_bo *bo;
|
||||
u32 domain;
|
||||
int r;
|
||||
|
||||
r = ttm_eu_reserve_buffers(head);
|
||||
@@ -366,9 +360,17 @@ int radeon_bo_list_validate(struct list_head *head)
|
||||
list_for_each_entry(lobj, head, tv.head) {
|
||||
bo = lobj->bo;
|
||||
if (!bo->pin_count) {
|
||||
domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;
|
||||
|
||||
retry:
|
||||
radeon_ttm_placement_from_domain(bo, domain);
|
||||
r = ttm_bo_validate(&bo->tbo, &bo->placement,
|
||||
true, false);
|
||||
if (unlikely(r)) {
|
||||
if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) {
|
||||
domain |= RADEON_GEM_DOMAIN_GTT;
|
||||
goto retry;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
@@ -377,6 +377,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi
|
||||
{
|
||||
int r;
|
||||
|
||||
/* make sure we aren't trying to allocate more space than there is on the ring */
|
||||
if (ndw > (ring->ring_size / 4))
|
||||
return -ENOMEM;
|
||||
/* Align requested size with padding so unlock_commit can
|
||||
* pad safely */
|
||||
ndw = (ndw + ring->align_mask) & ~ring->align_mask;
|
||||
@@ -784,6 +787,8 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
|
||||
}
|
||||
seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr);
|
||||
seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr);
|
||||
seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr);
|
||||
seq_printf(m, "last semaphore wait addr : 0x%016llx\n", ring->last_semaphore_wait_addr);
|
||||
seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
|
||||
seq_printf(m, "%u dwords in ring\n", count);
|
||||
/* print 8 dw before current rptr as often it's the last executed
|
||||
|
@@ -95,6 +95,10 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
|
||||
/* we assume caller has already allocated space on waiters ring */
|
||||
radeon_semaphore_emit_wait(rdev, waiter, semaphore);
|
||||
|
||||
/* for debugging lockup only, used by sysfs debug files */
|
||||
rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr;
|
||||
rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
cayman 0x9400
|
||||
0x0000802C GRBM_GFX_INDEX
|
||||
0x00008040 WAIT_UNTIL
|
||||
0x000084FC CP_STRMOUT_CNTL
|
||||
0x000085F0 CP_COHER_CNTL
|
||||
0x000085F4 CP_COHER_SIZE
|
||||
|
@@ -324,6 +324,8 @@ rv515 0x6d40
|
||||
0x46AC US_OUT_FMT_2
|
||||
0x46B0 US_OUT_FMT_3
|
||||
0x46B4 US_W_FMT
|
||||
0x46C0 RB3D_COLOR_CLEAR_VALUE_AR
|
||||
0x46C4 RB3D_COLOR_CLEAR_VALUE_GB
|
||||
0x4BC0 FG_FOG_BLEND
|
||||
0x4BC4 FG_FOG_FACTOR
|
||||
0x4BC8 FG_FOG_COLOR_R
|
||||
|
@@ -336,6 +336,8 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
|
||||
WREG32(R600_CITF_CNTL, blackout);
|
||||
}
|
||||
}
|
||||
/* wait for the MC to settle */
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
|
||||
|
@@ -2215,6 +2215,12 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
|
||||
{
|
||||
struct evergreen_mc_save save;
|
||||
|
||||
if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
|
||||
reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
|
||||
|
||||
if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
|
||||
reset_mask &= ~RADEON_RESET_DMA;
|
||||
|
||||
if (reset_mask == 0)
|
||||
return 0;
|
||||
|
||||
|
@@ -434,6 +434,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
|
||||
bo->mem = tmp_mem;
|
||||
bdev->driver->move_notify(bo, mem);
|
||||
bo->mem = *mem;
|
||||
*mem = tmp_mem;
|
||||
}
|
||||
|
||||
goto out_err;
|
||||
|
@@ -344,8 +344,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
|
||||
|
||||
if (ttm->state == tt_unpopulated) {
|
||||
ret = ttm->bdev->driver->ttm_tt_populate(ttm);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
/* if we fail here don't nuke the mm node
|
||||
* as the bo still owns it */
|
||||
old_copy.mm_node = NULL;
|
||||
goto out1;
|
||||
}
|
||||
}
|
||||
|
||||
add = 0;
|
||||
@@ -371,8 +375,11 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
|
||||
prot);
|
||||
} else
|
||||
ret = ttm_copy_io_page(new_iomap, old_iomap, page);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
/* failing here, means keep old copy as-is */
|
||||
old_copy.mm_node = NULL;
|
||||
goto out1;
|
||||
}
|
||||
}
|
||||
mb();
|
||||
out2:
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
|
||||
#include <linux/vgaarb.h>
|
||||
@@ -337,8 +338,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
|
||||
|
||||
if (new_client->fb_info) {
|
||||
struct fb_event event;
|
||||
console_lock();
|
||||
event.info = new_client->fb_info;
|
||||
fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
ret = vgasr_priv.handler->switchto(new_client->id);
|
||||
|
Reference in New Issue
Block a user