提交 bc794829 编写于 作者: P Patrik Jakobsson 提交者: Dave Airlie

gma500: handle poulsbo cursor restriction

Poulsbo needs a physical address in the cursor base register. We allocate a
stolen memory buffer and copy the cursor image provided by userspace into it.
When/If we get our own userspace driver we can map this stolen memory directly.
The patch also adds a mark in chip ops so we can identify devices that has this
requirement.
Signed-off-by: NPatrik Jakobsson <patrik.r.jakobsson@gmail.com>
Signed-off-by: NDave Airlie <airlied@redhat.com>
上级 ac0a5dd6
...@@ -563,6 +563,7 @@ const struct psb_ops cdv_chip_ops = { ...@@ -563,6 +563,7 @@ const struct psb_ops cdv_chip_ops = {
.crtcs = 2, .crtcs = 2,
.hdmi_mask = (1 << 0) | (1 << 1), .hdmi_mask = (1 << 0) | (1 << 1),
.lvds_mask = (1 << 1), .lvds_mask = (1 << 1),
.cursor_needs_phys = 0,
.sgx_offset = MRST_SGX_OFFSET, .sgx_offset = MRST_SGX_OFFSET,
.chip_setup = cdv_chip_setup, .chip_setup = cdv_chip_setup,
.errata = cdv_errata, .errata = cdv_errata,
......
...@@ -531,6 +531,7 @@ const struct psb_ops mdfld_chip_ops = { ...@@ -531,6 +531,7 @@ const struct psb_ops mdfld_chip_ops = {
.crtcs = 3, .crtcs = 3,
.lvds_mask = (1 << 1), .lvds_mask = (1 << 1),
.hdmi_mask = (1 << 1), .hdmi_mask = (1 << 1),
.cursor_needs_phys = 0,
.sgx_offset = MRST_SGX_OFFSET, .sgx_offset = MRST_SGX_OFFSET,
.chip_setup = mdfld_chip_setup, .chip_setup = mdfld_chip_setup,
......
...@@ -544,6 +544,7 @@ const struct psb_ops oaktrail_chip_ops = { ...@@ -544,6 +544,7 @@ const struct psb_ops oaktrail_chip_ops = {
.crtcs = 2, .crtcs = 2,
.hdmi_mask = (1 << 0), .hdmi_mask = (1 << 0),
.lvds_mask = (1 << 0), .lvds_mask = (1 << 0),
.cursor_needs_phys = 0,
.sgx_offset = MRST_SGX_OFFSET, .sgx_offset = MRST_SGX_OFFSET,
.chip_setup = oaktrail_chip_setup, .chip_setup = oaktrail_chip_setup,
......
...@@ -373,6 +373,7 @@ const struct psb_ops psb_chip_ops = { ...@@ -373,6 +373,7 @@ const struct psb_ops psb_chip_ops = {
.crtcs = 2, .crtcs = 2,
.hdmi_mask = (1 << 0), .hdmi_mask = (1 << 0),
.lvds_mask = (1 << 1), .lvds_mask = (1 << 1),
.cursor_needs_phys = 1,
.sgx_offset = PSB_SGX_OFFSET, .sgx_offset = PSB_SGX_OFFSET,
.chip_setup = psb_chip_setup, .chip_setup = psb_chip_setup,
.chip_teardown = psb_chip_teardown, .chip_teardown = psb_chip_teardown,
......
...@@ -655,6 +655,7 @@ struct psb_ops { ...@@ -655,6 +655,7 @@ struct psb_ops {
int sgx_offset; /* Base offset of SGX device */ int sgx_offset; /* Base offset of SGX device */
int hdmi_mask; /* Mask of HDMI CRTCs */ int hdmi_mask; /* Mask of HDMI CRTCs */
int lvds_mask; /* Mask of LVDS CRTCs */ int lvds_mask; /* Mask of LVDS CRTCs */
int cursor_needs_phys; /* If cursor base reg need physical address */
/* Sub functions */ /* Sub functions */
struct drm_crtc_helper_funcs const *crtc_helper; struct drm_crtc_helper_funcs const *crtc_helper;
......
...@@ -928,6 +928,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -928,6 +928,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t width, uint32_t height) uint32_t width, uint32_t height)
{ {
struct drm_device *dev = crtc->dev; 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 *psb_intel_crtc = to_psb_intel_crtc(crtc);
int pipe = psb_intel_crtc->pipe; int pipe = psb_intel_crtc->pipe;
uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
...@@ -935,8 +936,10 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -935,8 +936,10 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t temp; uint32_t temp;
size_t addr = 0; size_t addr = 0;
struct gtt_range *gt; struct gtt_range *gt;
struct gtt_range *cursor_gt = psb_intel_crtc->cursor_gt;
struct drm_gem_object *obj; struct drm_gem_object *obj;
int ret; void *tmp_dst, *tmp_src;
int ret, i, cursor_pages;
/* if we want to turn of the cursor ignore width and height */ /* if we want to turn of the cursor ignore width and height */
if (!handle) { if (!handle) {
...@@ -985,10 +988,32 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -985,10 +988,32 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
return ret; return ret;
} }
if (dev_priv->ops->cursor_needs_phys) {
if (cursor_gt == NULL) {
dev_err(dev->dev, "No hardware cursor mem available");
return -ENOMEM;
}
addr = gt->offset; /* Or resource.start ??? */ /* 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;
}
psb_intel_crtc->cursor_addr = addr; addr = psb_intel_crtc->cursor_addr;
} else {
addr = gt->offset; /* Or resource.start ??? */
psb_intel_crtc->cursor_addr = addr;
}
temp = 0; temp = 0;
/* set the pipe for the cursor */ /* set the pipe for the cursor */
...@@ -1213,6 +1238,9 @@ void psb_intel_crtc_destroy(struct drm_crtc *crtc) ...@@ -1213,6 +1238,9 @@ void psb_intel_crtc_destroy(struct drm_crtc *crtc)
drm_gem_object_unreference(psb_intel_crtc->cursor_obj); drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = NULL; 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); kfree(psb_intel_crtc->crtc_state);
drm_crtc_cleanup(crtc); drm_crtc_cleanup(crtc);
kfree(psb_intel_crtc); kfree(psb_intel_crtc);
...@@ -1241,13 +1269,33 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = { ...@@ -1241,13 +1269,33 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = {
* Set the default value of cursor control and base register * Set the default value of cursor control and base register
* to zero. This is a workaround for h/w defect on Oaktrail * to zero. This is a workaround for h/w defect on Oaktrail
*/ */
static void psb_intel_cursor_init(struct drm_device *dev, int pipe) static void psb_intel_cursor_init(struct drm_device *dev,
struct psb_intel_crtc *psb_intel_crtc)
{ {
struct drm_psb_private *dev_priv = dev->dev_private;
u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR };
u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; u32 base[3] = { CURABASE, CURBBASE, CURCBASE };
struct gtt_range *cursor_gt;
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;
goto out;
}
psb_intel_crtc->cursor_gt = cursor_gt;
psb_intel_crtc->cursor_addr = dev_priv->stolen_base +
cursor_gt->offset;
} else {
psb_intel_crtc->cursor_gt = NULL;
}
REG_WRITE(control[pipe], 0); out:
REG_WRITE(base[pipe], 0); REG_WRITE(control[psb_intel_crtc->pipe], 0);
REG_WRITE(base[psb_intel_crtc->pipe], 0);
} }
void psb_intel_crtc_init(struct drm_device *dev, int pipe, void psb_intel_crtc_init(struct drm_device *dev, int pipe,
...@@ -1313,7 +1361,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, ...@@ -1313,7 +1361,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
psb_intel_crtc->mode_set.connectors = psb_intel_crtc->mode_set.connectors =
(struct drm_connector **) (psb_intel_crtc + 1); (struct drm_connector **) (psb_intel_crtc + 1);
psb_intel_crtc->mode_set.num_connectors = 0; psb_intel_crtc->mode_set.num_connectors = 0;
psb_intel_cursor_init(dev, pipe); psb_intel_cursor_init(dev, psb_intel_crtc);
} }
int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
......
...@@ -105,11 +105,6 @@ struct psb_intel_mode_device { ...@@ -105,11 +105,6 @@ struct psb_intel_mode_device {
*/ */
size_t(*bo_offset) (struct drm_device *dev, void *bo); size_t(*bo_offset) (struct drm_device *dev, void *bo);
/*
* Cursor (Can go ?)
*/
int cursor_needs_physical;
/* /*
* LVDS info * LVDS info
*/ */
...@@ -176,6 +171,7 @@ struct psb_intel_crtc { ...@@ -176,6 +171,7 @@ struct psb_intel_crtc {
int pipe; int pipe;
int plane; int plane;
uint32_t cursor_addr; uint32_t cursor_addr;
struct gtt_range *cursor_gt;
u8 lut_r[256], lut_g[256], lut_b[256]; u8 lut_r[256], lut_g[256], lut_b[256];
u8 lut_adj[256]; u8 lut_adj[256];
struct psb_intel_framebuffer *fbdev_fb; struct psb_intel_framebuffer *fbdev_fb;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册