diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-25 19:46:44 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-25 19:46:44 -0500 |
| commit | fffddfd6c8e0c10c42c6e2cc54ba880fcc36ebbb (patch) | |
| tree | 71bc5e597124dbaf7550f1e089d675718b3ed5c0 /drivers/gpu/drm/udl | |
| parent | 69086a78bdc973ec0b722be790b146e84ba8a8c4 (diff) | |
| parent | be88298b0a3f771a4802f20c5e66af74bfd1dff1 (diff) | |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm merge from Dave Airlie:
"Highlights:
- TI LCD controller KMS driver
- TI OMAP KMS driver merged from staging
- drop gma500 stub driver
- the fbcon locking fixes
- the vgacon dirty like zebra fix.
- open firmware videomode and hdmi common code helpers
- major locking rework for kms object handling - pageflip/cursor
won't block on polling anymore!
- fbcon helper and prime helper cleanups
- i915: all over the map, haswell power well enhancements, valleyview
macro horrors cleaned up, killing lots of legacy GTT code,
- radeon: CS ioctl unification, deprecated UMS support, gpu reset
rework, VM fixes
- nouveau: reworked thermal code, external dp/tmds encoder support
(anx9805), fences sleep instead of polling,
- exynos: all over the driver fixes."
Lovely conflict in radeon/evergreen_cs.c between commit de0babd60d8d
("drm/radeon: enforce use of radeon_get_ib_value when reading user cmd")
and the new changes that modified that evergreen_dma_cs_parse()
function.
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (508 commits)
drm/tilcdc: only build on arm
drm/i915: Revert hdmi HDP pin checks
drm/tegra: Add list of framebuffers to debugfs
drm/tegra: Fix color expansion
drm/tegra: Split DC_CMD_STATE_CONTROL register write
drm/tegra: Implement page-flipping support
drm/tegra: Implement VBLANK support
drm/tegra: Implement .mode_set_base()
drm/tegra: Add plane support
drm/tegra: Remove bogus tegra_framebuffer structure
drm: Add consistency check for page-flipping
drm/radeon: Use generic HDMI infoframe helpers
drm/tegra: Use generic HDMI infoframe helpers
drm: Add EDID helper documentation
drm: Add HDMI infoframe helpers
video: Add generic HDMI infoframe helpers
drm: Add some missing forward declarations
drm: Move mode tables to drm_edid.c
drm: Remove duplicate drm_mode_cea_vic()
gma500: Fix n, m1 and m2 clock limits for sdvo and lvds
...
Diffstat (limited to 'drivers/gpu/drm/udl')
| -rw-r--r-- | drivers/gpu/drm/udl/udl_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/udl/udl_fb.c | 78 | ||||
| -rw-r--r-- | drivers/gpu/drm/udl/udl_transfer.c | 46 |
3 files changed, 81 insertions, 45 deletions
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 87aa5f5d3c88..cc6d90f28c71 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h | |||
| @@ -75,6 +75,8 @@ struct udl_framebuffer { | |||
| 75 | struct drm_framebuffer base; | 75 | struct drm_framebuffer base; |
| 76 | struct udl_gem_object *obj; | 76 | struct udl_gem_object *obj; |
| 77 | bool active_16; /* active on the 16-bit channel */ | 77 | bool active_16; /* active on the 16-bit channel */ |
| 78 | int x1, y1, x2, y2; /* dirty rect */ | ||
| 79 | spinlock_t dirty_lock; | ||
| 78 | }; | 80 | }; |
| 79 | 81 | ||
| 80 | #define to_udl_fb(x) container_of(x, struct udl_framebuffer, base) | 82 | #define to_udl_fb(x) container_of(x, struct udl_framebuffer, base) |
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index d4ab3beaada0..9f4be3d4a02e 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c | |||
| @@ -22,9 +22,9 @@ | |||
| 22 | 22 | ||
| 23 | #include <drm/drm_fb_helper.h> | 23 | #include <drm/drm_fb_helper.h> |
| 24 | 24 | ||
| 25 | #define DL_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */ | 25 | #define DL_DEFIO_WRITE_DELAY (HZ/20) /* fb_deferred_io.delay in jiffies */ |
| 26 | 26 | ||
| 27 | static int fb_defio = 1; /* Optionally enable experimental fb_defio mmap support */ | 27 | static int fb_defio = 0; /* Optionally enable experimental fb_defio mmap support */ |
| 28 | static int fb_bpp = 16; | 28 | static int fb_bpp = 16; |
| 29 | 29 | ||
| 30 | module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | 30 | module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); |
| @@ -153,6 +153,9 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, | |||
| 153 | struct urb *urb; | 153 | struct urb *urb; |
| 154 | int aligned_x; | 154 | int aligned_x; |
| 155 | int bpp = (fb->base.bits_per_pixel / 8); | 155 | int bpp = (fb->base.bits_per_pixel / 8); |
| 156 | int x2, y2; | ||
| 157 | bool store_for_later = false; | ||
| 158 | unsigned long flags; | ||
| 156 | 159 | ||
| 157 | if (!fb->active_16) | 160 | if (!fb->active_16) |
| 158 | return 0; | 161 | return 0; |
| @@ -169,8 +172,6 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, | |||
| 169 | } | 172 | } |
| 170 | } | 173 | } |
| 171 | 174 | ||
| 172 | start_cycles = get_cycles(); | ||
| 173 | |||
| 174 | aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long)); | 175 | aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long)); |
| 175 | width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long)); | 176 | width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long)); |
| 176 | x = aligned_x; | 177 | x = aligned_x; |
| @@ -180,19 +181,53 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, | |||
| 180 | (y + height > fb->base.height)) | 181 | (y + height > fb->base.height)) |
| 181 | return -EINVAL; | 182 | return -EINVAL; |
| 182 | 183 | ||
| 184 | /* if we are in atomic just store the info | ||
| 185 | can't test inside spin lock */ | ||
| 186 | if (in_atomic()) | ||
| 187 | store_for_later = true; | ||
| 188 | |||
| 189 | x2 = x + width - 1; | ||
| 190 | y2 = y + height - 1; | ||
| 191 | |||
| 192 | spin_lock_irqsave(&fb->dirty_lock, flags); | ||
| 193 | |||
| 194 | if (fb->y1 < y) | ||
| 195 | y = fb->y1; | ||
| 196 | if (fb->y2 > y2) | ||
| 197 | y2 = fb->y2; | ||
| 198 | if (fb->x1 < x) | ||
| 199 | x = fb->x1; | ||
| 200 | if (fb->x2 > x2) | ||
| 201 | x2 = fb->x2; | ||
| 202 | |||
| 203 | if (store_for_later) { | ||
| 204 | fb->x1 = x; | ||
| 205 | fb->x2 = x2; | ||
| 206 | fb->y1 = y; | ||
| 207 | fb->y2 = y2; | ||
| 208 | spin_unlock_irqrestore(&fb->dirty_lock, flags); | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | fb->x1 = fb->y1 = INT_MAX; | ||
| 213 | fb->x2 = fb->y2 = 0; | ||
| 214 | |||
| 215 | spin_unlock_irqrestore(&fb->dirty_lock, flags); | ||
| 216 | start_cycles = get_cycles(); | ||
| 217 | |||
| 183 | urb = udl_get_urb(dev); | 218 | urb = udl_get_urb(dev); |
| 184 | if (!urb) | 219 | if (!urb) |
| 185 | return 0; | 220 | return 0; |
| 186 | cmd = urb->transfer_buffer; | 221 | cmd = urb->transfer_buffer; |
| 187 | 222 | ||
| 188 | for (i = y; i < y + height ; i++) { | 223 | for (i = y; i <= y2 ; i++) { |
| 189 | const int line_offset = fb->base.pitches[0] * i; | 224 | const int line_offset = fb->base.pitches[0] * i; |
| 190 | const int byte_offset = line_offset + (x * bpp); | 225 | const int byte_offset = line_offset + (x * bpp); |
| 191 | const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); | 226 | const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); |
| 192 | if (udl_render_hline(dev, bpp, &urb, | 227 | if (udl_render_hline(dev, bpp, &urb, |
| 193 | (char *) fb->obj->vmapping, | 228 | (char *) fb->obj->vmapping, |
| 194 | &cmd, byte_offset, dev_byte_offset, | 229 | &cmd, byte_offset, dev_byte_offset, |
| 195 | width * bpp, | 230 | (x2 - x + 1) * bpp, |
| 196 | &bytes_identical, &bytes_sent)) | 231 | &bytes_identical, &bytes_sent)) |
| 197 | goto error; | 232 | goto error; |
| 198 | } | 233 | } |
| @@ -422,7 +457,6 @@ static void udl_user_framebuffer_destroy(struct drm_framebuffer *fb) | |||
| 422 | static const struct drm_framebuffer_funcs udlfb_funcs = { | 457 | static const struct drm_framebuffer_funcs udlfb_funcs = { |
| 423 | .destroy = udl_user_framebuffer_destroy, | 458 | .destroy = udl_user_framebuffer_destroy, |
| 424 | .dirty = udl_user_framebuffer_dirty, | 459 | .dirty = udl_user_framebuffer_dirty, |
| 425 | .create_handle = NULL, | ||
| 426 | }; | 460 | }; |
| 427 | 461 | ||
| 428 | 462 | ||
| @@ -434,16 +468,18 @@ udl_framebuffer_init(struct drm_device *dev, | |||
| 434 | { | 468 | { |
| 435 | int ret; | 469 | int ret; |
| 436 | 470 | ||
| 471 | spin_lock_init(&ufb->dirty_lock); | ||
| 437 | ufb->obj = obj; | 472 | ufb->obj = obj; |
| 438 | ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); | ||
| 439 | drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); | 473 | drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); |
| 474 | ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); | ||
| 440 | return ret; | 475 | return ret; |
| 441 | } | 476 | } |
| 442 | 477 | ||
| 443 | 478 | ||
| 444 | static int udlfb_create(struct udl_fbdev *ufbdev, | 479 | static int udlfb_create(struct drm_fb_helper *helper, |
| 445 | struct drm_fb_helper_surface_size *sizes) | 480 | struct drm_fb_helper_surface_size *sizes) |
| 446 | { | 481 | { |
| 482 | struct udl_fbdev *ufbdev = (struct udl_fbdev *)helper; | ||
| 447 | struct drm_device *dev = ufbdev->helper.dev; | 483 | struct drm_device *dev = ufbdev->helper.dev; |
| 448 | struct fb_info *info; | 484 | struct fb_info *info; |
| 449 | struct device *device = &dev->usbdev->dev; | 485 | struct device *device = &dev->usbdev->dev; |
| @@ -521,27 +557,10 @@ out: | |||
| 521 | return ret; | 557 | return ret; |
| 522 | } | 558 | } |
| 523 | 559 | ||
| 524 | static int udl_fb_find_or_create_single(struct drm_fb_helper *helper, | ||
| 525 | struct drm_fb_helper_surface_size *sizes) | ||
| 526 | { | ||
| 527 | struct udl_fbdev *ufbdev = (struct udl_fbdev *)helper; | ||
| 528 | int new_fb = 0; | ||
| 529 | int ret; | ||
| 530 | |||
| 531 | if (!helper->fb) { | ||
| 532 | ret = udlfb_create(ufbdev, sizes); | ||
| 533 | if (ret) | ||
| 534 | return ret; | ||
| 535 | |||
| 536 | new_fb = 1; | ||
| 537 | } | ||
| 538 | return new_fb; | ||
| 539 | } | ||
| 540 | |||
| 541 | static struct drm_fb_helper_funcs udl_fb_helper_funcs = { | 560 | static struct drm_fb_helper_funcs udl_fb_helper_funcs = { |
| 542 | .gamma_set = udl_crtc_fb_gamma_set, | 561 | .gamma_set = udl_crtc_fb_gamma_set, |
| 543 | .gamma_get = udl_crtc_fb_gamma_get, | 562 | .gamma_get = udl_crtc_fb_gamma_get, |
| 544 | .fb_probe = udl_fb_find_or_create_single, | 563 | .fb_probe = udlfb_create, |
| 545 | }; | 564 | }; |
| 546 | 565 | ||
| 547 | static void udl_fbdev_destroy(struct drm_device *dev, | 566 | static void udl_fbdev_destroy(struct drm_device *dev, |
| @@ -556,6 +575,7 @@ static void udl_fbdev_destroy(struct drm_device *dev, | |||
| 556 | framebuffer_release(info); | 575 | framebuffer_release(info); |
| 557 | } | 576 | } |
| 558 | drm_fb_helper_fini(&ufbdev->helper); | 577 | drm_fb_helper_fini(&ufbdev->helper); |
| 578 | drm_framebuffer_unregister_private(&ufbdev->ufb.base); | ||
| 559 | drm_framebuffer_cleanup(&ufbdev->ufb.base); | 579 | drm_framebuffer_cleanup(&ufbdev->ufb.base); |
| 560 | drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base); | 580 | drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base); |
| 561 | } | 581 | } |
| @@ -583,6 +603,10 @@ int udl_fbdev_init(struct drm_device *dev) | |||
| 583 | } | 603 | } |
| 584 | 604 | ||
| 585 | drm_fb_helper_single_add_all_connectors(&ufbdev->helper); | 605 | drm_fb_helper_single_add_all_connectors(&ufbdev->helper); |
| 606 | |||
| 607 | /* disable all the possible outputs/crtcs before entering KMS mode */ | ||
| 608 | drm_helper_disable_unused_functions(dev); | ||
| 609 | |||
| 586 | drm_fb_helper_initial_config(&ufbdev->helper, bpp_sel); | 610 | drm_fb_helper_initial_config(&ufbdev->helper, bpp_sel); |
| 587 | return 0; | 611 | return 0; |
| 588 | } | 612 | } |
diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index 142fee5f983f..f343db73e095 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c | |||
| @@ -75,15 +75,19 @@ static int udl_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes) | |||
| 75 | } | 75 | } |
| 76 | #endif | 76 | #endif |
| 77 | 77 | ||
| 78 | static inline u16 pixel32_to_be16p(const uint8_t *pixel) | 78 | static inline u16 pixel32_to_be16(const uint32_t pixel) |
| 79 | { | 79 | { |
| 80 | uint32_t pix = *(uint32_t *)pixel; | 80 | return (((pixel >> 3) & 0x001f) | |
| 81 | u16 retval; | 81 | ((pixel >> 5) & 0x07e0) | |
| 82 | ((pixel >> 8) & 0xf800)); | ||
| 83 | } | ||
| 82 | 84 | ||
| 83 | retval = (((pix >> 3) & 0x001f) | | 85 | static bool pixel_repeats(const void *pixel, const uint32_t repeat, int bpp) |
| 84 | ((pix >> 5) & 0x07e0) | | 86 | { |
| 85 | ((pix >> 8) & 0xf800)); | 87 | if (bpp == 2) |
| 86 | return retval; | 88 | return *(const uint16_t *)pixel == repeat; |
| 89 | else | ||
| 90 | return *(const uint32_t *)pixel == repeat; | ||
| 87 | } | 91 | } |
| 88 | 92 | ||
| 89 | /* | 93 | /* |
| @@ -152,29 +156,33 @@ static void udl_compress_hline16( | |||
| 152 | prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); | 156 | prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); |
| 153 | 157 | ||
| 154 | while (pixel < cmd_pixel_end) { | 158 | while (pixel < cmd_pixel_end) { |
| 155 | const u8 * const repeating_pixel = pixel; | 159 | const u8 *const start = pixel; |
| 156 | 160 | u32 repeating_pixel; | |
| 157 | if (bpp == 2) | 161 | |
| 158 | *(uint16_t *)cmd = cpu_to_be16p((uint16_t *)pixel); | 162 | if (bpp == 2) { |
| 159 | else if (bpp == 4) | 163 | repeating_pixel = *(uint16_t *)pixel; |
| 160 | *(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16p(pixel)); | 164 | *(uint16_t *)cmd = cpu_to_be16(repeating_pixel); |
| 165 | } else { | ||
| 166 | repeating_pixel = *(uint32_t *)pixel; | ||
| 167 | *(uint16_t *)cmd = cpu_to_be16(pixel32_to_be16(repeating_pixel)); | ||
| 168 | } | ||
| 161 | 169 | ||
| 162 | cmd += 2; | 170 | cmd += 2; |
| 163 | pixel += bpp; | 171 | pixel += bpp; |
| 164 | 172 | ||
| 165 | if (unlikely((pixel < cmd_pixel_end) && | 173 | if (unlikely((pixel < cmd_pixel_end) && |
| 166 | (!memcmp(pixel, repeating_pixel, bpp)))) { | 174 | (pixel_repeats(pixel, repeating_pixel, bpp)))) { |
| 167 | /* go back and fill in raw pixel count */ | 175 | /* go back and fill in raw pixel count */ |
| 168 | *raw_pixels_count_byte = (((repeating_pixel - | 176 | *raw_pixels_count_byte = (((start - |
| 169 | raw_pixel_start) / bpp) + 1) & 0xFF; | 177 | raw_pixel_start) / bpp) + 1) & 0xFF; |
| 170 | 178 | ||
| 171 | while ((pixel < cmd_pixel_end) | 179 | while ((pixel < cmd_pixel_end) && |
| 172 | && (!memcmp(pixel, repeating_pixel, bpp))) { | 180 | (pixel_repeats(pixel, repeating_pixel, bpp))) { |
| 173 | pixel += bpp; | 181 | pixel += bpp; |
| 174 | } | 182 | } |
| 175 | 183 | ||
| 176 | /* immediately after raw data is repeat byte */ | 184 | /* immediately after raw data is repeat byte */ |
| 177 | *cmd++ = (((pixel - repeating_pixel) / bpp) - 1) & 0xFF; | 185 | *cmd++ = (((pixel - start) / bpp) - 1) & 0xFF; |
| 178 | 186 | ||
| 179 | /* Then start another raw pixel span */ | 187 | /* Then start another raw pixel span */ |
| 180 | raw_pixel_start = pixel; | 188 | raw_pixel_start = pixel; |
| @@ -223,6 +231,8 @@ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, | |||
| 223 | u8 *cmd = *urb_buf_ptr; | 231 | u8 *cmd = *urb_buf_ptr; |
| 224 | u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; | 232 | u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; |
| 225 | 233 | ||
| 234 | BUG_ON(!(bpp == 2 || bpp == 4)); | ||
| 235 | |||
| 226 | line_start = (u8 *) (front + byte_offset); | 236 | line_start = (u8 *) (front + byte_offset); |
| 227 | next_pixel = line_start; | 237 | next_pixel = line_start; |
| 228 | line_end = next_pixel + byte_width; | 238 | line_end = next_pixel + byte_width; |
