aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/udl
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-25 19:46:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-25 19:46:44 -0500
commitfffddfd6c8e0c10c42c6e2cc54ba880fcc36ebbb (patch)
tree71bc5e597124dbaf7550f1e089d675718b3ed5c0 /drivers/gpu/drm/udl
parent69086a78bdc973ec0b722be790b146e84ba8a8c4 (diff)
parentbe88298b0a3f771a4802f20c5e66af74bfd1dff1 (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.h2
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c78
-rw-r--r--drivers/gpu/drm/udl/udl_transfer.c46
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
27static int fb_defio = 1; /* Optionally enable experimental fb_defio mmap support */ 27static int fb_defio = 0; /* Optionally enable experimental fb_defio mmap support */
28static int fb_bpp = 16; 28static int fb_bpp = 16;
29 29
30module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); 30module_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)
422static const struct drm_framebuffer_funcs udlfb_funcs = { 457static 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
444static int udlfb_create(struct udl_fbdev *ufbdev, 479static 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
524static 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
541static struct drm_fb_helper_funcs udl_fb_helper_funcs = { 560static 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
547static void udl_fbdev_destroy(struct drm_device *dev, 566static 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
78static inline u16 pixel32_to_be16p(const uint8_t *pixel) 78static 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) | 85static 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;