diff options
author | Patrik Jakobsson <patrik.r.jakobsson@gmail.com> | 2012-05-21 10:27:30 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-05-22 05:15:34 -0400 |
commit | bc794829141f28e14fe7d0e07e35870bd9aee78c (patch) | |
tree | d6cbf396d69caf53961e4c89b36cb359d51cc0f7 /drivers/gpu/drm/gma500 | |
parent | ac0a5dd6ae764ba228ec645920b78c70cee05eb7 (diff) |
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>
Diffstat (limited to 'drivers/gpu/drm/gma500')
-rw-r--r-- | drivers/gpu/drm/gma500/cdv_device.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/mdfld_device.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/oaktrail_device.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_device.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_intel_display.c | 62 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_intel_drv.h | 6 |
7 files changed, 61 insertions, 12 deletions
diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 8e393303f53..9764045428c 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c | |||
@@ -563,6 +563,7 @@ const struct psb_ops cdv_chip_ops = { | |||
563 | .crtcs = 2, | 563 | .crtcs = 2, |
564 | .hdmi_mask = (1 << 0) | (1 << 1), | 564 | .hdmi_mask = (1 << 0) | (1 << 1), |
565 | .lvds_mask = (1 << 1), | 565 | .lvds_mask = (1 << 1), |
566 | .cursor_needs_phys = 0, | ||
566 | .sgx_offset = MRST_SGX_OFFSET, | 567 | .sgx_offset = MRST_SGX_OFFSET, |
567 | .chip_setup = cdv_chip_setup, | 568 | .chip_setup = cdv_chip_setup, |
568 | .errata = cdv_errata, | 569 | .errata = cdv_errata, |
diff --git a/drivers/gpu/drm/gma500/mdfld_device.c b/drivers/gpu/drm/gma500/mdfld_device.c index 2d8e741e06d..265ad0de44a 100644 --- a/drivers/gpu/drm/gma500/mdfld_device.c +++ b/drivers/gpu/drm/gma500/mdfld_device.c | |||
@@ -531,6 +531,7 @@ const struct psb_ops mdfld_chip_ops = { | |||
531 | .crtcs = 3, | 531 | .crtcs = 3, |
532 | .lvds_mask = (1 << 1), | 532 | .lvds_mask = (1 << 1), |
533 | .hdmi_mask = (1 << 1), | 533 | .hdmi_mask = (1 << 1), |
534 | .cursor_needs_phys = 0, | ||
534 | .sgx_offset = MRST_SGX_OFFSET, | 535 | .sgx_offset = MRST_SGX_OFFSET, |
535 | 536 | ||
536 | .chip_setup = mdfld_chip_setup, | 537 | .chip_setup = mdfld_chip_setup, |
diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 7a8ff8e2dfc..0f9b7db80f6 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c | |||
@@ -544,6 +544,7 @@ const struct psb_ops oaktrail_chip_ops = { | |||
544 | .crtcs = 2, | 544 | .crtcs = 2, |
545 | .hdmi_mask = (1 << 0), | 545 | .hdmi_mask = (1 << 0), |
546 | .lvds_mask = (1 << 0), | 546 | .lvds_mask = (1 << 0), |
547 | .cursor_needs_phys = 0, | ||
547 | .sgx_offset = MRST_SGX_OFFSET, | 548 | .sgx_offset = MRST_SGX_OFFSET, |
548 | 549 | ||
549 | .chip_setup = oaktrail_chip_setup, | 550 | .chip_setup = oaktrail_chip_setup, |
diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index 1726c04dedd..2a3e2da4ea8 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c | |||
@@ -373,6 +373,7 @@ const struct psb_ops psb_chip_ops = { | |||
373 | .crtcs = 2, | 373 | .crtcs = 2, |
374 | .hdmi_mask = (1 << 0), | 374 | .hdmi_mask = (1 << 0), |
375 | .lvds_mask = (1 << 1), | 375 | .lvds_mask = (1 << 1), |
376 | .cursor_needs_phys = 1, | ||
376 | .sgx_offset = PSB_SGX_OFFSET, | 377 | .sgx_offset = PSB_SGX_OFFSET, |
377 | .chip_setup = psb_chip_setup, | 378 | .chip_setup = psb_chip_setup, |
378 | .chip_teardown = psb_chip_teardown, | 379 | .chip_teardown = psb_chip_teardown, |
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index a1b0c0bce97..1bd115ecefe 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h | |||
@@ -655,6 +655,7 @@ struct psb_ops { | |||
655 | int sgx_offset; /* Base offset of SGX device */ | 655 | int sgx_offset; /* Base offset of SGX device */ |
656 | int hdmi_mask; /* Mask of HDMI CRTCs */ | 656 | int hdmi_mask; /* Mask of HDMI CRTCs */ |
657 | int lvds_mask; /* Mask of LVDS CRTCs */ | 657 | int lvds_mask; /* Mask of LVDS CRTCs */ |
658 | int cursor_needs_phys; /* If cursor base reg need physical address */ | ||
658 | 659 | ||
659 | /* Sub functions */ | 660 | /* Sub functions */ |
660 | struct drm_crtc_helper_funcs const *crtc_helper; | 661 | struct drm_crtc_helper_funcs const *crtc_helper; |
diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index f3a3160aafd..36c3c99612f 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c | |||
@@ -928,6 +928,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
928 | uint32_t width, uint32_t height) | 928 | uint32_t width, uint32_t height) |
929 | { | 929 | { |
930 | struct drm_device *dev = crtc->dev; | 930 | struct drm_device *dev = crtc->dev; |
931 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
931 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | 932 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); |
932 | int pipe = psb_intel_crtc->pipe; | 933 | int pipe = psb_intel_crtc->pipe; |
933 | uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; | 934 | uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; |
@@ -935,8 +936,10 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
935 | uint32_t temp; | 936 | uint32_t temp; |
936 | size_t addr = 0; | 937 | size_t addr = 0; |
937 | struct gtt_range *gt; | 938 | struct gtt_range *gt; |
939 | struct gtt_range *cursor_gt = psb_intel_crtc->cursor_gt; | ||
938 | struct drm_gem_object *obj; | 940 | struct drm_gem_object *obj; |
939 | int ret; | 941 | void *tmp_dst, *tmp_src; |
942 | int ret, i, cursor_pages; | ||
940 | 943 | ||
941 | /* if we want to turn of the cursor ignore width and height */ | 944 | /* if we want to turn of the cursor ignore width and height */ |
942 | if (!handle) { | 945 | if (!handle) { |
@@ -985,10 +988,32 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
985 | return ret; | 988 | return ret; |
986 | } | 989 | } |
987 | 990 | ||
991 | if (dev_priv->ops->cursor_needs_phys) { | ||
992 | if (cursor_gt == NULL) { | ||
993 | dev_err(dev->dev, "No hardware cursor mem available"); | ||
994 | return -ENOMEM; | ||
995 | } | ||
988 | 996 | ||
989 | addr = gt->offset; /* Or resource.start ??? */ | 997 | /* Prevent overflow */ |
998 | if (gt->npage > 4) | ||
999 | cursor_pages = 4; | ||
1000 | else | ||
1001 | cursor_pages = gt->npage; | ||
1002 | |||
1003 | /* Copy the cursor to cursor mem */ | ||
1004 | tmp_dst = dev_priv->vram_addr + cursor_gt->offset; | ||
1005 | for (i = 0; i < cursor_pages; i++) { | ||
1006 | tmp_src = kmap(gt->pages[i]); | ||
1007 | memcpy(tmp_dst, tmp_src, PAGE_SIZE); | ||
1008 | kunmap(gt->pages[i]); | ||
1009 | tmp_dst += PAGE_SIZE; | ||
1010 | } | ||
990 | 1011 | ||
991 | psb_intel_crtc->cursor_addr = addr; | 1012 | addr = psb_intel_crtc->cursor_addr; |
1013 | } else { | ||
1014 | addr = gt->offset; /* Or resource.start ??? */ | ||
1015 | psb_intel_crtc->cursor_addr = addr; | ||
1016 | } | ||
992 | 1017 | ||
993 | temp = 0; | 1018 | temp = 0; |
994 | /* set the pipe for the cursor */ | 1019 | /* set the pipe for the cursor */ |
@@ -1213,6 +1238,9 @@ void psb_intel_crtc_destroy(struct drm_crtc *crtc) | |||
1213 | drm_gem_object_unreference(psb_intel_crtc->cursor_obj); | 1238 | drm_gem_object_unreference(psb_intel_crtc->cursor_obj); |
1214 | psb_intel_crtc->cursor_obj = NULL; | 1239 | psb_intel_crtc->cursor_obj = NULL; |
1215 | } | 1240 | } |
1241 | |||
1242 | if (psb_intel_crtc->cursor_gt != NULL) | ||
1243 | psb_gtt_free_range(crtc->dev, psb_intel_crtc->cursor_gt); | ||
1216 | kfree(psb_intel_crtc->crtc_state); | 1244 | kfree(psb_intel_crtc->crtc_state); |
1217 | drm_crtc_cleanup(crtc); | 1245 | drm_crtc_cleanup(crtc); |
1218 | kfree(psb_intel_crtc); | 1246 | kfree(psb_intel_crtc); |
@@ -1241,13 +1269,33 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = { | |||
1241 | * Set the default value of cursor control and base register | 1269 | * Set the default value of cursor control and base register |
1242 | * to zero. This is a workaround for h/w defect on Oaktrail | 1270 | * to zero. This is a workaround for h/w defect on Oaktrail |
1243 | */ | 1271 | */ |
1244 | static void psb_intel_cursor_init(struct drm_device *dev, int pipe) | 1272 | static void psb_intel_cursor_init(struct drm_device *dev, |
1273 | struct psb_intel_crtc *psb_intel_crtc) | ||
1245 | { | 1274 | { |
1275 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1246 | u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; | 1276 | u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; |
1247 | u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; | 1277 | u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; |
1278 | struct gtt_range *cursor_gt; | ||
1279 | |||
1280 | if (dev_priv->ops->cursor_needs_phys) { | ||
1281 | /* Allocate 4 pages of stolen mem for a hardware cursor. That | ||
1282 | * is enough for the 64 x 64 ARGB cursors we support. | ||
1283 | */ | ||
1284 | cursor_gt = psb_gtt_alloc_range(dev, 4 * PAGE_SIZE, "cursor", 1); | ||
1285 | if (!cursor_gt) { | ||
1286 | psb_intel_crtc->cursor_gt = NULL; | ||
1287 | goto out; | ||
1288 | } | ||
1289 | psb_intel_crtc->cursor_gt = cursor_gt; | ||
1290 | psb_intel_crtc->cursor_addr = dev_priv->stolen_base + | ||
1291 | cursor_gt->offset; | ||
1292 | } else { | ||
1293 | psb_intel_crtc->cursor_gt = NULL; | ||
1294 | } | ||
1248 | 1295 | ||
1249 | REG_WRITE(control[pipe], 0); | 1296 | out: |
1250 | REG_WRITE(base[pipe], 0); | 1297 | REG_WRITE(control[psb_intel_crtc->pipe], 0); |
1298 | REG_WRITE(base[psb_intel_crtc->pipe], 0); | ||
1251 | } | 1299 | } |
1252 | 1300 | ||
1253 | void psb_intel_crtc_init(struct drm_device *dev, int pipe, | 1301 | 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 | psb_intel_crtc->mode_set.connectors = | 1361 | psb_intel_crtc->mode_set.connectors = |
1314 | (struct drm_connector **) (psb_intel_crtc + 1); | 1362 | (struct drm_connector **) (psb_intel_crtc + 1); |
1315 | psb_intel_crtc->mode_set.num_connectors = 0; | 1363 | psb_intel_crtc->mode_set.num_connectors = 0; |
1316 | psb_intel_cursor_init(dev, pipe); | 1364 | psb_intel_cursor_init(dev, psb_intel_crtc); |
1317 | } | 1365 | } |
1318 | 1366 | ||
1319 | int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | 1367 | int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, |
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 81852b48654..2515f83248c 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h | |||
@@ -106,11 +106,6 @@ struct psb_intel_mode_device { | |||
106 | size_t(*bo_offset) (struct drm_device *dev, void *bo); | 106 | size_t(*bo_offset) (struct drm_device *dev, void *bo); |
107 | 107 | ||
108 | /* | 108 | /* |
109 | * Cursor (Can go ?) | ||
110 | */ | ||
111 | int cursor_needs_physical; | ||
112 | |||
113 | /* | ||
114 | * LVDS info | 109 | * LVDS info |
115 | */ | 110 | */ |
116 | int backlight_duty_cycle; /* restore backlight to this value */ | 111 | int backlight_duty_cycle; /* restore backlight to this value */ |
@@ -176,6 +171,7 @@ struct psb_intel_crtc { | |||
176 | int pipe; | 171 | int pipe; |
177 | int plane; | 172 | int plane; |
178 | uint32_t cursor_addr; | 173 | uint32_t cursor_addr; |
174 | struct gtt_range *cursor_gt; | ||
179 | u8 lut_r[256], lut_g[256], lut_b[256]; | 175 | u8 lut_r[256], lut_g[256], lut_b[256]; |
180 | u8 lut_adj[256]; | 176 | u8 lut_adj[256]; |
181 | struct psb_intel_framebuffer *fbdev_fb; | 177 | struct psb_intel_framebuffer *fbdev_fb; |