mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-07 15:18:15 +00:00
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: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
ac0a5dd6ae
commit
bc79482914
7 changed files with 61 additions and 12 deletions
|
@ -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 = {
|
||||||
.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 = {
|
||||||
.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 = {
|
||||||
.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 {
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prevent overflow */
|
||||||
|
if (gt->npage > 4)
|
||||||
|
cursor_pages = 4;
|
||||||
|
else
|
||||||
|
cursor_pages = gt->npage;
|
||||||
|
|
||||||
|
/* Copy the cursor to cursor mem */
|
||||||
|
tmp_dst = dev_priv->vram_addr + cursor_gt->offset;
|
||||||
|
for (i = 0; i < cursor_pages; i++) {
|
||||||
|
tmp_src = kmap(gt->pages[i]);
|
||||||
|
memcpy(tmp_dst, tmp_src, PAGE_SIZE);
|
||||||
|
kunmap(gt->pages[i]);
|
||||||
|
tmp_dst += PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = psb_intel_crtc->cursor_addr;
|
||||||
|
} else {
|
||||||
addr = gt->offset; /* Or resource.start ??? */
|
addr = gt->offset; /* Or resource.start ??? */
|
||||||
|
|
||||||
psb_intel_crtc->cursor_addr = addr;
|
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)
|
||||||
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 = {
|
||||||
* 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;
|
||||||
|
|
||||||
REG_WRITE(control[pipe], 0);
|
if (dev_priv->ops->cursor_needs_phys) {
|
||||||
REG_WRITE(base[pipe], 0);
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
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,
|
||||||
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 {
|
||||||
*/
|
*/
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue