aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/gma500
diff options
context:
space:
mode:
authorPatrik Jakobsson <patrik.r.jakobsson@gmail.com>2012-05-21 10:27:30 -0400
committerDave Airlie <airlied@redhat.com>2012-05-22 05:15:34 -0400
commitbc794829141f28e14fe7d0e07e35870bd9aee78c (patch)
treed6cbf396d69caf53961e4c89b36cb359d51cc0f7 /drivers/gpu/drm/gma500
parentac0a5dd6ae764ba228ec645920b78c70cee05eb7 (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.c1
-rw-r--r--drivers/gpu/drm/gma500/mdfld_device.c1
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_device.c1
-rw-r--r--drivers/gpu/drm/gma500/psb_device.c1
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h1
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_display.c62
-rw-r--r--drivers/gpu/drm/gma500/psb_intel_drv.h6
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 */
1244static void psb_intel_cursor_init(struct drm_device *dev, int pipe) 1272static 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); 1296out:
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
1253void psb_intel_crtc_init(struct drm_device *dev, int pipe, 1301void 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
1319int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, 1367int 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;