aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-08 13:02:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-08 13:02:59 -0400
commit537d84787659b355b3331813dc134c7497ddafa5 (patch)
treee43d376ed8522b09163ed1f7902e1fed25d2fe3b /drivers/video
parentd71048e22f47725a5808ea2e4e1e72fa36c1a788 (diff)
parentece350d3949e9a60b39e4f9853be118e98d48fbc (diff)
Merge branch 'for-linus' of git://gitorious.org/linux-omap-dss2/linux
* 'for-linus' of git://gitorious.org/linux-omap-dss2/linux: (64 commits) OMAP: DSS2: OMAPFB: add support for FBIO_WAITFORVSYNC OMAP: DSS2: Replace strncmp() with sysfs_streq() in overlay_manager_store() OMAP: DSS2: Fix error path in omap_dsi_update() OMAP: DSS2: TDO35S: fix video signaling OMAP: DSS2: OMAPFB: Fix invalid bpp for PAL and NTSC modes OMAP: DSS2: OMAPFB: Fix probe error path OMAP3EVM: Replace vdvi regulator supply with vdds_dsi OMAP: DSS2: Remove extra return statement OMAP: DSS2: adjust YUV overlay width to be even OMAP: DSS2: OMAPFB: Fix sysfs mirror input check OMAP: DSS2: OMAPFB: Remove redundant color register range check OMAP: DSS2: OMAPFB: Remove redundant rotate range check OMAP: DSS2: OMAPFB: Check fb2display() return value OMAP: DSS2: Taal: Optimize enable_te, rotate, mirror when value unchanged OMAP: DSS2: DSI: detect unsupported update requests OMAP: DSS2: DSI: increase FIFO low threshold OMAP: DSS2: DSI: Add error IRQ mask for DSI complexIO OMAP: DSS2: DSI: Remove BTA after set_max_rx_packet_size OMAP: DSS2: change manual update scaling setup OMAP: DSS2: DSI: use BTA to end the frame transfer ...
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/displays/panel-taal.c567
-rw-r--r--drivers/video/omap2/displays/panel-toppoly-tdo35s.c8
-rw-r--r--drivers/video/omap2/dss/dispc.c16
-rw-r--r--drivers/video/omap2/dss/display.c4
-rw-r--r--drivers/video/omap2/dss/dsi.c463
-rw-r--r--drivers/video/omap2/dss/dss.c6
-rw-r--r--drivers/video/omap2/dss/dss.h11
-rw-r--r--drivers/video/omap2/dss/manager.c204
-rw-r--r--drivers/video/omap2/dss/overlay.c2
-rw-r--r--drivers/video/omap2/dss/rfbi.c2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c188
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c229
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c70
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h29
14 files changed, 1223 insertions, 576 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index aaf5d308a046..e1c765d11419 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -28,12 +28,13 @@
28#include <linux/fb.h> 28#include <linux/fb.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/gpio.h> 30#include <linux/gpio.h>
31#include <linux/completion.h>
32#include <linux/workqueue.h> 31#include <linux/workqueue.h>
33#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/regulator/consumer.h>
34#include <linux/mutex.h> 34#include <linux/mutex.h>
35 35
36#include <plat/display.h> 36#include <plat/display.h>
37#include <plat/nokia-dsi-panel.h>
37 38
38/* DSI Virtual channel. Hardcoded for now. */ 39/* DSI Virtual channel. Hardcoded for now. */
39#define TCH 0 40#define TCH 0
@@ -62,11 +63,136 @@
62#define DCS_GET_ID2 0xdb 63#define DCS_GET_ID2 0xdb
63#define DCS_GET_ID3 0xdc 64#define DCS_GET_ID3 0xdc
64 65
65/* #define TAAL_USE_ESD_CHECK */
66#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000) 66#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
67 67
68static irqreturn_t taal_te_isr(int irq, void *data);
69static void taal_te_timeout_work_callback(struct work_struct *work);
68static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); 70static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
69 71
72struct panel_regulator {
73 struct regulator *regulator;
74 const char *name;
75 int min_uV;
76 int max_uV;
77};
78
79static void free_regulators(struct panel_regulator *regulators, int n)
80{
81 int i;
82
83 for (i = 0; i < n; i++) {
84 /* disable/put in reverse order */
85 regulator_disable(regulators[n - i - 1].regulator);
86 regulator_put(regulators[n - i - 1].regulator);
87 }
88}
89
90static int init_regulators(struct omap_dss_device *dssdev,
91 struct panel_regulator *regulators, int n)
92{
93 int r, i, v;
94
95 for (i = 0; i < n; i++) {
96 struct regulator *reg;
97
98 reg = regulator_get(&dssdev->dev, regulators[i].name);
99 if (IS_ERR(reg)) {
100 dev_err(&dssdev->dev, "failed to get regulator %s\n",
101 regulators[i].name);
102 r = PTR_ERR(reg);
103 goto err;
104 }
105
106 /* FIXME: better handling of fixed vs. variable regulators */
107 v = regulator_get_voltage(reg);
108 if (v < regulators[i].min_uV || v > regulators[i].max_uV) {
109 r = regulator_set_voltage(reg, regulators[i].min_uV,
110 regulators[i].max_uV);
111 if (r) {
112 dev_err(&dssdev->dev,
113 "failed to set regulator %s voltage\n",
114 regulators[i].name);
115 regulator_put(reg);
116 goto err;
117 }
118 }
119
120 r = regulator_enable(reg);
121 if (r) {
122 dev_err(&dssdev->dev, "failed to enable regulator %s\n",
123 regulators[i].name);
124 regulator_put(reg);
125 goto err;
126 }
127
128 regulators[i].regulator = reg;
129 }
130
131 return 0;
132
133err:
134 free_regulators(regulators, i);
135
136 return r;
137}
138
139/**
140 * struct panel_config - panel configuration
141 * @name: panel name
142 * @type: panel type
143 * @timings: panel resolution
144 * @sleep: various panel specific delays, passed to msleep() if non-zero
145 * @reset_sequence: reset sequence timings, passed to udelay() if non-zero
146 * @regulators: array of panel regulators
147 * @num_regulators: number of regulators in the array
148 */
149struct panel_config {
150 const char *name;
151 int type;
152
153 struct omap_video_timings timings;
154
155 struct {
156 unsigned int sleep_in;
157 unsigned int sleep_out;
158 unsigned int hw_reset;
159 unsigned int enable_te;
160 } sleep;
161
162 struct {
163 unsigned int high;
164 unsigned int low;
165 } reset_sequence;
166
167 struct panel_regulator *regulators;
168 int num_regulators;
169};
170
171enum {
172 PANEL_TAAL,
173};
174
175static struct panel_config panel_configs[] = {
176 {
177 .name = "taal",
178 .type = PANEL_TAAL,
179 .timings = {
180 .x_res = 864,
181 .y_res = 480,
182 },
183 .sleep = {
184 .sleep_in = 5,
185 .sleep_out = 5,
186 .hw_reset = 5,
187 .enable_te = 100, /* possible panel bug */
188 },
189 .reset_sequence = {
190 .high = 10,
191 .low = 10,
192 },
193 },
194};
195
70struct taal_data { 196struct taal_data {
71 struct mutex lock; 197 struct mutex lock;
72 198
@@ -84,8 +210,15 @@ struct taal_data {
84 bool mirror; 210 bool mirror;
85 211
86 bool te_enabled; 212 bool te_enabled;
87 bool use_ext_te; 213
88 struct completion te_completion; 214 atomic_t do_update;
215 struct {
216 u16 x;
217 u16 y;
218 u16 w;
219 u16 h;
220 } update_region;
221 struct delayed_work te_timeout_work;
89 222
90 bool use_dsi_bl; 223 bool use_dsi_bl;
91 224
@@ -96,8 +229,16 @@ struct taal_data {
96 229
97 struct workqueue_struct *esd_wq; 230 struct workqueue_struct *esd_wq;
98 struct delayed_work esd_work; 231 struct delayed_work esd_work;
232
233 struct panel_config *panel_config;
99}; 234};
100 235
236static inline struct nokia_dsi_panel_data
237*get_panel_data(const struct omap_dss_device *dssdev)
238{
239 return (struct nokia_dsi_panel_data *) dssdev->data;
240}
241
101static void taal_esd_work(struct work_struct *work); 242static void taal_esd_work(struct work_struct *work);
102 243
103static void hw_guard_start(struct taal_data *td, int guard_msec) 244static void hw_guard_start(struct taal_data *td, int guard_msec)
@@ -159,7 +300,8 @@ static int taal_sleep_in(struct taal_data *td)
159 300
160 hw_guard_start(td, 120); 301 hw_guard_start(td, 120);
161 302
162 msleep(5); 303 if (td->panel_config->sleep.sleep_in)
304 msleep(td->panel_config->sleep.sleep_in);
163 305
164 return 0; 306 return 0;
165} 307}
@@ -176,7 +318,8 @@ static int taal_sleep_out(struct taal_data *td)
176 318
177 hw_guard_start(td, 120); 319 hw_guard_start(td, 120);
178 320
179 msleep(5); 321 if (td->panel_config->sleep.sleep_out)
322 msleep(td->panel_config->sleep.sleep_out);
180 323
181 return 0; 324 return 0;
182} 325}
@@ -279,6 +422,7 @@ static int taal_bl_update_status(struct backlight_device *dev)
279{ 422{
280 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); 423 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
281 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 424 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
425 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
282 int r; 426 int r;
283 int level; 427 int level;
284 428
@@ -290,24 +434,26 @@ static int taal_bl_update_status(struct backlight_device *dev)
290 434
291 dev_dbg(&dssdev->dev, "update brightness to %d\n", level); 435 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
292 436
437 mutex_lock(&td->lock);
438
293 if (td->use_dsi_bl) { 439 if (td->use_dsi_bl) {
294 if (td->enabled) { 440 if (td->enabled) {
295 dsi_bus_lock(); 441 dsi_bus_lock();
296 r = taal_dcs_write_1(DCS_BRIGHTNESS, level); 442 r = taal_dcs_write_1(DCS_BRIGHTNESS, level);
297 dsi_bus_unlock(); 443 dsi_bus_unlock();
298 if (r) 444 } else {
299 return r; 445 r = 0;
300 } 446 }
301 } else { 447 } else {
302 if (!dssdev->set_backlight) 448 if (!panel_data->set_backlight)
303 return -EINVAL; 449 r = -EINVAL;
304 450 else
305 r = dssdev->set_backlight(dssdev, level); 451 r = panel_data->set_backlight(dssdev, level);
306 if (r)
307 return r;
308 } 452 }
309 453
310 return 0; 454 mutex_unlock(&td->lock);
455
456 return r;
311} 457}
312 458
313static int taal_bl_get_intensity(struct backlight_device *dev) 459static int taal_bl_get_intensity(struct backlight_device *dev)
@@ -344,16 +490,6 @@ static void taal_get_resolution(struct omap_dss_device *dssdev,
344 } 490 }
345} 491}
346 492
347static irqreturn_t taal_te_isr(int irq, void *data)
348{
349 struct omap_dss_device *dssdev = data;
350 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
351
352 complete_all(&td->te_completion);
353
354 return IRQ_HANDLED;
355}
356
357static ssize_t taal_num_errors_show(struct device *dev, 493static ssize_t taal_num_errors_show(struct device *dev,
358 struct device_attribute *attr, char *buf) 494 struct device_attribute *attr, char *buf)
359{ 495{
@@ -362,6 +498,8 @@ static ssize_t taal_num_errors_show(struct device *dev,
362 u8 errors; 498 u8 errors;
363 int r; 499 int r;
364 500
501 mutex_lock(&td->lock);
502
365 if (td->enabled) { 503 if (td->enabled) {
366 dsi_bus_lock(); 504 dsi_bus_lock();
367 r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); 505 r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors);
@@ -370,6 +508,8 @@ static ssize_t taal_num_errors_show(struct device *dev,
370 r = -ENODEV; 508 r = -ENODEV;
371 } 509 }
372 510
511 mutex_unlock(&td->lock);
512
373 if (r) 513 if (r)
374 return r; 514 return r;
375 515
@@ -384,6 +524,8 @@ static ssize_t taal_hw_revision_show(struct device *dev,
384 u8 id1, id2, id3; 524 u8 id1, id2, id3;
385 int r; 525 int r;
386 526
527 mutex_lock(&td->lock);
528
387 if (td->enabled) { 529 if (td->enabled) {
388 dsi_bus_lock(); 530 dsi_bus_lock();
389 r = taal_get_id(&id1, &id2, &id3); 531 r = taal_get_id(&id1, &id2, &id3);
@@ -392,6 +534,8 @@ static ssize_t taal_hw_revision_show(struct device *dev,
392 r = -ENODEV; 534 r = -ENODEV;
393 } 535 }
394 536
537 mutex_unlock(&td->lock);
538
395 if (r) 539 if (r)
396 return r; 540 return r;
397 541
@@ -441,6 +585,8 @@ static ssize_t store_cabc_mode(struct device *dev,
441 if (i == ARRAY_SIZE(cabc_modes)) 585 if (i == ARRAY_SIZE(cabc_modes))
442 return -EINVAL; 586 return -EINVAL;
443 587
588 mutex_lock(&td->lock);
589
444 if (td->enabled) { 590 if (td->enabled) {
445 dsi_bus_lock(); 591 dsi_bus_lock();
446 if (!td->cabc_broken) 592 if (!td->cabc_broken)
@@ -450,6 +596,8 @@ static ssize_t store_cabc_mode(struct device *dev,
450 596
451 td->cabc_mode = i; 597 td->cabc_mode = i;
452 598
599 mutex_unlock(&td->lock);
600
453 return count; 601 return count;
454} 602}
455 603
@@ -488,47 +636,93 @@ static struct attribute_group taal_attr_group = {
488 .attrs = taal_attrs, 636 .attrs = taal_attrs,
489}; 637};
490 638
639static void taal_hw_reset(struct omap_dss_device *dssdev)
640{
641 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
642 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
643
644 if (panel_data->reset_gpio == -1)
645 return;
646
647 gpio_set_value(panel_data->reset_gpio, 1);
648 if (td->panel_config->reset_sequence.high)
649 udelay(td->panel_config->reset_sequence.high);
650 /* reset the panel */
651 gpio_set_value(panel_data->reset_gpio, 0);
652 /* assert reset */
653 if (td->panel_config->reset_sequence.low)
654 udelay(td->panel_config->reset_sequence.low);
655 gpio_set_value(panel_data->reset_gpio, 1);
656 /* wait after releasing reset */
657 if (td->panel_config->sleep.hw_reset)
658 msleep(td->panel_config->sleep.hw_reset);
659}
660
491static int taal_probe(struct omap_dss_device *dssdev) 661static int taal_probe(struct omap_dss_device *dssdev)
492{ 662{
493 struct backlight_properties props; 663 struct backlight_properties props;
494 struct taal_data *td; 664 struct taal_data *td;
495 struct backlight_device *bldev; 665 struct backlight_device *bldev;
496 int r; 666 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
497 667 struct panel_config *panel_config = NULL;
498 const struct omap_video_timings taal_panel_timings = { 668 int r, i;
499 .x_res = 864,
500 .y_res = 480,
501 };
502 669
503 dev_dbg(&dssdev->dev, "probe\n"); 670 dev_dbg(&dssdev->dev, "probe\n");
504 671
672 if (!panel_data || !panel_data->name) {
673 r = -EINVAL;
674 goto err;
675 }
676
677 for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
678 if (strcmp(panel_data->name, panel_configs[i].name) == 0) {
679 panel_config = &panel_configs[i];
680 break;
681 }
682 }
683
684 if (!panel_config) {
685 r = -EINVAL;
686 goto err;
687 }
688
505 dssdev->panel.config = OMAP_DSS_LCD_TFT; 689 dssdev->panel.config = OMAP_DSS_LCD_TFT;
506 dssdev->panel.timings = taal_panel_timings; 690 dssdev->panel.timings = panel_config->timings;
507 dssdev->ctrl.pixel_size = 24; 691 dssdev->ctrl.pixel_size = 24;
508 692
509 td = kzalloc(sizeof(*td), GFP_KERNEL); 693 td = kzalloc(sizeof(*td), GFP_KERNEL);
510 if (!td) { 694 if (!td) {
511 r = -ENOMEM; 695 r = -ENOMEM;
512 goto err0; 696 goto err;
513 } 697 }
514 td->dssdev = dssdev; 698 td->dssdev = dssdev;
699 td->panel_config = panel_config;
515 700
516 mutex_init(&td->lock); 701 mutex_init(&td->lock);
517 702
703 atomic_set(&td->do_update, 0);
704
705 r = init_regulators(dssdev, panel_config->regulators,
706 panel_config->num_regulators);
707 if (r)
708 goto err_reg;
709
518 td->esd_wq = create_singlethread_workqueue("taal_esd"); 710 td->esd_wq = create_singlethread_workqueue("taal_esd");
519 if (td->esd_wq == NULL) { 711 if (td->esd_wq == NULL) {
520 dev_err(&dssdev->dev, "can't create ESD workqueue\n"); 712 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
521 r = -ENOMEM; 713 r = -ENOMEM;
522 goto err1; 714 goto err_wq;
523 } 715 }
524 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work); 716 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
525 717
526 dev_set_drvdata(&dssdev->dev, td); 718 dev_set_drvdata(&dssdev->dev, td);
527 719
720 taal_hw_reset(dssdev);
721
528 /* if no platform set_backlight() defined, presume DSI backlight 722 /* if no platform set_backlight() defined, presume DSI backlight
529 * control */ 723 * control */
530 memset(&props, 0, sizeof(struct backlight_properties)); 724 memset(&props, 0, sizeof(struct backlight_properties));
531 if (!dssdev->set_backlight) 725 if (!panel_data->set_backlight)
532 td->use_dsi_bl = true; 726 td->use_dsi_bl = true;
533 727
534 if (td->use_dsi_bl) 728 if (td->use_dsi_bl)
@@ -539,7 +733,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
539 &taal_bl_ops, &props); 733 &taal_bl_ops, &props);
540 if (IS_ERR(bldev)) { 734 if (IS_ERR(bldev)) {
541 r = PTR_ERR(bldev); 735 r = PTR_ERR(bldev);
542 goto err2; 736 goto err_bl;
543 } 737 }
544 738
545 td->bldev = bldev; 739 td->bldev = bldev;
@@ -553,13 +747,13 @@ static int taal_probe(struct omap_dss_device *dssdev)
553 747
554 taal_bl_update_status(bldev); 748 taal_bl_update_status(bldev);
555 749
556 if (dssdev->phy.dsi.ext_te) { 750 if (panel_data->use_ext_te) {
557 int gpio = dssdev->phy.dsi.ext_te_gpio; 751 int gpio = panel_data->ext_te_gpio;
558 752
559 r = gpio_request(gpio, "taal irq"); 753 r = gpio_request(gpio, "taal irq");
560 if (r) { 754 if (r) {
561 dev_err(&dssdev->dev, "GPIO request failed\n"); 755 dev_err(&dssdev->dev, "GPIO request failed\n");
562 goto err3; 756 goto err_gpio;
563 } 757 }
564 758
565 gpio_direction_input(gpio); 759 gpio_direction_input(gpio);
@@ -571,49 +765,52 @@ static int taal_probe(struct omap_dss_device *dssdev)
571 if (r) { 765 if (r) {
572 dev_err(&dssdev->dev, "IRQ request failed\n"); 766 dev_err(&dssdev->dev, "IRQ request failed\n");
573 gpio_free(gpio); 767 gpio_free(gpio);
574 goto err3; 768 goto err_irq;
575 } 769 }
576 770
577 init_completion(&td->te_completion); 771 INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work,
772 taal_te_timeout_work_callback);
578 773
579 td->use_ext_te = true; 774 dev_dbg(&dssdev->dev, "Using GPIO TE\n");
580 } 775 }
581 776
582 r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); 777 r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group);
583 if (r) { 778 if (r) {
584 dev_err(&dssdev->dev, "failed to create sysfs files\n"); 779 dev_err(&dssdev->dev, "failed to create sysfs files\n");
585 goto err4; 780 goto err_sysfs;
586 } 781 }
587 782
588 return 0; 783 return 0;
589err4: 784err_sysfs:
590 if (td->use_ext_te) { 785 if (panel_data->use_ext_te)
591 int gpio = dssdev->phy.dsi.ext_te_gpio; 786 free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
592 free_irq(gpio_to_irq(gpio), dssdev); 787err_irq:
593 gpio_free(gpio); 788 if (panel_data->use_ext_te)
594 } 789 gpio_free(panel_data->ext_te_gpio);
595err3: 790err_gpio:
596 backlight_device_unregister(bldev); 791 backlight_device_unregister(bldev);
597err2: 792err_bl:
598 cancel_delayed_work_sync(&td->esd_work);
599 destroy_workqueue(td->esd_wq); 793 destroy_workqueue(td->esd_wq);
600err1: 794err_wq:
795 free_regulators(panel_config->regulators, panel_config->num_regulators);
796err_reg:
601 kfree(td); 797 kfree(td);
602err0: 798err:
603 return r; 799 return r;
604} 800}
605 801
606static void taal_remove(struct omap_dss_device *dssdev) 802static void taal_remove(struct omap_dss_device *dssdev)
607{ 803{
608 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 804 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
805 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
609 struct backlight_device *bldev; 806 struct backlight_device *bldev;
610 807
611 dev_dbg(&dssdev->dev, "remove\n"); 808 dev_dbg(&dssdev->dev, "remove\n");
612 809
613 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); 810 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
614 811
615 if (td->use_ext_te) { 812 if (panel_data->use_ext_te) {
616 int gpio = dssdev->phy.dsi.ext_te_gpio; 813 int gpio = panel_data->ext_te_gpio;
617 free_irq(gpio_to_irq(gpio), dssdev); 814 free_irq(gpio_to_irq(gpio), dssdev);
618 gpio_free(gpio); 815 gpio_free(gpio);
619 } 816 }
@@ -623,9 +820,15 @@ static void taal_remove(struct omap_dss_device *dssdev)
623 taal_bl_update_status(bldev); 820 taal_bl_update_status(bldev);
624 backlight_device_unregister(bldev); 821 backlight_device_unregister(bldev);
625 822
626 cancel_delayed_work_sync(&td->esd_work); 823 cancel_delayed_work(&td->esd_work);
627 destroy_workqueue(td->esd_wq); 824 destroy_workqueue(td->esd_wq);
628 825
826 /* reset, to be sure that the panel is in a valid state */
827 taal_hw_reset(dssdev);
828
829 free_regulators(td->panel_config->regulators,
830 td->panel_config->num_regulators);
831
629 kfree(td); 832 kfree(td);
630} 833}
631 834
@@ -635,23 +838,14 @@ static int taal_power_on(struct omap_dss_device *dssdev)
635 u8 id1, id2, id3; 838 u8 id1, id2, id3;
636 int r; 839 int r;
637 840
638 if (dssdev->platform_enable) {
639 r = dssdev->platform_enable(dssdev);
640 if (r)
641 return r;
642 }
643
644 /* it seems we have to wait a bit until taal is ready */
645 msleep(5);
646
647 dsi_bus_lock();
648
649 r = omapdss_dsi_display_enable(dssdev); 841 r = omapdss_dsi_display_enable(dssdev);
650 if (r) { 842 if (r) {
651 dev_err(&dssdev->dev, "failed to enable DSI\n"); 843 dev_err(&dssdev->dev, "failed to enable DSI\n");
652 goto err0; 844 goto err0;
653 } 845 }
654 846
847 taal_hw_reset(dssdev);
848
655 omapdss_dsi_vc_enable_hs(TCH, false); 849 omapdss_dsi_vc_enable_hs(TCH, false);
656 850
657 r = taal_sleep_out(td); 851 r = taal_sleep_out(td);
@@ -662,34 +856,47 @@ static int taal_power_on(struct omap_dss_device *dssdev)
662 if (r) 856 if (r)
663 goto err; 857 goto err;
664 858
665 /* on early revisions CABC is broken */ 859 /* on early Taal revisions CABC is broken */
666 if (id2 == 0x00 || id2 == 0xff || id2 == 0x81) 860 if (td->panel_config->type == PANEL_TAAL &&
861 (id2 == 0x00 || id2 == 0xff || id2 == 0x81))
667 td->cabc_broken = true; 862 td->cabc_broken = true;
668 863
669 taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); 864 r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff);
670 taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */ 865 if (r)
866 goto err;
867
868 r = taal_dcs_write_1(DCS_CTRL_DISPLAY,
869 (1<<2) | (1<<5)); /* BL | BCTRL */
870 if (r)
871 goto err;
872
873 r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
874 if (r)
875 goto err;
671 876
672 taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ 877 r = taal_set_addr_mode(td->rotate, td->mirror);
878 if (r)
879 goto err;
673 880
674 taal_set_addr_mode(td->rotate, td->mirror); 881 if (!td->cabc_broken) {
675 if (!td->cabc_broken) 882 r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode);
676 taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); 883 if (r)
884 goto err;
885 }
677 886
678 taal_dcs_write_0(DCS_DISPLAY_ON); 887 r = taal_dcs_write_0(DCS_DISPLAY_ON);
888 if (r)
889 goto err;
679 890
680 r = _taal_enable_te(dssdev, td->te_enabled); 891 r = _taal_enable_te(dssdev, td->te_enabled);
681 if (r) 892 if (r)
682 goto err; 893 goto err;
683 894
684#ifdef TAAL_USE_ESD_CHECK
685 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
686#endif
687
688 td->enabled = 1; 895 td->enabled = 1;
689 896
690 if (!td->intro_printed) { 897 if (!td->intro_printed) {
691 dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n", 898 dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n",
692 id1, id2, id3); 899 td->panel_config->name, id1, id2, id3);
693 if (td->cabc_broken) 900 if (td->cabc_broken)
694 dev_info(&dssdev->dev, 901 dev_info(&dssdev->dev,
695 "old Taal version, CABC disabled\n"); 902 "old Taal version, CABC disabled\n");
@@ -698,46 +905,44 @@ static int taal_power_on(struct omap_dss_device *dssdev)
698 905
699 omapdss_dsi_vc_enable_hs(TCH, true); 906 omapdss_dsi_vc_enable_hs(TCH, true);
700 907
701 dsi_bus_unlock();
702
703 return 0; 908 return 0;
704err: 909err:
910 dev_err(&dssdev->dev, "error while enabling panel, issuing HW reset\n");
911
912 taal_hw_reset(dssdev);
913
705 omapdss_dsi_display_disable(dssdev); 914 omapdss_dsi_display_disable(dssdev);
706err0: 915err0:
707 dsi_bus_unlock();
708 if (dssdev->platform_disable)
709 dssdev->platform_disable(dssdev);
710
711 return r; 916 return r;
712} 917}
713 918
714static void taal_power_off(struct omap_dss_device *dssdev) 919static void taal_power_off(struct omap_dss_device *dssdev)
715{ 920{
716 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 921 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
922 int r;
717 923
718 dsi_bus_lock(); 924 r = taal_dcs_write_0(DCS_DISPLAY_OFF);
719 925 if (!r) {
720 cancel_delayed_work(&td->esd_work); 926 r = taal_sleep_in(td);
721 927 /* HACK: wait a bit so that the message goes through */
722 taal_dcs_write_0(DCS_DISPLAY_OFF); 928 msleep(10);
723 taal_sleep_in(td); 929 }
724 930
725 /* wait a bit so that the message goes through */ 931 if (r) {
726 msleep(10); 932 dev_err(&dssdev->dev,
933 "error disabling panel, issuing HW reset\n");
934 taal_hw_reset(dssdev);
935 }
727 936
728 omapdss_dsi_display_disable(dssdev); 937 omapdss_dsi_display_disable(dssdev);
729 938
730 if (dssdev->platform_disable)
731 dssdev->platform_disable(dssdev);
732
733 td->enabled = 0; 939 td->enabled = 0;
734
735 dsi_bus_unlock();
736} 940}
737 941
738static int taal_enable(struct omap_dss_device *dssdev) 942static int taal_enable(struct omap_dss_device *dssdev)
739{ 943{
740 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 944 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
945 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
741 int r; 946 int r;
742 947
743 dev_dbg(&dssdev->dev, "enable\n"); 948 dev_dbg(&dssdev->dev, "enable\n");
@@ -749,10 +954,19 @@ static int taal_enable(struct omap_dss_device *dssdev)
749 goto err; 954 goto err;
750 } 955 }
751 956
957 dsi_bus_lock();
958
752 r = taal_power_on(dssdev); 959 r = taal_power_on(dssdev);
960
961 dsi_bus_unlock();
962
753 if (r) 963 if (r)
754 goto err; 964 goto err;
755 965
966 if (panel_data->use_esd_check)
967 queue_delayed_work(td->esd_wq, &td->esd_work,
968 TAAL_ESD_CHECK_PERIOD);
969
756 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 970 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
757 971
758 mutex_unlock(&td->lock); 972 mutex_unlock(&td->lock);
@@ -772,9 +986,15 @@ static void taal_disable(struct omap_dss_device *dssdev)
772 986
773 mutex_lock(&td->lock); 987 mutex_lock(&td->lock);
774 988
989 cancel_delayed_work(&td->esd_work);
990
991 dsi_bus_lock();
992
775 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 993 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
776 taal_power_off(dssdev); 994 taal_power_off(dssdev);
777 995
996 dsi_bus_unlock();
997
778 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 998 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
779 999
780 mutex_unlock(&td->lock); 1000 mutex_unlock(&td->lock);
@@ -794,7 +1014,14 @@ static int taal_suspend(struct omap_dss_device *dssdev)
794 goto err; 1014 goto err;
795 } 1015 }
796 1016
1017 cancel_delayed_work(&td->esd_work);
1018
1019 dsi_bus_lock();
1020
797 taal_power_off(dssdev); 1021 taal_power_off(dssdev);
1022
1023 dsi_bus_unlock();
1024
798 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 1025 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
799 1026
800 mutex_unlock(&td->lock); 1027 mutex_unlock(&td->lock);
@@ -808,6 +1035,7 @@ err:
808static int taal_resume(struct omap_dss_device *dssdev) 1035static int taal_resume(struct omap_dss_device *dssdev)
809{ 1036{
810 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1037 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1038 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
811 int r; 1039 int r;
812 1040
813 dev_dbg(&dssdev->dev, "resume\n"); 1041 dev_dbg(&dssdev->dev, "resume\n");
@@ -819,8 +1047,20 @@ static int taal_resume(struct omap_dss_device *dssdev)
819 goto err; 1047 goto err;
820 } 1048 }
821 1049
1050 dsi_bus_lock();
1051
822 r = taal_power_on(dssdev); 1052 r = taal_power_on(dssdev);
823 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 1053
1054 dsi_bus_unlock();
1055
1056 if (r) {
1057 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
1058 } else {
1059 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
1060 if (panel_data->use_esd_check)
1061 queue_delayed_work(td->esd_wq, &td->esd_work,
1062 TAAL_ESD_CHECK_PERIOD);
1063 }
824 1064
825 mutex_unlock(&td->lock); 1065 mutex_unlock(&td->lock);
826 1066
@@ -837,10 +1077,52 @@ static void taal_framedone_cb(int err, void *data)
837 dsi_bus_unlock(); 1077 dsi_bus_unlock();
838} 1078}
839 1079
1080static irqreturn_t taal_te_isr(int irq, void *data)
1081{
1082 struct omap_dss_device *dssdev = data;
1083 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1084 int old;
1085 int r;
1086
1087 old = atomic_cmpxchg(&td->do_update, 1, 0);
1088
1089 if (old) {
1090 cancel_delayed_work(&td->te_timeout_work);
1091
1092 r = omap_dsi_update(dssdev, TCH,
1093 td->update_region.x,
1094 td->update_region.y,
1095 td->update_region.w,
1096 td->update_region.h,
1097 taal_framedone_cb, dssdev);
1098 if (r)
1099 goto err;
1100 }
1101
1102 return IRQ_HANDLED;
1103err:
1104 dev_err(&dssdev->dev, "start update failed\n");
1105 dsi_bus_unlock();
1106 return IRQ_HANDLED;
1107}
1108
1109static void taal_te_timeout_work_callback(struct work_struct *work)
1110{
1111 struct taal_data *td = container_of(work, struct taal_data,
1112 te_timeout_work.work);
1113 struct omap_dss_device *dssdev = td->dssdev;
1114
1115 dev_err(&dssdev->dev, "TE not received for 250ms!\n");
1116
1117 atomic_set(&td->do_update, 0);
1118 dsi_bus_unlock();
1119}
1120
840static int taal_update(struct omap_dss_device *dssdev, 1121static int taal_update(struct omap_dss_device *dssdev,
841 u16 x, u16 y, u16 w, u16 h) 1122 u16 x, u16 y, u16 w, u16 h)
842{ 1123{
843 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1124 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1125 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
844 int r; 1126 int r;
845 1127
846 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); 1128 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
@@ -853,7 +1135,7 @@ static int taal_update(struct omap_dss_device *dssdev,
853 goto err; 1135 goto err;
854 } 1136 }
855 1137
856 r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h); 1138 r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true);
857 if (r) 1139 if (r)
858 goto err; 1140 goto err;
859 1141
@@ -861,10 +1143,21 @@ static int taal_update(struct omap_dss_device *dssdev,
861 if (r) 1143 if (r)
862 goto err; 1144 goto err;
863 1145
864 r = omap_dsi_update(dssdev, TCH, x, y, w, h, 1146 if (td->te_enabled && panel_data->use_ext_te) {
865 taal_framedone_cb, dssdev); 1147 td->update_region.x = x;
866 if (r) 1148 td->update_region.y = y;
867 goto err; 1149 td->update_region.w = w;
1150 td->update_region.h = h;
1151 barrier();
1152 schedule_delayed_work(&td->te_timeout_work,
1153 msecs_to_jiffies(250));
1154 atomic_set(&td->do_update, 1);
1155 } else {
1156 r = omap_dsi_update(dssdev, TCH, x, y, w, h,
1157 taal_framedone_cb, dssdev);
1158 if (r)
1159 goto err;
1160 }
868 1161
869 /* note: no bus_unlock here. unlock is in framedone_cb */ 1162 /* note: no bus_unlock here. unlock is in framedone_cb */
870 mutex_unlock(&td->lock); 1163 mutex_unlock(&td->lock);
@@ -894,20 +1187,19 @@ static int taal_sync(struct omap_dss_device *dssdev)
894static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) 1187static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
895{ 1188{
896 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1189 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1190 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
897 int r; 1191 int r;
898 1192
899 td->te_enabled = enable;
900
901 if (enable) 1193 if (enable)
902 r = taal_dcs_write_1(DCS_TEAR_ON, 0); 1194 r = taal_dcs_write_1(DCS_TEAR_ON, 0);
903 else 1195 else
904 r = taal_dcs_write_0(DCS_TEAR_OFF); 1196 r = taal_dcs_write_0(DCS_TEAR_OFF);
905 1197
906 omapdss_dsi_enable_te(dssdev, enable); 1198 if (!panel_data->use_ext_te)
1199 omapdss_dsi_enable_te(dssdev, enable);
907 1200
908 /* XXX for some reason, DSI TE breaks if we don't wait here. 1201 if (td->panel_config->sleep.enable_te)
909 * Panel bug? Needs more studying */ 1202 msleep(td->panel_config->sleep.enable_te);
910 msleep(100);
911 1203
912 return r; 1204 return r;
913} 1205}
@@ -918,10 +1210,26 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
918 int r; 1210 int r;
919 1211
920 mutex_lock(&td->lock); 1212 mutex_lock(&td->lock);
1213
1214 if (td->te_enabled == enable)
1215 goto end;
1216
921 dsi_bus_lock(); 1217 dsi_bus_lock();
922 1218
923 r = _taal_enable_te(dssdev, enable); 1219 if (td->enabled) {
1220 r = _taal_enable_te(dssdev, enable);
1221 if (r)
1222 goto err;
1223 }
1224
1225 td->te_enabled = enable;
1226
1227 dsi_bus_unlock();
1228end:
1229 mutex_unlock(&td->lock);
924 1230
1231 return 0;
1232err:
925 dsi_bus_unlock(); 1233 dsi_bus_unlock();
926 mutex_unlock(&td->lock); 1234 mutex_unlock(&td->lock);
927 1235
@@ -948,6 +1256,10 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
948 dev_dbg(&dssdev->dev, "rotate %d\n", rotate); 1256 dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
949 1257
950 mutex_lock(&td->lock); 1258 mutex_lock(&td->lock);
1259
1260 if (td->rotate == rotate)
1261 goto end;
1262
951 dsi_bus_lock(); 1263 dsi_bus_lock();
952 1264
953 if (td->enabled) { 1265 if (td->enabled) {
@@ -959,6 +1271,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
959 td->rotate = rotate; 1271 td->rotate = rotate;
960 1272
961 dsi_bus_unlock(); 1273 dsi_bus_unlock();
1274end:
962 mutex_unlock(&td->lock); 1275 mutex_unlock(&td->lock);
963 return 0; 1276 return 0;
964err: 1277err:
@@ -987,6 +1300,10 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
987 dev_dbg(&dssdev->dev, "mirror %d\n", enable); 1300 dev_dbg(&dssdev->dev, "mirror %d\n", enable);
988 1301
989 mutex_lock(&td->lock); 1302 mutex_lock(&td->lock);
1303
1304 if (td->mirror == enable)
1305 goto end;
1306
990 dsi_bus_lock(); 1307 dsi_bus_lock();
991 if (td->enabled) { 1308 if (td->enabled) {
992 r = taal_set_addr_mode(td->rotate, enable); 1309 r = taal_set_addr_mode(td->rotate, enable);
@@ -997,6 +1314,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
997 td->mirror = enable; 1314 td->mirror = enable;
998 1315
999 dsi_bus_unlock(); 1316 dsi_bus_unlock();
1317end:
1000 mutex_unlock(&td->lock); 1318 mutex_unlock(&td->lock);
1001 return 0; 1319 return 0;
1002err: 1320err:
@@ -1024,23 +1342,30 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
1024 int r; 1342 int r;
1025 1343
1026 mutex_lock(&td->lock); 1344 mutex_lock(&td->lock);
1345
1346 if (!td->enabled) {
1347 r = -ENODEV;
1348 goto err1;
1349 }
1350
1027 dsi_bus_lock(); 1351 dsi_bus_lock();
1028 1352
1029 r = taal_dcs_read_1(DCS_GET_ID1, &id1); 1353 r = taal_dcs_read_1(DCS_GET_ID1, &id1);
1030 if (r) 1354 if (r)
1031 goto err; 1355 goto err2;
1032 r = taal_dcs_read_1(DCS_GET_ID2, &id2); 1356 r = taal_dcs_read_1(DCS_GET_ID2, &id2);
1033 if (r) 1357 if (r)
1034 goto err; 1358 goto err2;
1035 r = taal_dcs_read_1(DCS_GET_ID3, &id3); 1359 r = taal_dcs_read_1(DCS_GET_ID3, &id3);
1036 if (r) 1360 if (r)
1037 goto err; 1361 goto err2;
1038 1362
1039 dsi_bus_unlock(); 1363 dsi_bus_unlock();
1040 mutex_unlock(&td->lock); 1364 mutex_unlock(&td->lock);
1041 return 0; 1365 return 0;
1042err: 1366err2:
1043 dsi_bus_unlock(); 1367 dsi_bus_unlock();
1368err1:
1044 mutex_unlock(&td->lock); 1369 mutex_unlock(&td->lock);
1045 return r; 1370 return r;
1046} 1371}
@@ -1128,6 +1453,7 @@ static void taal_esd_work(struct work_struct *work)
1128 struct taal_data *td = container_of(work, struct taal_data, 1453 struct taal_data *td = container_of(work, struct taal_data,
1129 esd_work.work); 1454 esd_work.work);
1130 struct omap_dss_device *dssdev = td->dssdev; 1455 struct omap_dss_device *dssdev = td->dssdev;
1456 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1131 u8 state1, state2; 1457 u8 state1, state2;
1132 int r; 1458 int r;
1133 1459
@@ -1168,7 +1494,7 @@ static void taal_esd_work(struct work_struct *work)
1168 } 1494 }
1169 /* Self-diagnostics result is also shown on TE GPIO line. We need 1495 /* Self-diagnostics result is also shown on TE GPIO line. We need
1170 * to re-enable TE after self diagnostics */ 1496 * to re-enable TE after self diagnostics */
1171 if (td->use_ext_te && td->te_enabled) { 1497 if (td->te_enabled && panel_data->use_ext_te) {
1172 r = taal_dcs_write_1(DCS_TEAR_ON, 0); 1498 r = taal_dcs_write_1(DCS_TEAR_ON, 0);
1173 if (r) 1499 if (r)
1174 goto err; 1500 goto err;
@@ -1184,6 +1510,7 @@ err:
1184 dev_err(&dssdev->dev, "performing LCD reset\n"); 1510 dev_err(&dssdev->dev, "performing LCD reset\n");
1185 1511
1186 taal_power_off(dssdev); 1512 taal_power_off(dssdev);
1513 taal_hw_reset(dssdev);
1187 taal_power_on(dssdev); 1514 taal_power_on(dssdev);
1188 1515
1189 dsi_bus_unlock(); 1516 dsi_bus_unlock();
diff --git a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
index fa434ca6e4b7..e320e67d06f3 100644
--- a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
+++ b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c
@@ -73,8 +73,12 @@ static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
73 73
74static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev) 74static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev)
75{ 75{
76 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | 76 dssdev->panel.config = OMAP_DSS_LCD_TFT |
77 OMAP_DSS_LCD_IHS; 77 OMAP_DSS_LCD_IVS |
78 OMAP_DSS_LCD_IHS |
79 OMAP_DSS_LCD_IPC |
80 OMAP_DSS_LCD_ONOFF;
81
78 dssdev->panel.timings = toppoly_tdo_panel_timings; 82 dssdev->panel.timings = toppoly_tdo_panel_timings;
79 83
80 return 0; 84 return 0;
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index e777e352dbcd..5ecdc0004094 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -31,6 +31,7 @@
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/workqueue.h> 33#include <linux/workqueue.h>
34#include <linux/hardirq.h>
34 35
35#include <plat/sram.h> 36#include <plat/sram.h>
36#include <plat/clock.h> 37#include <plat/clock.h>
@@ -335,7 +336,7 @@ void dispc_save_context(void)
335void dispc_restore_context(void) 336void dispc_restore_context(void)
336{ 337{
337 RR(SYSCONFIG); 338 RR(SYSCONFIG);
338 RR(IRQENABLE); 339 /*RR(IRQENABLE);*/
339 /*RR(CONTROL);*/ 340 /*RR(CONTROL);*/
340 RR(CONFIG); 341 RR(CONFIG);
341 RR(DEFAULT_COLOR0); 342 RR(DEFAULT_COLOR0);
@@ -472,6 +473,15 @@ void dispc_restore_context(void)
472 473
473 /* enable last, because LCD & DIGIT enable are here */ 474 /* enable last, because LCD & DIGIT enable are here */
474 RR(CONTROL); 475 RR(CONTROL);
476
477 /* clear spurious SYNC_LOST_DIGIT interrupts */
478 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
479
480 /*
481 * enable last so IRQs won't trigger before
482 * the context is fully restored
483 */
484 RR(IRQENABLE);
475} 485}
476 486
477#undef SR 487#undef SR
@@ -3019,7 +3029,7 @@ void dispc_fake_vsync_irq(void)
3019 u32 irqstatus = DISPC_IRQ_VSYNC; 3029 u32 irqstatus = DISPC_IRQ_VSYNC;
3020 int i; 3030 int i;
3021 3031
3022 local_irq_disable(); 3032 WARN_ON(!in_interrupt());
3023 3033
3024 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 3034 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3025 struct omap_dispc_isr_data *isr_data; 3035 struct omap_dispc_isr_data *isr_data;
@@ -3031,8 +3041,6 @@ void dispc_fake_vsync_irq(void)
3031 if (isr_data->mask & irqstatus) 3041 if (isr_data->mask & irqstatus)
3032 isr_data->isr(isr_data->arg, irqstatus); 3042 isr_data->isr(isr_data->arg, irqstatus);
3033 } 3043 }
3034
3035 local_irq_enable();
3036} 3044}
3037#endif 3045#endif
3038 3046
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index ef8c8529dda2..22dd7a474f79 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -82,6 +82,9 @@ static ssize_t display_upd_mode_store(struct device *dev,
82 int val, r; 82 int val, r;
83 enum omap_dss_update_mode mode; 83 enum omap_dss_update_mode mode;
84 84
85 if (!dssdev->driver->set_update_mode)
86 return -EINVAL;
87
85 val = simple_strtoul(buf, NULL, 10); 88 val = simple_strtoul(buf, NULL, 10);
86 89
87 switch (val) { 90 switch (val) {
@@ -343,7 +346,6 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
343 case OMAP_DISPLAY_TYPE_VENC: 346 case OMAP_DISPLAY_TYPE_VENC:
344 case OMAP_DISPLAY_TYPE_SDI: 347 case OMAP_DISPLAY_TYPE_SDI:
345 return 24; 348 return 24;
346 return 24;
347 default: 349 default:
348 BUG(); 350 BUG();
349 } 351 }
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 3af207b2bde3..b3fa3a7db911 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -165,6 +165,14 @@ struct dsi_reg { u16 idx; };
165#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) 165#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
166#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) 166#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
167#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) 167#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
168#define DSI_CIO_IRQ_ERROR_MASK \
169 (DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \
170 DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \
171 DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRCONTROL1 | \
172 DSI_CIO_IRQ_ERRCONTROL2 | DSI_CIO_IRQ_ERRCONTROL3 | \
173 DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \
174 DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \
175 DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3)
168 176
169#define DSI_DT_DCS_SHORT_WRITE_0 0x05 177#define DSI_DT_DCS_SHORT_WRITE_0 0x05
170#define DSI_DT_DCS_SHORT_WRITE_1 0x15 178#define DSI_DT_DCS_SHORT_WRITE_1 0x15
@@ -232,13 +240,15 @@ static struct
232 unsigned pll_locked; 240 unsigned pll_locked;
233 241
234 struct completion bta_completion; 242 struct completion bta_completion;
243 void (*bta_callback)(void);
235 244
236 int update_channel; 245 int update_channel;
237 struct dsi_update_region update_region; 246 struct dsi_update_region update_region;
238 247
239 bool te_enabled; 248 bool te_enabled;
240 249
241 struct work_struct framedone_work; 250 struct workqueue_struct *workqueue;
251
242 void (*framedone_callback)(int, void *); 252 void (*framedone_callback)(int, void *);
243 void *framedone_data; 253 void *framedone_data;
244 254
@@ -509,9 +519,13 @@ void dsi_irq_handler(void)
509 dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); 519 dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]);
510#endif 520#endif
511 521
512 if (vcstatus & DSI_VC_IRQ_BTA) 522 if (vcstatus & DSI_VC_IRQ_BTA) {
513 complete(&dsi.bta_completion); 523 complete(&dsi.bta_completion);
514 524
525 if (dsi.bta_callback)
526 dsi.bta_callback();
527 }
528
515 if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { 529 if (vcstatus & DSI_VC_IRQ_ERROR_MASK) {
516 DSSERR("DSI VC(%d) error, vc irqstatus %x\n", 530 DSSERR("DSI VC(%d) error, vc irqstatus %x\n",
517 i, vcstatus); 531 i, vcstatus);
@@ -536,8 +550,12 @@ void dsi_irq_handler(void)
536 /* flush posted write */ 550 /* flush posted write */
537 dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); 551 dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
538 552
539 DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); 553 if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) {
540 print_irq_status_cio(ciostatus); 554 DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus);
555 print_irq_status_cio(ciostatus);
556 } else if (debug_irq) {
557 print_irq_status_cio(ciostatus);
558 }
541 } 559 }
542 560
543 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); 561 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
@@ -584,11 +602,8 @@ static void _dsi_initialize_irq(void)
584 for (i = 0; i < 4; ++i) 602 for (i = 0; i < 4; ++i)
585 dsi_write_reg(DSI_VC_IRQENABLE(i), l); 603 dsi_write_reg(DSI_VC_IRQENABLE(i), l);
586 604
587 /* XXX zonda responds incorrectly, causing control error: 605 l = DSI_CIO_IRQ_ERROR_MASK;
588 Exit from LP-ESC mode to LP11 uses wrong transition states on the 606 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l);
589 data lines LP0 and LN0. */
590 dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE,
591 -1 & (~DSI_CIO_IRQ_ERRCONTROL2));
592} 607}
593 608
594static u32 dsi_get_errors(void) 609static u32 dsi_get_errors(void)
@@ -1098,6 +1113,7 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
1098 if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { 1113 if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) {
1099 DSSERR("PLL not coming out of reset.\n"); 1114 DSSERR("PLL not coming out of reset.\n");
1100 r = -ENODEV; 1115 r = -ENODEV;
1116 dispc_pck_free_enable(0);
1101 goto err1; 1117 goto err1;
1102 } 1118 }
1103 1119
@@ -1740,42 +1756,52 @@ static void dsi_vc_initial_config(int channel)
1740 dsi.vc[channel].mode = DSI_VC_MODE_L4; 1756 dsi.vc[channel].mode = DSI_VC_MODE_L4;
1741} 1757}
1742 1758
1743static void dsi_vc_config_l4(int channel) 1759static int dsi_vc_config_l4(int channel)
1744{ 1760{
1745 if (dsi.vc[channel].mode == DSI_VC_MODE_L4) 1761 if (dsi.vc[channel].mode == DSI_VC_MODE_L4)
1746 return; 1762 return 0;
1747 1763
1748 DSSDBGF("%d", channel); 1764 DSSDBGF("%d", channel);
1749 1765
1750 dsi_vc_enable(channel, 0); 1766 dsi_vc_enable(channel, 0);
1751 1767
1752 if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ 1768 /* VC_BUSY */
1769 if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) {
1753 DSSERR("vc(%d) busy when trying to config for L4\n", channel); 1770 DSSERR("vc(%d) busy when trying to config for L4\n", channel);
1771 return -EIO;
1772 }
1754 1773
1755 REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ 1774 REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
1756 1775
1757 dsi_vc_enable(channel, 1); 1776 dsi_vc_enable(channel, 1);
1758 1777
1759 dsi.vc[channel].mode = DSI_VC_MODE_L4; 1778 dsi.vc[channel].mode = DSI_VC_MODE_L4;
1779
1780 return 0;
1760} 1781}
1761 1782
1762static void dsi_vc_config_vp(int channel) 1783static int dsi_vc_config_vp(int channel)
1763{ 1784{
1764 if (dsi.vc[channel].mode == DSI_VC_MODE_VP) 1785 if (dsi.vc[channel].mode == DSI_VC_MODE_VP)
1765 return; 1786 return 0;
1766 1787
1767 DSSDBGF("%d", channel); 1788 DSSDBGF("%d", channel);
1768 1789
1769 dsi_vc_enable(channel, 0); 1790 dsi_vc_enable(channel, 0);
1770 1791
1771 if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ 1792 /* VC_BUSY */
1793 if (wait_for_bit_change(DSI_VC_CTRL(channel), 15, 0) != 0) {
1772 DSSERR("vc(%d) busy when trying to config for VP\n", channel); 1794 DSSERR("vc(%d) busy when trying to config for VP\n", channel);
1795 return -EIO;
1796 }
1773 1797
1774 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ 1798 REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
1775 1799
1776 dsi_vc_enable(channel, 1); 1800 dsi_vc_enable(channel, 1);
1777 1801
1778 dsi.vc[channel].mode = DSI_VC_MODE_VP; 1802 dsi.vc[channel].mode = DSI_VC_MODE_VP;
1803
1804 return 0;
1779} 1805}
1780 1806
1781 1807
@@ -1854,19 +1880,19 @@ static u16 dsi_vc_flush_receive_data(int channel)
1854 u32 val; 1880 u32 val;
1855 u8 dt; 1881 u8 dt;
1856 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); 1882 val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel));
1857 DSSDBG("\trawval %#08x\n", val); 1883 DSSERR("\trawval %#08x\n", val);
1858 dt = FLD_GET(val, 5, 0); 1884 dt = FLD_GET(val, 5, 0);
1859 if (dt == DSI_DT_RX_ACK_WITH_ERR) { 1885 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
1860 u16 err = FLD_GET(val, 23, 8); 1886 u16 err = FLD_GET(val, 23, 8);
1861 dsi_show_rx_ack_with_err(err); 1887 dsi_show_rx_ack_with_err(err);
1862 } else if (dt == DSI_DT_RX_SHORT_READ_1) { 1888 } else if (dt == DSI_DT_RX_SHORT_READ_1) {
1863 DSSDBG("\tDCS short response, 1 byte: %#x\n", 1889 DSSERR("\tDCS short response, 1 byte: %#x\n",
1864 FLD_GET(val, 23, 8)); 1890 FLD_GET(val, 23, 8));
1865 } else if (dt == DSI_DT_RX_SHORT_READ_2) { 1891 } else if (dt == DSI_DT_RX_SHORT_READ_2) {
1866 DSSDBG("\tDCS short response, 2 byte: %#x\n", 1892 DSSERR("\tDCS short response, 2 byte: %#x\n",
1867 FLD_GET(val, 23, 8)); 1893 FLD_GET(val, 23, 8));
1868 } else if (dt == DSI_DT_RX_DCS_LONG_READ) { 1894 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
1869 DSSDBG("\tDCS long response, len %d\n", 1895 DSSERR("\tDCS long response, len %d\n",
1870 FLD_GET(val, 23, 8)); 1896 FLD_GET(val, 23, 8));
1871 dsi_vc_flush_long_data(channel); 1897 dsi_vc_flush_long_data(channel);
1872 } else { 1898 } else {
@@ -2087,6 +2113,13 @@ int dsi_vc_dcs_write(int channel, u8 *data, int len)
2087 if (r) 2113 if (r)
2088 goto err; 2114 goto err;
2089 2115
2116 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */
2117 DSSERR("rx fifo not empty after write, dumping data:\n");
2118 dsi_vc_flush_receive_data(channel);
2119 r = -EIO;
2120 goto err;
2121 }
2122
2090 return 0; 2123 return 0;
2091err: 2124err:
2092 DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n", 2125 DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n",
@@ -2233,11 +2266,12 @@ int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data)
2233} 2266}
2234EXPORT_SYMBOL(dsi_vc_dcs_read_1); 2267EXPORT_SYMBOL(dsi_vc_dcs_read_1);
2235 2268
2236int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data) 2269int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2)
2237{ 2270{
2271 u8 buf[2];
2238 int r; 2272 int r;
2239 2273
2240 r = dsi_vc_dcs_read(channel, dcs_cmd, (u8 *)data, 2); 2274 r = dsi_vc_dcs_read(channel, dcs_cmd, buf, 2);
2241 2275
2242 if (r < 0) 2276 if (r < 0)
2243 return r; 2277 return r;
@@ -2245,231 +2279,122 @@ int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data)
2245 if (r != 2) 2279 if (r != 2)
2246 return -EIO; 2280 return -EIO;
2247 2281
2282 *data1 = buf[0];
2283 *data2 = buf[1];
2284
2248 return 0; 2285 return 0;
2249} 2286}
2250EXPORT_SYMBOL(dsi_vc_dcs_read_2); 2287EXPORT_SYMBOL(dsi_vc_dcs_read_2);
2251 2288
2252int dsi_vc_set_max_rx_packet_size(int channel, u16 len) 2289int dsi_vc_set_max_rx_packet_size(int channel, u16 len)
2253{ 2290{
2254 int r; 2291 return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
2255 r = dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
2256 len, 0); 2292 len, 0);
2257
2258 if (r)
2259 return r;
2260
2261 r = dsi_vc_send_bta_sync(channel);
2262
2263 return r;
2264} 2293}
2265EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); 2294EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
2266 2295
2267static void dsi_set_lp_rx_timeout(unsigned long ns) 2296static void dsi_set_lp_rx_timeout(unsigned ticks, bool x4, bool x16)
2268{ 2297{
2269 u32 r;
2270 unsigned x4, x16;
2271 unsigned long fck; 2298 unsigned long fck;
2272 unsigned long ticks; 2299 unsigned long total_ticks;
2300 u32 r;
2273 2301
2274 /* ticks in DSI_FCK */ 2302 BUG_ON(ticks > 0x1fff);
2275 2303
2304 /* ticks in DSI_FCK */
2276 fck = dsi_fclk_rate(); 2305 fck = dsi_fclk_rate();
2277 ticks = (fck / 1000 / 1000) * ns / 1000;
2278 x4 = 0;
2279 x16 = 0;
2280
2281 if (ticks > 0x1fff) {
2282 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2283 x4 = 1;
2284 x16 = 0;
2285 }
2286
2287 if (ticks > 0x1fff) {
2288 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2289 x4 = 0;
2290 x16 = 1;
2291 }
2292
2293 if (ticks > 0x1fff) {
2294 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2295 x4 = 1;
2296 x16 = 1;
2297 }
2298
2299 if (ticks > 0x1fff) {
2300 DSSWARN("LP_TX_TO over limit, setting it to max\n");
2301 ticks = 0x1fff;
2302 x4 = 1;
2303 x16 = 1;
2304 }
2305 2306
2306 r = dsi_read_reg(DSI_TIMING2); 2307 r = dsi_read_reg(DSI_TIMING2);
2307 r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ 2308 r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */
2308 r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */ 2309 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* LP_RX_TO_X16 */
2309 r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */ 2310 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* LP_RX_TO_X4 */
2310 r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ 2311 r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */
2311 dsi_write_reg(DSI_TIMING2, r); 2312 dsi_write_reg(DSI_TIMING2, r);
2312 2313
2313 DSSDBG("LP_RX_TO %lu ns (%#lx ticks%s%s)\n", 2314 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
2314 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / 2315
2315 (fck / 1000 / 1000), 2316 DSSDBG("LP_RX_TO %lu ticks (%#x%s%s) = %lu ns\n",
2316 ticks, x4 ? " x4" : "", x16 ? " x16" : ""); 2317 total_ticks,
2318 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
2319 (total_ticks * 1000) / (fck / 1000 / 1000));
2317} 2320}
2318 2321
2319static void dsi_set_ta_timeout(unsigned long ns) 2322static void dsi_set_ta_timeout(unsigned ticks, bool x8, bool x16)
2320{ 2323{
2321 u32 r;
2322 unsigned x8, x16;
2323 unsigned long fck; 2324 unsigned long fck;
2324 unsigned long ticks; 2325 unsigned long total_ticks;
2326 u32 r;
2327
2328 BUG_ON(ticks > 0x1fff);
2325 2329
2326 /* ticks in DSI_FCK */ 2330 /* ticks in DSI_FCK */
2327 fck = dsi_fclk_rate(); 2331 fck = dsi_fclk_rate();
2328 ticks = (fck / 1000 / 1000) * ns / 1000;
2329 x8 = 0;
2330 x16 = 0;
2331
2332 if (ticks > 0x1fff) {
2333 ticks = (fck / 1000 / 1000) * ns / 1000 / 8;
2334 x8 = 1;
2335 x16 = 0;
2336 }
2337
2338 if (ticks > 0x1fff) {
2339 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2340 x8 = 0;
2341 x16 = 1;
2342 }
2343
2344 if (ticks > 0x1fff) {
2345 ticks = (fck / 1000 / 1000) * ns / 1000 / (8 * 16);
2346 x8 = 1;
2347 x16 = 1;
2348 }
2349
2350 if (ticks > 0x1fff) {
2351 DSSWARN("TA_TO over limit, setting it to max\n");
2352 ticks = 0x1fff;
2353 x8 = 1;
2354 x16 = 1;
2355 }
2356 2332
2357 r = dsi_read_reg(DSI_TIMING1); 2333 r = dsi_read_reg(DSI_TIMING1);
2358 r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ 2334 r = FLD_MOD(r, 1, 31, 31); /* TA_TO */
2359 r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */ 2335 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* TA_TO_X16 */
2360 r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */ 2336 r = FLD_MOD(r, x8 ? 1 : 0, 29, 29); /* TA_TO_X8 */
2361 r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ 2337 r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */
2362 dsi_write_reg(DSI_TIMING1, r); 2338 dsi_write_reg(DSI_TIMING1, r);
2363 2339
2364 DSSDBG("TA_TO %lu ns (%#lx ticks%s%s)\n", 2340 total_ticks = ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1);
2365 (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) / 2341
2366 (fck / 1000 / 1000), 2342 DSSDBG("TA_TO %lu ticks (%#x%s%s) = %lu ns\n",
2367 ticks, x8 ? " x8" : "", x16 ? " x16" : ""); 2343 total_ticks,
2344 ticks, x8 ? " x8" : "", x16 ? " x16" : "",
2345 (total_ticks * 1000) / (fck / 1000 / 1000));
2368} 2346}
2369 2347
2370static void dsi_set_stop_state_counter(unsigned long ns) 2348static void dsi_set_stop_state_counter(unsigned ticks, bool x4, bool x16)
2371{ 2349{
2372 u32 r;
2373 unsigned x4, x16;
2374 unsigned long fck; 2350 unsigned long fck;
2375 unsigned long ticks; 2351 unsigned long total_ticks;
2352 u32 r;
2376 2353
2377 /* ticks in DSI_FCK */ 2354 BUG_ON(ticks > 0x1fff);
2378 2355
2356 /* ticks in DSI_FCK */
2379 fck = dsi_fclk_rate(); 2357 fck = dsi_fclk_rate();
2380 ticks = (fck / 1000 / 1000) * ns / 1000;
2381 x4 = 0;
2382 x16 = 0;
2383
2384 if (ticks > 0x1fff) {
2385 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2386 x4 = 1;
2387 x16 = 0;
2388 }
2389
2390 if (ticks > 0x1fff) {
2391 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2392 x4 = 0;
2393 x16 = 1;
2394 }
2395
2396 if (ticks > 0x1fff) {
2397 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2398 x4 = 1;
2399 x16 = 1;
2400 }
2401
2402 if (ticks > 0x1fff) {
2403 DSSWARN("STOP_STATE_COUNTER_IO over limit, "
2404 "setting it to max\n");
2405 ticks = 0x1fff;
2406 x4 = 1;
2407 x16 = 1;
2408 }
2409 2358
2410 r = dsi_read_reg(DSI_TIMING1); 2359 r = dsi_read_reg(DSI_TIMING1);
2411 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ 2360 r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */
2412 r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */ 2361 r = FLD_MOD(r, x16 ? 1 : 0, 14, 14); /* STOP_STATE_X16_IO */
2413 r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */ 2362 r = FLD_MOD(r, x4 ? 1 : 0, 13, 13); /* STOP_STATE_X4_IO */
2414 r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ 2363 r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */
2415 dsi_write_reg(DSI_TIMING1, r); 2364 dsi_write_reg(DSI_TIMING1, r);
2416 2365
2417 DSSDBG("STOP_STATE_COUNTER %lu ns (%#lx ticks%s%s)\n", 2366 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
2418 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / 2367
2419 (fck / 1000 / 1000), 2368 DSSDBG("STOP_STATE_COUNTER %lu ticks (%#x%s%s) = %lu ns\n",
2420 ticks, x4 ? " x4" : "", x16 ? " x16" : ""); 2369 total_ticks,
2370 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
2371 (total_ticks * 1000) / (fck / 1000 / 1000));
2421} 2372}
2422 2373
2423static void dsi_set_hs_tx_timeout(unsigned long ns) 2374static void dsi_set_hs_tx_timeout(unsigned ticks, bool x4, bool x16)
2424{ 2375{
2425 u32 r;
2426 unsigned x4, x16;
2427 unsigned long fck; 2376 unsigned long fck;
2428 unsigned long ticks; 2377 unsigned long total_ticks;
2378 u32 r;
2429 2379
2430 /* ticks in TxByteClkHS */ 2380 BUG_ON(ticks > 0x1fff);
2431 2381
2382 /* ticks in TxByteClkHS */
2432 fck = dsi_get_txbyteclkhs(); 2383 fck = dsi_get_txbyteclkhs();
2433 ticks = (fck / 1000 / 1000) * ns / 1000;
2434 x4 = 0;
2435 x16 = 0;
2436
2437 if (ticks > 0x1fff) {
2438 ticks = (fck / 1000 / 1000) * ns / 1000 / 4;
2439 x4 = 1;
2440 x16 = 0;
2441 }
2442
2443 if (ticks > 0x1fff) {
2444 ticks = (fck / 1000 / 1000) * ns / 1000 / 16;
2445 x4 = 0;
2446 x16 = 1;
2447 }
2448
2449 if (ticks > 0x1fff) {
2450 ticks = (fck / 1000 / 1000) * ns / 1000 / (4 * 16);
2451 x4 = 1;
2452 x16 = 1;
2453 }
2454
2455 if (ticks > 0x1fff) {
2456 DSSWARN("HS_TX_TO over limit, setting it to max\n");
2457 ticks = 0x1fff;
2458 x4 = 1;
2459 x16 = 1;
2460 }
2461 2384
2462 r = dsi_read_reg(DSI_TIMING2); 2385 r = dsi_read_reg(DSI_TIMING2);
2463 r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ 2386 r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */
2464 r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */ 2387 r = FLD_MOD(r, x16 ? 1 : 0, 30, 30); /* HS_TX_TO_X16 */
2465 r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */ 2388 r = FLD_MOD(r, x4 ? 1 : 0, 29, 29); /* HS_TX_TO_X8 (4 really) */
2466 r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ 2389 r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */
2467 dsi_write_reg(DSI_TIMING2, r); 2390 dsi_write_reg(DSI_TIMING2, r);
2468 2391
2469 DSSDBG("HS_TX_TO %lu ns (%#lx ticks%s%s)\n", 2392 total_ticks = ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1);
2470 (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / 2393
2471 (fck / 1000 / 1000), 2394 DSSDBG("HS_TX_TO %lu ticks (%#x%s%s) = %lu ns\n",
2472 ticks, x4 ? " x4" : "", x16 ? " x16" : ""); 2395 total_ticks,
2396 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
2397 (total_ticks * 1000) / (fck / 1000 / 1000));
2473} 2398}
2474static int dsi_proto_config(struct omap_dss_device *dssdev) 2399static int dsi_proto_config(struct omap_dss_device *dssdev)
2475{ 2400{
@@ -2487,10 +2412,10 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
2487 DSI_FIFO_SIZE_32); 2412 DSI_FIFO_SIZE_32);
2488 2413
2489 /* XXX what values for the timeouts? */ 2414 /* XXX what values for the timeouts? */
2490 dsi_set_stop_state_counter(1000); 2415 dsi_set_stop_state_counter(0x1000, false, false);
2491 dsi_set_ta_timeout(6400000); 2416 dsi_set_ta_timeout(0x1fff, true, true);
2492 dsi_set_lp_rx_timeout(48000); 2417 dsi_set_lp_rx_timeout(0x1fff, true, true);
2493 dsi_set_hs_tx_timeout(1000000); 2418 dsi_set_hs_tx_timeout(0x1fff, true, true);
2494 2419
2495 switch (dssdev->ctrl.pixel_size) { 2420 switch (dssdev->ctrl.pixel_size) {
2496 case 16: 2421 case 16:
@@ -2759,6 +2684,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2759 unsigned packet_payload; 2684 unsigned packet_payload;
2760 unsigned packet_len; 2685 unsigned packet_len;
2761 u32 l; 2686 u32 l;
2687 int r;
2762 const unsigned channel = dsi.update_channel; 2688 const unsigned channel = dsi.update_channel;
2763 /* line buffer is 1024 x 24bits */ 2689 /* line buffer is 1024 x 24bits */
2764 /* XXX: for some reason using full buffer size causes considerable TX 2690 /* XXX: for some reason using full buffer size causes considerable TX
@@ -2809,8 +2735,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
2809 2735
2810 dsi_perf_mark_start(); 2736 dsi_perf_mark_start();
2811 2737
2812 schedule_delayed_work(&dsi.framedone_timeout_work, 2738 r = queue_delayed_work(dsi.workqueue, &dsi.framedone_timeout_work,
2813 msecs_to_jiffies(250)); 2739 msecs_to_jiffies(250));
2740 BUG_ON(r == 0);
2814 2741
2815 dss_start_update(dssdev); 2742 dss_start_update(dssdev);
2816 2743
@@ -2834,62 +2761,70 @@ static void dsi_te_timeout(unsigned long arg)
2834} 2761}
2835#endif 2762#endif
2836 2763
2837static void dsi_framedone_timeout_work_callback(struct work_struct *work) 2764static void dsi_handle_framedone(int error)
2838{ 2765{
2839 int r;
2840 const int channel = dsi.update_channel; 2766 const int channel = dsi.update_channel;
2841 2767
2842 DSSERR("Framedone not received for 250ms!\n"); 2768 cancel_delayed_work(&dsi.framedone_timeout_work);
2769
2770 dsi_vc_disable_bta_irq(channel);
2843 2771
2844 /* SIDLEMODE back to smart-idle */ 2772 /* SIDLEMODE back to smart-idle */
2845 dispc_enable_sidle(); 2773 dispc_enable_sidle();
2846 2774
2775 dsi.bta_callback = NULL;
2776
2847 if (dsi.te_enabled) { 2777 if (dsi.te_enabled) {
2848 /* enable LP_RX_TO again after the TE */ 2778 /* enable LP_RX_TO again after the TE */
2849 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ 2779 REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
2850 } 2780 }
2851 2781
2852 /* Send BTA after the frame. We need this for the TE to work, as TE
2853 * trigger is only sent for BTAs without preceding packet. Thus we need
2854 * to BTA after the pixel packets so that next BTA will cause TE
2855 * trigger.
2856 *
2857 * This is not needed when TE is not in use, but we do it anyway to
2858 * make sure that the transfer has been completed. It would be more
2859 * optimal, but more complex, to wait only just before starting next
2860 * transfer. */
2861 r = dsi_vc_send_bta_sync(channel);
2862 if (r)
2863 DSSERR("BTA after framedone failed\n");
2864
2865 /* RX_FIFO_NOT_EMPTY */ 2782 /* RX_FIFO_NOT_EMPTY */
2866 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { 2783 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
2867 DSSERR("Received error during frame transfer:\n"); 2784 DSSERR("Received error during frame transfer:\n");
2868 dsi_vc_flush_receive_data(channel); 2785 dsi_vc_flush_receive_data(channel);
2786 if (!error)
2787 error = -EIO;
2869 } 2788 }
2870 2789
2871 dsi.framedone_callback(-ETIMEDOUT, dsi.framedone_data); 2790 dsi.framedone_callback(error, dsi.framedone_data);
2791
2792 if (!error)
2793 dsi_perf_show("DISPC");
2872} 2794}
2873 2795
2874static void dsi_framedone_irq_callback(void *data, u32 mask) 2796static void dsi_framedone_timeout_work_callback(struct work_struct *work)
2875{ 2797{
2876 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and 2798 /* XXX While extremely unlikely, we could get FRAMEDONE interrupt after
2877 * turns itself off. However, DSI still has the pixels in its buffers, 2799 * 250ms which would conflict with this timeout work. What should be
2878 * and is sending the data. 2800 * done is first cancel the transfer on the HW, and then cancel the
2879 */ 2801 * possibly scheduled framedone work. However, cancelling the transfer
2802 * on the HW is buggy, and would probably require resetting the whole
2803 * DSI */
2880 2804
2881 /* SIDLEMODE back to smart-idle */ 2805 DSSERR("Framedone not received for 250ms!\n");
2882 dispc_enable_sidle();
2883 2806
2884 schedule_work(&dsi.framedone_work); 2807 dsi_handle_framedone(-ETIMEDOUT);
2885} 2808}
2886 2809
2887static void dsi_handle_framedone(void) 2810static void dsi_framedone_bta_callback(void)
2811{
2812 dsi_handle_framedone(0);
2813
2814#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2815 dispc_fake_vsync_irq();
2816#endif
2817}
2818
2819static void dsi_framedone_irq_callback(void *data, u32 mask)
2888{ 2820{
2889 int r;
2890 const int channel = dsi.update_channel; 2821 const int channel = dsi.update_channel;
2822 int r;
2891 2823
2892 DSSDBG("FRAMEDONE\n"); 2824 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
2825 * turns itself off. However, DSI still has the pixels in its buffers,
2826 * and is sending the data.
2827 */
2893 2828
2894 if (dsi.te_enabled) { 2829 if (dsi.te_enabled) {
2895 /* enable LP_RX_TO again after the TE */ 2830 /* enable LP_RX_TO again after the TE */
@@ -2904,37 +2839,30 @@ static void dsi_handle_framedone(void)
2904 * This is not needed when TE is not in use, but we do it anyway to 2839 * This is not needed when TE is not in use, but we do it anyway to
2905 * make sure that the transfer has been completed. It would be more 2840 * make sure that the transfer has been completed. It would be more
2906 * optimal, but more complex, to wait only just before starting next 2841 * optimal, but more complex, to wait only just before starting next
2907 * transfer. */ 2842 * transfer.
2908 r = dsi_vc_send_bta_sync(channel); 2843 *
2909 if (r) 2844 * Also, as there's no interrupt telling when the transfer has been
2910 DSSERR("BTA after framedone failed\n"); 2845 * done and the channel could be reconfigured, the only way is to
2911 2846 * busyloop until TE_SIZE is zero. With BTA we can do this
2912 /* RX_FIFO_NOT_EMPTY */ 2847 * asynchronously.
2913 if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { 2848 * */
2914 DSSERR("Received error during frame transfer:\n");
2915 dsi_vc_flush_receive_data(channel);
2916 }
2917
2918#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
2919 dispc_fake_vsync_irq();
2920#endif
2921}
2922
2923static void dsi_framedone_work_callback(struct work_struct *work)
2924{
2925 DSSDBGF();
2926 2849
2927 cancel_delayed_work_sync(&dsi.framedone_timeout_work); 2850 dsi.bta_callback = dsi_framedone_bta_callback;
2928 2851
2929 dsi_handle_framedone(); 2852 barrier();
2930 2853
2931 dsi_perf_show("DISPC"); 2854 dsi_vc_enable_bta_irq(channel);
2932 2855
2933 dsi.framedone_callback(0, dsi.framedone_data); 2856 r = dsi_vc_send_bta(channel);
2857 if (r) {
2858 DSSERR("BTA after framedone failed\n");
2859 dsi_handle_framedone(-EIO);
2860 }
2934} 2861}
2935 2862
2936int omap_dsi_prepare_update(struct omap_dss_device *dssdev, 2863int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
2937 u16 *x, u16 *y, u16 *w, u16 *h) 2864 u16 *x, u16 *y, u16 *w, u16 *h,
2865 bool enlarge_update_area)
2938{ 2866{
2939 u16 dw, dh; 2867 u16 dw, dh;
2940 2868
@@ -2958,7 +2886,8 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
2958 dsi_perf_mark_setup(); 2886 dsi_perf_mark_setup();
2959 2887
2960 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 2888 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2961 dss_setup_partial_planes(dssdev, x, y, w, h); 2889 dss_setup_partial_planes(dssdev, x, y, w, h,
2890 enlarge_update_area);
2962 dispc_set_lcd_size(*w, *h); 2891 dispc_set_lcd_size(*w, *h);
2963 } 2892 }
2964 2893
@@ -2973,6 +2902,12 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
2973{ 2902{
2974 dsi.update_channel = channel; 2903 dsi.update_channel = channel;
2975 2904
2905 /* OMAP DSS cannot send updates of odd widths.
2906 * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON
2907 * here to make sure we catch erroneous updates. Otherwise we'll only
2908 * see rather obscure HW error happening, as DSS halts. */
2909 BUG_ON(x % 2 == 1);
2910
2976 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 2911 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
2977 dsi.framedone_callback = callback; 2912 dsi.framedone_callback = callback;
2978 dsi.framedone_data = data; 2913 dsi.framedone_data = data;
@@ -2985,7 +2920,12 @@ int omap_dsi_update(struct omap_dss_device *dssdev,
2985 2920
2986 dsi_update_screen_dispc(dssdev, x, y, w, h); 2921 dsi_update_screen_dispc(dssdev, x, y, w, h);
2987 } else { 2922 } else {
2988 dsi_update_screen_l4(dssdev, x, y, w, h); 2923 int r;
2924
2925 r = dsi_update_screen_l4(dssdev, x, y, w, h);
2926 if (r)
2927 return r;
2928
2989 dsi_perf_show("L4"); 2929 dsi_perf_show("L4");
2990 callback(0, data); 2930 callback(0, data);
2991 } 2931 }
@@ -3048,8 +2988,10 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
3048 cinfo.regm3 = dssdev->phy.dsi.div.regm3; 2988 cinfo.regm3 = dssdev->phy.dsi.div.regm3;
3049 cinfo.regm4 = dssdev->phy.dsi.div.regm4; 2989 cinfo.regm4 = dssdev->phy.dsi.div.regm4;
3050 r = dsi_calc_clock_rates(&cinfo); 2990 r = dsi_calc_clock_rates(&cinfo);
3051 if (r) 2991 if (r) {
2992 DSSERR("Failed to calc dsi clocks\n");
3052 return r; 2993 return r;
2994 }
3053 2995
3054 r = dsi_pll_set_clock_div(&cinfo); 2996 r = dsi_pll_set_clock_div(&cinfo);
3055 if (r) { 2997 if (r) {
@@ -3147,6 +3089,13 @@ err0:
3147 3089
3148static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) 3090static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
3149{ 3091{
3092 /* disable interface */
3093 dsi_if_enable(0);
3094 dsi_vc_enable(0, 0);
3095 dsi_vc_enable(1, 0);
3096 dsi_vc_enable(2, 0);
3097 dsi_vc_enable(3, 0);
3098
3150 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); 3099 dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
3151 dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); 3100 dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
3152 dsi_complexio_uninit(); 3101 dsi_complexio_uninit();
@@ -3257,7 +3206,7 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
3257 burst_size_bytes = 16 * 32 / 8; 3206 burst_size_bytes = 16 * 32 / 8;
3258 3207
3259 *fifo_high = fifo_size - burst_size_bytes; 3208 *fifo_high = fifo_size - burst_size_bytes;
3260 *fifo_low = fifo_size - burst_size_bytes * 8; 3209 *fifo_low = fifo_size - burst_size_bytes * 2;
3261} 3210}
3262 3211
3263int dsi_init_display(struct omap_dss_device *dssdev) 3212int dsi_init_display(struct omap_dss_device *dssdev)
@@ -3274,6 +3223,18 @@ int dsi_init_display(struct omap_dss_device *dssdev)
3274 return 0; 3223 return 0;
3275} 3224}
3276 3225
3226void dsi_wait_dsi1_pll_active(void)
3227{
3228 if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1)
3229 DSSERR("DSI1 PLL clock not active\n");
3230}
3231
3232void dsi_wait_dsi2_pll_active(void)
3233{
3234 if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1)
3235 DSSERR("DSI2 PLL clock not active\n");
3236}
3237
3277int dsi_init(struct platform_device *pdev) 3238int dsi_init(struct platform_device *pdev)
3278{ 3239{
3279 u32 rev; 3240 u32 rev;
@@ -3292,7 +3253,10 @@ int dsi_init(struct platform_device *pdev)
3292 mutex_init(&dsi.lock); 3253 mutex_init(&dsi.lock);
3293 sema_init(&dsi.bus_lock, 1); 3254 sema_init(&dsi.bus_lock, 1);
3294 3255
3295 INIT_WORK(&dsi.framedone_work, dsi_framedone_work_callback); 3256 dsi.workqueue = create_singlethread_workqueue("dsi");
3257 if (dsi.workqueue == NULL)
3258 return -ENOMEM;
3259
3296 INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work, 3260 INIT_DELAYED_WORK_DEFERRABLE(&dsi.framedone_timeout_work,
3297 dsi_framedone_timeout_work_callback); 3261 dsi_framedone_timeout_work_callback);
3298 3262
@@ -3328,6 +3292,7 @@ int dsi_init(struct platform_device *pdev)
3328err2: 3292err2:
3329 iounmap(dsi.base); 3293 iounmap(dsi.base);
3330err1: 3294err1:
3295 destroy_workqueue(dsi.workqueue);
3331 return r; 3296 return r;
3332} 3297}
3333 3298
@@ -3335,6 +3300,8 @@ void dsi_exit(void)
3335{ 3300{
3336 iounmap(dsi.base); 3301 iounmap(dsi.base);
3337 3302
3303 destroy_workqueue(dsi.workqueue);
3304
3338 DSSDBG("omap_dsi_exit\n"); 3305 DSSDBG("omap_dsi_exit\n");
3339} 3306}
3340 3307
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 24b18258654f..77c3621c9171 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -265,6 +265,9 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
265 265
266 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; 266 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
267 267
268 if (clk_src == DSS_SRC_DSI1_PLL_FCLK)
269 dsi_wait_dsi1_pll_active();
270
268 REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ 271 REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */
269 272
270 dss.dispc_clk_source = clk_src; 273 dss.dispc_clk_source = clk_src;
@@ -279,6 +282,9 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
279 282
280 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; 283 b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
281 284
285 if (clk_src == DSS_SRC_DSI2_PLL_FCLK)
286 dsi_wait_dsi2_pll_active();
287
282 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ 288 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
283 289
284 dss.dsi_clk_source = clk_src; 290 dss.dsi_clk_source = clk_src;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 786f433fd571..5c7940d5f282 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -199,7 +199,8 @@ int dss_init_overlay_managers(struct platform_device *pdev);
199void dss_uninit_overlay_managers(struct platform_device *pdev); 199void dss_uninit_overlay_managers(struct platform_device *pdev);
200int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); 200int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
201void dss_setup_partial_planes(struct omap_dss_device *dssdev, 201void dss_setup_partial_planes(struct omap_dss_device *dssdev,
202 u16 *x, u16 *y, u16 *w, u16 *h); 202 u16 *x, u16 *y, u16 *w, u16 *h,
203 bool enlarge_update_area);
203void dss_start_update(struct omap_dss_device *dssdev); 204void dss_start_update(struct omap_dss_device *dssdev);
204 205
205/* overlay */ 206/* overlay */
@@ -281,6 +282,8 @@ void dsi_pll_uninit(void);
281void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, 282void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
282 u32 fifo_size, enum omap_burst_size *burst_size, 283 u32 fifo_size, enum omap_burst_size *burst_size,
283 u32 *fifo_low, u32 *fifo_high); 284 u32 *fifo_low, u32 *fifo_high);
285void dsi_wait_dsi1_pll_active(void);
286void dsi_wait_dsi2_pll_active(void);
284#else 287#else
285static inline int dsi_init(struct platform_device *pdev) 288static inline int dsi_init(struct platform_device *pdev)
286{ 289{
@@ -289,6 +292,12 @@ static inline int dsi_init(struct platform_device *pdev)
289static inline void dsi_exit(void) 292static inline void dsi_exit(void)
290{ 293{
291} 294}
295static inline void dsi_wait_dsi1_pll_active(void)
296{
297}
298static inline void dsi_wait_dsi2_pll_active(void)
299{
300}
292#endif 301#endif
293 302
294/* DPI */ 303/* DPI */
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 9e1fbe531bf0..6a649ab5539e 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -440,6 +440,10 @@ struct manager_cache_data {
440 440
441 /* manual update region */ 441 /* manual update region */
442 u16 x, y, w, h; 442 u16 x, y, w, h;
443
444 /* enlarge the update area if the update area contains scaled
445 * overlays */
446 bool enlarge_update_area;
443}; 447};
444 448
445static struct { 449static struct {
@@ -525,7 +529,7 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
525 int i; 529 int i;
526 struct omap_dss_device *dssdev = mgr->device; 530 struct omap_dss_device *dssdev = mgr->device;
527 531
528 if (!dssdev) 532 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
529 return 0; 533 return 0;
530 534
531 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { 535 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
@@ -596,11 +600,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
596 int r; 600 int r;
597 int i; 601 int i;
598 602
599 if (!ovl->manager || !ovl->manager->device) 603 if (!ovl->manager)
600 return 0; 604 return 0;
601 605
602 dssdev = ovl->manager->device; 606 dssdev = ovl->manager->device;
603 607
608 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
609 return 0;
610
604 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { 611 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
605 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; 612 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
606 channel = OMAP_DSS_CHANNEL_DIGIT; 613 channel = OMAP_DSS_CHANNEL_DIGIT;
@@ -718,6 +725,7 @@ static int configure_overlay(enum omap_plane plane)
718 u16 x, y, w, h; 725 u16 x, y, w, h;
719 u32 paddr; 726 u32 paddr;
720 int r; 727 int r;
728 u16 orig_w, orig_h, orig_outw, orig_outh;
721 729
722 DSSDBGF("%d", plane); 730 DSSDBGF("%d", plane);
723 731
@@ -738,8 +746,16 @@ static int configure_overlay(enum omap_plane plane)
738 outh = c->out_height == 0 ? c->height : c->out_height; 746 outh = c->out_height == 0 ? c->height : c->out_height;
739 paddr = c->paddr; 747 paddr = c->paddr;
740 748
749 orig_w = w;
750 orig_h = h;
751 orig_outw = outw;
752 orig_outh = outh;
753
741 if (c->manual_update && mc->do_manual_update) { 754 if (c->manual_update && mc->do_manual_update) {
742 unsigned bpp; 755 unsigned bpp;
756 unsigned scale_x_m = w, scale_x_d = outw;
757 unsigned scale_y_m = h, scale_y_d = outh;
758
743 /* If the overlay is outside the update region, disable it */ 759 /* If the overlay is outside the update region, disable it */
744 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, 760 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
745 x, y, outw, outh)) { 761 x, y, outw, outh)) {
@@ -770,38 +786,47 @@ static int configure_overlay(enum omap_plane plane)
770 BUG(); 786 BUG();
771 } 787 }
772 788
773 if (dispc_is_overlay_scaled(c)) { 789 if (mc->x > c->pos_x) {
774 /* If the overlay is scaled, the update area has 790 x = 0;
775 * already been enlarged to cover the whole overlay. We 791 outw -= (mc->x - c->pos_x);
776 * only need to adjust x/y here */ 792 paddr += (mc->x - c->pos_x) *
777 x = c->pos_x - mc->x; 793 scale_x_m / scale_x_d * bpp / 8;
778 y = c->pos_y - mc->y;
779 } else { 794 } else {
780 if (mc->x > c->pos_x) { 795 x = c->pos_x - mc->x;
781 x = 0; 796 }
782 w -= (mc->x - c->pos_x);
783 paddr += (mc->x - c->pos_x) * bpp / 8;
784 } else {
785 x = c->pos_x - mc->x;
786 }
787
788 if (mc->y > c->pos_y) {
789 y = 0;
790 h -= (mc->y - c->pos_y);
791 paddr += (mc->y - c->pos_y) * c->screen_width *
792 bpp / 8;
793 } else {
794 y = c->pos_y - mc->y;
795 }
796
797 if (mc->w < (x+w))
798 w -= (x+w) - (mc->w);
799 797
800 if (mc->h < (y+h)) 798 if (mc->y > c->pos_y) {
801 h -= (y+h) - (mc->h); 799 y = 0;
800 outh -= (mc->y - c->pos_y);
801 paddr += (mc->y - c->pos_y) *
802 scale_y_m / scale_y_d *
803 c->screen_width * bpp / 8;
804 } else {
805 y = c->pos_y - mc->y;
806 }
802 807
803 outw = w; 808 if (mc->w < (x + outw))
804 outh = h; 809 outw -= (x + outw) - (mc->w);
810
811 if (mc->h < (y + outh))
812 outh -= (y + outh) - (mc->h);
813
814 w = w * outw / orig_outw;
815 h = h * outh / orig_outh;
816
817 /* YUV mode overlay's input width has to be even and the
818 * algorithm above may adjust the width to be odd.
819 *
820 * Here we adjust the width if needed, preferring to increase
821 * the width if the original width was bigger.
822 */
823 if ((w & 1) &&
824 (c->color_mode == OMAP_DSS_COLOR_YUV2 ||
825 c->color_mode == OMAP_DSS_COLOR_UYVY)) {
826 if (orig_w > w)
827 w += 1;
828 else
829 w -= 1;
805 } 830 }
806 } 831 }
807 832
@@ -960,7 +985,7 @@ static void make_even(u16 *x, u16 *w)
960/* Configure dispc for partial update. Return possibly modified update 985/* Configure dispc for partial update. Return possibly modified update
961 * area */ 986 * area */
962void dss_setup_partial_planes(struct omap_dss_device *dssdev, 987void dss_setup_partial_planes(struct omap_dss_device *dssdev,
963 u16 *xi, u16 *yi, u16 *wi, u16 *hi) 988 u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
964{ 989{
965 struct overlay_cache_data *oc; 990 struct overlay_cache_data *oc;
966 struct manager_cache_data *mc; 991 struct manager_cache_data *mc;
@@ -969,6 +994,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
969 int i; 994 int i;
970 u16 x, y, w, h; 995 u16 x, y, w, h;
971 unsigned long flags; 996 unsigned long flags;
997 bool area_changed;
972 998
973 x = *xi; 999 x = *xi;
974 y = *yi; 1000 y = *yi;
@@ -989,73 +1015,91 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
989 1015
990 spin_lock_irqsave(&dss_cache.lock, flags); 1016 spin_lock_irqsave(&dss_cache.lock, flags);
991 1017
992 /* We need to show the whole overlay if it is scaled. So look for 1018 /*
993 * those, and make the update area larger if found. 1019 * Execute the outer loop until the inner loop has completed
994 * Also mark the overlay cache dirty */ 1020 * once without increasing the update area. This will ensure that
995 for (i = 0; i < num_ovls; ++i) { 1021 * all scaled overlays end up completely within the update area.
996 unsigned x1, y1, x2, y2; 1022 */
997 unsigned outw, outh; 1023 do {
1024 area_changed = false;
998 1025
999 oc = &dss_cache.overlay_cache[i]; 1026 /* We need to show the whole overlay if it is scaled. So look
1027 * for those, and make the update area larger if found.
1028 * Also mark the overlay cache dirty */
1029 for (i = 0; i < num_ovls; ++i) {
1030 unsigned x1, y1, x2, y2;
1031 unsigned outw, outh;
1000 1032
1001 if (oc->channel != mgr->id) 1033 oc = &dss_cache.overlay_cache[i];
1002 continue;
1003 1034
1004 oc->dirty = true; 1035 if (oc->channel != mgr->id)
1036 continue;
1005 1037
1006 if (!oc->enabled) 1038 oc->dirty = true;
1007 continue;
1008 1039
1009 if (!dispc_is_overlay_scaled(oc)) 1040 if (!enlarge_update_area)
1010 continue; 1041 continue;
1011 1042
1012 outw = oc->out_width == 0 ? oc->width : oc->out_width; 1043 if (!oc->enabled)
1013 outh = oc->out_height == 0 ? oc->height : oc->out_height; 1044 continue;
1014 1045
1015 /* is the overlay outside the update region? */ 1046 if (!dispc_is_overlay_scaled(oc))
1016 if (!rectangle_intersects(x, y, w, h, 1047 continue;
1017 oc->pos_x, oc->pos_y,
1018 outw, outh))
1019 continue;
1020 1048
1021 /* if the overlay totally inside the update region? */ 1049 outw = oc->out_width == 0 ?
1022 if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh, 1050 oc->width : oc->out_width;
1023 x, y, w, h)) 1051 outh = oc->out_height == 0 ?
1024 continue; 1052 oc->height : oc->out_height;
1053
1054 /* is the overlay outside the update region? */
1055 if (!rectangle_intersects(x, y, w, h,
1056 oc->pos_x, oc->pos_y,
1057 outw, outh))
1058 continue;
1025 1059
1026 if (x > oc->pos_x) 1060 /* if the overlay totally inside the update region? */
1027 x1 = oc->pos_x; 1061 if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
1028 else 1062 x, y, w, h))
1029 x1 = x; 1063 continue;
1030 1064
1031 if (y > oc->pos_y) 1065 if (x > oc->pos_x)
1032 y1 = oc->pos_y; 1066 x1 = oc->pos_x;
1033 else 1067 else
1034 y1 = y; 1068 x1 = x;
1035 1069
1036 if ((x + w) < (oc->pos_x + outw)) 1070 if (y > oc->pos_y)
1037 x2 = oc->pos_x + outw; 1071 y1 = oc->pos_y;
1038 else 1072 else
1039 x2 = x + w; 1073 y1 = y;
1040 1074
1041 if ((y + h) < (oc->pos_y + outh)) 1075 if ((x + w) < (oc->pos_x + outw))
1042 y2 = oc->pos_y + outh; 1076 x2 = oc->pos_x + outw;
1043 else 1077 else
1044 y2 = y + h; 1078 x2 = x + w;
1045 1079
1046 x = x1; 1080 if ((y + h) < (oc->pos_y + outh))
1047 y = y1; 1081 y2 = oc->pos_y + outh;
1048 w = x2 - x1; 1082 else
1049 h = y2 - y1; 1083 y2 = y + h;
1050 1084
1051 make_even(&x, &w); 1085 x = x1;
1086 y = y1;
1087 w = x2 - x1;
1088 h = y2 - y1;
1052 1089
1053 DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", 1090 make_even(&x, &w);
1091
1092 DSSDBG("changing upd area due to ovl(%d) "
1093 "scaling %d,%d %dx%d\n",
1054 i, x, y, w, h); 1094 i, x, y, w, h);
1055 } 1095
1096 area_changed = true;
1097 }
1098 } while (area_changed);
1056 1099
1057 mc = &dss_cache.manager_cache[mgr->id]; 1100 mc = &dss_cache.manager_cache[mgr->id];
1058 mc->do_manual_update = true; 1101 mc->do_manual_update = true;
1102 mc->enlarge_update_area = enlarge_update_area;
1059 mc->x = x; 1103 mc->x = x;
1060 mc->y = y; 1104 mc->y = y;
1061 mc->w = w; 1105 mc->w = w;
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 82336583adef..244dca81a399 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -65,7 +65,7 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
65 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 65 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
66 mgr = omap_dss_get_overlay_manager(i); 66 mgr = omap_dss_get_overlay_manager(i);
67 67
68 if (strncmp(buf, mgr->name, len) == 0) 68 if (sysfs_streq(buf, mgr->name))
69 break; 69 break;
70 70
71 mgr = NULL; 71 mgr = NULL;
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index cc23f53cc62d..bbe62464e92d 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -886,7 +886,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
886 return -EINVAL; 886 return -EINVAL;
887 887
888 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 888 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
889 dss_setup_partial_planes(dssdev, x, y, w, h); 889 dss_setup_partial_planes(dssdev, x, y, w, h, true);
890 dispc_set_lcd_size(*w, *h); 890 dispc_set_lcd_size(*w, *h);
891 } 891 }
892 892
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 9c7361871d78..6f435450987e 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -34,12 +34,37 @@
34 34
35#include "omapfb.h" 35#include "omapfb.h"
36 36
37static u8 get_mem_idx(struct omapfb_info *ofbi)
38{
39 if (ofbi->id == ofbi->region->id)
40 return 0;
41
42 return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
43}
44
45static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
46 u8 mem_idx)
47{
48 struct omapfb2_device *fbdev = ofbi->fbdev;
49
50 if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
51 mem_idx &= OMAPFB_MEM_IDX_MASK;
52 else
53 mem_idx = ofbi->id;
54
55 if (mem_idx >= fbdev->num_fbs)
56 return NULL;
57
58 return &fbdev->regions[mem_idx];
59}
60
37static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) 61static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
38{ 62{
39 struct omapfb_info *ofbi = FB2OFB(fbi); 63 struct omapfb_info *ofbi = FB2OFB(fbi);
40 struct omapfb2_device *fbdev = ofbi->fbdev; 64 struct omapfb2_device *fbdev = ofbi->fbdev;
41 struct omap_overlay *ovl; 65 struct omap_overlay *ovl;
42 struct omap_overlay_info info; 66 struct omap_overlay_info old_info;
67 struct omapfb2_mem_region *old_rg, *new_rg;
43 int r = 0; 68 int r = 0;
44 69
45 DBG("omapfb_setup_plane\n"); 70 DBG("omapfb_setup_plane\n");
@@ -52,36 +77,106 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
52 /* XXX uses only the first overlay */ 77 /* XXX uses only the first overlay */
53 ovl = ofbi->overlays[0]; 78 ovl = ofbi->overlays[0];
54 79
55 if (pi->enabled && !ofbi->region.size) { 80 old_rg = ofbi->region;
81 new_rg = get_mem_region(ofbi, pi->mem_idx);
82 if (!new_rg) {
83 r = -EINVAL;
84 goto out;
85 }
86
87 /* Take the locks in a specific order to keep lockdep happy */
88 if (old_rg->id < new_rg->id) {
89 omapfb_get_mem_region(old_rg);
90 omapfb_get_mem_region(new_rg);
91 } else if (new_rg->id < old_rg->id) {
92 omapfb_get_mem_region(new_rg);
93 omapfb_get_mem_region(old_rg);
94 } else
95 omapfb_get_mem_region(old_rg);
96
97 if (pi->enabled && !new_rg->size) {
56 /* 98 /*
57 * This plane's memory was freed, can't enable it 99 * This plane's memory was freed, can't enable it
58 * until it's reallocated. 100 * until it's reallocated.
59 */ 101 */
60 r = -EINVAL; 102 r = -EINVAL;
61 goto out; 103 goto put_mem;
62 } 104 }
63 105
64 ovl->get_overlay_info(ovl, &info); 106 ovl->get_overlay_info(ovl, &old_info);
65 107
66 info.pos_x = pi->pos_x; 108 if (old_rg != new_rg) {
67 info.pos_y = pi->pos_y; 109 ofbi->region = new_rg;
68 info.out_width = pi->out_width; 110 set_fb_fix(fbi);
69 info.out_height = pi->out_height; 111 }
70 info.enabled = pi->enabled;
71 112
72 r = ovl->set_overlay_info(ovl, &info); 113 if (pi->enabled) {
73 if (r) 114 struct omap_overlay_info info;
74 goto out;
75 115
76 if (ovl->manager) { 116 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
77 r = ovl->manager->apply(ovl->manager); 117 pi->out_width, pi->out_height);
78 if (r) 118 if (r)
79 goto out; 119 goto undo;
120
121 ovl->get_overlay_info(ovl, &info);
122
123 if (!info.enabled) {
124 info.enabled = pi->enabled;
125 r = ovl->set_overlay_info(ovl, &info);
126 if (r)
127 goto undo;
128 }
129 } else {
130 struct omap_overlay_info info;
131
132 ovl->get_overlay_info(ovl, &info);
133
134 info.enabled = pi->enabled;
135 info.pos_x = pi->pos_x;
136 info.pos_y = pi->pos_y;
137 info.out_width = pi->out_width;
138 info.out_height = pi->out_height;
139
140 r = ovl->set_overlay_info(ovl, &info);
141 if (r)
142 goto undo;
80 } 143 }
81 144
82out: 145 if (ovl->manager)
83 if (r) 146 ovl->manager->apply(ovl->manager);
84 dev_err(fbdev->dev, "setup_plane failed\n"); 147
148 /* Release the locks in a specific order to keep lockdep happy */
149 if (old_rg->id > new_rg->id) {
150 omapfb_put_mem_region(old_rg);
151 omapfb_put_mem_region(new_rg);
152 } else if (new_rg->id > old_rg->id) {
153 omapfb_put_mem_region(new_rg);
154 omapfb_put_mem_region(old_rg);
155 } else
156 omapfb_put_mem_region(old_rg);
157
158 return 0;
159
160 undo:
161 if (old_rg != new_rg) {
162 ofbi->region = old_rg;
163 set_fb_fix(fbi);
164 }
165
166 ovl->set_overlay_info(ovl, &old_info);
167 put_mem:
168 /* Release the locks in a specific order to keep lockdep happy */
169 if (old_rg->id > new_rg->id) {
170 omapfb_put_mem_region(old_rg);
171 omapfb_put_mem_region(new_rg);
172 } else if (new_rg->id > old_rg->id) {
173 omapfb_put_mem_region(new_rg);
174 omapfb_put_mem_region(old_rg);
175 } else
176 omapfb_put_mem_region(old_rg);
177 out:
178 dev_err(fbdev->dev, "setup_plane failed\n");
179
85 return r; 180 return r;
86} 181}
87 182
@@ -92,8 +187,8 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
92 if (ofbi->num_overlays != 1) { 187 if (ofbi->num_overlays != 1) {
93 memset(pi, 0, sizeof(*pi)); 188 memset(pi, 0, sizeof(*pi));
94 } else { 189 } else {
95 struct omap_overlay_info *ovli;
96 struct omap_overlay *ovl; 190 struct omap_overlay *ovl;
191 struct omap_overlay_info *ovli;
97 192
98 ovl = ofbi->overlays[0]; 193 ovl = ofbi->overlays[0];
99 ovli = &ovl->info; 194 ovli = &ovl->info;
@@ -103,6 +198,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
103 pi->enabled = ovli->enabled; 198 pi->enabled = ovli->enabled;
104 pi->channel_out = 0; /* xxx */ 199 pi->channel_out = 0; /* xxx */
105 pi->mirror = 0; 200 pi->mirror = 0;
201 pi->mem_idx = get_mem_idx(ofbi);
106 pi->out_width = ovli->out_width; 202 pi->out_width = ovli->out_width;
107 pi->out_height = ovli->out_height; 203 pi->out_height = ovli->out_height;
108 } 204 }
@@ -115,7 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
115 struct omapfb_info *ofbi = FB2OFB(fbi); 211 struct omapfb_info *ofbi = FB2OFB(fbi);
116 struct omapfb2_device *fbdev = ofbi->fbdev; 212 struct omapfb2_device *fbdev = ofbi->fbdev;
117 struct omapfb2_mem_region *rg; 213 struct omapfb2_mem_region *rg;
118 int r, i; 214 int r = 0, i;
119 size_t size; 215 size_t size;
120 216
121 if (mi->type > OMAPFB_MEMTYPE_MAX) 217 if (mi->type > OMAPFB_MEMTYPE_MAX)
@@ -123,22 +219,44 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
123 219
124 size = PAGE_ALIGN(mi->size); 220 size = PAGE_ALIGN(mi->size);
125 221
126 rg = &ofbi->region; 222 rg = ofbi->region;
127 223
128 for (i = 0; i < ofbi->num_overlays; i++) { 224 down_write_nested(&rg->lock, rg->id);
129 if (ofbi->overlays[i]->info.enabled) 225 atomic_inc(&rg->lock_count);
130 return -EBUSY; 226
227 if (atomic_read(&rg->map_count)) {
228 r = -EBUSY;
229 goto out;
230 }
231
232 for (i = 0; i < fbdev->num_fbs; i++) {
233 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
234 int j;
235
236 if (ofbi2->region != rg)
237 continue;
238
239 for (j = 0; j < ofbi2->num_overlays; j++) {
240 if (ofbi2->overlays[j]->info.enabled) {
241 r = -EBUSY;
242 goto out;
243 }
244 }
131 } 245 }
132 246
133 if (rg->size != size || rg->type != mi->type) { 247 if (rg->size != size || rg->type != mi->type) {
134 r = omapfb_realloc_fbmem(fbi, size, mi->type); 248 r = omapfb_realloc_fbmem(fbi, size, mi->type);
135 if (r) { 249 if (r) {
136 dev_err(fbdev->dev, "realloc fbmem failed\n"); 250 dev_err(fbdev->dev, "realloc fbmem failed\n");
137 return r; 251 goto out;
138 } 252 }
139 } 253 }
140 254
141 return 0; 255 out:
256 atomic_dec(&rg->lock_count);
257 up_write(&rg->lock);
258
259 return r;
142} 260}
143 261
144static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) 262static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
@@ -146,12 +264,14 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
146 struct omapfb_info *ofbi = FB2OFB(fbi); 264 struct omapfb_info *ofbi = FB2OFB(fbi);
147 struct omapfb2_mem_region *rg; 265 struct omapfb2_mem_region *rg;
148 266
149 rg = &ofbi->region; 267 rg = omapfb_get_mem_region(ofbi->region);
150 memset(mi, 0, sizeof(*mi)); 268 memset(mi, 0, sizeof(*mi));
151 269
152 mi->size = rg->size; 270 mi->size = rg->size;
153 mi->type = rg->type; 271 mi->type = rg->type;
154 272
273 omapfb_put_mem_region(rg);
274
155 return 0; 275 return 0;
156} 276}
157 277
@@ -490,6 +610,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
490 struct omapfb_vram_info vram_info; 610 struct omapfb_vram_info vram_info;
491 struct omapfb_tearsync_info tearsync_info; 611 struct omapfb_tearsync_info tearsync_info;
492 struct omapfb_display_info display_info; 612 struct omapfb_display_info display_info;
613 u32 crt;
493 } p; 614 } p;
494 615
495 int r = 0; 616 int r = 0;
@@ -648,6 +769,17 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
648 r = -EFAULT; 769 r = -EFAULT;
649 break; 770 break;
650 771
772 case FBIO_WAITFORVSYNC:
773 if (get_user(p.crt, (__u32 __user *)arg)) {
774 r = -EFAULT;
775 break;
776 }
777 if (p.crt != 0) {
778 r = -ENODEV;
779 break;
780 }
781 /* FALLTHROUGH */
782
651 case OMAPFB_WAITFORVSYNC: 783 case OMAPFB_WAITFORVSYNC:
652 DBG("ioctl WAITFORVSYNC\n"); 784 DBG("ioctl WAITFORVSYNC\n");
653 if (!display) { 785 if (!display) {
@@ -738,7 +870,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
738 break; 870 break;
739 } 871 }
740 872
741 if (!display->driver->enable_te) { 873 if (!display || !display->driver->enable_te) {
742 r = -ENODEV; 874 r = -ENODEV;
743 break; 875 break;
744 } 876 }
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 4b4506da96da..04034d410d6d 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -157,7 +157,7 @@ static void fill_fb(struct fb_info *fbi)
157 157
158static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot) 158static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
159{ 159{
160 const struct vrfb *vrfb = &ofbi->region.vrfb; 160 const struct vrfb *vrfb = &ofbi->region->vrfb;
161 unsigned offset; 161 unsigned offset;
162 162
163 switch (rot) { 163 switch (rot) {
@@ -185,27 +185,27 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
185static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot) 185static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
186{ 186{
187 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 187 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
188 return ofbi->region.vrfb.paddr[rot] 188 return ofbi->region->vrfb.paddr[rot]
189 + omapfb_get_vrfb_offset(ofbi, rot); 189 + omapfb_get_vrfb_offset(ofbi, rot);
190 } else { 190 } else {
191 return ofbi->region.paddr; 191 return ofbi->region->paddr;
192 } 192 }
193} 193}
194 194
195static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi) 195static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
196{ 196{
197 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 197 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
198 return ofbi->region.vrfb.paddr[0]; 198 return ofbi->region->vrfb.paddr[0];
199 else 199 else
200 return ofbi->region.paddr; 200 return ofbi->region->paddr;
201} 201}
202 202
203static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi) 203static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
204{ 204{
205 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 205 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
206 return ofbi->region.vrfb.vaddr[0]; 206 return ofbi->region->vrfb.vaddr[0];
207 else 207 else
208 return ofbi->region.vaddr; 208 return ofbi->region->vaddr;
209} 209}
210 210
211static struct omapfb_colormode omapfb_colormodes[] = { 211static struct omapfb_colormode omapfb_colormodes[] = {
@@ -450,7 +450,7 @@ static int check_vrfb_fb_size(unsigned long region_size,
450static int check_fb_size(const struct omapfb_info *ofbi, 450static int check_fb_size(const struct omapfb_info *ofbi,
451 struct fb_var_screeninfo *var) 451 struct fb_var_screeninfo *var)
452{ 452{
453 unsigned long max_frame_size = ofbi->region.size; 453 unsigned long max_frame_size = ofbi->region->size;
454 int bytespp = var->bits_per_pixel >> 3; 454 int bytespp = var->bits_per_pixel >> 3;
455 unsigned long line_size = var->xres_virtual * bytespp; 455 unsigned long line_size = var->xres_virtual * bytespp;
456 456
@@ -497,7 +497,7 @@ static int check_fb_size(const struct omapfb_info *ofbi,
497static int setup_vrfb_rotation(struct fb_info *fbi) 497static int setup_vrfb_rotation(struct fb_info *fbi)
498{ 498{
499 struct omapfb_info *ofbi = FB2OFB(fbi); 499 struct omapfb_info *ofbi = FB2OFB(fbi);
500 struct omapfb2_mem_region *rg = &ofbi->region; 500 struct omapfb2_mem_region *rg = ofbi->region;
501 struct vrfb *vrfb = &rg->vrfb; 501 struct vrfb *vrfb = &rg->vrfb;
502 struct fb_var_screeninfo *var = &fbi->var; 502 struct fb_var_screeninfo *var = &fbi->var;
503 struct fb_fix_screeninfo *fix = &fbi->fix; 503 struct fb_fix_screeninfo *fix = &fbi->fix;
@@ -558,9 +558,9 @@ static int setup_vrfb_rotation(struct fb_info *fbi)
558 return r; 558 return r;
559 559
560 /* used by open/write in fbmem.c */ 560 /* used by open/write in fbmem.c */
561 fbi->screen_base = ofbi->region.vrfb.vaddr[0]; 561 fbi->screen_base = ofbi->region->vrfb.vaddr[0];
562 562
563 fix->smem_start = ofbi->region.vrfb.paddr[0]; 563 fix->smem_start = ofbi->region->vrfb.paddr[0];
564 564
565 switch (var->nonstd) { 565 switch (var->nonstd) {
566 case OMAPFB_COLOR_YUV422: 566 case OMAPFB_COLOR_YUV422:
@@ -599,7 +599,7 @@ void set_fb_fix(struct fb_info *fbi)
599 struct fb_fix_screeninfo *fix = &fbi->fix; 599 struct fb_fix_screeninfo *fix = &fbi->fix;
600 struct fb_var_screeninfo *var = &fbi->var; 600 struct fb_var_screeninfo *var = &fbi->var;
601 struct omapfb_info *ofbi = FB2OFB(fbi); 601 struct omapfb_info *ofbi = FB2OFB(fbi);
602 struct omapfb2_mem_region *rg = &ofbi->region; 602 struct omapfb2_mem_region *rg = ofbi->region;
603 603
604 DBG("set_fb_fix\n"); 604 DBG("set_fb_fix\n");
605 605
@@ -668,8 +668,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
668 668
669 DBG("check_fb_var %d\n", ofbi->id); 669 DBG("check_fb_var %d\n", ofbi->id);
670 670
671 if (ofbi->region.size == 0) 671 WARN_ON(!atomic_read(&ofbi->region->lock_count));
672 return 0;
673 672
674 r = fb_mode_to_dss_mode(var, &mode); 673 r = fb_mode_to_dss_mode(var, &mode);
675 if (r) { 674 if (r) {
@@ -684,13 +683,14 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
684 } 683 }
685 } 684 }
686 685
687 if (var->rotate < 0 || var->rotate > 3) 686 if (var->rotate > 3)
688 return -EINVAL; 687 return -EINVAL;
689 688
690 if (check_fb_res_bounds(var)) 689 if (check_fb_res_bounds(var))
691 return -EINVAL; 690 return -EINVAL;
692 691
693 if (check_fb_size(ofbi, var)) 692 /* When no memory is allocated ignore the size check */
693 if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
694 return -EINVAL; 694 return -EINVAL;
695 695
696 if (var->xres + var->xoffset > var->xres_virtual) 696 if (var->xres + var->xoffset > var->xres_virtual)
@@ -822,9 +822,43 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
822 return offset; 822 return offset;
823} 823}
824 824
825static void omapfb_calc_addr(const struct omapfb_info *ofbi,
826 const struct fb_var_screeninfo *var,
827 const struct fb_fix_screeninfo *fix,
828 int rotation, u32 *paddr, void __iomem **vaddr)
829{
830 u32 data_start_p;
831 void __iomem *data_start_v;
832 int offset;
833
834 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
835 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
836 data_start_v = NULL;
837 } else {
838 data_start_p = omapfb_get_region_paddr(ofbi);
839 data_start_v = omapfb_get_region_vaddr(ofbi);
840 }
841
842 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
843 offset = calc_rotation_offset_vrfb(var, fix, rotation);
844 else
845 offset = calc_rotation_offset_dma(var, fix, rotation);
846
847 data_start_p += offset;
848 data_start_v += offset;
849
850 if (offset)
851 DBG("offset %d, %d = %d\n",
852 var->xoffset, var->yoffset, offset);
853
854 DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
855
856 *paddr = data_start_p;
857 *vaddr = data_start_v;
858}
825 859
826/* setup overlay according to the fb */ 860/* setup overlay according to the fb */
827static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, 861int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
828 u16 posx, u16 posy, u16 outw, u16 outh) 862 u16 posx, u16 posy, u16 outw, u16 outh)
829{ 863{
830 int r = 0; 864 int r = 0;
@@ -832,9 +866,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
832 struct fb_var_screeninfo *var = &fbi->var; 866 struct fb_var_screeninfo *var = &fbi->var;
833 struct fb_fix_screeninfo *fix = &fbi->fix; 867 struct fb_fix_screeninfo *fix = &fbi->fix;
834 enum omap_color_mode mode = 0; 868 enum omap_color_mode mode = 0;
835 int offset; 869 u32 data_start_p = 0;
836 u32 data_start_p; 870 void __iomem *data_start_v = NULL;
837 void __iomem *data_start_v;
838 struct omap_overlay_info info; 871 struct omap_overlay_info info;
839 int xres, yres; 872 int xres, yres;
840 int screen_width; 873 int screen_width;
@@ -842,6 +875,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
842 int rotation = var->rotate; 875 int rotation = var->rotate;
843 int i; 876 int i;
844 877
878 WARN_ON(!atomic_read(&ofbi->region->lock_count));
879
845 for (i = 0; i < ofbi->num_overlays; i++) { 880 for (i = 0; i < ofbi->num_overlays; i++) {
846 if (ovl != ofbi->overlays[i]) 881 if (ovl != ofbi->overlays[i])
847 continue; 882 continue;
@@ -861,28 +896,9 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
861 yres = var->yres; 896 yres = var->yres;
862 } 897 }
863 898
864 899 if (ofbi->region->size)
865 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 900 omapfb_calc_addr(ofbi, var, fix, rotation,
866 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); 901 &data_start_p, &data_start_v);
867 data_start_v = NULL;
868 } else {
869 data_start_p = omapfb_get_region_paddr(ofbi);
870 data_start_v = omapfb_get_region_vaddr(ofbi);
871 }
872
873 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
874 offset = calc_rotation_offset_vrfb(var, fix, rotation);
875 else
876 offset = calc_rotation_offset_dma(var, fix, rotation);
877
878 data_start_p += offset;
879 data_start_v += offset;
880
881 if (offset)
882 DBG("offset %d, %d = %d\n",
883 var->xoffset, var->yoffset, offset);
884
885 DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
886 902
887 r = fb_mode_to_dss_mode(var, &mode); 903 r = fb_mode_to_dss_mode(var, &mode);
888 if (r) { 904 if (r) {
@@ -954,12 +970,14 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
954 fill_fb(fbi); 970 fill_fb(fbi);
955#endif 971#endif
956 972
973 WARN_ON(!atomic_read(&ofbi->region->lock_count));
974
957 for (i = 0; i < ofbi->num_overlays; i++) { 975 for (i = 0; i < ofbi->num_overlays; i++) {
958 ovl = ofbi->overlays[i]; 976 ovl = ofbi->overlays[i];
959 977
960 DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); 978 DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
961 979
962 if (ofbi->region.size == 0) { 980 if (ofbi->region->size == 0) {
963 /* the fb is not available. disable the overlay */ 981 /* the fb is not available. disable the overlay */
964 omapfb_overlay_enable(ovl, 0); 982 omapfb_overlay_enable(ovl, 0);
965 if (!init && ovl->manager) 983 if (!init && ovl->manager)
@@ -1007,36 +1025,48 @@ err:
1007 * DO NOT MODIFY PAR */ 1025 * DO NOT MODIFY PAR */
1008static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) 1026static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
1009{ 1027{
1028 struct omapfb_info *ofbi = FB2OFB(fbi);
1010 int r; 1029 int r;
1011 1030
1012 DBG("check_var(%d)\n", FB2OFB(fbi)->id); 1031 DBG("check_var(%d)\n", FB2OFB(fbi)->id);
1013 1032
1033 omapfb_get_mem_region(ofbi->region);
1034
1014 r = check_fb_var(fbi, var); 1035 r = check_fb_var(fbi, var);
1015 1036
1037 omapfb_put_mem_region(ofbi->region);
1038
1016 return r; 1039 return r;
1017} 1040}
1018 1041
1019/* set the video mode according to info->var */ 1042/* set the video mode according to info->var */
1020static int omapfb_set_par(struct fb_info *fbi) 1043static int omapfb_set_par(struct fb_info *fbi)
1021{ 1044{
1045 struct omapfb_info *ofbi = FB2OFB(fbi);
1022 int r; 1046 int r;
1023 1047
1024 DBG("set_par(%d)\n", FB2OFB(fbi)->id); 1048 DBG("set_par(%d)\n", FB2OFB(fbi)->id);
1025 1049
1050 omapfb_get_mem_region(ofbi->region);
1051
1026 set_fb_fix(fbi); 1052 set_fb_fix(fbi);
1027 1053
1028 r = setup_vrfb_rotation(fbi); 1054 r = setup_vrfb_rotation(fbi);
1029 if (r) 1055 if (r)
1030 return r; 1056 goto out;
1031 1057
1032 r = omapfb_apply_changes(fbi, 0); 1058 r = omapfb_apply_changes(fbi, 0);
1033 1059
1060 out:
1061 omapfb_put_mem_region(ofbi->region);
1062
1034 return r; 1063 return r;
1035} 1064}
1036 1065
1037static int omapfb_pan_display(struct fb_var_screeninfo *var, 1066static int omapfb_pan_display(struct fb_var_screeninfo *var,
1038 struct fb_info *fbi) 1067 struct fb_info *fbi)
1039{ 1068{
1069 struct omapfb_info *ofbi = FB2OFB(fbi);
1040 struct fb_var_screeninfo new_var; 1070 struct fb_var_screeninfo new_var;
1041 int r; 1071 int r;
1042 1072
@@ -1052,23 +1082,31 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var,
1052 1082
1053 fbi->var = new_var; 1083 fbi->var = new_var;
1054 1084
1085 omapfb_get_mem_region(ofbi->region);
1086
1055 r = omapfb_apply_changes(fbi, 0); 1087 r = omapfb_apply_changes(fbi, 0);
1056 1088
1089 omapfb_put_mem_region(ofbi->region);
1090
1057 return r; 1091 return r;
1058} 1092}
1059 1093
1060static void mmap_user_open(struct vm_area_struct *vma) 1094static void mmap_user_open(struct vm_area_struct *vma)
1061{ 1095{
1062 struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; 1096 struct omapfb2_mem_region *rg = vma->vm_private_data;
1063 1097
1064 atomic_inc(&ofbi->map_count); 1098 omapfb_get_mem_region(rg);
1099 atomic_inc(&rg->map_count);
1100 omapfb_put_mem_region(rg);
1065} 1101}
1066 1102
1067static void mmap_user_close(struct vm_area_struct *vma) 1103static void mmap_user_close(struct vm_area_struct *vma)
1068{ 1104{
1069 struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; 1105 struct omapfb2_mem_region *rg = vma->vm_private_data;
1070 1106
1071 atomic_dec(&ofbi->map_count); 1107 omapfb_get_mem_region(rg);
1108 atomic_dec(&rg->map_count);
1109 omapfb_put_mem_region(rg);
1072} 1110}
1073 1111
1074static struct vm_operations_struct mmap_user_ops = { 1112static struct vm_operations_struct mmap_user_ops = {
@@ -1080,9 +1118,11 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1080{ 1118{
1081 struct omapfb_info *ofbi = FB2OFB(fbi); 1119 struct omapfb_info *ofbi = FB2OFB(fbi);
1082 struct fb_fix_screeninfo *fix = &fbi->fix; 1120 struct fb_fix_screeninfo *fix = &fbi->fix;
1121 struct omapfb2_mem_region *rg;
1083 unsigned long off; 1122 unsigned long off;
1084 unsigned long start; 1123 unsigned long start;
1085 u32 len; 1124 u32 len;
1125 int r = -EINVAL;
1086 1126
1087 if (vma->vm_end - vma->vm_start == 0) 1127 if (vma->vm_end - vma->vm_start == 0)
1088 return 0; 1128 return 0;
@@ -1090,12 +1130,14 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1090 return -EINVAL; 1130 return -EINVAL;
1091 off = vma->vm_pgoff << PAGE_SHIFT; 1131 off = vma->vm_pgoff << PAGE_SHIFT;
1092 1132
1133 rg = omapfb_get_mem_region(ofbi->region);
1134
1093 start = omapfb_get_region_paddr(ofbi); 1135 start = omapfb_get_region_paddr(ofbi);
1094 len = fix->smem_len; 1136 len = fix->smem_len;
1095 if (off >= len) 1137 if (off >= len)
1096 return -EINVAL; 1138 goto error;
1097 if ((vma->vm_end - vma->vm_start + off) > len) 1139 if ((vma->vm_end - vma->vm_start + off) > len)
1098 return -EINVAL; 1140 goto error;
1099 1141
1100 off += start; 1142 off += start;
1101 1143
@@ -1105,13 +1147,25 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1105 vma->vm_flags |= VM_IO | VM_RESERVED; 1147 vma->vm_flags |= VM_IO | VM_RESERVED;
1106 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 1148 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1107 vma->vm_ops = &mmap_user_ops; 1149 vma->vm_ops = &mmap_user_ops;
1108 vma->vm_private_data = ofbi; 1150 vma->vm_private_data = rg;
1109 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 1151 if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
1110 vma->vm_end - vma->vm_start, vma->vm_page_prot)) 1152 vma->vm_end - vma->vm_start,
1111 return -EAGAIN; 1153 vma->vm_page_prot)) {
1154 r = -EAGAIN;
1155 goto error;
1156 }
1157
1112 /* vm_ops.open won't be called for mmap itself. */ 1158 /* vm_ops.open won't be called for mmap itself. */
1113 atomic_inc(&ofbi->map_count); 1159 atomic_inc(&rg->map_count);
1160
1161 omapfb_put_mem_region(rg);
1162
1114 return 0; 1163 return 0;
1164
1165 error:
1166 omapfb_put_mem_region(ofbi->region);
1167
1168 return r;
1115} 1169}
1116 1170
1117/* Store a single color palette entry into a pseudo palette or the hardware 1171/* Store a single color palette entry into a pseudo palette or the hardware
@@ -1154,11 +1208,6 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
1154 if (r != 0) 1208 if (r != 0)
1155 break; 1209 break;
1156 1210
1157 if (regno < 0) {
1158 r = -EINVAL;
1159 break;
1160 }
1161
1162 if (regno < 16) { 1211 if (regno < 16) {
1163 u16 pal; 1212 u16 pal;
1164 pal = ((red >> (16 - var->red.length)) << 1213 pal = ((red >> (16 - var->red.length)) <<
@@ -1217,6 +1266,9 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1217 int do_update = 0; 1266 int do_update = 0;
1218 int r = 0; 1267 int r = 0;
1219 1268
1269 if (!display)
1270 return -EINVAL;
1271
1220 omapfb_lock(fbdev); 1272 omapfb_lock(fbdev);
1221 1273
1222 switch (blank) { 1274 switch (blank) {
@@ -1300,7 +1352,9 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
1300 struct omapfb2_device *fbdev = ofbi->fbdev; 1352 struct omapfb2_device *fbdev = ofbi->fbdev;
1301 struct omapfb2_mem_region *rg; 1353 struct omapfb2_mem_region *rg;
1302 1354
1303 rg = &ofbi->region; 1355 rg = ofbi->region;
1356
1357 WARN_ON(atomic_read(&rg->map_count));
1304 1358
1305 if (rg->paddr) 1359 if (rg->paddr)
1306 if (omap_vram_free(rg->paddr, rg->size)) 1360 if (omap_vram_free(rg->paddr, rg->size))
@@ -1355,8 +1409,15 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1355 void __iomem *vaddr; 1409 void __iomem *vaddr;
1356 int r; 1410 int r;
1357 1411
1358 rg = &ofbi->region; 1412 rg = ofbi->region;
1359 memset(rg, 0, sizeof(*rg)); 1413
1414 rg->paddr = 0;
1415 rg->vaddr = NULL;
1416 memset(&rg->vrfb, 0, sizeof rg->vrfb);
1417 rg->size = 0;
1418 rg->type = 0;
1419 rg->alloc = false;
1420 rg->map = false;
1360 1421
1361 size = PAGE_ALIGN(size); 1422 size = PAGE_ALIGN(size);
1362 1423
@@ -1609,7 +1670,7 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1609 for (i = 0; i < fbdev->num_fbs; i++) { 1670 for (i = 0; i < fbdev->num_fbs; i++) {
1610 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); 1671 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
1611 struct omapfb2_mem_region *rg; 1672 struct omapfb2_mem_region *rg;
1612 rg = &ofbi->region; 1673 rg = ofbi->region;
1613 1674
1614 DBG("region%d phys %08x virt %p size=%lu\n", 1675 DBG("region%d phys %08x virt %p size=%lu\n",
1615 i, 1676 i,
@@ -1626,7 +1687,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1626 struct omapfb_info *ofbi = FB2OFB(fbi); 1687 struct omapfb_info *ofbi = FB2OFB(fbi);
1627 struct omapfb2_device *fbdev = ofbi->fbdev; 1688 struct omapfb2_device *fbdev = ofbi->fbdev;
1628 struct omap_dss_device *display = fb2display(fbi); 1689 struct omap_dss_device *display = fb2display(fbi);
1629 struct omapfb2_mem_region *rg = &ofbi->region; 1690 struct omapfb2_mem_region *rg = ofbi->region;
1630 unsigned long old_size = rg->size; 1691 unsigned long old_size = rg->size;
1631 unsigned long old_paddr = rg->paddr; 1692 unsigned long old_paddr = rg->paddr;
1632 int old_type = rg->type; 1693 int old_type = rg->type;
@@ -1709,7 +1770,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1709 fbi->flags = FBINFO_FLAG_DEFAULT; 1770 fbi->flags = FBINFO_FLAG_DEFAULT;
1710 fbi->pseudo_palette = fbdev->pseudo_palette; 1771 fbi->pseudo_palette = fbdev->pseudo_palette;
1711 1772
1712 if (ofbi->region.size == 0) { 1773 if (ofbi->region->size == 0) {
1713 clear_fb_info(fbi); 1774 clear_fb_info(fbi);
1714 return 0; 1775 return 0;
1715 } 1776 }
@@ -1871,6 +1932,10 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1871 ofbi->fbdev = fbdev; 1932 ofbi->fbdev = fbdev;
1872 ofbi->id = i; 1933 ofbi->id = i;
1873 1934
1935 ofbi->region = &fbdev->regions[i];
1936 ofbi->region->id = i;
1937 init_rwsem(&ofbi->region->lock);
1938
1874 /* assign these early, so that fb alloc can use them */ 1939 /* assign these early, so that fb alloc can use them */
1875 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : 1940 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
1876 OMAP_DSS_ROT_DMA; 1941 OMAP_DSS_ROT_DMA;
@@ -1900,7 +1965,13 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1900 1965
1901 /* setup fb_infos */ 1966 /* setup fb_infos */
1902 for (i = 0; i < fbdev->num_fbs; i++) { 1967 for (i = 0; i < fbdev->num_fbs; i++) {
1903 r = omapfb_fb_init(fbdev, fbdev->fbs[i]); 1968 struct fb_info *fbi = fbdev->fbs[i];
1969 struct omapfb_info *ofbi = FB2OFB(fbi);
1970
1971 omapfb_get_mem_region(ofbi->region);
1972 r = omapfb_fb_init(fbdev, fbi);
1973 omapfb_put_mem_region(ofbi->region);
1974
1904 if (r) { 1975 if (r) {
1905 dev_err(fbdev->dev, "failed to setup fb_info\n"); 1976 dev_err(fbdev->dev, "failed to setup fb_info\n");
1906 return r; 1977 return r;
@@ -1921,20 +1992,19 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1921 DBG("framebuffers registered\n"); 1992 DBG("framebuffers registered\n");
1922 1993
1923 for (i = 0; i < fbdev->num_fbs; i++) { 1994 for (i = 0; i < fbdev->num_fbs; i++) {
1924 r = omapfb_apply_changes(fbdev->fbs[i], 1); 1995 struct fb_info *fbi = fbdev->fbs[i];
1996 struct omapfb_info *ofbi = FB2OFB(fbi);
1997
1998 omapfb_get_mem_region(ofbi->region);
1999 r = omapfb_apply_changes(fbi, 1);
2000 omapfb_put_mem_region(ofbi->region);
2001
1925 if (r) { 2002 if (r) {
1926 dev_err(fbdev->dev, "failed to change mode\n"); 2003 dev_err(fbdev->dev, "failed to change mode\n");
1927 return r; 2004 return r;
1928 } 2005 }
1929 } 2006 }
1930 2007
1931 DBG("create sysfs for fbs\n");
1932 r = omapfb_create_sysfs(fbdev);
1933 if (r) {
1934 dev_err(fbdev->dev, "failed to create sysfs entries\n");
1935 return r;
1936 }
1937
1938 /* Enable fb0 */ 2008 /* Enable fb0 */
1939 if (fbdev->num_fbs > 0) { 2009 if (fbdev->num_fbs > 0) {
1940 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); 2010 struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
@@ -1968,11 +2038,11 @@ static int omapfb_mode_to_timings(const char *mode_str,
1968#ifdef CONFIG_OMAP2_DSS_VENC 2038#ifdef CONFIG_OMAP2_DSS_VENC
1969 if (strcmp(mode_str, "pal") == 0) { 2039 if (strcmp(mode_str, "pal") == 0) {
1970 *timings = omap_dss_pal_timings; 2040 *timings = omap_dss_pal_timings;
1971 *bpp = 0; 2041 *bpp = 24;
1972 return 0; 2042 return 0;
1973 } else if (strcmp(mode_str, "ntsc") == 0) { 2043 } else if (strcmp(mode_str, "ntsc") == 0) {
1974 *timings = omap_dss_ntsc_timings; 2044 *timings = omap_dss_ntsc_timings;
1975 *bpp = 0; 2045 *bpp = 24;
1976 return 0; 2046 return 0;
1977 } 2047 }
1978#endif 2048#endif
@@ -2220,6 +2290,13 @@ static int omapfb_probe(struct platform_device *pdev)
2220 } 2290 }
2221 } 2291 }
2222 2292
2293 DBG("create sysfs for fbs\n");
2294 r = omapfb_create_sysfs(fbdev);
2295 if (r) {
2296 dev_err(fbdev->dev, "failed to create sysfs entries\n");
2297 goto cleanup;
2298 }
2299
2223 return 0; 2300 return 0;
2224 2301
2225cleanup: 2302cleanup:
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 5179219128bd..6f9c72cd6bb0 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -49,6 +49,7 @@ static ssize_t store_rotate_type(struct device *dev,
49{ 49{
50 struct fb_info *fbi = dev_get_drvdata(dev); 50 struct fb_info *fbi = dev_get_drvdata(dev);
51 struct omapfb_info *ofbi = FB2OFB(fbi); 51 struct omapfb_info *ofbi = FB2OFB(fbi);
52 struct omapfb2_mem_region *rg;
52 enum omap_dss_rotation_type rot_type; 53 enum omap_dss_rotation_type rot_type;
53 int r; 54 int r;
54 55
@@ -64,9 +65,11 @@ static ssize_t store_rotate_type(struct device *dev,
64 if (rot_type == ofbi->rotation_type) 65 if (rot_type == ofbi->rotation_type)
65 goto out; 66 goto out;
66 67
67 if (ofbi->region.size) { 68 rg = omapfb_get_mem_region(ofbi->region);
69
70 if (rg->size) {
68 r = -EBUSY; 71 r = -EBUSY;
69 goto out; 72 goto put_region;
70 } 73 }
71 74
72 ofbi->rotation_type = rot_type; 75 ofbi->rotation_type = rot_type;
@@ -75,6 +78,8 @@ static ssize_t store_rotate_type(struct device *dev,
75 * Since the VRAM for this FB is not allocated at the moment we don't 78 * Since the VRAM for this FB is not allocated at the moment we don't
76 * need to do any further parameter checking at this point. 79 * need to do any further parameter checking at this point.
77 */ 80 */
81put_region:
82 omapfb_put_mem_region(rg);
78out: 83out:
79 unlock_fb_info(fbi); 84 unlock_fb_info(fbi);
80 85
@@ -97,7 +102,7 @@ static ssize_t store_mirror(struct device *dev,
97{ 102{
98 struct fb_info *fbi = dev_get_drvdata(dev); 103 struct fb_info *fbi = dev_get_drvdata(dev);
99 struct omapfb_info *ofbi = FB2OFB(fbi); 104 struct omapfb_info *ofbi = FB2OFB(fbi);
100 bool mirror; 105 unsigned long mirror;
101 int r; 106 int r;
102 struct fb_var_screeninfo new_var; 107 struct fb_var_screeninfo new_var;
103 108
@@ -111,6 +116,8 @@ static ssize_t store_mirror(struct device *dev,
111 116
112 ofbi->mirror = mirror; 117 ofbi->mirror = mirror;
113 118
119 omapfb_get_mem_region(ofbi->region);
120
114 memcpy(&new_var, &fbi->var, sizeof(new_var)); 121 memcpy(&new_var, &fbi->var, sizeof(new_var));
115 r = check_fb_var(fbi, &new_var); 122 r = check_fb_var(fbi, &new_var);
116 if (r) 123 if (r)
@@ -125,6 +132,8 @@ static ssize_t store_mirror(struct device *dev,
125 132
126 r = count; 133 r = count;
127out: 134out:
135 omapfb_put_mem_region(ofbi->region);
136
128 unlock_fb_info(fbi); 137 unlock_fb_info(fbi);
129 138
130 return r; 139 return r;
@@ -263,11 +272,15 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
263 272
264 DBG("detaching %d\n", ofbi->overlays[i]->id); 273 DBG("detaching %d\n", ofbi->overlays[i]->id);
265 274
275 omapfb_get_mem_region(ofbi->region);
276
266 omapfb_overlay_enable(ovl, 0); 277 omapfb_overlay_enable(ovl, 0);
267 278
268 if (ovl->manager) 279 if (ovl->manager)
269 ovl->manager->apply(ovl->manager); 280 ovl->manager->apply(ovl->manager);
270 281
282 omapfb_put_mem_region(ofbi->region);
283
271 for (t = i + 1; t < ofbi->num_overlays; t++) { 284 for (t = i + 1; t < ofbi->num_overlays; t++) {
272 ofbi->rotation[t-1] = ofbi->rotation[t]; 285 ofbi->rotation[t-1] = ofbi->rotation[t];
273 ofbi->overlays[t-1] = ofbi->overlays[t]; 286 ofbi->overlays[t-1] = ofbi->overlays[t];
@@ -300,7 +313,12 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
300 } 313 }
301 314
302 if (added) { 315 if (added) {
316 omapfb_get_mem_region(ofbi->region);
317
303 r = omapfb_apply_changes(fbi, 0); 318 r = omapfb_apply_changes(fbi, 0);
319
320 omapfb_put_mem_region(ofbi->region);
321
304 if (r) 322 if (r)
305 goto out; 323 goto out;
306 } 324 }
@@ -388,7 +406,12 @@ static ssize_t store_overlays_rotate(struct device *dev,
388 for (i = 0; i < num_ovls; ++i) 406 for (i = 0; i < num_ovls; ++i)
389 ofbi->rotation[i] = rotation[i]; 407 ofbi->rotation[i] = rotation[i];
390 408
409 omapfb_get_mem_region(ofbi->region);
410
391 r = omapfb_apply_changes(fbi, 0); 411 r = omapfb_apply_changes(fbi, 0);
412
413 omapfb_put_mem_region(ofbi->region);
414
392 if (r) 415 if (r)
393 goto out; 416 goto out;
394 417
@@ -408,7 +431,7 @@ static ssize_t show_size(struct device *dev,
408 struct fb_info *fbi = dev_get_drvdata(dev); 431 struct fb_info *fbi = dev_get_drvdata(dev);
409 struct omapfb_info *ofbi = FB2OFB(fbi); 432 struct omapfb_info *ofbi = FB2OFB(fbi);
410 433
411 return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size); 434 return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
412} 435}
413 436
414static ssize_t store_size(struct device *dev, struct device_attribute *attr, 437static ssize_t store_size(struct device *dev, struct device_attribute *attr,
@@ -416,6 +439,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
416{ 439{
417 struct fb_info *fbi = dev_get_drvdata(dev); 440 struct fb_info *fbi = dev_get_drvdata(dev);
418 struct omapfb_info *ofbi = FB2OFB(fbi); 441 struct omapfb_info *ofbi = FB2OFB(fbi);
442 struct omapfb2_device *fbdev = ofbi->fbdev;
443 struct omapfb2_mem_region *rg;
419 unsigned long size; 444 unsigned long size;
420 int r; 445 int r;
421 int i; 446 int i;
@@ -425,15 +450,33 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
425 if (!lock_fb_info(fbi)) 450 if (!lock_fb_info(fbi))
426 return -ENODEV; 451 return -ENODEV;
427 452
428 for (i = 0; i < ofbi->num_overlays; i++) { 453 rg = ofbi->region;
429 if (ofbi->overlays[i]->info.enabled) { 454
430 r = -EBUSY; 455 down_write_nested(&rg->lock, rg->id);
431 goto out; 456 atomic_inc(&rg->lock_count);
457
458 if (atomic_read(&rg->map_count)) {
459 r = -EBUSY;
460 goto out;
461 }
462
463 for (i = 0; i < fbdev->num_fbs; i++) {
464 struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
465 int j;
466
467 if (ofbi2->region != rg)
468 continue;
469
470 for (j = 0; j < ofbi2->num_overlays; j++) {
471 if (ofbi2->overlays[j]->info.enabled) {
472 r = -EBUSY;
473 goto out;
474 }
432 } 475 }
433 } 476 }
434 477
435 if (size != ofbi->region.size) { 478 if (size != ofbi->region->size) {
436 r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type); 479 r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
437 if (r) { 480 if (r) {
438 dev_err(dev, "realloc fbmem failed\n"); 481 dev_err(dev, "realloc fbmem failed\n");
439 goto out; 482 goto out;
@@ -442,6 +485,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
442 485
443 r = count; 486 r = count;
444out: 487out:
488 atomic_dec(&rg->lock_count);
489 up_write(&rg->lock);
490
445 unlock_fb_info(fbi); 491 unlock_fb_info(fbi);
446 492
447 return r; 493 return r;
@@ -453,7 +499,7 @@ static ssize_t show_phys(struct device *dev,
453 struct fb_info *fbi = dev_get_drvdata(dev); 499 struct fb_info *fbi = dev_get_drvdata(dev);
454 struct omapfb_info *ofbi = FB2OFB(fbi); 500 struct omapfb_info *ofbi = FB2OFB(fbi);
455 501
456 return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr); 502 return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
457} 503}
458 504
459static ssize_t show_virt(struct device *dev, 505static ssize_t show_virt(struct device *dev,
@@ -462,7 +508,7 @@ static ssize_t show_virt(struct device *dev,
462 struct fb_info *fbi = dev_get_drvdata(dev); 508 struct fb_info *fbi = dev_get_drvdata(dev);
463 struct omapfb_info *ofbi = FB2OFB(fbi); 509 struct omapfb_info *ofbi = FB2OFB(fbi);
464 510
465 return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr); 511 return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
466} 512}
467 513
468static struct device_attribute omapfb_attrs[] = { 514static struct device_attribute omapfb_attrs[] = {
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index cd54fdbfd8bb..1305fc9880ba 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -27,6 +27,8 @@
27#define DEBUG 27#define DEBUG
28#endif 28#endif
29 29
30#include <linux/rwsem.h>
31
30#include <plat/display.h> 32#include <plat/display.h>
31 33
32#ifdef DEBUG 34#ifdef DEBUG
@@ -44,6 +46,7 @@ extern unsigned int omapfb_debug;
44#define OMAPFB_MAX_OVL_PER_FB 3 46#define OMAPFB_MAX_OVL_PER_FB 3
45 47
46struct omapfb2_mem_region { 48struct omapfb2_mem_region {
49 int id;
47 u32 paddr; 50 u32 paddr;
48 void __iomem *vaddr; 51 void __iomem *vaddr;
49 struct vrfb vrfb; 52 struct vrfb vrfb;
@@ -51,13 +54,15 @@ struct omapfb2_mem_region {
51 u8 type; /* OMAPFB_PLANE_MEM_* */ 54 u8 type; /* OMAPFB_PLANE_MEM_* */
52 bool alloc; /* allocated by the driver */ 55 bool alloc; /* allocated by the driver */
53 bool map; /* kernel mapped by the driver */ 56 bool map; /* kernel mapped by the driver */
57 atomic_t map_count;
58 struct rw_semaphore lock;
59 atomic_t lock_count;
54}; 60};
55 61
56/* appended to fb_info */ 62/* appended to fb_info */
57struct omapfb_info { 63struct omapfb_info {
58 int id; 64 int id;
59 struct omapfb2_mem_region region; 65 struct omapfb2_mem_region *region;
60 atomic_t map_count;
61 int num_overlays; 66 int num_overlays;
62 struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; 67 struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
63 struct omapfb2_device *fbdev; 68 struct omapfb2_device *fbdev;
@@ -76,6 +81,7 @@ struct omapfb2_device {
76 81
77 unsigned num_fbs; 82 unsigned num_fbs;
78 struct fb_info *fbs[10]; 83 struct fb_info *fbs[10];
84 struct omapfb2_mem_region regions[10];
79 85
80 unsigned num_displays; 86 unsigned num_displays;
81 struct omap_dss_device *displays[10]; 87 struct omap_dss_device *displays[10];
@@ -117,6 +123,9 @@ int omapfb_update_window(struct fb_info *fbi,
117int dss_mode_to_fb_mode(enum omap_color_mode dssmode, 123int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
118 struct fb_var_screeninfo *var); 124 struct fb_var_screeninfo *var);
119 125
126int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
127 u16 posx, u16 posy, u16 outw, u16 outh);
128
120/* find the display connected to this fb, if any */ 129/* find the display connected to this fb, if any */
121static inline struct omap_dss_device *fb2display(struct fb_info *fbi) 130static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
122{ 131{
@@ -148,8 +157,24 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
148 struct omap_overlay_info info; 157 struct omap_overlay_info info;
149 158
150 ovl->get_overlay_info(ovl, &info); 159 ovl->get_overlay_info(ovl, &info);
160 if (info.enabled == enable)
161 return 0;
151 info.enabled = enable; 162 info.enabled = enable;
152 return ovl->set_overlay_info(ovl, &info); 163 return ovl->set_overlay_info(ovl, &info);
153} 164}
154 165
166static inline struct omapfb2_mem_region *
167omapfb_get_mem_region(struct omapfb2_mem_region *rg)
168{
169 down_read_nested(&rg->lock, rg->id);
170 atomic_inc(&rg->lock_count);
171 return rg;
172}
173
174static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
175{
176 atomic_dec(&rg->lock_count);
177 up_read(&rg->lock);
178}
179
155#endif 180#endif