Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Patrik Jakobsson and committed by
Dave Airlie
bc794829 ac0a5dd6

+61 -12
+1
drivers/gpu/drm/gma500/cdv_device.c
··· 563 563 .crtcs = 2, 564 564 .hdmi_mask = (1 << 0) | (1 << 1), 565 565 .lvds_mask = (1 << 1), 566 + .cursor_needs_phys = 0, 566 567 .sgx_offset = MRST_SGX_OFFSET, 567 568 .chip_setup = cdv_chip_setup, 568 569 .errata = cdv_errata,
+1
drivers/gpu/drm/gma500/mdfld_device.c
··· 531 531 .crtcs = 3, 532 532 .lvds_mask = (1 << 1), 533 533 .hdmi_mask = (1 << 1), 534 + .cursor_needs_phys = 0, 534 535 .sgx_offset = MRST_SGX_OFFSET, 535 536 536 537 .chip_setup = mdfld_chip_setup,
+1
drivers/gpu/drm/gma500/oaktrail_device.c
··· 544 544 .crtcs = 2, 545 545 .hdmi_mask = (1 << 0), 546 546 .lvds_mask = (1 << 0), 547 + .cursor_needs_phys = 0, 547 548 .sgx_offset = MRST_SGX_OFFSET, 548 549 549 550 .chip_setup = oaktrail_chip_setup,
+1
drivers/gpu/drm/gma500/psb_device.c
··· 373 373 .crtcs = 2, 374 374 .hdmi_mask = (1 << 0), 375 375 .lvds_mask = (1 << 1), 376 + .cursor_needs_phys = 1, 376 377 .sgx_offset = PSB_SGX_OFFSET, 377 378 .chip_setup = psb_chip_setup, 378 379 .chip_teardown = psb_chip_teardown,
+1
drivers/gpu/drm/gma500/psb_drv.h
··· 655 655 int sgx_offset; /* Base offset of SGX device */ 656 656 int hdmi_mask; /* Mask of HDMI CRTCs */ 657 657 int lvds_mask; /* Mask of LVDS CRTCs */ 658 + int cursor_needs_phys; /* If cursor base reg need physical address */ 658 659 659 660 /* Sub functions */ 660 661 struct drm_crtc_helper_funcs const *crtc_helper;
+55 -7
drivers/gpu/drm/gma500/psb_intel_display.c
··· 928 928 uint32_t width, uint32_t height) 929 929 { 930 930 struct drm_device *dev = crtc->dev; 931 + struct drm_psb_private *dev_priv = dev->dev_private; 931 932 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); 932 933 int pipe = psb_intel_crtc->pipe; 933 934 uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; ··· 936 935 uint32_t temp; 937 936 size_t addr = 0; 938 937 struct gtt_range *gt; 938 + struct gtt_range *cursor_gt = psb_intel_crtc->cursor_gt; 939 939 struct drm_gem_object *obj; 940 - int ret; 940 + void *tmp_dst, *tmp_src; 941 + int ret, i, cursor_pages; 941 942 942 943 /* if we want to turn of the cursor ignore width and height */ 943 944 if (!handle) { ··· 988 985 return ret; 989 986 } 990 987 988 + if (dev_priv->ops->cursor_needs_phys) { 989 + if (cursor_gt == NULL) { 990 + dev_err(dev->dev, "No hardware cursor mem available"); 991 + return -ENOMEM; 992 + } 991 993 992 - addr = gt->offset; /* Or resource.start ??? */ 994 + /* Prevent overflow */ 995 + if (gt->npage > 4) 996 + cursor_pages = 4; 997 + else 998 + cursor_pages = gt->npage; 993 999 994 - psb_intel_crtc->cursor_addr = addr; 1000 + /* Copy the cursor to cursor mem */ 1001 + tmp_dst = dev_priv->vram_addr + cursor_gt->offset; 1002 + for (i = 0; i < cursor_pages; i++) { 1003 + tmp_src = kmap(gt->pages[i]); 1004 + memcpy(tmp_dst, tmp_src, PAGE_SIZE); 1005 + kunmap(gt->pages[i]); 1006 + tmp_dst += PAGE_SIZE; 1007 + } 1008 + 1009 + addr = psb_intel_crtc->cursor_addr; 1010 + } else { 1011 + addr = gt->offset; /* Or resource.start ??? */ 1012 + psb_intel_crtc->cursor_addr = addr; 1013 + } 995 1014 996 1015 temp = 0; 997 1016 /* set the pipe for the cursor */ ··· 1238 1213 drm_gem_object_unreference(psb_intel_crtc->cursor_obj); 1239 1214 psb_intel_crtc->cursor_obj = NULL; 1240 1215 } 1216 + 1217 + if (psb_intel_crtc->cursor_gt != NULL) 1218 + psb_gtt_free_range(crtc->dev, psb_intel_crtc->cursor_gt); 1241 1219 kfree(psb_intel_crtc->crtc_state); 1242 1220 drm_crtc_cleanup(crtc); 1243 1221 kfree(psb_intel_crtc); ··· 1269 1241 * Set the default value of cursor control and base register 1270 1242 * to zero. This is a workaround for h/w defect on Oaktrail 1271 1243 */ 1272 - static void psb_intel_cursor_init(struct drm_device *dev, int pipe) 1244 + static void psb_intel_cursor_init(struct drm_device *dev, 1245 + struct psb_intel_crtc *psb_intel_crtc) 1273 1246 { 1247 + struct drm_psb_private *dev_priv = dev->dev_private; 1274 1248 u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; 1275 1249 u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; 1250 + struct gtt_range *cursor_gt; 1276 1251 1277 - REG_WRITE(control[pipe], 0); 1278 - REG_WRITE(base[pipe], 0); 1252 + if (dev_priv->ops->cursor_needs_phys) { 1253 + /* Allocate 4 pages of stolen mem for a hardware cursor. That 1254 + * is enough for the 64 x 64 ARGB cursors we support. 1255 + */ 1256 + cursor_gt = psb_gtt_alloc_range(dev, 4 * PAGE_SIZE, "cursor", 1); 1257 + if (!cursor_gt) { 1258 + psb_intel_crtc->cursor_gt = NULL; 1259 + goto out; 1260 + } 1261 + psb_intel_crtc->cursor_gt = cursor_gt; 1262 + psb_intel_crtc->cursor_addr = dev_priv->stolen_base + 1263 + cursor_gt->offset; 1264 + } else { 1265 + psb_intel_crtc->cursor_gt = NULL; 1266 + } 1267 + 1268 + out: 1269 + REG_WRITE(control[psb_intel_crtc->pipe], 0); 1270 + REG_WRITE(base[psb_intel_crtc->pipe], 0); 1279 1271 } 1280 1272 1281 1273 void psb_intel_crtc_init(struct drm_device *dev, int pipe, ··· 1361 1313 psb_intel_crtc->mode_set.connectors = 1362 1314 (struct drm_connector **) (psb_intel_crtc + 1); 1363 1315 psb_intel_crtc->mode_set.num_connectors = 0; 1364 - psb_intel_cursor_init(dev, pipe); 1316 + psb_intel_cursor_init(dev, psb_intel_crtc); 1365 1317 } 1366 1318 1367 1319 int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+1 -5
drivers/gpu/drm/gma500/psb_intel_drv.h
··· 106 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 109 * LVDS info 115 110 */ 116 111 int backlight_duty_cycle; /* restore backlight to this value */ ··· 171 176 int pipe; 172 177 int plane; 173 178 uint32_t cursor_addr; 179 + struct gtt_range *cursor_gt; 174 180 u8 lut_r[256], lut_g[256], lut_b[256]; 175 181 u8 lut_adj[256]; 176 182 struct psb_intel_framebuffer *fbdev_fb;