Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie: "Intel, radeon and exynos fixes. Nothing too major or wierd: one dmar fix and a radeon cursor corruption, along with misc exynos fixes." * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: (21 commits) drm/exynos: add check for the device power status drm/exynos: Make 'drm_hdmi_get_edid' static drm/exynos: fimd and ipp are broken on multiplatform drm/exynos: don't include plat/gpio-cfg.h drm/exynos: Remove "internal" interrupt handling drm/exynos: Add missing static specifiers in exynos_drm_rotator.c drm/exynos: Replace mdelay with usleep_range drm/exynos: Make ipp_handle_cmd_work static drm/exynos: Make g2d_userptr_get_dma_addr static drm/exynos: consider DMA_NONE flag to dmabuf import drm/exynos: free sg object if dma_map_sg is failed drm/exynos: added validation of edid for vidi connection drm/exynos: let drm handle edid allocations drm/radeon: Enable DMA_IB_SWAP_ENABLE on big endian hosts. drm/radeon: fix a rare case of double kfree radeon_display: Use pointer return error codes drm/radeon: fix cursor corruption on DCE6 and newer drm/i915: dump UTS_RELEASE into the error_state iommu/intel: disable DMAR for g4x integrated gfx drm/i915: GFX_MODE Flush TLB Invalidate Mode must be '1' for scanline waits ...
This commit is contained in:
commit
2e51b231a8
|
@ -24,7 +24,7 @@ config DRM_EXYNOS_DMABUF
|
||||||
|
|
||||||
config DRM_EXYNOS_FIMD
|
config DRM_EXYNOS_FIMD
|
||||||
bool "Exynos DRM FIMD"
|
bool "Exynos DRM FIMD"
|
||||||
depends on DRM_EXYNOS && !FB_S3C
|
depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
|
||||||
help
|
help
|
||||||
Choose this option if you want to use Exynos FIMD for DRM.
|
Choose this option if you want to use Exynos FIMD for DRM.
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ config DRM_EXYNOS_G2D
|
||||||
|
|
||||||
config DRM_EXYNOS_IPP
|
config DRM_EXYNOS_IPP
|
||||||
bool "Exynos DRM IPP"
|
bool "Exynos DRM IPP"
|
||||||
depends on DRM_EXYNOS
|
depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM
|
||||||
help
|
help
|
||||||
Choose this option if you want to use IPP feature for DRM.
|
Choose this option if you want to use IPP feature for DRM.
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "exynos_drm_drv.h"
|
#include "exynos_drm_drv.h"
|
||||||
#include "exynos_drm_encoder.h"
|
#include "exynos_drm_encoder.h"
|
||||||
|
|
||||||
#define MAX_EDID 256
|
|
||||||
#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
|
#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\
|
||||||
drm_connector)
|
drm_connector)
|
||||||
|
|
||||||
|
@ -96,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
|
||||||
to_exynos_connector(connector);
|
to_exynos_connector(connector);
|
||||||
struct exynos_drm_manager *manager = exynos_connector->manager;
|
struct exynos_drm_manager *manager = exynos_connector->manager;
|
||||||
struct exynos_drm_display_ops *display_ops = manager->display_ops;
|
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__);
|
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.
|
* because lcd panel has only one mode.
|
||||||
*/
|
*/
|
||||||
if (display_ops->get_edid) {
|
if (display_ops->get_edid) {
|
||||||
int ret;
|
edid = display_ops->get_edid(manager->dev, connector);
|
||||||
void *edid;
|
if (IS_ERR_OR_NULL(edid)) {
|
||||||
|
ret = PTR_ERR(edid);
|
||||||
edid = kzalloc(MAX_EDID, GFP_KERNEL);
|
edid = NULL;
|
||||||
if (!edid) {
|
DRM_ERROR("Panel operation get_edid failed %d\n", ret);
|
||||||
DRM_ERROR("failed to allocate edid\n");
|
goto out;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = display_ops->get_edid(manager->dev, connector,
|
count = drm_add_edid_modes(connector, edid);
|
||||||
edid, MAX_EDID);
|
if (count < 0) {
|
||||||
if (ret < 0) {
|
DRM_ERROR("Add edid modes failed %d\n", count);
|
||||||
DRM_ERROR("failed to get edid data.\n");
|
goto out;
|
||||||
kfree(edid);
|
|
||||||
edid = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drm_mode_connector_update_edid_property(connector, edid);
|
drm_mode_connector_update_edid_property(connector, edid);
|
||||||
count = drm_add_edid_modes(connector, edid);
|
|
||||||
kfree(edid);
|
|
||||||
} else {
|
} else {
|
||||||
struct exynos_drm_panel_info *panel;
|
struct exynos_drm_panel_info *panel;
|
||||||
struct drm_display_mode *mode = drm_mode_create(connector->dev);
|
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;
|
count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
kfree(edid);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
struct exynos_drm_dmabuf_attachment {
|
struct exynos_drm_dmabuf_attachment {
|
||||||
struct sg_table sgt;
|
struct sg_table sgt;
|
||||||
enum dma_data_direction dir;
|
enum dma_data_direction dir;
|
||||||
|
bool is_mapped;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf,
|
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__);
|
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||||
|
|
||||||
if (WARN_ON(dir == DMA_NONE))
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
|
|
||||||
/* just return current sgt if already requested. */
|
/* 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;
|
return &exynos_attach->sgt;
|
||||||
|
|
||||||
/* reattaching is not allowed. */
|
|
||||||
if (WARN_ON(exynos_attach->dir != DMA_NONE))
|
|
||||||
return ERR_PTR(-EBUSY);
|
|
||||||
|
|
||||||
buf = gem_obj->buffer;
|
buf = gem_obj->buffer;
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
DRM_ERROR("buffer is null.\n");
|
DRM_ERROR("buffer is null.\n");
|
||||||
|
@ -107,13 +101,17 @@ static struct sg_table *
|
||||||
wr = sg_next(wr);
|
wr = sg_next(wr);
|
||||||
}
|
}
|
||||||
|
|
||||||
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
|
if (dir != DMA_NONE) {
|
||||||
if (!nents) {
|
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
|
||||||
DRM_ERROR("failed to map sgl with iommu.\n");
|
if (!nents) {
|
||||||
sgt = ERR_PTR(-EIO);
|
DRM_ERROR("failed to map sgl with iommu.\n");
|
||||||
goto err_unlock;
|
sg_free_table(sgt);
|
||||||
|
sgt = ERR_PTR(-EIO);
|
||||||
|
goto err_unlock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exynos_attach->is_mapped = true;
|
||||||
exynos_attach->dir = dir;
|
exynos_attach->dir = dir;
|
||||||
attach->priv = exynos_attach;
|
attach->priv = exynos_attach;
|
||||||
|
|
||||||
|
|
|
@ -148,8 +148,8 @@ struct exynos_drm_overlay {
|
||||||
struct exynos_drm_display_ops {
|
struct exynos_drm_display_ops {
|
||||||
enum exynos_drm_output_type type;
|
enum exynos_drm_output_type type;
|
||||||
bool (*is_connected)(struct device *dev);
|
bool (*is_connected)(struct device *dev);
|
||||||
int (*get_edid)(struct device *dev, struct drm_connector *connector,
|
struct edid *(*get_edid)(struct device *dev,
|
||||||
u8 *edid, int len);
|
struct drm_connector *connector);
|
||||||
void *(*get_panel)(struct device *dev);
|
void *(*get_panel)(struct device *dev);
|
||||||
int (*check_timing)(struct device *dev, void *timing);
|
int (*check_timing)(struct device *dev, void *timing);
|
||||||
int (*power_on)(struct device *dev, int mode);
|
int (*power_on)(struct device *dev, int mode);
|
||||||
|
|
|
@ -324,7 +324,7 @@ out:
|
||||||
g2d_userptr = NULL;
|
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 userptr,
|
||||||
unsigned long size,
|
unsigned long size,
|
||||||
struct drm_file *filp,
|
struct drm_file *filp,
|
||||||
|
|
|
@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drm_hdmi_get_edid(struct device *dev,
|
static struct edid *drm_hdmi_get_edid(struct device *dev,
|
||||||
struct drm_connector *connector, u8 *edid, int len)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct drm_hdmi_context *ctx = to_context(dev);
|
struct drm_hdmi_context *ctx = to_context(dev);
|
||||||
|
|
||||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||||
|
|
||||||
if (hdmi_ops && hdmi_ops->get_edid)
|
if (hdmi_ops && hdmi_ops->get_edid)
|
||||||
return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid,
|
return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
|
||||||
len);
|
|
||||||
|
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int drm_hdmi_check_timing(struct device *dev, void *timing)
|
static int drm_hdmi_check_timing(struct device *dev, void *timing)
|
||||||
|
|
|
@ -30,8 +30,8 @@ struct exynos_drm_hdmi_context {
|
||||||
struct exynos_hdmi_ops {
|
struct exynos_hdmi_ops {
|
||||||
/* display */
|
/* display */
|
||||||
bool (*is_connected)(void *ctx);
|
bool (*is_connected)(void *ctx);
|
||||||
int (*get_edid)(void *ctx, struct drm_connector *connector,
|
struct edid *(*get_edid)(void *ctx,
|
||||||
u8 *edid, int len);
|
struct drm_connector *connector);
|
||||||
int (*check_timing)(void *ctx, void *timing);
|
int (*check_timing)(void *ctx, void *timing);
|
||||||
int (*power_on)(void *ctx, int mode);
|
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 exynos_drm_ippdrv *ippdrv,
|
||||||
struct drm_exynos_ipp_cmd_work *cmd_work,
|
struct drm_exynos_ipp_cmd_work *cmd_work,
|
||||||
struct drm_exynos_ipp_cmd_node *c_node)
|
struct drm_exynos_ipp_cmd_node *c_node)
|
||||||
|
|
|
@ -734,7 +734,7 @@ static int rotator_remove(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rot_limit_table rot_limit_tbl = {
|
static struct rot_limit_table rot_limit_tbl = {
|
||||||
.ycbcr420_2p = {
|
.ycbcr420_2p = {
|
||||||
.min_w = 32,
|
.min_w = 32,
|
||||||
.min_h = 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",
|
.name = "exynos-rot",
|
||||||
.driver_data = (unsigned long)&rot_limit_tbl,
|
.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;
|
return ctx->connected ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
|
static struct edid *vidi_get_edid(struct device *dev,
|
||||||
u8 *edid, int len)
|
struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct vidi_context *ctx = get_vidi_context(dev);
|
struct vidi_context *ctx = get_vidi_context(dev);
|
||||||
|
struct edid *edid;
|
||||||
|
int edid_len;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
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) {
|
if (!ctx->raw_edid) {
|
||||||
DRM_DEBUG_KMS("raw_edid is null.\n");
|
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_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
|
||||||
* EDID_LENGTH, len));
|
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)
|
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_manager *manager;
|
||||||
struct exynos_drm_display_ops *display_ops;
|
struct exynos_drm_display_ops *display_ops;
|
||||||
struct drm_exynos_vidi_connection *vidi = data;
|
struct drm_exynos_vidi_connection *vidi = data;
|
||||||
struct edid *raw_edid;
|
|
||||||
int edid_len;
|
int edid_len;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
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->connection) {
|
||||||
if (!vidi->edid) {
|
struct edid *raw_edid = (struct edid *)(uint32_t)vidi->edid;
|
||||||
DRM_DEBUG_KMS("edid data is null.\n");
|
if (!drm_edid_is_valid(raw_edid)) {
|
||||||
|
DRM_DEBUG_KMS("edid data is invalid.\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
raw_edid = (struct edid *)(uint32_t)vidi->edid;
|
|
||||||
edid_len = (1 + raw_edid->extensions) * EDID_LENGTH;
|
edid_len = (1 + raw_edid->extensions) * EDID_LENGTH;
|
||||||
ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL);
|
ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL);
|
||||||
if (!ctx->raw_edid) {
|
if (!ctx->raw_edid) {
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
#include <plat/gpio-cfg.h>
|
|
||||||
|
|
||||||
#include <drm/exynos_drm.h>
|
#include <drm/exynos_drm.h>
|
||||||
|
|
||||||
|
@ -98,8 +97,7 @@ struct hdmi_context {
|
||||||
|
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
void *parent_ctx;
|
void *parent_ctx;
|
||||||
int external_irq;
|
int irq;
|
||||||
int internal_irq;
|
|
||||||
|
|
||||||
struct i2c_client *ddc_port;
|
struct i2c_client *ddc_port;
|
||||||
struct i2c_client *hdmiphy_port;
|
struct i2c_client *hdmiphy_port;
|
||||||
|
@ -1391,8 +1389,7 @@ static bool hdmi_is_connected(void *ctx)
|
||||||
return hdata->hpd;
|
return hdata->hpd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
|
static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
|
||||||
u8 *edid, int len)
|
|
||||||
{
|
{
|
||||||
struct edid *raw_edid;
|
struct edid *raw_edid;
|
||||||
struct hdmi_context *hdata = ctx;
|
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__);
|
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||||
|
|
||||||
if (!hdata->ddc_port)
|
if (!hdata->ddc_port)
|
||||||
return -ENODEV;
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
|
raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
|
||||||
if (raw_edid) {
|
if (!raw_edid)
|
||||||
hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
|
return ERR_PTR(-ENODEV);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
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 */
|
/* resetting HDMI core */
|
||||||
hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
|
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);
|
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)
|
static void hdmi_conf_init(struct hdmi_context *hdata)
|
||||||
{
|
{
|
||||||
struct hdmi_infoframe infoframe;
|
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_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
|
||||||
HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
|
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);
|
u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
|
||||||
if (val & HDMI_PHY_STATUS_READY)
|
if (val & HDMI_PHY_STATUS_READY)
|
||||||
break;
|
break;
|
||||||
mdelay(1);
|
usleep_range(1000, 2000);
|
||||||
}
|
}
|
||||||
/* steady state not achieved */
|
/* steady state not achieved */
|
||||||
if (tries == 0) {
|
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);
|
u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
|
||||||
if (val & HDMI_PHY_STATUS_READY)
|
if (val & HDMI_PHY_STATUS_READY)
|
||||||
break;
|
break;
|
||||||
mdelay(1);
|
usleep_range(1000, 2000);
|
||||||
}
|
}
|
||||||
/* steady state not achieved */
|
/* steady state not achieved */
|
||||||
if (tries == 0) {
|
if (tries == 0) {
|
||||||
|
@ -1998,9 +1991,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
|
||||||
|
|
||||||
/* reset hdmiphy */
|
/* reset hdmiphy */
|
||||||
hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
|
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);
|
hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
|
||||||
mdelay(10);
|
usleep_range(10000, 12000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hdmiphy_poweron(struct hdmi_context *hdata)
|
static void hdmiphy_poweron(struct hdmi_context *hdata)
|
||||||
|
@ -2048,7 +2041,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mdelay(10);
|
usleep_range(10000, 12000);
|
||||||
|
|
||||||
/* operation mode */
|
/* operation mode */
|
||||||
operation[0] = 0x1f;
|
operation[0] = 0x1f;
|
||||||
|
@ -2170,6 +2163,13 @@ static void hdmi_commit(void *ctx)
|
||||||
|
|
||||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
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);
|
hdmi_conf_apply(hdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2265,7 +2265,7 @@ static struct exynos_hdmi_ops hdmi_ops = {
|
||||||
.dpms = hdmi_dpms,
|
.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 exynos_drm_hdmi_context *ctx = arg;
|
||||||
struct hdmi_context *hdata = ctx->ctx;
|
struct hdmi_context *hdata = ctx->ctx;
|
||||||
|
@ -2280,31 +2280,6 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
|
||||||
return IRQ_HANDLED;
|
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)
|
static int hdmi_resources_init(struct hdmi_context *hdata)
|
||||||
{
|
{
|
||||||
struct device *dev = hdata->dev;
|
struct device *dev = hdata->dev;
|
||||||
|
@ -2555,39 +2530,24 @@ static int hdmi_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
hdata->hdmiphy_port = hdmi_hdmiphy;
|
hdata->hdmiphy_port = hdmi_hdmiphy;
|
||||||
|
|
||||||
hdata->external_irq = gpio_to_irq(hdata->hpd_gpio);
|
hdata->irq = gpio_to_irq(hdata->hpd_gpio);
|
||||||
if (hdata->external_irq < 0) {
|
if (hdata->irq < 0) {
|
||||||
DRM_ERROR("failed to get GPIO external irq\n");
|
DRM_ERROR("failed to get GPIO irq\n");
|
||||||
ret = hdata->external_irq;
|
ret = hdata->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;
|
|
||||||
goto err_hdmiphy;
|
goto err_hdmiphy;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdata->hpd = gpio_get_value(hdata->hpd_gpio);
|
hdata->hpd = gpio_get_value(hdata->hpd_gpio);
|
||||||
|
|
||||||
ret = request_threaded_irq(hdata->external_irq, NULL,
|
ret = request_threaded_irq(hdata->irq, NULL,
|
||||||
hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
|
hdmi_irq_thread, IRQF_TRIGGER_RISING |
|
||||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||||
"hdmi_external", drm_hdmi_ctx);
|
"hdmi", drm_hdmi_ctx);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRM_ERROR("failed to register hdmi external interrupt\n");
|
DRM_ERROR("failed to register hdmi interrupt\n");
|
||||||
goto err_hdmiphy;
|
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. */
|
/* Attach HDMI Driver to common hdmi. */
|
||||||
exynos_hdmi_drv_attach(drm_hdmi_ctx);
|
exynos_hdmi_drv_attach(drm_hdmi_ctx);
|
||||||
|
|
||||||
|
@ -2598,8 +2558,6 @@ static int hdmi_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_free_irq:
|
|
||||||
free_irq(hdata->external_irq, drm_hdmi_ctx);
|
|
||||||
err_hdmiphy:
|
err_hdmiphy:
|
||||||
i2c_del_driver(&hdmiphy_driver);
|
i2c_del_driver(&hdmiphy_driver);
|
||||||
err_ddc:
|
err_ddc:
|
||||||
|
@ -2617,8 +2575,7 @@ static int hdmi_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
pm_runtime_disable(dev);
|
pm_runtime_disable(dev);
|
||||||
|
|
||||||
free_irq(hdata->internal_irq, hdata);
|
free_irq(hdata->irq, hdata);
|
||||||
free_irq(hdata->external_irq, hdata);
|
|
||||||
|
|
||||||
|
|
||||||
/* hdmiphy i2c driver */
|
/* hdmiphy i2c driver */
|
||||||
|
@ -2637,8 +2594,7 @@ static int hdmi_suspend(struct device *dev)
|
||||||
|
|
||||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||||
|
|
||||||
disable_irq(hdata->internal_irq);
|
disable_irq(hdata->irq);
|
||||||
disable_irq(hdata->external_irq);
|
|
||||||
|
|
||||||
hdata->hpd = false;
|
hdata->hpd = false;
|
||||||
if (ctx->drm_dev)
|
if (ctx->drm_dev)
|
||||||
|
@ -2663,8 +2619,7 @@ static int hdmi_resume(struct device *dev)
|
||||||
|
|
||||||
hdata->hpd = gpio_get_value(hdata->hpd_gpio);
|
hdata->hpd = gpio_get_value(hdata->hpd_gpio);
|
||||||
|
|
||||||
enable_irq(hdata->external_irq);
|
enable_irq(hdata->irq);
|
||||||
enable_irq(hdata->internal_irq);
|
|
||||||
|
|
||||||
if (!pm_runtime_suspended(dev)) {
|
if (!pm_runtime_suspended(dev)) {
|
||||||
DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
|
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 */
|
/* waiting until VP_SRESET_PROCESSING is 0 */
|
||||||
if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
|
if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
|
||||||
break;
|
break;
|
||||||
mdelay(10);
|
usleep_range(10000, 12000);
|
||||||
}
|
}
|
||||||
WARN(tries == 0, "failed to reset Video Processor\n");
|
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);
|
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)
|
if (win > 1 && mixer_ctx->vp_enabled)
|
||||||
vp_video_buffer(mixer_ctx, win);
|
vp_video_buffer(mixer_ctx, win);
|
||||||
else
|
else
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
|
#include <generated/utsrelease.h>
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
#include "intel_drv.h"
|
#include "intel_drv.h"
|
||||||
#include "intel_ringbuffer.h"
|
#include "intel_ringbuffer.h"
|
||||||
|
@ -690,6 +691,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
||||||
|
|
||||||
seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
|
seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
|
||||||
error->time.tv_usec);
|
error->time.tv_usec);
|
||||||
|
seq_printf(m, "Kernel: " UTS_RELEASE);
|
||||||
seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
|
seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
|
||||||
seq_printf(m, "EIR: 0x%08x\n", error->eir);
|
seq_printf(m, "EIR: 0x%08x\n", error->eir);
|
||||||
seq_printf(m, "IER: 0x%08x\n", error->ier);
|
seq_printf(m, "IER: 0x%08x\n", error->ier);
|
||||||
|
|
|
@ -533,6 +533,7 @@
|
||||||
#define MI_MODE 0x0209c
|
#define MI_MODE 0x0209c
|
||||||
# define VS_TIMER_DISPATCH (1 << 6)
|
# define VS_TIMER_DISPATCH (1 << 6)
|
||||||
# define MI_FLUSH_ENABLE (1 << 12)
|
# define MI_FLUSH_ENABLE (1 << 12)
|
||||||
|
# define ASYNC_FLIP_PERF_DISABLE (1 << 14)
|
||||||
|
|
||||||
#define GEN6_GT_MODE 0x20d0
|
#define GEN6_GT_MODE 0x20d0
|
||||||
#define GEN6_GT_MODE_HI (1 << 9)
|
#define GEN6_GT_MODE_HI (1 << 9)
|
||||||
|
|
|
@ -505,13 +505,25 @@ static int init_render_ring(struct intel_ring_buffer *ring)
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
int ret = init_ring_common(ring);
|
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));
|
I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
|
||||||
if (IS_GEN7(dev))
|
|
||||||
I915_WRITE(GFX_MODE_GEN7,
|
/* We need to disable the AsyncFlip performance optimisations in order
|
||||||
_MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
|
* to use MI_WAIT_FOR_EVENT within the CS. It should already be
|
||||||
_MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
|
* 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) {
|
if (INTEL_INFO(dev)->gen >= 5) {
|
||||||
ret = init_pipe_control(ring);
|
ret = init_pipe_control(ring);
|
||||||
|
|
|
@ -1216,7 +1216,7 @@ void cayman_dma_stop(struct radeon_device *rdev)
|
||||||
int cayman_dma_resume(struct radeon_device *rdev)
|
int cayman_dma_resume(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
struct radeon_ring *ring;
|
struct radeon_ring *ring;
|
||||||
u32 rb_cntl, dma_cntl;
|
u32 rb_cntl, dma_cntl, ib_cntl;
|
||||||
u32 rb_bufsz;
|
u32 rb_bufsz;
|
||||||
u32 reg_offset, wb_offset;
|
u32 reg_offset, wb_offset;
|
||||||
int i, r;
|
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);
|
WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8);
|
||||||
|
|
||||||
/* enable DMA IBs */
|
/* 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 = RREG32(DMA_CNTL + reg_offset);
|
||||||
dma_cntl &= ~CTXEMPTY_INT_ENABLE;
|
dma_cntl &= ~CTXEMPTY_INT_ENABLE;
|
||||||
|
|
|
@ -2313,7 +2313,7 @@ void r600_dma_stop(struct radeon_device *rdev)
|
||||||
int r600_dma_resume(struct radeon_device *rdev)
|
int r600_dma_resume(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
|
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;
|
u32 rb_bufsz;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -2353,7 +2353,11 @@ int r600_dma_resume(struct radeon_device *rdev)
|
||||||
WREG32(DMA_RB_BASE, ring->gpu_addr >> 8);
|
WREG32(DMA_RB_BASE, ring->gpu_addr >> 8);
|
||||||
|
|
||||||
/* enable DMA IBs */
|
/* 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 = RREG32(DMA_CNTL);
|
||||||
dma_cntl &= ~CTXEMPTY_INT_ENABLE;
|
dma_cntl &= ~CTXEMPTY_INT_ENABLE;
|
||||||
|
|
|
@ -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) {
|
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[0]);
|
||||||
kfree(p->chunks[p->chunk_ib_idx].kpage[1]);
|
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;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,7 +241,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
|
||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ASIC_IS_AVIVO(rdev)) {
|
/* fixed on DCE6 and newer */
|
||||||
|
if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct drm_crtc *crtc_p;
|
struct drm_crtc *crtc_p;
|
||||||
|
|
||||||
|
|
|
@ -1122,7 +1122,7 @@ radeon_user_framebuffer_create(struct drm_device *dev,
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(radeon_fb);
|
kfree(radeon_fb);
|
||||||
drm_gem_object_unreference_unlocked(obj);
|
drm_gem_object_unreference_unlocked(obj);
|
||||||
return NULL;
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &radeon_fb->base;
|
return &radeon_fb->base;
|
||||||
|
|
|
@ -4234,6 +4234,21 @@ static struct iommu_ops intel_iommu_ops = {
|
||||||
.pgsize_bitmap = INTEL_IOMMU_PGSIZES,
|
.pgsize_bitmap = INTEL_IOMMU_PGSIZES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
/* G4x/GM45 integrated gfx dmar support is totally busted. */
|
||||||
|
printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
|
||||||
|
dmar_map_gfx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
|
||||||
|
|
||||||
static void quirk_iommu_rwbf(struct pci_dev *dev)
|
static void quirk_iommu_rwbf(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -4242,12 +4257,6 @@ static void quirk_iommu_rwbf(struct pci_dev *dev)
|
||||||
*/
|
*/
|
||||||
printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
|
printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
|
||||||
rwbf_quirk = 1;
|
rwbf_quirk = 1;
|
||||||
|
|
||||||
/* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
|
|
||||||
if (dev->revision == 0x07) {
|
|
||||||
printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
|
|
||||||
dmar_map_gfx = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
|
||||||
|
|
Loading…
Reference in New Issue