aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-10-09 22:16:30 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-10-09 22:16:30 -0400
commit0febd3bccff3ac005a570180209e44fb7de188df (patch)
tree2af5177fb8fef95900f68c64121ad6bdc78d8761 /drivers/video
parent8d93241b923bcb6a60994f8ed20fda8cc06d0fda (diff)
parent13b1ba7de8d0ecc42e4f9c002d5b0c1a48f05e58 (diff)
Merge tag 'omapdss-for-3.7' of git://gitorious.org/linux-omap-dss2/linux into fbdev-next
Omapdss driver changes for the 3.7 merge window. Notable changes: * Basic writeback support for DISPC level. Writeback is not yet usable, though, as we need higher level code to actually expose the writeback feature to userspace. * Rewriting the omapdss output drivers. We're trying to remove the hard links between the omapdss and the panels, and this rewrite work moves us closer to that goal. * Cleanup and restructuring patches that have been made while working on device tree support for omapdss. Device tree support is still some way ahead, but these patches are good cleanups in themselves. * Basic OMAP5 DSS support for DPI and DSI outputs. * Workaround for the problem that GFX overlay's fifo is too small for high resolution scenarios, causing underflows. * Cleanups that remove dependencies to omap platform code.
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap/hwa742.c1
-rw-r--r--drivers/video/omap/lcd_ams_delta.c1
-rw-r--r--drivers/video/omap/lcd_palmte.c1
-rw-r--r--drivers/video/omap/omapfb_main.c9
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c14
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c76
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c3
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c31
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c3
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c4
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c3
-rw-r--r--drivers/video/omap2/displays/panel-taal.c239
-rw-r--r--drivers/video/omap2/displays/panel-tfp410.c20
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c7
-rw-r--r--drivers/video/omap2/dss/Kconfig2
-rw-r--r--drivers/video/omap2/dss/Makefile4
-rw-r--r--drivers/video/omap2/dss/apply.c330
-rw-r--r--drivers/video/omap2/dss/core.c91
-rw-r--r--drivers/video/omap2/dss/dispc.c1019
-rw-r--r--drivers/video/omap2/dss/dispc.h37
-rw-r--r--drivers/video/omap2/dss/display.c108
-rw-r--r--drivers/video/omap2/dss/dpi.c181
-rw-r--r--drivers/video/omap2/dss/dsi.c675
-rw-r--r--drivers/video/omap2/dss/dss.c257
-rw-r--r--drivers/video/omap2/dss/dss.h79
-rw-r--r--drivers/video/omap2/dss/dss_features.c278
-rw-r--r--drivers/video/omap2/dss/dss_features.h7
-rw-r--r--drivers/video/omap2/dss/hdmi.c247
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c31
-rw-r--r--drivers/video/omap2/dss/manager-sysfs.c512
-rw-r--r--drivers/video/omap2/dss/manager.c473
-rw-r--r--drivers/video/omap2/dss/output.c148
-rw-r--r--drivers/video/omap2/dss/overlay-sysfs.c456
-rw-r--r--drivers/video/omap2/dss/overlay.c492
-rw-r--r--drivers/video/omap2/dss/rfbi.c222
-rw-r--r--drivers/video/omap2/dss/sdi.c126
-rw-r--r--drivers/video/omap2/dss/venc.c337
-rw-r--r--drivers/video/omap2/dss/venc_panel.c251
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c7
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c32
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h5
-rw-r--r--drivers/video/omap2/vram.c56
42 files changed, 4419 insertions, 2456 deletions
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index 9f1d23c319cb..f349ee6f0cea 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -27,7 +27,6 @@
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29 29
30#include <plat/dma.h>
31#include "omapfb.h" 30#include "omapfb.h"
32 31
33#define HWA742_REV_CODE_REG 0x0 32#define HWA742_REV_CODE_REG 0x0
diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
index d3a311327227..5cca6b373af7 100644
--- a/drivers/video/omap/lcd_ams_delta.c
+++ b/drivers/video/omap/lcd_ams_delta.c
@@ -28,7 +28,6 @@
28#include <linux/gpio.h> 28#include <linux/gpio.h>
29 29
30#include <plat/board-ams-delta.h> 30#include <plat/board-ams-delta.h>
31#include <mach/hardware.h>
32 31
33#include "omapfb.h" 32#include "omapfb.h"
34 33
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
index 88c31eb0cd6c..ff4fb624b904 100644
--- a/drivers/video/omap/lcd_palmte.c
+++ b/drivers/video/omap/lcd_palmte.c
@@ -23,7 +23,6 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/io.h> 24#include <linux/io.h>
25 25
26#include <plat/fpga.h>
27#include "omapfb.h" 26#include "omapfb.h"
28 27
29static int palmte_panel_init(struct lcd_panel *panel, 28static int palmte_panel_init(struct lcd_panel *panel,
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index f54b463709e9..4351c438b76f 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -131,15 +131,6 @@ static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
131 * LCD controller and LCD DMA 131 * LCD controller and LCD DMA
132 * --------------------------------------------------------------------------- 132 * ---------------------------------------------------------------------------
133 */ 133 */
134/* Lookup table to map elem size to elem type. */
135static const int dma_elem_type[] = {
136 0,
137 OMAP_DMA_DATA_TYPE_S8,
138 OMAP_DMA_DATA_TYPE_S16,
139 0,
140 OMAP_DMA_DATA_TYPE_S32,
141};
142
143/* 134/*
144 * Allocate resources needed for LCD controller and LCD DMA operations. Video 135 * Allocate resources needed for LCD controller and LCD DMA operations. Video
145 * memory is allocated from system memory according to the virtual display 136 * memory is allocated from system memory according to the virtual display
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index eaeed4340e04..c835aa70f96f 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -600,6 +600,9 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
600 600
601 mutex_lock(&md->mutex); 601 mutex_lock(&md->mutex);
602 602
603 omapdss_sdi_set_timings(dssdev, &dssdev->panel.timings);
604 omapdss_sdi_set_datapairs(dssdev, dssdev->phy.sdi.datapairs);
605
603 r = omapdss_sdi_display_enable(dssdev); 606 r = omapdss_sdi_display_enable(dssdev);
604 if (r) { 607 if (r) {
605 pr_err("%s sdi enable failed\n", __func__); 608 pr_err("%s sdi enable failed\n", __func__);
@@ -731,18 +734,9 @@ static int acx_panel_resume(struct omap_dss_device *dssdev)
731static void acx_panel_set_timings(struct omap_dss_device *dssdev, 734static void acx_panel_set_timings(struct omap_dss_device *dssdev,
732 struct omap_video_timings *timings) 735 struct omap_video_timings *timings)
733{ 736{
734 int r; 737 omapdss_sdi_set_timings(dssdev, timings);
735
736 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
737 omapdss_sdi_display_disable(dssdev);
738 738
739 dssdev->panel.timings = *timings; 739 dssdev->panel.timings = *timings;
740
741 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
742 r = omapdss_sdi_display_enable(dssdev);
743 if (r)
744 dev_err(&dssdev->dev, "%s enable failed\n", __func__);
745 }
746} 740}
747 741
748static int acx_panel_check_timings(struct omap_dss_device *dssdev, 742static int acx_panel_check_timings(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index bc5af2500eb9..88295c526815 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -545,6 +545,8 @@ struct panel_drv_data {
545 struct omap_dss_device *dssdev; 545 struct omap_dss_device *dssdev;
546 546
547 struct panel_config *panel_config; 547 struct panel_config *panel_config;
548
549 struct mutex lock;
548}; 550};
549 551
550static inline struct panel_generic_dpi_data 552static inline struct panel_generic_dpi_data
@@ -563,6 +565,9 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
563 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 565 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
564 return 0; 566 return 0;
565 567
568 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
569 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
570
566 r = omapdss_dpi_display_enable(dssdev); 571 r = omapdss_dpi_display_enable(dssdev);
567 if (r) 572 if (r)
568 goto err0; 573 goto err0;
@@ -634,6 +639,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
634 drv_data->dssdev = dssdev; 639 drv_data->dssdev = dssdev;
635 drv_data->panel_config = panel_config; 640 drv_data->panel_config = panel_config;
636 641
642 mutex_init(&drv_data->lock);
643
637 dev_set_drvdata(&dssdev->dev, drv_data); 644 dev_set_drvdata(&dssdev->dev, drv_data);
638 645
639 return 0; 646 return 0;
@@ -652,56 +659,108 @@ static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
652 659
653static int generic_dpi_panel_enable(struct omap_dss_device *dssdev) 660static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
654{ 661{
655 int r = 0; 662 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
663 int r;
664
665 mutex_lock(&drv_data->lock);
656 666
657 r = generic_dpi_panel_power_on(dssdev); 667 r = generic_dpi_panel_power_on(dssdev);
658 if (r) 668 if (r)
659 return r; 669 goto err;
660 670
661 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 671 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
672err:
673 mutex_unlock(&drv_data->lock);
662 674
663 return 0; 675 return r;
664} 676}
665 677
666static void generic_dpi_panel_disable(struct omap_dss_device *dssdev) 678static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
667{ 679{
680 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
681
682 mutex_lock(&drv_data->lock);
683
668 generic_dpi_panel_power_off(dssdev); 684 generic_dpi_panel_power_off(dssdev);
669 685
670 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 686 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
687
688 mutex_unlock(&drv_data->lock);
671} 689}
672 690
673static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev) 691static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
674{ 692{
693 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
694
695 mutex_lock(&drv_data->lock);
696
675 generic_dpi_panel_power_off(dssdev); 697 generic_dpi_panel_power_off(dssdev);
676 698
677 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 699 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
678 700
701 mutex_unlock(&drv_data->lock);
702
679 return 0; 703 return 0;
680} 704}
681 705
682static int generic_dpi_panel_resume(struct omap_dss_device *dssdev) 706static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
683{ 707{
684 int r = 0; 708 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
709 int r;
710
711 mutex_lock(&drv_data->lock);
685 712
686 r = generic_dpi_panel_power_on(dssdev); 713 r = generic_dpi_panel_power_on(dssdev);
687 if (r) 714 if (r)
688 return r; 715 goto err;
689 716
690 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 717 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
691 718
692 return 0; 719err:
720 mutex_unlock(&drv_data->lock);
721
722 return r;
693} 723}
694 724
695static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, 725static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
696 struct omap_video_timings *timings) 726 struct omap_video_timings *timings)
697{ 727{
698 dpi_set_timings(dssdev, timings); 728 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
729
730 mutex_lock(&drv_data->lock);
731
732 omapdss_dpi_set_timings(dssdev, timings);
733
734 dssdev->panel.timings = *timings;
735
736 mutex_unlock(&drv_data->lock);
737}
738
739static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
740 struct omap_video_timings *timings)
741{
742 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
743
744 mutex_lock(&drv_data->lock);
745
746 *timings = dssdev->panel.timings;
747
748 mutex_unlock(&drv_data->lock);
699} 749}
700 750
701static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, 751static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
702 struct omap_video_timings *timings) 752 struct omap_video_timings *timings)
703{ 753{
704 return dpi_check_timings(dssdev, timings); 754 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
755 int r;
756
757 mutex_lock(&drv_data->lock);
758
759 r = dpi_check_timings(dssdev, timings);
760
761 mutex_unlock(&drv_data->lock);
762
763 return r;
705} 764}
706 765
707static struct omap_dss_driver dpi_driver = { 766static struct omap_dss_driver dpi_driver = {
@@ -714,6 +773,7 @@ static struct omap_dss_driver dpi_driver = {
714 .resume = generic_dpi_panel_resume, 773 .resume = generic_dpi_panel_resume,
715 774
716 .set_timings = generic_dpi_panel_set_timings, 775 .set_timings = generic_dpi_panel_set_timings,
776 .get_timings = generic_dpi_panel_get_timings,
717 .check_timings = generic_dpi_panel_check_timings, 777 .check_timings = generic_dpi_panel_check_timings,
718 778
719 .driver = { 779 .driver = {
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index 802807798846..90c1cabf244e 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -55,6 +55,9 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
55 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 55 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
56 return 0; 56 return 0;
57 57
58 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
59 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
60
58 r = omapdss_dpi_display_enable(dssdev); 61 r = omapdss_dpi_display_enable(dssdev);
59 if (r) 62 if (r)
60 goto err0; 63 goto err0;
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index e6c115373c00..3fc5ad081a21 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -150,11 +150,17 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
150 BLIZZARD_SRC_WRITE_LCD : 150 BLIZZARD_SRC_WRITE_LCD :
151 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; 151 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
152 152
153 omap_rfbi_configure(dssdev, 16, 8); 153 omapdss_rfbi_set_pixel_size(dssdev, 16);
154 omapdss_rfbi_set_data_lines(dssdev, 8);
155
156 omap_rfbi_configure(dssdev);
154 157
155 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); 158 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
156 159
157 omap_rfbi_configure(dssdev, 16, 16); 160 omapdss_rfbi_set_pixel_size(dssdev, 16);
161 omapdss_rfbi_set_data_lines(dssdev, 16);
162
163 omap_rfbi_configure(dssdev);
158} 164}
159 165
160static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf, 166static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
@@ -297,6 +303,12 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
297 goto err_plat_en; 303 goto err_plat_en;
298 } 304 }
299 305
306 omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
307 dssdev->panel.timings.y_res);
308 omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
309 omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
310 omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
311
300 r = omapdss_rfbi_display_enable(dssdev); 312 r = omapdss_rfbi_display_enable(dssdev);
301 if (r) 313 if (r)
302 goto err_rfbi_en; 314 goto err_rfbi_en;
@@ -477,6 +489,7 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
477 dssdev->panel.timings.y_res = 480; 489 dssdev->panel.timings.y_res = 480;
478 dssdev->ctrl.pixel_size = 16; 490 dssdev->ctrl.pixel_size = 16;
479 dssdev->ctrl.rfbi_timings = n8x0_panel_timings; 491 dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
492 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
480 493
481 memset(&props, 0, sizeof(props)); 494 memset(&props, 0, sizeof(props));
482 props.max_brightness = 127; 495 props.max_brightness = 127;
@@ -625,17 +638,25 @@ static int n8x0_panel_update(struct omap_dss_device *dssdev,
625 u16 x, u16 y, u16 w, u16 h) 638 u16 x, u16 y, u16 w, u16 h)
626{ 639{
627 struct panel_drv_data *ddata = get_drv_data(dssdev); 640 struct panel_drv_data *ddata = get_drv_data(dssdev);
641 u16 dw, dh;
628 642
629 dev_dbg(&dssdev->dev, "update\n"); 643 dev_dbg(&dssdev->dev, "update\n");
630 644
645 dw = dssdev->panel.timings.x_res;
646 dh = dssdev->panel.timings.y_res;
647
648 if (x != 0 || y != 0 || w != dw || h != dh) {
649 dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
650 x, y, w, h);
651 return -EINVAL;
652 }
653
631 mutex_lock(&ddata->lock); 654 mutex_lock(&ddata->lock);
632 rfbi_bus_lock(); 655 rfbi_bus_lock();
633 656
634 omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
635
636 blizzard_ctrl_setup_update(dssdev, x, y, w, h); 657 blizzard_ctrl_setup_update(dssdev, x, y, w, h);
637 658
638 omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL); 659 omap_rfbi_update(dssdev, update_done, NULL);
639 660
640 mutex_unlock(&ddata->lock); 661 mutex_unlock(&ddata->lock);
641 662
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index b122b0f31c43..908fd268f3dc 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -175,6 +175,9 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
175 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 175 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
176 return 0; 176 return 0;
177 177
178 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
179 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
180
178 r = omapdss_dpi_display_enable(dssdev); 181 r = omapdss_dpi_display_enable(dssdev);
179 if (r) 182 if (r)
180 goto err0; 183 goto err0;
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
index 2d35bd388860..9df87640ddd2 100644
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -377,6 +377,10 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
377 * then only i2c commands can be successfully sent to dpp2600 377 * then only i2c commands can be successfully sent to dpp2600
378 */ 378 */
379 msleep(1000); 379 msleep(1000);
380
381 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
382 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
383
380 r = omapdss_dpi_display_enable(dssdev); 384 r = omapdss_dpi_display_enable(dssdev);
381 if (r) { 385 if (r) {
382 dev_err(&dssdev->dev, "failed to enable DPI\n"); 386 dev_err(&dssdev->dev, "failed to enable DPI\n");
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index bd86ba9ccf76..1ec3b277ff15 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -142,6 +142,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
142 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 142 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
143 return 0; 143 return 0;
144 144
145 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
146 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
147
145 r = omapdss_dpi_display_enable(dssdev); 148 r = omapdss_dpi_display_enable(dssdev);
146 if (r) 149 if (r)
147 goto err0; 150 goto err0;
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 3f5acc7771da..4cf94161ff51 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -121,6 +121,18 @@ struct taal_data {
121 121
122 struct omap_dss_device *dssdev; 122 struct omap_dss_device *dssdev;
123 123
124 /* panel specific HW info */
125 struct panel_config *panel_config;
126
127 /* panel HW configuration from DT or platform data */
128 int reset_gpio;
129 int ext_te_gpio;
130
131 bool use_dsi_backlight;
132
133 struct omap_dsi_pin_config pin_config;
134
135 /* runtime variables */
124 bool enabled; 136 bool enabled;
125 u8 rotate; 137 u8 rotate;
126 bool mirror; 138 bool mirror;
@@ -145,16 +157,8 @@ struct taal_data {
145 bool ulps_enabled; 157 bool ulps_enabled;
146 unsigned ulps_timeout; 158 unsigned ulps_timeout;
147 struct delayed_work ulps_work; 159 struct delayed_work ulps_work;
148
149 struct panel_config *panel_config;
150}; 160};
151 161
152static inline struct nokia_dsi_panel_data
153*get_panel_data(const struct omap_dss_device *dssdev)
154{
155 return (struct nokia_dsi_panel_data *) dssdev->data;
156}
157
158static void taal_esd_work(struct work_struct *work); 162static void taal_esd_work(struct work_struct *work);
159static void taal_ulps_work(struct work_struct *work); 163static void taal_ulps_work(struct work_struct *work);
160 164
@@ -371,7 +375,6 @@ static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
371static int taal_enter_ulps(struct omap_dss_device *dssdev) 375static int taal_enter_ulps(struct omap_dss_device *dssdev)
372{ 376{
373 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 377 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
374 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
375 int r; 378 int r;
376 379
377 if (td->ulps_enabled) 380 if (td->ulps_enabled)
@@ -383,7 +386,8 @@ static int taal_enter_ulps(struct omap_dss_device *dssdev)
383 if (r) 386 if (r)
384 goto err; 387 goto err;
385 388
386 disable_irq(gpio_to_irq(panel_data->ext_te_gpio)); 389 if (gpio_is_valid(td->ext_te_gpio))
390 disable_irq(gpio_to_irq(td->ext_te_gpio));
387 391
388 omapdss_dsi_display_disable(dssdev, false, true); 392 omapdss_dsi_display_disable(dssdev, false, true);
389 393
@@ -405,7 +409,6 @@ err:
405static int taal_exit_ulps(struct omap_dss_device *dssdev) 409static int taal_exit_ulps(struct omap_dss_device *dssdev)
406{ 410{
407 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 411 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
408 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
409 int r; 412 int r;
410 413
411 if (!td->ulps_enabled) 414 if (!td->ulps_enabled)
@@ -425,7 +428,8 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
425 goto err2; 428 goto err2;
426 } 429 }
427 430
428 enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); 431 if (gpio_is_valid(td->ext_te_gpio))
432 enable_irq(gpio_to_irq(td->ext_te_gpio));
429 433
430 taal_queue_ulps_work(dssdev); 434 taal_queue_ulps_work(dssdev);
431 435
@@ -438,7 +442,8 @@ err2:
438 442
439 r = taal_panel_reset(dssdev); 443 r = taal_panel_reset(dssdev);
440 if (!r) { 444 if (!r) {
441 enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); 445 if (gpio_is_valid(td->ext_te_gpio))
446 enable_irq(gpio_to_irq(td->ext_te_gpio));
442 td->ulps_enabled = false; 447 td->ulps_enabled = false;
443 } 448 }
444err1: 449err1:
@@ -835,94 +840,135 @@ static struct attribute_group taal_attr_group = {
835static void taal_hw_reset(struct omap_dss_device *dssdev) 840static void taal_hw_reset(struct omap_dss_device *dssdev)
836{ 841{
837 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 842 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
838 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
839 843
840 if (panel_data->reset_gpio == -1) 844 if (!gpio_is_valid(td->reset_gpio))
841 return; 845 return;
842 846
843 gpio_set_value(panel_data->reset_gpio, 1); 847 gpio_set_value(td->reset_gpio, 1);
844 if (td->panel_config->reset_sequence.high) 848 if (td->panel_config->reset_sequence.high)
845 udelay(td->panel_config->reset_sequence.high); 849 udelay(td->panel_config->reset_sequence.high);
846 /* reset the panel */ 850 /* reset the panel */
847 gpio_set_value(panel_data->reset_gpio, 0); 851 gpio_set_value(td->reset_gpio, 0);
848 /* assert reset */ 852 /* assert reset */
849 if (td->panel_config->reset_sequence.low) 853 if (td->panel_config->reset_sequence.low)
850 udelay(td->panel_config->reset_sequence.low); 854 udelay(td->panel_config->reset_sequence.low);
851 gpio_set_value(panel_data->reset_gpio, 1); 855 gpio_set_value(td->reset_gpio, 1);
852 /* wait after releasing reset */ 856 /* wait after releasing reset */
853 if (td->panel_config->sleep.hw_reset) 857 if (td->panel_config->sleep.hw_reset)
854 msleep(td->panel_config->sleep.hw_reset); 858 msleep(td->panel_config->sleep.hw_reset);
855} 859}
856 860
861static void taal_probe_pdata(struct taal_data *td,
862 const struct nokia_dsi_panel_data *pdata)
863{
864 td->reset_gpio = pdata->reset_gpio;
865
866 if (pdata->use_ext_te)
867 td->ext_te_gpio = pdata->ext_te_gpio;
868 else
869 td->ext_te_gpio = -1;
870
871 td->esd_interval = pdata->esd_interval;
872 td->ulps_timeout = pdata->ulps_timeout;
873
874 td->use_dsi_backlight = pdata->use_dsi_backlight;
875
876 td->pin_config = pdata->pin_config;
877}
878
857static int taal_probe(struct omap_dss_device *dssdev) 879static int taal_probe(struct omap_dss_device *dssdev)
858{ 880{
859 struct backlight_properties props; 881 struct backlight_properties props;
860 struct taal_data *td; 882 struct taal_data *td;
861 struct backlight_device *bldev = NULL; 883 struct backlight_device *bldev = NULL;
862 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
863 struct panel_config *panel_config = NULL;
864 int r, i; 884 int r, i;
885 const char *panel_name;
865 886
866 dev_dbg(&dssdev->dev, "probe\n"); 887 dev_dbg(&dssdev->dev, "probe\n");
867 888
868 if (!panel_data || !panel_data->name) { 889 td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL);
869 r = -EINVAL; 890 if (!td)
870 goto err; 891 return -ENOMEM;
892
893 dev_set_drvdata(&dssdev->dev, td);
894 td->dssdev = dssdev;
895
896 if (dssdev->data) {
897 const struct nokia_dsi_panel_data *pdata = dssdev->data;
898
899 taal_probe_pdata(td, pdata);
900
901 panel_name = pdata->name;
902 } else {
903 return -ENODEV;
871 } 904 }
872 905
906 if (panel_name == NULL)
907 return -EINVAL;
908
873 for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { 909 for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
874 if (strcmp(panel_data->name, panel_configs[i].name) == 0) { 910 if (strcmp(panel_name, panel_configs[i].name) == 0) {
875 panel_config = &panel_configs[i]; 911 td->panel_config = &panel_configs[i];
876 break; 912 break;
877 } 913 }
878 } 914 }
879 915
880 if (!panel_config) { 916 if (!td->panel_config)
881 r = -EINVAL; 917 return -EINVAL;
882 goto err;
883 }
884 918
885 dssdev->panel.timings = panel_config->timings; 919 dssdev->panel.timings = td->panel_config->timings;
886 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; 920 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
887 921 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
888 td = kzalloc(sizeof(*td), GFP_KERNEL); 922 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
889 if (!td) {
890 r = -ENOMEM;
891 goto err;
892 }
893 td->dssdev = dssdev;
894 td->panel_config = panel_config;
895 td->esd_interval = panel_data->esd_interval;
896 td->ulps_enabled = false;
897 td->ulps_timeout = panel_data->ulps_timeout;
898 923
899 mutex_init(&td->lock); 924 mutex_init(&td->lock);
900 925
901 atomic_set(&td->do_update, 0); 926 atomic_set(&td->do_update, 0);
902 927
903 td->workqueue = create_singlethread_workqueue("taal_esd"); 928 if (gpio_is_valid(td->reset_gpio)) {
904 if (td->workqueue == NULL) { 929 r = devm_gpio_request_one(&dssdev->dev, td->reset_gpio,
905 dev_err(&dssdev->dev, "can't create ESD workqueue\n"); 930 GPIOF_OUT_INIT_LOW, "taal rst");
906 r = -ENOMEM; 931 if (r) {
907 goto err_wq; 932 dev_err(&dssdev->dev, "failed to request reset gpio\n");
933 return r;
934 }
908 } 935 }
909 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
910 INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
911 936
912 dev_set_drvdata(&dssdev->dev, td); 937 if (gpio_is_valid(td->ext_te_gpio)) {
938 r = devm_gpio_request_one(&dssdev->dev, td->ext_te_gpio,
939 GPIOF_IN, "taal irq");
940 if (r) {
941 dev_err(&dssdev->dev, "GPIO request failed\n");
942 return r;
943 }
944
945 r = devm_request_irq(&dssdev->dev, gpio_to_irq(td->ext_te_gpio),
946 taal_te_isr,
947 IRQF_TRIGGER_RISING,
948 "taal vsync", dssdev);
913 949
914 if (gpio_is_valid(panel_data->reset_gpio)) {
915 r = gpio_request_one(panel_data->reset_gpio, GPIOF_OUT_INIT_LOW,
916 "taal rst");
917 if (r) { 950 if (r) {
918 dev_err(&dssdev->dev, "failed to request reset gpio\n"); 951 dev_err(&dssdev->dev, "IRQ request failed\n");
919 goto err_rst_gpio; 952 return r;
920 } 953 }
954
955 INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work,
956 taal_te_timeout_work_callback);
957
958 dev_dbg(&dssdev->dev, "Using GPIO TE\n");
921 } 959 }
922 960
961 td->workqueue = create_singlethread_workqueue("taal_esd");
962 if (td->workqueue == NULL) {
963 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
964 return -ENOMEM;
965 }
966 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
967 INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
968
923 taal_hw_reset(dssdev); 969 taal_hw_reset(dssdev);
924 970
925 if (panel_data->use_dsi_backlight) { 971 if (td->use_dsi_backlight) {
926 memset(&props, 0, sizeof(struct backlight_properties)); 972 memset(&props, 0, sizeof(struct backlight_properties));
927 props.max_brightness = 255; 973 props.max_brightness = 255;
928 974
@@ -943,31 +989,6 @@ static int taal_probe(struct omap_dss_device *dssdev)
943 taal_bl_update_status(bldev); 989 taal_bl_update_status(bldev);
944 } 990 }
945 991
946 if (panel_data->use_ext_te) {
947 int gpio = panel_data->ext_te_gpio;
948
949 r = gpio_request_one(gpio, GPIOF_IN, "taal irq");
950 if (r) {
951 dev_err(&dssdev->dev, "GPIO request failed\n");
952 goto err_gpio;
953 }
954
955 r = request_irq(gpio_to_irq(gpio), taal_te_isr,
956 IRQF_TRIGGER_RISING,
957 "taal vsync", dssdev);
958
959 if (r) {
960 dev_err(&dssdev->dev, "IRQ request failed\n");
961 gpio_free(gpio);
962 goto err_irq;
963 }
964
965 INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work,
966 taal_te_timeout_work_callback);
967
968 dev_dbg(&dssdev->dev, "Using GPIO TE\n");
969 }
970
971 r = omap_dsi_request_vc(dssdev, &td->channel); 992 r = omap_dsi_request_vc(dssdev, &td->channel);
972 if (r) { 993 if (r) {
973 dev_err(&dssdev->dev, "failed to get virtual channel\n"); 994 dev_err(&dssdev->dev, "failed to get virtual channel\n");
@@ -991,29 +1012,16 @@ static int taal_probe(struct omap_dss_device *dssdev)
991err_vc_id: 1012err_vc_id:
992 omap_dsi_release_vc(dssdev, td->channel); 1013 omap_dsi_release_vc(dssdev, td->channel);
993err_req_vc: 1014err_req_vc:
994 if (panel_data->use_ext_te)
995 free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
996err_irq:
997 if (panel_data->use_ext_te)
998 gpio_free(panel_data->ext_te_gpio);
999err_gpio:
1000 if (bldev != NULL) 1015 if (bldev != NULL)
1001 backlight_device_unregister(bldev); 1016 backlight_device_unregister(bldev);
1002err_bl: 1017err_bl:
1003 if (gpio_is_valid(panel_data->reset_gpio))
1004 gpio_free(panel_data->reset_gpio);
1005err_rst_gpio:
1006 destroy_workqueue(td->workqueue); 1018 destroy_workqueue(td->workqueue);
1007err_wq:
1008 kfree(td);
1009err:
1010 return r; 1019 return r;
1011} 1020}
1012 1021
1013static void __exit taal_remove(struct omap_dss_device *dssdev) 1022static void __exit taal_remove(struct omap_dss_device *dssdev)
1014{ 1023{
1015 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1024 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1016 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1017 struct backlight_device *bldev; 1025 struct backlight_device *bldev;
1018 1026
1019 dev_dbg(&dssdev->dev, "remove\n"); 1027 dev_dbg(&dssdev->dev, "remove\n");
@@ -1021,12 +1029,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
1021 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); 1029 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
1022 omap_dsi_release_vc(dssdev, td->channel); 1030 omap_dsi_release_vc(dssdev, td->channel);
1023 1031
1024 if (panel_data->use_ext_te) {
1025 int gpio = panel_data->ext_te_gpio;
1026 free_irq(gpio_to_irq(gpio), dssdev);
1027 gpio_free(gpio);
1028 }
1029
1030 bldev = td->bldev; 1032 bldev = td->bldev;
1031 if (bldev != NULL) { 1033 if (bldev != NULL) {
1032 bldev->props.power = FB_BLANK_POWERDOWN; 1034 bldev->props.power = FB_BLANK_POWERDOWN;
@@ -1040,26 +1042,31 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
1040 1042
1041 /* reset, to be sure that the panel is in a valid state */ 1043 /* reset, to be sure that the panel is in a valid state */
1042 taal_hw_reset(dssdev); 1044 taal_hw_reset(dssdev);
1043
1044 if (gpio_is_valid(panel_data->reset_gpio))
1045 gpio_free(panel_data->reset_gpio);
1046
1047 kfree(td);
1048} 1045}
1049 1046
1050static int taal_power_on(struct omap_dss_device *dssdev) 1047static int taal_power_on(struct omap_dss_device *dssdev)
1051{ 1048{
1052 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1049 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1053 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1054 u8 id1, id2, id3; 1050 u8 id1, id2, id3;
1055 int r; 1051 int r;
1056 1052
1057 r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config); 1053 r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
1058 if (r) { 1054 if (r) {
1059 dev_err(&dssdev->dev, "failed to configure DSI pins\n"); 1055 dev_err(&dssdev->dev, "failed to configure DSI pins\n");
1060 goto err0; 1056 goto err0;
1061 }; 1057 };
1062 1058
1059 omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
1060 dssdev->panel.timings.y_res);
1061 omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
1062 omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
1063
1064 r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
1065 if (r) {
1066 dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
1067 goto err0;
1068 }
1069
1063 r = omapdss_dsi_display_enable(dssdev); 1070 r = omapdss_dsi_display_enable(dssdev);
1064 if (r) { 1071 if (r) {
1065 dev_err(&dssdev->dev, "failed to enable DSI\n"); 1072 dev_err(&dssdev->dev, "failed to enable DSI\n");
@@ -1356,7 +1363,6 @@ static int taal_update(struct omap_dss_device *dssdev,
1356 u16 x, u16 y, u16 w, u16 h) 1363 u16 x, u16 y, u16 w, u16 h)
1357{ 1364{
1358 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1365 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1359 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1360 int r; 1366 int r;
1361 1367
1362 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); 1368 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
@@ -1380,7 +1386,7 @@ static int taal_update(struct omap_dss_device *dssdev,
1380 if (r) 1386 if (r)
1381 goto err; 1387 goto err;
1382 1388
1383 if (td->te_enabled && panel_data->use_ext_te) { 1389 if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
1384 schedule_delayed_work(&td->te_timeout_work, 1390 schedule_delayed_work(&td->te_timeout_work,
1385 msecs_to_jiffies(250)); 1391 msecs_to_jiffies(250));
1386 atomic_set(&td->do_update, 1); 1392 atomic_set(&td->do_update, 1);
@@ -1419,7 +1425,6 @@ static int taal_sync(struct omap_dss_device *dssdev)
1419static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) 1425static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1420{ 1426{
1421 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1427 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1422 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1423 int r; 1428 int r;
1424 1429
1425 if (enable) 1430 if (enable)
@@ -1427,7 +1432,7 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1427 else 1432 else
1428 r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF); 1433 r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
1429 1434
1430 if (!panel_data->use_ext_te) 1435 if (!gpio_is_valid(td->ext_te_gpio))
1431 omapdss_dsi_enable_te(dssdev, enable); 1436 omapdss_dsi_enable_te(dssdev, enable);
1432 1437
1433 if (td->panel_config->sleep.enable_te) 1438 if (td->panel_config->sleep.enable_te)
@@ -1487,6 +1492,7 @@ static int taal_get_te(struct omap_dss_device *dssdev)
1487static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) 1492static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
1488{ 1493{
1489 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1494 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1495 u16 dw, dh;
1490 int r; 1496 int r;
1491 1497
1492 dev_dbg(&dssdev->dev, "rotate %d\n", rotate); 1498 dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
@@ -1508,6 +1514,16 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
1508 goto err; 1514 goto err;
1509 } 1515 }
1510 1516
1517 if (rotate == 0 || rotate == 2) {
1518 dw = dssdev->panel.timings.x_res;
1519 dh = dssdev->panel.timings.y_res;
1520 } else {
1521 dw = dssdev->panel.timings.y_res;
1522 dh = dssdev->panel.timings.x_res;
1523 }
1524
1525 omapdss_dsi_set_size(dssdev, dw, dh);
1526
1511 td->rotate = rotate; 1527 td->rotate = rotate;
1512 1528
1513 dsi_bus_unlock(dssdev); 1529 dsi_bus_unlock(dssdev);
@@ -1726,7 +1742,6 @@ static void taal_esd_work(struct work_struct *work)
1726 struct taal_data *td = container_of(work, struct taal_data, 1742 struct taal_data *td = container_of(work, struct taal_data,
1727 esd_work.work); 1743 esd_work.work);
1728 struct omap_dss_device *dssdev = td->dssdev; 1744 struct omap_dss_device *dssdev = td->dssdev;
1729 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1730 u8 state1, state2; 1745 u8 state1, state2;
1731 int r; 1746 int r;
1732 1747
@@ -1773,7 +1788,7 @@ static void taal_esd_work(struct work_struct *work)
1773 } 1788 }
1774 /* Self-diagnostics result is also shown on TE GPIO line. We need 1789 /* Self-diagnostics result is also shown on TE GPIO line. We need
1775 * to re-enable TE after self diagnostics */ 1790 * to re-enable TE after self diagnostics */
1776 if (td->te_enabled && panel_data->use_ext_te) { 1791 if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
1777 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); 1792 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
1778 if (r) 1793 if (r)
1779 goto err; 1794 goto err;
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index 40cc0cfa5d17..383811cf8648 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -65,6 +65,9 @@ static int tfp410_power_on(struct omap_dss_device *dssdev)
65 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 65 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
66 return 0; 66 return 0;
67 67
68 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
69 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
70
68 r = omapdss_dpi_display_enable(dssdev); 71 r = omapdss_dpi_display_enable(dssdev);
69 if (r) 72 if (r)
70 goto err0; 73 goto err0;
@@ -116,8 +119,8 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
116 } 119 }
117 120
118 if (gpio_is_valid(ddata->pd_gpio)) { 121 if (gpio_is_valid(ddata->pd_gpio)) {
119 r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW, 122 r = devm_gpio_request_one(&dssdev->dev, ddata->pd_gpio,
120 "tfp410 pd"); 123 GPIOF_OUT_INIT_LOW, "tfp410 pd");
121 if (r) { 124 if (r) {
122 dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n", 125 dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
123 ddata->pd_gpio); 126 ddata->pd_gpio);
@@ -132,8 +135,7 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
132 if (!adapter) { 135 if (!adapter) {
133 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", 136 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
134 i2c_bus_num); 137 i2c_bus_num);
135 r = -EINVAL; 138 return -EINVAL;
136 goto err_i2c;
137 } 139 }
138 140
139 ddata->i2c_adapter = adapter; 141 ddata->i2c_adapter = adapter;
@@ -142,10 +144,6 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
142 dev_set_drvdata(&dssdev->dev, ddata); 144 dev_set_drvdata(&dssdev->dev, ddata);
143 145
144 return 0; 146 return 0;
145err_i2c:
146 if (gpio_is_valid(ddata->pd_gpio))
147 gpio_free(ddata->pd_gpio);
148 return r;
149} 147}
150 148
151static void __exit tfp410_remove(struct omap_dss_device *dssdev) 149static void __exit tfp410_remove(struct omap_dss_device *dssdev)
@@ -157,9 +155,6 @@ static void __exit tfp410_remove(struct omap_dss_device *dssdev)
157 if (ddata->i2c_adapter) 155 if (ddata->i2c_adapter)
158 i2c_put_adapter(ddata->i2c_adapter); 156 i2c_put_adapter(ddata->i2c_adapter);
159 157
160 if (gpio_is_valid(ddata->pd_gpio))
161 gpio_free(ddata->pd_gpio);
162
163 dev_set_drvdata(&dssdev->dev, NULL); 158 dev_set_drvdata(&dssdev->dev, NULL);
164 159
165 mutex_unlock(&ddata->lock); 160 mutex_unlock(&ddata->lock);
@@ -231,7 +226,8 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev,
231 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 226 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
232 227
233 mutex_lock(&ddata->lock); 228 mutex_lock(&ddata->lock);
234 dpi_set_timings(dssdev, timings); 229 omapdss_dpi_set_timings(dssdev, timings);
230 dssdev->panel.timings = *timings;
235 mutex_unlock(&ddata->lock); 231 mutex_unlock(&ddata->lock);
236} 232}
237 233
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index fa7baa650ae0..b5e6dbc59f0a 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -337,6 +337,9 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
337 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 337 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
338 return 0; 338 return 0;
339 339
340 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
341 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
342
340 r = omapdss_dpi_display_enable(dssdev); 343 r = omapdss_dpi_display_enable(dssdev);
341 if (r) 344 if (r)
342 goto err0; 345 goto err0;
@@ -480,7 +483,9 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
480static void tpo_td043_set_timings(struct omap_dss_device *dssdev, 483static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
481 struct omap_video_timings *timings) 484 struct omap_video_timings *timings)
482{ 485{
483 dpi_set_timings(dssdev, timings); 486 omapdss_dpi_set_timings(dssdev, timings);
487
488 dssdev->panel.timings = *timings;
484} 489}
485 490
486static int tpo_td043_check_timings(struct omap_dss_device *dssdev, 491static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index b337a8469fd8..80f5390aa136 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -84,7 +84,7 @@ config OMAP2_DSS_SDI
84 84
85config OMAP2_DSS_DSI 85config OMAP2_DSS_DSI
86 bool "DSI support" 86 bool "DSI support"
87 depends on ARCH_OMAP3 || ARCH_OMAP4 87 depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
88 default n 88 default n
89 help 89 help
90 MIPI DSI (Display Serial Interface) support. 90 MIPI DSI (Display Serial Interface) support.
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 5c450b0f94d0..4549869bfe1a 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,9 +1,9 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 2omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
3 manager.o overlay.o apply.o 3 manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o
4omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 4omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
5omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 5omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
6omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 6omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
7omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 7omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
8omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 8omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
9omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ 9omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 0fefc68372b9..19d66f471b4b 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -111,9 +111,6 @@ static struct {
111 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS]; 111 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
112 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS]; 112 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
113 113
114 bool fifo_merge_dirty;
115 bool fifo_merge;
116
117 bool irq_enabled; 114 bool irq_enabled;
118} dss_data; 115} dss_data;
119 116
@@ -424,17 +421,25 @@ static void wait_pending_extra_info_updates(void)
424int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) 421int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
425{ 422{
426 unsigned long timeout = msecs_to_jiffies(500); 423 unsigned long timeout = msecs_to_jiffies(500);
427 struct mgr_priv_data *mp; 424 struct mgr_priv_data *mp = get_mgr_priv(mgr);
428 u32 irq; 425 u32 irq;
426 unsigned long flags;
429 int r; 427 int r;
430 int i; 428 int i;
431 struct omap_dss_device *dssdev = mgr->device;
432 429
433 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 430 spin_lock_irqsave(&data_lock, flags);
431
432 if (mgr_manual_update(mgr)) {
433 spin_unlock_irqrestore(&data_lock, flags);
434 return 0; 434 return 0;
435 }
435 436
436 if (mgr_manual_update(mgr)) 437 if (!mp->enabled) {
438 spin_unlock_irqrestore(&data_lock, flags);
437 return 0; 439 return 0;
440 }
441
442 spin_unlock_irqrestore(&data_lock, flags);
438 443
439 r = dispc_runtime_get(); 444 r = dispc_runtime_get();
440 if (r) 445 if (r)
@@ -442,10 +447,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
442 447
443 irq = dispc_mgr_get_vsync_irq(mgr->id); 448 irq = dispc_mgr_get_vsync_irq(mgr->id);
444 449
445 mp = get_mgr_priv(mgr);
446 i = 0; 450 i = 0;
447 while (1) { 451 while (1) {
448 unsigned long flags;
449 bool shadow_dirty, dirty; 452 bool shadow_dirty, dirty;
450 453
451 spin_lock_irqsave(&data_lock, flags); 454 spin_lock_irqsave(&data_lock, flags);
@@ -489,21 +492,30 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
489{ 492{
490 unsigned long timeout = msecs_to_jiffies(500); 493 unsigned long timeout = msecs_to_jiffies(500);
491 struct ovl_priv_data *op; 494 struct ovl_priv_data *op;
492 struct omap_dss_device *dssdev; 495 struct mgr_priv_data *mp;
493 u32 irq; 496 u32 irq;
497 unsigned long flags;
494 int r; 498 int r;
495 int i; 499 int i;
496 500
497 if (!ovl->manager) 501 if (!ovl->manager)
498 return 0; 502 return 0;
499 503
500 dssdev = ovl->manager->device; 504 mp = get_mgr_priv(ovl->manager);
505
506 spin_lock_irqsave(&data_lock, flags);
501 507
502 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 508 if (ovl_manual_update(ovl)) {
509 spin_unlock_irqrestore(&data_lock, flags);
503 return 0; 510 return 0;
511 }
504 512
505 if (ovl_manual_update(ovl)) 513 if (!mp->enabled) {
514 spin_unlock_irqrestore(&data_lock, flags);
506 return 0; 515 return 0;
516 }
517
518 spin_unlock_irqrestore(&data_lock, flags);
507 519
508 r = dispc_runtime_get(); 520 r = dispc_runtime_get();
509 if (r) 521 if (r)
@@ -514,7 +526,6 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
514 op = get_ovl_priv(ovl); 526 op = get_ovl_priv(ovl);
515 i = 0; 527 i = 0;
516 while (1) { 528 while (1) {
517 unsigned long flags;
518 bool shadow_dirty, dirty; 529 bool shadow_dirty, dirty;
519 530
520 spin_lock_irqsave(&data_lock, flags); 531 spin_lock_irqsave(&data_lock, flags);
@@ -573,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
573 584
574 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode); 585 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
575 586
576 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings); 587 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
577 if (r) { 588 if (r) {
578 /* 589 /*
579 * We can't do much here, as this function can be called from 590 * We can't do much here, as this function can be called from
@@ -677,40 +688,11 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
677 mp->shadow_extra_info_dirty = true; 688 mp->shadow_extra_info_dirty = true;
678} 689}
679 690
680static void dss_write_regs_common(void)
681{
682 const int num_mgrs = omap_dss_get_num_overlay_managers();
683 int i;
684
685 if (!dss_data.fifo_merge_dirty)
686 return;
687
688 for (i = 0; i < num_mgrs; ++i) {
689 struct omap_overlay_manager *mgr;
690 struct mgr_priv_data *mp;
691
692 mgr = omap_dss_get_overlay_manager(i);
693 mp = get_mgr_priv(mgr);
694
695 if (mp->enabled) {
696 if (dss_data.fifo_merge_dirty) {
697 dispc_enable_fifomerge(dss_data.fifo_merge);
698 dss_data.fifo_merge_dirty = false;
699 }
700
701 if (mp->updating)
702 mp->shadow_info_dirty = true;
703 }
704 }
705}
706
707static void dss_write_regs(void) 691static void dss_write_regs(void)
708{ 692{
709 const int num_mgrs = omap_dss_get_num_overlay_managers(); 693 const int num_mgrs = omap_dss_get_num_overlay_managers();
710 int i; 694 int i;
711 695
712 dss_write_regs_common();
713
714 for (i = 0; i < num_mgrs; ++i) { 696 for (i = 0; i < num_mgrs; ++i) {
715 struct omap_overlay_manager *mgr; 697 struct omap_overlay_manager *mgr;
716 struct mgr_priv_data *mp; 698 struct mgr_priv_data *mp;
@@ -799,8 +781,6 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
799 dss_mgr_write_regs(mgr); 781 dss_mgr_write_regs(mgr);
800 dss_mgr_write_regs_extra(mgr); 782 dss_mgr_write_regs_extra(mgr);
801 783
802 dss_write_regs_common();
803
804 mp->updating = true; 784 mp->updating = true;
805 785
806 if (!dss_data.irq_enabled && need_isr()) 786 if (!dss_data.irq_enabled && need_isr())
@@ -984,20 +964,11 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
984 op->extra_info_dirty = true; 964 op->extra_info_dirty = true;
985} 965}
986 966
987static void dss_apply_fifo_merge(bool use_fifo_merge) 967static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
988{
989 if (dss_data.fifo_merge == use_fifo_merge)
990 return;
991
992 dss_data.fifo_merge = use_fifo_merge;
993 dss_data.fifo_merge_dirty = true;
994}
995
996static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
997 bool use_fifo_merge)
998{ 968{
999 struct ovl_priv_data *op = get_ovl_priv(ovl); 969 struct ovl_priv_data *op = get_ovl_priv(ovl);
1000 u32 fifo_low, fifo_high; 970 u32 fifo_low, fifo_high;
971 bool use_fifo_merge = false;
1001 972
1002 if (!op->enabled && !op->enabling) 973 if (!op->enabled && !op->enabling)
1003 return; 974 return;
@@ -1008,8 +979,7 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
1008 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); 979 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
1009} 980}
1010 981
1011static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr, 982static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
1012 bool use_fifo_merge)
1013{ 983{
1014 struct omap_overlay *ovl; 984 struct omap_overlay *ovl;
1015 struct mgr_priv_data *mp; 985 struct mgr_priv_data *mp;
@@ -1020,94 +990,19 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
1020 return; 990 return;
1021 991
1022 list_for_each_entry(ovl, &mgr->overlays, list) 992 list_for_each_entry(ovl, &mgr->overlays, list)
1023 dss_ovl_setup_fifo(ovl, use_fifo_merge); 993 dss_ovl_setup_fifo(ovl);
1024}
1025
1026static void dss_setup_fifos(bool use_fifo_merge)
1027{
1028 const int num_mgrs = omap_dss_get_num_overlay_managers();
1029 struct omap_overlay_manager *mgr;
1030 int i;
1031
1032 for (i = 0; i < num_mgrs; ++i) {
1033 mgr = omap_dss_get_overlay_manager(i);
1034 dss_mgr_setup_fifos(mgr, use_fifo_merge);
1035 }
1036} 994}
1037 995
1038static int get_num_used_managers(void) 996static void dss_setup_fifos(void)
1039{ 997{
1040 const int num_mgrs = omap_dss_get_num_overlay_managers(); 998 const int num_mgrs = omap_dss_get_num_overlay_managers();
1041 struct omap_overlay_manager *mgr; 999 struct omap_overlay_manager *mgr;
1042 struct mgr_priv_data *mp;
1043 int i; 1000 int i;
1044 int enabled_mgrs;
1045
1046 enabled_mgrs = 0;
1047 1001
1048 for (i = 0; i < num_mgrs; ++i) { 1002 for (i = 0; i < num_mgrs; ++i) {
1049 mgr = omap_dss_get_overlay_manager(i); 1003 mgr = omap_dss_get_overlay_manager(i);
1050 mp = get_mgr_priv(mgr); 1004 dss_mgr_setup_fifos(mgr);
1051
1052 if (!mp->enabled)
1053 continue;
1054
1055 enabled_mgrs++;
1056 } 1005 }
1057
1058 return enabled_mgrs;
1059}
1060
1061static int get_num_used_overlays(void)
1062{
1063 const int num_ovls = omap_dss_get_num_overlays();
1064 struct omap_overlay *ovl;
1065 struct ovl_priv_data *op;
1066 struct mgr_priv_data *mp;
1067 int i;
1068 int enabled_ovls;
1069
1070 enabled_ovls = 0;
1071
1072 for (i = 0; i < num_ovls; ++i) {
1073 ovl = omap_dss_get_overlay(i);
1074 op = get_ovl_priv(ovl);
1075
1076 if (!op->enabled && !op->enabling)
1077 continue;
1078
1079 mp = get_mgr_priv(ovl->manager);
1080
1081 if (!mp->enabled)
1082 continue;
1083
1084 enabled_ovls++;
1085 }
1086
1087 return enabled_ovls;
1088}
1089
1090static bool get_use_fifo_merge(void)
1091{
1092 int enabled_mgrs = get_num_used_managers();
1093 int enabled_ovls = get_num_used_overlays();
1094
1095 if (!dss_has_feature(FEAT_FIFO_MERGE))
1096 return false;
1097
1098 /*
1099 * In theory the only requirement for fifomerge is enabled_ovls <= 1.
1100 * However, if we have two managers enabled and set/unset the fifomerge,
1101 * we need to set the GO bits in particular sequence for the managers,
1102 * and wait in between.
1103 *
1104 * This is rather difficult as new apply calls can happen at any time,
1105 * so we simplify the problem by requiring also that enabled_mgrs <= 1.
1106 * In practice this shouldn't matter, because when only one overlay is
1107 * enabled, most likely only one output is enabled.
1108 */
1109
1110 return enabled_mgrs <= 1 && enabled_ovls <= 1;
1111} 1006}
1112 1007
1113int dss_mgr_enable(struct omap_overlay_manager *mgr) 1008int dss_mgr_enable(struct omap_overlay_manager *mgr)
@@ -1115,7 +1010,6 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
1115 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1010 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1116 unsigned long flags; 1011 unsigned long flags;
1117 int r; 1012 int r;
1118 bool fifo_merge;
1119 1013
1120 mutex_lock(&apply_lock); 1014 mutex_lock(&apply_lock);
1121 1015
@@ -1133,23 +1027,11 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
1133 goto err; 1027 goto err;
1134 } 1028 }
1135 1029
1136 /* step 1: setup fifos/fifomerge before enabling the manager */ 1030 dss_setup_fifos();
1137
1138 fifo_merge = get_use_fifo_merge();
1139 dss_setup_fifos(fifo_merge);
1140 dss_apply_fifo_merge(fifo_merge);
1141 1031
1142 dss_write_regs(); 1032 dss_write_regs();
1143 dss_set_go_bits(); 1033 dss_set_go_bits();
1144 1034
1145 spin_unlock_irqrestore(&data_lock, flags);
1146
1147 /* wait until fifo config is in */
1148 wait_pending_extra_info_updates();
1149
1150 /* step 2: enable the manager */
1151 spin_lock_irqsave(&data_lock, flags);
1152
1153 if (!mgr_manual_update(mgr)) 1035 if (!mgr_manual_update(mgr))
1154 mp->updating = true; 1036 mp->updating = true;
1155 1037
@@ -1174,7 +1056,6 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1174{ 1056{
1175 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1057 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1176 unsigned long flags; 1058 unsigned long flags;
1177 bool fifo_merge;
1178 1059
1179 mutex_lock(&apply_lock); 1060 mutex_lock(&apply_lock);
1180 1061
@@ -1189,16 +1070,8 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1189 mp->updating = false; 1070 mp->updating = false;
1190 mp->enabled = false; 1071 mp->enabled = false;
1191 1072
1192 fifo_merge = get_use_fifo_merge();
1193 dss_setup_fifos(fifo_merge);
1194 dss_apply_fifo_merge(fifo_merge);
1195
1196 dss_write_regs();
1197 dss_set_go_bits();
1198
1199 spin_unlock_irqrestore(&data_lock, flags); 1073 spin_unlock_irqrestore(&data_lock, flags);
1200 1074
1201 wait_pending_extra_info_updates();
1202out: 1075out:
1203 mutex_unlock(&apply_lock); 1076 mutex_unlock(&apply_lock);
1204} 1077}
@@ -1237,29 +1110,29 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1237 spin_unlock_irqrestore(&data_lock, flags); 1110 spin_unlock_irqrestore(&data_lock, flags);
1238} 1111}
1239 1112
1240int dss_mgr_set_device(struct omap_overlay_manager *mgr, 1113int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1241 struct omap_dss_device *dssdev) 1114 struct omap_dss_output *output)
1242{ 1115{
1243 int r; 1116 int r;
1244 1117
1245 mutex_lock(&apply_lock); 1118 mutex_lock(&apply_lock);
1246 1119
1247 if (dssdev->manager) { 1120 if (mgr->output) {
1248 DSSERR("display '%s' already has a manager '%s'\n", 1121 DSSERR("manager %s is already connected to an output\n",
1249 dssdev->name, dssdev->manager->name); 1122 mgr->name);
1250 r = -EINVAL; 1123 r = -EINVAL;
1251 goto err; 1124 goto err;
1252 } 1125 }
1253 1126
1254 if ((mgr->supported_displays & dssdev->type) == 0) { 1127 if ((mgr->supported_outputs & output->id) == 0) {
1255 DSSERR("display '%s' does not support manager '%s'\n", 1128 DSSERR("output does not support manager %s\n",
1256 dssdev->name, mgr->name); 1129 mgr->name);
1257 r = -EINVAL; 1130 r = -EINVAL;
1258 goto err; 1131 goto err;
1259 } 1132 }
1260 1133
1261 dssdev->manager = mgr; 1134 output->manager = mgr;
1262 mgr->device = dssdev; 1135 mgr->output = output;
1263 1136
1264 mutex_unlock(&apply_lock); 1137 mutex_unlock(&apply_lock);
1265 1138
@@ -1269,40 +1142,46 @@ err:
1269 return r; 1142 return r;
1270} 1143}
1271 1144
1272int dss_mgr_unset_device(struct omap_overlay_manager *mgr) 1145int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1273{ 1146{
1274 int r; 1147 int r;
1148 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1149 unsigned long flags;
1275 1150
1276 mutex_lock(&apply_lock); 1151 mutex_lock(&apply_lock);
1277 1152
1278 if (!mgr->device) { 1153 if (!mgr->output) {
1279 DSSERR("failed to unset display, display not set.\n"); 1154 DSSERR("failed to unset output, output not set\n");
1280 r = -EINVAL; 1155 r = -EINVAL;
1281 goto err; 1156 goto err;
1282 } 1157 }
1283 1158
1284 /* 1159 spin_lock_irqsave(&data_lock, flags);
1285 * Don't allow currently enabled displays to have the overlay manager 1160
1286 * pulled out from underneath them 1161 if (mp->enabled) {
1287 */ 1162 DSSERR("output can't be unset when manager is enabled\n");
1288 if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) {
1289 r = -EINVAL; 1163 r = -EINVAL;
1290 goto err; 1164 goto err1;
1291 } 1165 }
1292 1166
1293 mgr->device->manager = NULL; 1167 spin_unlock_irqrestore(&data_lock, flags);
1294 mgr->device = NULL; 1168
1169 mgr->output->manager = NULL;
1170 mgr->output = NULL;
1295 1171
1296 mutex_unlock(&apply_lock); 1172 mutex_unlock(&apply_lock);
1297 1173
1298 return 0; 1174 return 0;
1175err1:
1176 spin_unlock_irqrestore(&data_lock, flags);
1299err: 1177err:
1300 mutex_unlock(&apply_lock); 1178 mutex_unlock(&apply_lock);
1179
1301 return r; 1180 return r;
1302} 1181}
1303 1182
1304static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, 1183static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1305 struct omap_video_timings *timings) 1184 const struct omap_video_timings *timings)
1306{ 1185{
1307 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1186 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1308 1187
@@ -1311,24 +1190,22 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1311} 1190}
1312 1191
1313void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 1192void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
1314 struct omap_video_timings *timings) 1193 const struct omap_video_timings *timings)
1315{ 1194{
1316 unsigned long flags; 1195 unsigned long flags;
1317 1196 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1318 mutex_lock(&apply_lock);
1319 1197
1320 spin_lock_irqsave(&data_lock, flags); 1198 spin_lock_irqsave(&data_lock, flags);
1321 1199
1322 dss_apply_mgr_timings(mgr, timings); 1200 if (mp->updating) {
1323 1201 DSSERR("cannot set timings for %s: manager needs to be disabled\n",
1324 dss_write_regs(); 1202 mgr->name);
1325 dss_set_go_bits(); 1203 goto out;
1204 }
1326 1205
1206 dss_apply_mgr_timings(mgr, timings);
1207out:
1327 spin_unlock_irqrestore(&data_lock, flags); 1208 spin_unlock_irqrestore(&data_lock, flags);
1328
1329 wait_pending_extra_info_updates();
1330
1331 mutex_unlock(&apply_lock);
1332} 1209}
1333 1210
1334static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr, 1211static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
@@ -1346,7 +1223,7 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
1346 unsigned long flags; 1223 unsigned long flags;
1347 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1224 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1348 1225
1349 mutex_lock(&apply_lock); 1226 spin_lock_irqsave(&data_lock, flags);
1350 1227
1351 if (mp->enabled) { 1228 if (mp->enabled) {
1352 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n", 1229 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
@@ -1354,19 +1231,9 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
1354 goto out; 1231 goto out;
1355 } 1232 }
1356 1233
1357 spin_lock_irqsave(&data_lock, flags);
1358
1359 dss_apply_mgr_lcd_config(mgr, config); 1234 dss_apply_mgr_lcd_config(mgr, config);
1360
1361 dss_write_regs();
1362 dss_set_go_bits();
1363
1364 spin_unlock_irqrestore(&data_lock, flags);
1365
1366 wait_pending_extra_info_updates();
1367
1368out: 1235out:
1369 mutex_unlock(&apply_lock); 1236 spin_unlock_irqrestore(&data_lock, flags);
1370} 1237}
1371 1238
1372int dss_ovl_set_info(struct omap_overlay *ovl, 1239int dss_ovl_set_info(struct omap_overlay *ovl,
@@ -1483,6 +1350,13 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
1483 goto err; 1350 goto err;
1484 } 1351 }
1485 1352
1353 spin_unlock_irqrestore(&data_lock, flags);
1354
1355 /* wait for pending extra_info updates to ensure the ovl is disabled */
1356 wait_pending_extra_info_updates();
1357
1358 spin_lock_irqsave(&data_lock, flags);
1359
1486 op->channel = -1; 1360 op->channel = -1;
1487 1361
1488 ovl->manager = NULL; 1362 ovl->manager = NULL;
@@ -1517,7 +1391,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1517{ 1391{
1518 struct ovl_priv_data *op = get_ovl_priv(ovl); 1392 struct ovl_priv_data *op = get_ovl_priv(ovl);
1519 unsigned long flags; 1393 unsigned long flags;
1520 bool fifo_merge;
1521 int r; 1394 int r;
1522 1395
1523 mutex_lock(&apply_lock); 1396 mutex_lock(&apply_lock);
@@ -1527,7 +1400,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1527 goto err1; 1400 goto err1;
1528 } 1401 }
1529 1402
1530 if (ovl->manager == NULL || ovl->manager->device == NULL) { 1403 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1531 r = -EINVAL; 1404 r = -EINVAL;
1532 goto err1; 1405 goto err1;
1533 } 1406 }
@@ -1543,22 +1416,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1543 goto err2; 1416 goto err2;
1544 } 1417 }
1545 1418
1546 /* step 1: configure fifos/fifomerge for currently enabled ovls */ 1419 dss_setup_fifos();
1547
1548 fifo_merge = get_use_fifo_merge();
1549 dss_setup_fifos(fifo_merge);
1550 dss_apply_fifo_merge(fifo_merge);
1551
1552 dss_write_regs();
1553 dss_set_go_bits();
1554
1555 spin_unlock_irqrestore(&data_lock, flags);
1556
1557 /* wait for fifo configs to go in */
1558 wait_pending_extra_info_updates();
1559
1560 /* step 2: enable the overlay */
1561 spin_lock_irqsave(&data_lock, flags);
1562 1420
1563 op->enabling = false; 1421 op->enabling = false;
1564 dss_apply_ovl_enable(ovl, true); 1422 dss_apply_ovl_enable(ovl, true);
@@ -1568,9 +1426,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1568 1426
1569 spin_unlock_irqrestore(&data_lock, flags); 1427 spin_unlock_irqrestore(&data_lock, flags);
1570 1428
1571 /* wait for overlay to be enabled */
1572 wait_pending_extra_info_updates();
1573
1574 mutex_unlock(&apply_lock); 1429 mutex_unlock(&apply_lock);
1575 1430
1576 return 0; 1431 return 0;
@@ -1586,7 +1441,6 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1586{ 1441{
1587 struct ovl_priv_data *op = get_ovl_priv(ovl); 1442 struct ovl_priv_data *op = get_ovl_priv(ovl);
1588 unsigned long flags; 1443 unsigned long flags;
1589 bool fifo_merge;
1590 int r; 1444 int r;
1591 1445
1592 mutex_lock(&apply_lock); 1446 mutex_lock(&apply_lock);
@@ -1596,39 +1450,19 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1596 goto err; 1450 goto err;
1597 } 1451 }
1598 1452
1599 if (ovl->manager == NULL || ovl->manager->device == NULL) { 1453 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1600 r = -EINVAL; 1454 r = -EINVAL;
1601 goto err; 1455 goto err;
1602 } 1456 }
1603 1457
1604 /* step 1: disable the overlay */
1605 spin_lock_irqsave(&data_lock, flags); 1458 spin_lock_irqsave(&data_lock, flags);
1606 1459
1607 dss_apply_ovl_enable(ovl, false); 1460 dss_apply_ovl_enable(ovl, false);
1608
1609 dss_write_regs(); 1461 dss_write_regs();
1610 dss_set_go_bits(); 1462 dss_set_go_bits();
1611 1463
1612 spin_unlock_irqrestore(&data_lock, flags); 1464 spin_unlock_irqrestore(&data_lock, flags);
1613 1465
1614 /* wait for the overlay to be disabled */
1615 wait_pending_extra_info_updates();
1616
1617 /* step 2: configure fifos/fifomerge */
1618 spin_lock_irqsave(&data_lock, flags);
1619
1620 fifo_merge = get_use_fifo_merge();
1621 dss_setup_fifos(fifo_merge);
1622 dss_apply_fifo_merge(fifo_merge);
1623
1624 dss_write_regs();
1625 dss_set_go_bits();
1626
1627 spin_unlock_irqrestore(&data_lock, flags);
1628
1629 /* wait for fifo config to go in */
1630 wait_pending_extra_info_updates();
1631
1632 mutex_unlock(&apply_lock); 1466 mutex_unlock(&apply_lock);
1633 1467
1634 return 0; 1468 return 0;
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 58bd9c27369d..b2af72dc20bd 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -33,6 +33,7 @@
33#include <linux/device.h> 33#include <linux/device.h>
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35#include <linux/suspend.h> 35#include <linux/suspend.h>
36#include <linux/slab.h>
36 37
37#include <video/omapdss.h> 38#include <video/omapdss.h>
38 39
@@ -57,6 +58,11 @@ bool dss_debug;
57module_param_named(debug, dss_debug, bool, 0644); 58module_param_named(debug, dss_debug, bool, 0644);
58#endif 59#endif
59 60
61const char *dss_get_default_display_name(void)
62{
63 return core.default_display_name;
64}
65
60/* REGULATORS */ 66/* REGULATORS */
61 67
62struct regulator *dss_get_vdds_dsi(void) 68struct regulator *dss_get_vdds_dsi(void)
@@ -347,17 +353,14 @@ static int dss_driver_probe(struct device *dev)
347 int r; 353 int r;
348 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 354 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
349 struct omap_dss_device *dssdev = to_dss_device(dev); 355 struct omap_dss_device *dssdev = to_dss_device(dev);
350 bool force;
351 356
352 DSSDBG("driver_probe: dev %s/%s, drv %s\n", 357 DSSDBG("driver_probe: dev %s/%s, drv %s\n",
353 dev_name(dev), dssdev->driver_name, 358 dev_name(dev), dssdev->driver_name,
354 dssdrv->driver.name); 359 dssdrv->driver.name);
355 360
356 dss_init_device(core.pdev, dssdev); 361 r = dss_init_device(core.pdev, dssdev);
357 362 if (r)
358 force = core.default_display_name && 363 return r;
359 strcmp(core.default_display_name, dssdev->name) == 0;
360 dss_recheck_connections(dssdev, force);
361 364
362 r = dssdrv->probe(dssdev); 365 r = dssdrv->probe(dssdev);
363 366
@@ -416,54 +419,44 @@ void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
416EXPORT_SYMBOL(omap_dss_unregister_driver); 419EXPORT_SYMBOL(omap_dss_unregister_driver);
417 420
418/* DEVICE */ 421/* DEVICE */
419static void reset_device(struct device *dev, int check)
420{
421 u8 *dev_p = (u8 *)dev;
422 u8 *dev_end = dev_p + sizeof(*dev);
423 void *saved_pdata;
424
425 saved_pdata = dev->platform_data;
426 if (check) {
427 /*
428 * Check if there is any other setting than platform_data
429 * in struct device; warn that these will be reset by our
430 * init.
431 */
432 dev->platform_data = NULL;
433 while (dev_p < dev_end) {
434 if (*dev_p) {
435 WARN("%s: struct device fields will be "
436 "discarded\n",
437 __func__);
438 break;
439 }
440 dev_p++;
441 }
442 }
443 memset(dev, 0, sizeof(*dev));
444 dev->platform_data = saved_pdata;
445}
446
447 422
448static void omap_dss_dev_release(struct device *dev) 423static void omap_dss_dev_release(struct device *dev)
449{ 424{
450 reset_device(dev, 0); 425 struct omap_dss_device *dssdev = to_dss_device(dev);
426 kfree(dssdev);
451} 427}
452 428
453int omap_dss_register_device(struct omap_dss_device *dssdev, 429static int disp_num_counter;
454 struct device *parent, int disp_num) 430
431struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)
455{ 432{
456 WARN_ON(!dssdev->driver_name); 433 struct omap_dss_device *dssdev;
434
435 dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL);
436 if (!dssdev)
437 return NULL;
457 438
458 reset_device(&dssdev->dev, 1);
459 dssdev->dev.bus = &dss_bus_type; 439 dssdev->dev.bus = &dss_bus_type;
460 dssdev->dev.parent = parent; 440 dssdev->dev.parent = parent;
461 dssdev->dev.release = omap_dss_dev_release; 441 dssdev->dev.release = omap_dss_dev_release;
462 dev_set_name(&dssdev->dev, "display%d", disp_num); 442 dev_set_name(&dssdev->dev, "display%d", disp_num_counter++);
463 return device_register(&dssdev->dev); 443
444 device_initialize(&dssdev->dev);
445
446 return dssdev;
447}
448
449int dss_add_device(struct omap_dss_device *dssdev)
450{
451 return device_add(&dssdev->dev);
452}
453
454void dss_put_device(struct omap_dss_device *dssdev)
455{
456 put_device(&dssdev->dev);
464} 457}
465 458
466void omap_dss_unregister_device(struct omap_dss_device *dssdev) 459void dss_unregister_device(struct omap_dss_device *dssdev)
467{ 460{
468 device_unregister(&dssdev->dev); 461 device_unregister(&dssdev->dev);
469} 462}
@@ -471,15 +464,25 @@ void omap_dss_unregister_device(struct omap_dss_device *dssdev)
471static int dss_unregister_dss_dev(struct device *dev, void *data) 464static int dss_unregister_dss_dev(struct device *dev, void *data)
472{ 465{
473 struct omap_dss_device *dssdev = to_dss_device(dev); 466 struct omap_dss_device *dssdev = to_dss_device(dev);
474 omap_dss_unregister_device(dssdev); 467 dss_unregister_device(dssdev);
475 return 0; 468 return 0;
476} 469}
477 470
478void omap_dss_unregister_child_devices(struct device *parent) 471void dss_unregister_child_devices(struct device *parent)
479{ 472{
480 device_for_each_child(parent, NULL, dss_unregister_dss_dev); 473 device_for_each_child(parent, NULL, dss_unregister_dss_dev);
481} 474}
482 475
476void dss_copy_device_pdata(struct omap_dss_device *dst,
477 const struct omap_dss_device *src)
478{
479 u8 *d = (u8 *)dst;
480 u8 *s = (u8 *)src;
481 size_t dsize = sizeof(struct device);
482
483 memcpy(d + dsize, s + dsize, sizeof(struct omap_dss_device) - dsize);
484}
485
483/* BUS */ 486/* BUS */
484static int __init omap_dss_bus_register(void) 487static int __init omap_dss_bus_register(void)
485{ 488{
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 5b289c5f695b..a173a9481a23 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -37,8 +37,6 @@
37#include <linux/platform_device.h> 37#include <linux/platform_device.h>
38#include <linux/pm_runtime.h> 38#include <linux/pm_runtime.h>
39 39
40#include <plat/clock.h>
41
42#include <video/omapdss.h> 40#include <video/omapdss.h>
43 41
44#include "dss.h" 42#include "dss.h"
@@ -81,6 +79,30 @@ struct dispc_irq_stats {
81 unsigned irqs[32]; 79 unsigned irqs[32];
82}; 80};
83 81
82struct dispc_features {
83 u8 sw_start;
84 u8 fp_start;
85 u8 bp_start;
86 u16 sw_max;
87 u16 vp_max;
88 u16 hp_max;
89 int (*calc_scaling) (enum omap_plane plane,
90 const struct omap_video_timings *mgr_timings,
91 u16 width, u16 height, u16 out_width, u16 out_height,
92 enum omap_color_mode color_mode, bool *five_taps,
93 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
94 u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
95 unsigned long (*calc_core_clk) (enum omap_plane plane,
96 u16 width, u16 height, u16 out_width, u16 out_height,
97 bool mem_to_mem);
98 u8 num_fifos;
99
100 /* swap GFX & WB fifos */
101 bool gfx_fifo_workaround:1;
102};
103
104#define DISPC_MAX_NR_FIFOS 5
105
84static struct { 106static struct {
85 struct platform_device *pdev; 107 struct platform_device *pdev;
86 void __iomem *base; 108 void __iomem *base;
@@ -90,7 +112,9 @@ static struct {
90 int irq; 112 int irq;
91 struct clk *dss_clk; 113 struct clk *dss_clk;
92 114
93 u32 fifo_size[MAX_DSS_OVERLAYS]; 115 u32 fifo_size[DISPC_MAX_NR_FIFOS];
116 /* maps which plane is using a fifo. fifo-id -> plane-id */
117 int fifo_assignment[DISPC_MAX_NR_FIFOS];
94 118
95 spinlock_t irq_lock; 119 spinlock_t irq_lock;
96 u32 irq_error_mask; 120 u32 irq_error_mask;
@@ -101,6 +125,8 @@ static struct {
101 bool ctx_valid; 125 bool ctx_valid;
102 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 126 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
103 127
128 const struct dispc_features *feat;
129
104#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 130#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
105 spinlock_t irq_stats_lock; 131 spinlock_t irq_stats_lock;
106 struct dispc_irq_stats irq_stats; 132 struct dispc_irq_stats irq_stats;
@@ -210,7 +236,14 @@ static const struct {
210 }, 236 },
211}; 237};
212 238
239struct color_conv_coef {
240 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
241 int full_range;
242};
243
213static void _omap_dispc_set_irqs(void); 244static void _omap_dispc_set_irqs(void);
245static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
246static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
214 247
215static inline void dispc_write_reg(const u16 idx, u32 val) 248static inline void dispc_write_reg(const u16 idx, u32 val)
216{ 249{
@@ -508,6 +541,11 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
508 return mgr_desc[channel].framedone_irq; 541 return mgr_desc[channel].framedone_irq;
509} 542}
510 543
544u32 dispc_wb_get_framedone_irq(void)
545{
546 return DISPC_IRQ_FRAMEDONEWB;
547}
548
511bool dispc_mgr_go_busy(enum omap_channel channel) 549bool dispc_mgr_go_busy(enum omap_channel channel)
512{ 550{
513 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; 551 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
@@ -535,6 +573,30 @@ void dispc_mgr_go(enum omap_channel channel)
535 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); 573 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
536} 574}
537 575
576bool dispc_wb_go_busy(void)
577{
578 return REG_GET(DISPC_CONTROL2, 6, 6) == 1;
579}
580
581void dispc_wb_go(void)
582{
583 enum omap_plane plane = OMAP_DSS_WB;
584 bool enable, go;
585
586 enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
587
588 if (!enable)
589 return;
590
591 go = REG_GET(DISPC_CONTROL2, 6, 6) == 1;
592 if (go) {
593 DSSERR("GO bit not down for WB\n");
594 return;
595 }
596
597 REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6);
598}
599
538static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) 600static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
539{ 601{
540 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); 602 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
@@ -617,41 +679,41 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
617 } 679 }
618} 680}
619 681
620static void _dispc_setup_color_conv_coef(void)
621{
622 int i;
623 const struct color_conv_coef {
624 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
625 int full_range;
626 } ctbl_bt601_5 = {
627 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
628 };
629
630 const struct color_conv_coef *ct;
631 682
683static void dispc_ovl_write_color_conv_coef(enum omap_plane plane,
684 const struct color_conv_coef *ct)
685{
632#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) 686#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
633 687
634 ct = &ctbl_bt601_5; 688 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
689 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb));
690 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
691 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
692 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
635 693
636 for (i = 1; i < dss_feat_get_num_ovls(); i++) { 694 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
637 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0),
638 CVAL(ct->rcr, ct->ry));
639 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1),
640 CVAL(ct->gy, ct->rcb));
641 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2),
642 CVAL(ct->gcb, ct->gcr));
643 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3),
644 CVAL(ct->bcr, ct->by));
645 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4),
646 CVAL(0, ct->bcb));
647
648 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range,
649 11, 11);
650 }
651 695
652#undef CVAL 696#undef CVAL
653} 697}
654 698
699static void dispc_setup_color_conv_coef(void)
700{
701 int i;
702 int num_ovl = dss_feat_get_num_ovls();
703 int num_wb = dss_feat_get_num_wbs();
704 const struct color_conv_coef ctbl_bt601_5_ovl = {
705 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
706 };
707 const struct color_conv_coef ctbl_bt601_5_wb = {
708 66, 112, -38, 129, -94, -74, 25, -18, 112, 0,
709 };
710
711 for (i = 1; i < num_ovl; i++)
712 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl);
713
714 for (; i < num_wb; i++)
715 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb);
716}
655 717
656static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) 718static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
657{ 719{
@@ -673,24 +735,32 @@ static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
673 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); 735 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
674} 736}
675 737
676static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y) 738static void dispc_ovl_set_pos(enum omap_plane plane,
739 enum omap_overlay_caps caps, int x, int y)
677{ 740{
678 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); 741 u32 val;
742
743 if ((caps & OMAP_DSS_OVL_CAP_POS) == 0)
744 return;
745
746 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
679 747
680 dispc_write_reg(DISPC_OVL_POSITION(plane), val); 748 dispc_write_reg(DISPC_OVL_POSITION(plane), val);
681} 749}
682 750
683static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height) 751static void dispc_ovl_set_input_size(enum omap_plane plane, int width,
752 int height)
684{ 753{
685 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 754 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
686 755
687 if (plane == OMAP_DSS_GFX) 756 if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB)
688 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 757 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
689 else 758 else
690 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); 759 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
691} 760}
692 761
693static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) 762static void dispc_ovl_set_output_size(enum omap_plane plane, int width,
763 int height)
694{ 764{
695 u32 val; 765 u32 val;
696 766
@@ -698,14 +768,16 @@ static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
698 768
699 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 769 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
700 770
701 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 771 if (plane == OMAP_DSS_WB)
772 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
773 else
774 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
702} 775}
703 776
704static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) 777static void dispc_ovl_set_zorder(enum omap_plane plane,
778 enum omap_overlay_caps caps, u8 zorder)
705{ 779{
706 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 780 if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
707
708 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
709 return; 781 return;
710 782
711 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); 783 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
@@ -722,23 +794,22 @@ static void dispc_ovl_enable_zorder_planes(void)
722 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); 794 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
723} 795}
724 796
725static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) 797static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
798 enum omap_overlay_caps caps, bool enable)
726{ 799{
727 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 800 if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
728
729 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
730 return; 801 return;
731 802
732 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); 803 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
733} 804}
734 805
735static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha) 806static void dispc_ovl_setup_global_alpha(enum omap_plane plane,
807 enum omap_overlay_caps caps, u8 global_alpha)
736{ 808{
737 static const unsigned shifts[] = { 0, 8, 16, 24, }; 809 static const unsigned shifts[] = { 0, 8, 16, 24, };
738 int shift; 810 int shift;
739 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
740 811
741 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) 812 if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
742 return; 813 return;
743 814
744 shift = shifts[plane]; 815 shift = shifts[plane];
@@ -946,10 +1017,17 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
946 return channel; 1017 return channel;
947} 1018}
948 1019
1020void dispc_wb_set_channel_in(enum dss_writeback_channel channel)
1021{
1022 enum omap_plane plane = OMAP_DSS_WB;
1023
1024 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16);
1025}
1026
949static void dispc_ovl_set_burst_size(enum omap_plane plane, 1027static void dispc_ovl_set_burst_size(enum omap_plane plane,
950 enum omap_burst_size burst_size) 1028 enum omap_burst_size burst_size)
951{ 1029{
952 static const unsigned shifts[] = { 6, 14, 14, 14, }; 1030 static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
953 int shift; 1031 int shift;
954 1032
955 shift = shifts[plane]; 1033 shift = shifts[plane];
@@ -1026,11 +1104,15 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
1026 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 1104 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1027} 1105}
1028 1106
1029static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) 1107static void dispc_ovl_enable_replication(enum omap_plane plane,
1108 enum omap_overlay_caps caps, bool enable)
1030{ 1109{
1031 static const unsigned shifts[] = { 5, 10, 10, 10 }; 1110 static const unsigned shifts[] = { 5, 10, 10, 10 };
1032 int shift; 1111 int shift;
1033 1112
1113 if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0)
1114 return;
1115
1034 shift = shifts[plane]; 1116 shift = shifts[plane];
1035 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); 1117 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1036} 1118}
@@ -1044,10 +1126,10 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
1044 dispc_write_reg(DISPC_SIZE_MGR(channel), val); 1126 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
1045} 1127}
1046 1128
1047static void dispc_read_plane_fifo_sizes(void) 1129static void dispc_init_fifos(void)
1048{ 1130{
1049 u32 size; 1131 u32 size;
1050 int plane; 1132 int fifo;
1051 u8 start, end; 1133 u8 start, end;
1052 u32 unit; 1134 u32 unit;
1053 1135
@@ -1055,16 +1137,53 @@ static void dispc_read_plane_fifo_sizes(void)
1055 1137
1056 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); 1138 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
1057 1139
1058 for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) { 1140 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
1059 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end); 1141 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);
1060 size *= unit; 1142 size *= unit;
1061 dispc.fifo_size[plane] = size; 1143 dispc.fifo_size[fifo] = size;
1144
1145 /*
1146 * By default fifos are mapped directly to overlays, fifo 0 to
1147 * ovl 0, fifo 1 to ovl 1, etc.
1148 */
1149 dispc.fifo_assignment[fifo] = fifo;
1150 }
1151
1152 /*
1153 * The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo
1154 * causes problems with certain use cases, like using the tiler in 2D
1155 * mode. The below hack swaps the fifos of GFX and WB planes, thus
1156 * giving GFX plane a larger fifo. WB but should work fine with a
1157 * smaller fifo.
1158 */
1159 if (dispc.feat->gfx_fifo_workaround) {
1160 u32 v;
1161
1162 v = dispc_read_reg(DISPC_GLOBAL_BUFFER);
1163
1164 v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */
1165 v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */
1166 v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */
1167 v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */
1168
1169 dispc_write_reg(DISPC_GLOBAL_BUFFER, v);
1170
1171 dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
1172 dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
1062 } 1173 }
1063} 1174}
1064 1175
1065static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) 1176static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
1066{ 1177{
1067 return dispc.fifo_size[plane]; 1178 int fifo;
1179 u32 size = 0;
1180
1181 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
1182 if (dispc.fifo_assignment[fifo] == plane)
1183 size += dispc.fifo_size[fifo];
1184 }
1185
1186 return size;
1068} 1187}
1069 1188
1070void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) 1189void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
@@ -1140,6 +1259,14 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
1140 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { 1259 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
1141 *fifo_low = ovl_fifo_size - burst_size * 2; 1260 *fifo_low = ovl_fifo_size - burst_size * 2;
1142 *fifo_high = total_fifo_size - burst_size; 1261 *fifo_high = total_fifo_size - burst_size;
1262 } else if (plane == OMAP_DSS_WB) {
1263 /*
1264 * Most optimal configuration for writeback is to push out data
1265 * to the interconnect the moment writeback pushes enough pixels
1266 * in the FIFO to form a burst
1267 */
1268 *fifo_low = 0;
1269 *fifo_high = burst_size;
1143 } else { 1270 } else {
1144 *fifo_low = ovl_fifo_size - burst_size; 1271 *fifo_low = ovl_fifo_size - burst_size;
1145 *fifo_high = total_fifo_size - buf_unit; 1272 *fifo_high = total_fifo_size - buf_unit;
@@ -1382,6 +1509,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1382{ 1509{
1383 int scale_x = out_width != orig_width; 1510 int scale_x = out_width != orig_width;
1384 int scale_y = out_height != orig_height; 1511 int scale_y = out_height != orig_height;
1512 bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
1385 1513
1386 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) 1514 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
1387 return; 1515 return;
@@ -1389,7 +1517,8 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1389 color_mode != OMAP_DSS_COLOR_UYVY && 1517 color_mode != OMAP_DSS_COLOR_UYVY &&
1390 color_mode != OMAP_DSS_COLOR_NV12)) { 1518 color_mode != OMAP_DSS_COLOR_NV12)) {
1391 /* reset chroma resampling for RGB formats */ 1519 /* reset chroma resampling for RGB formats */
1392 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); 1520 if (plane != OMAP_DSS_WB)
1521 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1393 return; 1522 return;
1394 } 1523 }
1395 1524
@@ -1398,23 +1527,34 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1398 1527
1399 switch (color_mode) { 1528 switch (color_mode) {
1400 case OMAP_DSS_COLOR_NV12: 1529 case OMAP_DSS_COLOR_NV12:
1401 /* UV is subsampled by 2 vertically*/ 1530 if (chroma_upscale) {
1402 orig_height >>= 1; 1531 /* UV is subsampled by 2 horizontally and vertically */
1403 /* UV is subsampled by 2 horz.*/ 1532 orig_height >>= 1;
1404 orig_width >>= 1; 1533 orig_width >>= 1;
1534 } else {
1535 /* UV is downsampled by 2 horizontally and vertically */
1536 orig_height <<= 1;
1537 orig_width <<= 1;
1538 }
1539
1405 break; 1540 break;
1406 case OMAP_DSS_COLOR_YUV2: 1541 case OMAP_DSS_COLOR_YUV2:
1407 case OMAP_DSS_COLOR_UYVY: 1542 case OMAP_DSS_COLOR_UYVY:
1408 /*For YUV422 with 90/270 rotation, 1543 /* For YUV422 with 90/270 rotation, we don't upsample chroma */
1409 *we don't upsample chroma
1410 */
1411 if (rotation == OMAP_DSS_ROT_0 || 1544 if (rotation == OMAP_DSS_ROT_0 ||
1412 rotation == OMAP_DSS_ROT_180) 1545 rotation == OMAP_DSS_ROT_180) {
1413 /* UV is subsampled by 2 hrz*/ 1546 if (chroma_upscale)
1414 orig_width >>= 1; 1547 /* UV is subsampled by 2 horizontally */
1548 orig_width >>= 1;
1549 else
1550 /* UV is downsampled by 2 horizontally */
1551 orig_width <<= 1;
1552 }
1553
1415 /* must use FIR for YUV422 if rotated */ 1554 /* must use FIR for YUV422 if rotated */
1416 if (rotation != OMAP_DSS_ROT_0) 1555 if (rotation != OMAP_DSS_ROT_0)
1417 scale_x = scale_y = true; 1556 scale_x = scale_y = true;
1557
1418 break; 1558 break;
1419 default: 1559 default:
1420 BUG(); 1560 BUG();
@@ -1430,8 +1570,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1430 out_width, out_height, five_taps, 1570 out_width, out_height, five_taps,
1431 rotation, DISPC_COLOR_COMPONENT_UV); 1571 rotation, DISPC_COLOR_COMPONENT_UV);
1432 1572
1433 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 1573 if (plane != OMAP_DSS_WB)
1434 (scale_x || scale_y) ? 1 : 0, 8, 8); 1574 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
1575 (scale_x || scale_y) ? 1 : 0, 8, 8);
1576
1435 /* set H scaling */ 1577 /* set H scaling */
1436 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); 1578 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1437 /* set V scaling */ 1579 /* set V scaling */
@@ -1847,22 +1989,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1847 * This function is used to avoid synclosts in OMAP3, because of some 1989 * This function is used to avoid synclosts in OMAP3, because of some
1848 * undocumented horizontal position and timing related limitations. 1990 * undocumented horizontal position and timing related limitations.
1849 */ 1991 */
1850static int check_horiz_timing_omap3(enum omap_channel channel, 1992static int check_horiz_timing_omap3(enum omap_plane plane,
1851 const struct omap_video_timings *t, u16 pos_x, 1993 const struct omap_video_timings *t, u16 pos_x,
1852 u16 width, u16 height, u16 out_width, u16 out_height) 1994 u16 width, u16 height, u16 out_width, u16 out_height)
1853{ 1995{
1854 int DS = DIV_ROUND_UP(height, out_height); 1996 int DS = DIV_ROUND_UP(height, out_height);
1855 unsigned long nonactive, lclk, pclk; 1997 unsigned long nonactive;
1856 static const u8 limits[3] = { 8, 10, 20 }; 1998 static const u8 limits[3] = { 8, 10, 20 };
1857 u64 val, blank; 1999 u64 val, blank;
2000 unsigned long pclk = dispc_plane_pclk_rate(plane);
2001 unsigned long lclk = dispc_plane_lclk_rate(plane);
1858 int i; 2002 int i;
1859 2003
1860 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; 2004 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
1861 pclk = dispc_mgr_pclk_rate(channel);
1862 if (dss_mgr_is_lcd(channel))
1863 lclk = dispc_mgr_lclk_rate(channel);
1864 else
1865 lclk = dispc_fclk_rate();
1866 2005
1867 i = 0; 2006 i = 0;
1868 if (out_height < height) 2007 if (out_height < height)
@@ -1899,13 +2038,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel,
1899 return 0; 2038 return 0;
1900} 2039}
1901 2040
1902static unsigned long calc_core_clk_five_taps(enum omap_channel channel, 2041static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
1903 const struct omap_video_timings *mgr_timings, u16 width, 2042 const struct omap_video_timings *mgr_timings, u16 width,
1904 u16 height, u16 out_width, u16 out_height, 2043 u16 height, u16 out_width, u16 out_height,
1905 enum omap_color_mode color_mode) 2044 enum omap_color_mode color_mode)
1906{ 2045{
1907 u32 core_clk = 0; 2046 u32 core_clk = 0;
1908 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 2047 u64 tmp;
2048 unsigned long pclk = dispc_plane_pclk_rate(plane);
1909 2049
1910 if (height <= out_height && width <= out_width) 2050 if (height <= out_height && width <= out_width)
1911 return (unsigned long) pclk; 2051 return (unsigned long) pclk;
@@ -1939,11 +2079,22 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
1939 return core_clk; 2079 return core_clk;
1940} 2080}
1941 2081
1942static unsigned long calc_core_clk(enum omap_channel channel, u16 width, 2082static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
1943 u16 height, u16 out_width, u16 out_height) 2083 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2084{
2085 unsigned long pclk = dispc_plane_pclk_rate(plane);
2086
2087 if (height > out_height && width > out_width)
2088 return pclk * 4;
2089 else
2090 return pclk * 2;
2091}
2092
2093static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
2094 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
1944{ 2095{
1945 unsigned int hf, vf; 2096 unsigned int hf, vf;
1946 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2097 unsigned long pclk = dispc_plane_pclk_rate(plane);
1947 2098
1948 /* 2099 /*
1949 * FIXME how to determine the 'A' factor 2100 * FIXME how to determine the 'A' factor
@@ -1958,51 +2109,207 @@ static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
1958 hf = 2; 2109 hf = 2;
1959 else 2110 else
1960 hf = 1; 2111 hf = 1;
1961
1962 if (height > out_height) 2112 if (height > out_height)
1963 vf = 2; 2113 vf = 2;
1964 else 2114 else
1965 vf = 1; 2115 vf = 1;
1966 2116
1967 if (cpu_is_omap24xx()) { 2117 return pclk * vf * hf;
1968 if (vf > 1 && hf > 1) 2118}
1969 return pclk * 4; 2119
1970 else 2120static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
1971 return pclk * 2; 2121 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
1972 } else if (cpu_is_omap34xx()) { 2122{
1973 return pclk * vf * hf; 2123 unsigned long pclk;
1974 } else { 2124
1975 if (hf > 1) 2125 /*
1976 return DIV_ROUND_UP(pclk, out_width) * width; 2126 * If the overlay/writeback is in mem to mem mode, there are no
1977 else 2127 * downscaling limitations with respect to pixel clock, return 1 as
1978 return pclk; 2128 * required core clock to represent that we have sufficient enough
2129 * core clock to do maximum downscaling
2130 */
2131 if (mem_to_mem)
2132 return 1;
2133
2134 pclk = dispc_plane_pclk_rate(plane);
2135
2136 if (width > out_width)
2137 return DIV_ROUND_UP(pclk, out_width) * width;
2138 else
2139 return pclk;
2140}
2141
2142static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
2143 const struct omap_video_timings *mgr_timings,
2144 u16 width, u16 height, u16 out_width, u16 out_height,
2145 enum omap_color_mode color_mode, bool *five_taps,
2146 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2147 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2148{
2149 int error;
2150 u16 in_width, in_height;
2151 int min_factor = min(*decim_x, *decim_y);
2152 const int maxsinglelinewidth =
2153 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2154
2155 *five_taps = false;
2156
2157 do {
2158 in_height = DIV_ROUND_UP(height, *decim_y);
2159 in_width = DIV_ROUND_UP(width, *decim_x);
2160 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2161 in_height, out_width, out_height, mem_to_mem);
2162 error = (in_width > maxsinglelinewidth || !*core_clk ||
2163 *core_clk > dispc_core_clk_rate());
2164 if (error) {
2165 if (*decim_x == *decim_y) {
2166 *decim_x = min_factor;
2167 ++*decim_y;
2168 } else {
2169 swap(*decim_x, *decim_y);
2170 if (*decim_x < *decim_y)
2171 ++*decim_x;
2172 }
2173 }
2174 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2175
2176 if (in_width > maxsinglelinewidth) {
2177 DSSERR("Cannot scale max input width exceeded");
2178 return -EINVAL;
1979 } 2179 }
2180 return 0;
1980} 2181}
1981 2182
1982static int dispc_ovl_calc_scaling(enum omap_plane plane, 2183static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
1983 enum omap_channel channel,
1984 const struct omap_video_timings *mgr_timings, 2184 const struct omap_video_timings *mgr_timings,
1985 u16 width, u16 height, u16 out_width, u16 out_height, 2185 u16 width, u16 height, u16 out_width, u16 out_height,
1986 enum omap_color_mode color_mode, bool *five_taps, 2186 enum omap_color_mode color_mode, bool *five_taps,
1987 int *x_predecim, int *y_predecim, u16 pos_x) 2187 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2188 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
1988{ 2189{
1989 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 2190 int error;
1990 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 2191 u16 in_width, in_height;
2192 int min_factor = min(*decim_x, *decim_y);
2193 const int maxsinglelinewidth =
2194 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2195
2196 do {
2197 in_height = DIV_ROUND_UP(height, *decim_y);
2198 in_width = DIV_ROUND_UP(width, *decim_x);
2199 *core_clk = calc_core_clk_five_taps(plane, mgr_timings,
2200 in_width, in_height, out_width, out_height, color_mode);
2201
2202 error = check_horiz_timing_omap3(plane, mgr_timings,
2203 pos_x, in_width, in_height, out_width,
2204 out_height);
2205
2206 if (in_width > maxsinglelinewidth)
2207 if (in_height > out_height &&
2208 in_height < out_height * 2)
2209 *five_taps = false;
2210 if (!*five_taps)
2211 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2212 in_height, out_width, out_height,
2213 mem_to_mem);
2214
2215 error = (error || in_width > maxsinglelinewidth * 2 ||
2216 (in_width > maxsinglelinewidth && *five_taps) ||
2217 !*core_clk || *core_clk > dispc_core_clk_rate());
2218 if (error) {
2219 if (*decim_x == *decim_y) {
2220 *decim_x = min_factor;
2221 ++*decim_y;
2222 } else {
2223 swap(*decim_x, *decim_y);
2224 if (*decim_x < *decim_y)
2225 ++*decim_x;
2226 }
2227 }
2228 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2229
2230 if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
2231 out_width, out_height)){
2232 DSSERR("horizontal timing too tight\n");
2233 return -EINVAL;
2234 }
2235
2236 if (in_width > (maxsinglelinewidth * 2)) {
2237 DSSERR("Cannot setup scaling");
2238 DSSERR("width exceeds maximum width possible");
2239 return -EINVAL;
2240 }
2241
2242 if (in_width > maxsinglelinewidth && *five_taps) {
2243 DSSERR("cannot setup scaling with five taps");
2244 return -EINVAL;
2245 }
2246 return 0;
2247}
2248
2249static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
2250 const struct omap_video_timings *mgr_timings,
2251 u16 width, u16 height, u16 out_width, u16 out_height,
2252 enum omap_color_mode color_mode, bool *five_taps,
2253 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2254 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2255{
2256 u16 in_width, in_width_max;
2257 int decim_x_min = *decim_x;
2258 u16 in_height = DIV_ROUND_UP(height, *decim_y);
1991 const int maxsinglelinewidth = 2259 const int maxsinglelinewidth =
1992 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2260 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2261 unsigned long pclk = dispc_plane_pclk_rate(plane);
2262 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2263
2264 if (mem_to_mem)
2265 in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
2266 else
2267 in_width_max = dispc_core_clk_rate() /
2268 DIV_ROUND_UP(pclk, out_width);
2269
2270 *decim_x = DIV_ROUND_UP(width, in_width_max);
2271
2272 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
2273 if (*decim_x > *x_predecim)
2274 return -EINVAL;
2275
2276 do {
2277 in_width = DIV_ROUND_UP(width, *decim_x);
2278 } while (*decim_x <= *x_predecim &&
2279 in_width > maxsinglelinewidth && ++*decim_x);
2280
2281 if (in_width > maxsinglelinewidth) {
2282 DSSERR("Cannot scale width exceeds max line width");
2283 return -EINVAL;
2284 }
2285
2286 *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
2287 out_width, out_height, mem_to_mem);
2288 return 0;
2289}
2290
2291static int dispc_ovl_calc_scaling(enum omap_plane plane,
2292 enum omap_overlay_caps caps,
2293 const struct omap_video_timings *mgr_timings,
2294 u16 width, u16 height, u16 out_width, u16 out_height,
2295 enum omap_color_mode color_mode, bool *five_taps,
2296 int *x_predecim, int *y_predecim, u16 pos_x,
2297 enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
2298{
2299 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
1993 const int max_decim_limit = 16; 2300 const int max_decim_limit = 16;
1994 unsigned long core_clk = 0; 2301 unsigned long core_clk = 0;
1995 int decim_x, decim_y, error, min_factor; 2302 int decim_x, decim_y, ret;
1996 u16 in_width, in_height, in_width_max = 0;
1997 2303
1998 if (width == out_width && height == out_height) 2304 if (width == out_width && height == out_height)
1999 return 0; 2305 return 0;
2000 2306
2001 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) 2307 if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
2002 return -EINVAL; 2308 return -EINVAL;
2003 2309
2004 *x_predecim = max_decim_limit; 2310 *x_predecim = max_decim_limit;
2005 *y_predecim = max_decim_limit; 2311 *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
2312 dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;
2006 2313
2007 if (color_mode == OMAP_DSS_COLOR_CLUT1 || 2314 if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
2008 color_mode == OMAP_DSS_COLOR_CLUT2 || 2315 color_mode == OMAP_DSS_COLOR_CLUT2 ||
@@ -2017,118 +2324,18 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2017 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); 2324 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
2018 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); 2325 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
2019 2326
2020 min_factor = min(decim_x, decim_y);
2021
2022 if (decim_x > *x_predecim || out_width > width * 8) 2327 if (decim_x > *x_predecim || out_width > width * 8)
2023 return -EINVAL; 2328 return -EINVAL;
2024 2329
2025 if (decim_y > *y_predecim || out_height > height * 8) 2330 if (decim_y > *y_predecim || out_height > height * 8)
2026 return -EINVAL; 2331 return -EINVAL;
2027 2332
2028 if (cpu_is_omap24xx()) { 2333 ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
2029 *five_taps = false; 2334 out_width, out_height, color_mode, five_taps,
2030 2335 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
2031 do { 2336 mem_to_mem);
2032 in_height = DIV_ROUND_UP(height, decim_y); 2337 if (ret)
2033 in_width = DIV_ROUND_UP(width, decim_x); 2338 return ret;
2034 core_clk = calc_core_clk(channel, in_width, in_height,
2035 out_width, out_height);
2036 error = (in_width > maxsinglelinewidth || !core_clk ||
2037 core_clk > dispc_core_clk_rate());
2038 if (error) {
2039 if (decim_x == decim_y) {
2040 decim_x = min_factor;
2041 decim_y++;
2042 } else {
2043 swap(decim_x, decim_y);
2044 if (decim_x < decim_y)
2045 decim_x++;
2046 }
2047 }
2048 } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
2049 error);
2050
2051 if (in_width > maxsinglelinewidth) {
2052 DSSERR("Cannot scale max input width exceeded");
2053 return -EINVAL;
2054 }
2055 } else if (cpu_is_omap34xx()) {
2056
2057 do {
2058 in_height = DIV_ROUND_UP(height, decim_y);
2059 in_width = DIV_ROUND_UP(width, decim_x);
2060 core_clk = calc_core_clk_five_taps(channel, mgr_timings,
2061 in_width, in_height, out_width, out_height,
2062 color_mode);
2063
2064 error = check_horiz_timing_omap3(channel, mgr_timings,
2065 pos_x, in_width, in_height, out_width,
2066 out_height);
2067
2068 if (in_width > maxsinglelinewidth)
2069 if (in_height > out_height &&
2070 in_height < out_height * 2)
2071 *five_taps = false;
2072 if (!*five_taps)
2073 core_clk = calc_core_clk(channel, in_width,
2074 in_height, out_width, out_height);
2075 error = (error || in_width > maxsinglelinewidth * 2 ||
2076 (in_width > maxsinglelinewidth && *five_taps) ||
2077 !core_clk || core_clk > dispc_core_clk_rate());
2078 if (error) {
2079 if (decim_x == decim_y) {
2080 decim_x = min_factor;
2081 decim_y++;
2082 } else {
2083 swap(decim_x, decim_y);
2084 if (decim_x < decim_y)
2085 decim_x++;
2086 }
2087 }
2088 } while (decim_x <= *x_predecim && decim_y <= *y_predecim
2089 && error);
2090
2091 if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width,
2092 height, out_width, out_height)){
2093 DSSERR("horizontal timing too tight\n");
2094 return -EINVAL;
2095 }
2096
2097 if (in_width > (maxsinglelinewidth * 2)) {
2098 DSSERR("Cannot setup scaling");
2099 DSSERR("width exceeds maximum width possible");
2100 return -EINVAL;
2101 }
2102
2103 if (in_width > maxsinglelinewidth && *five_taps) {
2104 DSSERR("cannot setup scaling with five taps");
2105 return -EINVAL;
2106 }
2107 } else {
2108 int decim_x_min = decim_x;
2109 in_height = DIV_ROUND_UP(height, decim_y);
2110 in_width_max = dispc_core_clk_rate() /
2111 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
2112 out_width);
2113 decim_x = DIV_ROUND_UP(width, in_width_max);
2114
2115 decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
2116 if (decim_x > *x_predecim)
2117 return -EINVAL;
2118
2119 do {
2120 in_width = DIV_ROUND_UP(width, decim_x);
2121 } while (decim_x <= *x_predecim &&
2122 in_width > maxsinglelinewidth && decim_x++);
2123
2124 if (in_width > maxsinglelinewidth) {
2125 DSSERR("Cannot scale width exceeds max line width");
2126 return -EINVAL;
2127 }
2128
2129 core_clk = calc_core_clk(channel, in_width, in_height,
2130 out_width, out_height);
2131 }
2132 2339
2133 DSSDBG("required core clk rate = %lu Hz\n", core_clk); 2340 DSSDBG("required core clk rate = %lu Hz\n", core_clk);
2134 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); 2341 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
@@ -2146,69 +2353,64 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2146 return 0; 2353 return 0;
2147} 2354}
2148 2355
2149int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 2356static int dispc_ovl_setup_common(enum omap_plane plane,
2150 bool replication, const struct omap_video_timings *mgr_timings) 2357 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2358 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
2359 u16 out_width, u16 out_height, enum omap_color_mode color_mode,
2360 u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
2361 u8 global_alpha, enum omap_dss_rotation_type rotation_type,
2362 bool replication, const struct omap_video_timings *mgr_timings,
2363 bool mem_to_mem)
2151{ 2364{
2152 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
2153 bool five_taps = true; 2365 bool five_taps = true;
2154 bool fieldmode = 0; 2366 bool fieldmode = 0;
2155 int r, cconv = 0; 2367 int r, cconv = 0;
2156 unsigned offset0, offset1; 2368 unsigned offset0, offset1;
2157 s32 row_inc; 2369 s32 row_inc;
2158 s32 pix_inc; 2370 s32 pix_inc;
2159 u16 frame_height = oi->height; 2371 u16 frame_height = height;
2160 unsigned int field_offset = 0; 2372 unsigned int field_offset = 0;
2161 u16 in_height = oi->height; 2373 u16 in_height = height;
2162 u16 in_width = oi->width; 2374 u16 in_width = width;
2163 u16 out_width, out_height;
2164 enum omap_channel channel;
2165 int x_predecim = 1, y_predecim = 1; 2375 int x_predecim = 1, y_predecim = 1;
2166 bool ilace = mgr_timings->interlace; 2376 bool ilace = mgr_timings->interlace;
2167 2377
2168 channel = dispc_ovl_get_channel_out(plane); 2378 if (paddr == 0)
2169
2170 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
2171 "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
2172 plane, oi->paddr, oi->p_uv_addr,
2173 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2174 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2175 oi->mirror, ilace, channel, replication);
2176
2177 if (oi->paddr == 0)
2178 return -EINVAL; 2379 return -EINVAL;
2179 2380
2180 out_width = oi->out_width == 0 ? oi->width : oi->out_width; 2381 out_width = out_width == 0 ? width : out_width;
2181 out_height = oi->out_height == 0 ? oi->height : oi->out_height; 2382 out_height = out_height == 0 ? height : out_height;
2182 2383
2183 if (ilace && oi->height == out_height) 2384 if (ilace && height == out_height)
2184 fieldmode = 1; 2385 fieldmode = 1;
2185 2386
2186 if (ilace) { 2387 if (ilace) {
2187 if (fieldmode) 2388 if (fieldmode)
2188 in_height /= 2; 2389 in_height /= 2;
2189 oi->pos_y /= 2; 2390 pos_y /= 2;
2190 out_height /= 2; 2391 out_height /= 2;
2191 2392
2192 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 2393 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
2193 "out_height %d\n", 2394 "out_height %d\n", in_height, pos_y,
2194 in_height, oi->pos_y, out_height); 2395 out_height);
2195 } 2396 }
2196 2397
2197 if (!dss_feat_color_mode_supported(plane, oi->color_mode)) 2398 if (!dss_feat_color_mode_supported(plane, color_mode))
2198 return -EINVAL; 2399 return -EINVAL;
2199 2400
2200 r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width, 2401 r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
2201 in_height, out_width, out_height, oi->color_mode, 2402 in_height, out_width, out_height, color_mode,
2202 &five_taps, &x_predecim, &y_predecim, oi->pos_x); 2403 &five_taps, &x_predecim, &y_predecim, pos_x,
2404 rotation_type, mem_to_mem);
2203 if (r) 2405 if (r)
2204 return r; 2406 return r;
2205 2407
2206 in_width = DIV_ROUND_UP(in_width, x_predecim); 2408 in_width = DIV_ROUND_UP(in_width, x_predecim);
2207 in_height = DIV_ROUND_UP(in_height, y_predecim); 2409 in_height = DIV_ROUND_UP(in_height, y_predecim);
2208 2410
2209 if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || 2411 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
2210 oi->color_mode == OMAP_DSS_COLOR_UYVY || 2412 color_mode == OMAP_DSS_COLOR_UYVY ||
2211 oi->color_mode == OMAP_DSS_COLOR_NV12) 2413 color_mode == OMAP_DSS_COLOR_NV12)
2212 cconv = 1; 2414 cconv = 1;
2213 2415
2214 if (ilace && !fieldmode) { 2416 if (ilace && !fieldmode) {
@@ -2234,70 +2436,144 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
2234 row_inc = 0; 2436 row_inc = 0;
2235 pix_inc = 0; 2437 pix_inc = 0;
2236 2438
2237 if (oi->rotation_type == OMAP_DSS_ROT_TILER) 2439 if (rotation_type == OMAP_DSS_ROT_TILER)
2238 calc_tiler_rotation_offset(oi->screen_width, in_width, 2440 calc_tiler_rotation_offset(screen_width, in_width,
2239 oi->color_mode, fieldmode, field_offset, 2441 color_mode, fieldmode, field_offset,
2240 &offset0, &offset1, &row_inc, &pix_inc, 2442 &offset0, &offset1, &row_inc, &pix_inc,
2241 x_predecim, y_predecim); 2443 x_predecim, y_predecim);
2242 else if (oi->rotation_type == OMAP_DSS_ROT_DMA) 2444 else if (rotation_type == OMAP_DSS_ROT_DMA)
2243 calc_dma_rotation_offset(oi->rotation, oi->mirror, 2445 calc_dma_rotation_offset(rotation, mirror,
2244 oi->screen_width, in_width, frame_height, 2446 screen_width, in_width, frame_height,
2245 oi->color_mode, fieldmode, field_offset, 2447 color_mode, fieldmode, field_offset,
2246 &offset0, &offset1, &row_inc, &pix_inc, 2448 &offset0, &offset1, &row_inc, &pix_inc,
2247 x_predecim, y_predecim); 2449 x_predecim, y_predecim);
2248 else 2450 else
2249 calc_vrfb_rotation_offset(oi->rotation, oi->mirror, 2451 calc_vrfb_rotation_offset(rotation, mirror,
2250 oi->screen_width, in_width, frame_height, 2452 screen_width, in_width, frame_height,
2251 oi->color_mode, fieldmode, field_offset, 2453 color_mode, fieldmode, field_offset,
2252 &offset0, &offset1, &row_inc, &pix_inc, 2454 &offset0, &offset1, &row_inc, &pix_inc,
2253 x_predecim, y_predecim); 2455 x_predecim, y_predecim);
2254 2456
2255 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", 2457 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
2256 offset0, offset1, row_inc, pix_inc); 2458 offset0, offset1, row_inc, pix_inc);
2257 2459
2258 dispc_ovl_set_color_mode(plane, oi->color_mode); 2460 dispc_ovl_set_color_mode(plane, color_mode);
2259 2461
2260 dispc_ovl_configure_burst_type(plane, oi->rotation_type); 2462 dispc_ovl_configure_burst_type(plane, rotation_type);
2261 2463
2262 dispc_ovl_set_ba0(plane, oi->paddr + offset0); 2464 dispc_ovl_set_ba0(plane, paddr + offset0);
2263 dispc_ovl_set_ba1(plane, oi->paddr + offset1); 2465 dispc_ovl_set_ba1(plane, paddr + offset1);
2264 2466
2265 if (OMAP_DSS_COLOR_NV12 == oi->color_mode) { 2467 if (OMAP_DSS_COLOR_NV12 == color_mode) {
2266 dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0); 2468 dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
2267 dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1); 2469 dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
2268 } 2470 }
2269 2471
2270
2271 dispc_ovl_set_row_inc(plane, row_inc); 2472 dispc_ovl_set_row_inc(plane, row_inc);
2272 dispc_ovl_set_pix_inc(plane, pix_inc); 2473 dispc_ovl_set_pix_inc(plane, pix_inc);
2273 2474
2274 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width, 2475 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width,
2275 in_height, out_width, out_height); 2476 in_height, out_width, out_height);
2276 2477
2277 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); 2478 dispc_ovl_set_pos(plane, caps, pos_x, pos_y);
2278 2479
2279 dispc_ovl_set_pic_size(plane, in_width, in_height); 2480 dispc_ovl_set_input_size(plane, in_width, in_height);
2280 2481
2281 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { 2482 if (caps & OMAP_DSS_OVL_CAP_SCALE) {
2282 dispc_ovl_set_scaling(plane, in_width, in_height, out_width, 2483 dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
2283 out_height, ilace, five_taps, fieldmode, 2484 out_height, ilace, five_taps, fieldmode,
2284 oi->color_mode, oi->rotation); 2485 color_mode, rotation);
2285 dispc_ovl_set_vid_size(plane, out_width, out_height); 2486 dispc_ovl_set_output_size(plane, out_width, out_height);
2286 dispc_ovl_set_vid_color_conv(plane, cconv); 2487 dispc_ovl_set_vid_color_conv(plane, cconv);
2287 } 2488 }
2288 2489
2289 dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror, 2490 dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode);
2290 oi->color_mode);
2291 2491
2292 dispc_ovl_set_zorder(plane, oi->zorder); 2492 dispc_ovl_set_zorder(plane, caps, zorder);
2293 dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); 2493 dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
2294 dispc_ovl_setup_global_alpha(plane, oi->global_alpha); 2494 dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
2295 2495
2296 dispc_ovl_enable_replication(plane, replication); 2496 dispc_ovl_enable_replication(plane, caps, replication);
2297 2497
2298 return 0; 2498 return 0;
2299} 2499}
2300 2500
2501int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2502 bool replication, const struct omap_video_timings *mgr_timings,
2503 bool mem_to_mem)
2504{
2505 int r;
2506 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
2507 enum omap_channel channel;
2508
2509 channel = dispc_ovl_get_channel_out(plane);
2510
2511 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
2512 "%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n",
2513 plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x,
2514 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2515 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2516
2517 r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
2518 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2519 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2520 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
2521 oi->rotation_type, replication, mgr_timings, mem_to_mem);
2522
2523 return r;
2524}
2525
2526int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
2527 bool mem_to_mem, const struct omap_video_timings *mgr_timings)
2528{
2529 int r;
2530 u32 l;
2531 enum omap_plane plane = OMAP_DSS_WB;
2532 const int pos_x = 0, pos_y = 0;
2533 const u8 zorder = 0, global_alpha = 0;
2534 const bool replication = false;
2535 bool truncation;
2536 int in_width = mgr_timings->x_res;
2537 int in_height = mgr_timings->y_res;
2538 enum omap_overlay_caps caps =
2539 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
2540
2541 DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
2542 "rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width,
2543 in_height, wi->width, wi->height, wi->color_mode, wi->rotation,
2544 wi->mirror);
2545
2546 r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr,
2547 wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
2548 wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
2549 wi->pre_mult_alpha, global_alpha, wi->rotation_type,
2550 replication, mgr_timings, mem_to_mem);
2551
2552 switch (wi->color_mode) {
2553 case OMAP_DSS_COLOR_RGB16:
2554 case OMAP_DSS_COLOR_RGB24P:
2555 case OMAP_DSS_COLOR_ARGB16:
2556 case OMAP_DSS_COLOR_RGBA16:
2557 case OMAP_DSS_COLOR_RGB12U:
2558 case OMAP_DSS_COLOR_ARGB16_1555:
2559 case OMAP_DSS_COLOR_XRGB16_1555:
2560 case OMAP_DSS_COLOR_RGBX16:
2561 truncation = true;
2562 break;
2563 default:
2564 truncation = false;
2565 break;
2566 }
2567
2568 /* setup extra DISPC_WB_ATTRIBUTES */
2569 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
2570 l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */
2571 l = FLD_MOD(l, mem_to_mem, 19, 19); /* WRITEBACKMODE */
2572 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
2573
2574 return r;
2575}
2576
2301int dispc_ovl_enable(enum omap_plane plane, bool enable) 2577int dispc_ovl_enable(enum omap_plane plane, bool enable)
2302{ 2578{
2303 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); 2579 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
@@ -2450,6 +2726,47 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable)
2450 BUG(); 2726 BUG();
2451} 2727}
2452 2728
2729void dispc_wb_enable(bool enable)
2730{
2731 enum omap_plane plane = OMAP_DSS_WB;
2732 struct completion frame_done_completion;
2733 bool is_on;
2734 int r;
2735 u32 irq;
2736
2737 is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2738 irq = DISPC_IRQ_FRAMEDONEWB;
2739
2740 if (!enable && is_on) {
2741 init_completion(&frame_done_completion);
2742
2743 r = omap_dispc_register_isr(dispc_disable_isr,
2744 &frame_done_completion, irq);
2745 if (r)
2746 DSSERR("failed to register FRAMEDONEWB isr\n");
2747 }
2748
2749 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2750
2751 if (!enable && is_on) {
2752 if (!wait_for_completion_timeout(&frame_done_completion,
2753 msecs_to_jiffies(100)))
2754 DSSERR("timeout waiting for FRAMEDONEWB\n");
2755
2756 r = omap_dispc_unregister_isr(dispc_disable_isr,
2757 &frame_done_completion, irq);
2758 if (r)
2759 DSSERR("failed to unregister FRAMEDONEWB isr\n");
2760 }
2761}
2762
2763bool dispc_wb_is_enabled(void)
2764{
2765 enum omap_plane plane = OMAP_DSS_WB;
2766
2767 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2768}
2769
2453void dispc_lcd_enable_signal_polarity(bool act_high) 2770void dispc_lcd_enable_signal_polarity(bool act_high)
2454{ 2771{
2455 if (!dss_has_feature(FEAT_LCDENABLEPOL)) 2772 if (!dss_has_feature(FEAT_LCDENABLEPOL))
@@ -2604,24 +2921,13 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height)
2604static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2921static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2605 int vsw, int vfp, int vbp) 2922 int vsw, int vfp, int vbp)
2606{ 2923{
2607 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2924 if (hsw < 1 || hsw > dispc.feat->sw_max ||
2608 if (hsw < 1 || hsw > 64 || 2925 hfp < 1 || hfp > dispc.feat->hp_max ||
2609 hfp < 1 || hfp > 256 || 2926 hbp < 1 || hbp > dispc.feat->hp_max ||
2610 hbp < 1 || hbp > 256 || 2927 vsw < 1 || vsw > dispc.feat->sw_max ||
2611 vsw < 1 || vsw > 64 || 2928 vfp < 0 || vfp > dispc.feat->vp_max ||
2612 vfp < 0 || vfp > 255 || 2929 vbp < 0 || vbp > dispc.feat->vp_max)
2613 vbp < 0 || vbp > 255) 2930 return false;
2614 return false;
2615 } else {
2616 if (hsw < 1 || hsw > 256 ||
2617 hfp < 1 || hfp > 4096 ||
2618 hbp < 1 || hbp > 4096 ||
2619 vsw < 1 || vsw > 256 ||
2620 vfp < 0 || vfp > 4095 ||
2621 vbp < 0 || vbp > 4095)
2622 return false;
2623 }
2624
2625 return true; 2931 return true;
2626} 2932}
2627 2933
@@ -2653,19 +2959,12 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
2653 u32 timing_h, timing_v, l; 2959 u32 timing_h, timing_v, l;
2654 bool onoff, rf, ipc; 2960 bool onoff, rf, ipc;
2655 2961
2656 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2962 timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
2657 timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | 2963 FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
2658 FLD_VAL(hbp-1, 27, 20); 2964 FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
2659 2965 timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
2660 timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | 2966 FLD_VAL(vfp, dispc.feat->fp_start, 8) |
2661 FLD_VAL(vbp, 27, 20); 2967 FLD_VAL(vbp, dispc.feat->bp_start, 20);
2662 } else {
2663 timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
2664 FLD_VAL(hbp-1, 31, 20);
2665
2666 timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
2667 FLD_VAL(vbp, 31, 20);
2668 }
2669 2968
2670 dispc_write_reg(DISPC_TIMING_H(channel), timing_h); 2969 dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
2671 dispc_write_reg(DISPC_TIMING_V(channel), timing_v); 2970 dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
@@ -2871,6 +3170,23 @@ unsigned long dispc_core_clk_rate(void)
2871 return fclk / lcd; 3170 return fclk / lcd;
2872} 3171}
2873 3172
3173static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
3174{
3175 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3176
3177 return dispc_mgr_pclk_rate(channel);
3178}
3179
3180static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
3181{
3182 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3183
3184 if (dss_mgr_is_lcd(channel))
3185 return dispc_mgr_lclk_rate(channel);
3186 else
3187 return dispc_fclk_rate();
3188
3189}
2874static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) 3190static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
2875{ 3191{
2876 int lcd, pcd; 3192 int lcd, pcd;
@@ -3491,7 +3807,7 @@ static void dispc_error_worker(struct work_struct *work)
3491 ovl->name); 3807 ovl->name);
3492 dispc_ovl_enable(ovl->id, false); 3808 dispc_ovl_enable(ovl->id, false);
3493 dispc_mgr_go(ovl->manager->id); 3809 dispc_mgr_go(ovl->manager->id);
3494 mdelay(50); 3810 msleep(50);
3495 } 3811 }
3496 } 3812 }
3497 3813
@@ -3503,7 +3819,7 @@ static void dispc_error_worker(struct work_struct *work)
3503 bit = mgr_desc[i].sync_lost_irq; 3819 bit = mgr_desc[i].sync_lost_irq;
3504 3820
3505 if (bit & errors) { 3821 if (bit & errors) {
3506 struct omap_dss_device *dssdev = mgr->device; 3822 struct omap_dss_device *dssdev = mgr->get_device(mgr);
3507 bool enable; 3823 bool enable;
3508 3824
3509 DSSERR("SYNC_LOST on channel %s, restarting the output " 3825 DSSERR("SYNC_LOST on channel %s, restarting the output "
@@ -3523,7 +3839,7 @@ static void dispc_error_worker(struct work_struct *work)
3523 } 3839 }
3524 3840
3525 dispc_mgr_go(mgr->id); 3841 dispc_mgr_go(mgr->id);
3526 mdelay(50); 3842 msleep(50);
3527 3843
3528 if (enable) 3844 if (enable)
3529 dssdev->driver->enable(dssdev); 3845 dssdev->driver->enable(dssdev);
@@ -3534,9 +3850,13 @@ static void dispc_error_worker(struct work_struct *work)
3534 DSSERR("OCP_ERR\n"); 3850 DSSERR("OCP_ERR\n");
3535 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 3851 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3536 struct omap_overlay_manager *mgr; 3852 struct omap_overlay_manager *mgr;
3853 struct omap_dss_device *dssdev;
3854
3537 mgr = omap_dss_get_overlay_manager(i); 3855 mgr = omap_dss_get_overlay_manager(i);
3538 if (mgr->device && mgr->device->driver) 3856 dssdev = mgr->get_device(mgr);
3539 mgr->device->driver->disable(mgr->device); 3857
3858 if (dssdev && dssdev->driver)
3859 dssdev->driver->disable(dssdev);
3540 } 3860 }
3541 } 3861 }
3542 3862
@@ -3660,17 +3980,98 @@ static void _omap_dispc_initial_config(void)
3660 if (dss_has_feature(FEAT_FUNCGATED)) 3980 if (dss_has_feature(FEAT_FUNCGATED))
3661 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); 3981 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3662 3982
3663 _dispc_setup_color_conv_coef(); 3983 dispc_setup_color_conv_coef();
3664 3984
3665 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); 3985 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
3666 3986
3667 dispc_read_plane_fifo_sizes(); 3987 dispc_init_fifos();
3668 3988
3669 dispc_configure_burst_sizes(); 3989 dispc_configure_burst_sizes();
3670 3990
3671 dispc_ovl_enable_zorder_planes(); 3991 dispc_ovl_enable_zorder_planes();
3672} 3992}
3673 3993
3994static const struct dispc_features omap24xx_dispc_feats __initconst = {
3995 .sw_start = 5,
3996 .fp_start = 15,
3997 .bp_start = 27,
3998 .sw_max = 64,
3999 .vp_max = 255,
4000 .hp_max = 256,
4001 .calc_scaling = dispc_ovl_calc_scaling_24xx,
4002 .calc_core_clk = calc_core_clk_24xx,
4003 .num_fifos = 3,
4004};
4005
4006static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
4007 .sw_start = 5,
4008 .fp_start = 15,
4009 .bp_start = 27,
4010 .sw_max = 64,
4011 .vp_max = 255,
4012 .hp_max = 256,
4013 .calc_scaling = dispc_ovl_calc_scaling_34xx,
4014 .calc_core_clk = calc_core_clk_34xx,
4015 .num_fifos = 3,
4016};
4017
4018static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
4019 .sw_start = 7,
4020 .fp_start = 19,
4021 .bp_start = 31,
4022 .sw_max = 256,
4023 .vp_max = 4095,
4024 .hp_max = 4096,
4025 .calc_scaling = dispc_ovl_calc_scaling_34xx,
4026 .calc_core_clk = calc_core_clk_34xx,
4027 .num_fifos = 3,
4028};
4029
4030static const struct dispc_features omap44xx_dispc_feats __initconst = {
4031 .sw_start = 7,
4032 .fp_start = 19,
4033 .bp_start = 31,
4034 .sw_max = 256,
4035 .vp_max = 4095,
4036 .hp_max = 4096,
4037 .calc_scaling = dispc_ovl_calc_scaling_44xx,
4038 .calc_core_clk = calc_core_clk_44xx,
4039 .num_fifos = 5,
4040 .gfx_fifo_workaround = true,
4041};
4042
4043static int __init dispc_init_features(struct device *dev)
4044{
4045 const struct dispc_features *src;
4046 struct dispc_features *dst;
4047
4048 dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
4049 if (!dst) {
4050 dev_err(dev, "Failed to allocate DISPC Features\n");
4051 return -ENOMEM;
4052 }
4053
4054 if (cpu_is_omap24xx()) {
4055 src = &omap24xx_dispc_feats;
4056 } else if (cpu_is_omap34xx()) {
4057 if (omap_rev() < OMAP3430_REV_ES3_0)
4058 src = &omap34xx_rev1_0_dispc_feats;
4059 else
4060 src = &omap34xx_rev3_0_dispc_feats;
4061 } else if (cpu_is_omap44xx()) {
4062 src = &omap44xx_dispc_feats;
4063 } else if (soc_is_omap54xx()) {
4064 src = &omap44xx_dispc_feats;
4065 } else {
4066 return -ENODEV;
4067 }
4068
4069 memcpy(dst, src, sizeof(*dst));
4070 dispc.feat = dst;
4071
4072 return 0;
4073}
4074
3674/* DISPC HW IP initialisation */ 4075/* DISPC HW IP initialisation */
3675static int __init omap_dispchw_probe(struct platform_device *pdev) 4076static int __init omap_dispchw_probe(struct platform_device *pdev)
3676{ 4077{
@@ -3681,6 +4082,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
3681 4082
3682 dispc.pdev = pdev; 4083 dispc.pdev = pdev;
3683 4084
4085 r = dispc_init_features(&dispc.pdev->dev);
4086 if (r)
4087 return r;
4088
3684 spin_lock_init(&dispc.irq_lock); 4089 spin_lock_init(&dispc.irq_lock);
3685 4090
3686#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 4091#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index 92d8a9be86fc..222363c6e623 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -36,6 +36,7 @@
36#define DISPC_CONTROL2 0x0238 36#define DISPC_CONTROL2 0x0238
37#define DISPC_CONFIG2 0x0620 37#define DISPC_CONFIG2 0x0620
38#define DISPC_DIVISOR 0x0804 38#define DISPC_DIVISOR 0x0804
39#define DISPC_GLOBAL_BUFFER 0x0800
39#define DISPC_CONTROL3 0x0848 40#define DISPC_CONTROL3 0x0848
40#define DISPC_CONFIG3 0x084C 41#define DISPC_CONFIG3 0x084C
41 42
@@ -355,6 +356,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
355 return 0x014C; 356 return 0x014C;
356 case OMAP_DSS_VIDEO3: 357 case OMAP_DSS_VIDEO3:
357 return 0x0300; 358 return 0x0300;
359 case OMAP_DSS_WB:
360 return 0x0500;
358 default: 361 default:
359 BUG(); 362 BUG();
360 return 0; 363 return 0;
@@ -370,6 +373,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
370 case OMAP_DSS_VIDEO2: 373 case OMAP_DSS_VIDEO2:
371 return 0x0000; 374 return 0x0000;
372 case OMAP_DSS_VIDEO3: 375 case OMAP_DSS_VIDEO3:
376 case OMAP_DSS_WB:
373 return 0x0008; 377 return 0x0008;
374 default: 378 default:
375 BUG(); 379 BUG();
@@ -385,6 +389,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
385 case OMAP_DSS_VIDEO2: 389 case OMAP_DSS_VIDEO2:
386 return 0x0004; 390 return 0x0004;
387 case OMAP_DSS_VIDEO3: 391 case OMAP_DSS_VIDEO3:
392 case OMAP_DSS_WB:
388 return 0x000C; 393 return 0x000C;
389 default: 394 default:
390 BUG(); 395 BUG();
@@ -404,6 +409,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
404 return 0x04BC; 409 return 0x04BC;
405 case OMAP_DSS_VIDEO3: 410 case OMAP_DSS_VIDEO3:
406 return 0x0310; 411 return 0x0310;
412 case OMAP_DSS_WB:
413 return 0x0118;
407 default: 414 default:
408 BUG(); 415 BUG();
409 return 0; 416 return 0;
@@ -422,6 +429,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
422 return 0x04C0; 429 return 0x04C0;
423 case OMAP_DSS_VIDEO3: 430 case OMAP_DSS_VIDEO3:
424 return 0x0314; 431 return 0x0314;
432 case OMAP_DSS_WB:
433 return 0x011C;
425 default: 434 default:
426 BUG(); 435 BUG();
427 return 0; 436 return 0;
@@ -451,6 +460,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
451 case OMAP_DSS_VIDEO2: 460 case OMAP_DSS_VIDEO2:
452 return 0x000C; 461 return 0x000C;
453 case OMAP_DSS_VIDEO3: 462 case OMAP_DSS_VIDEO3:
463 case OMAP_DSS_WB:
454 return 0x00A8; 464 return 0x00A8;
455 default: 465 default:
456 BUG(); 466 BUG();
@@ -467,6 +477,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
467 case OMAP_DSS_VIDEO2: 477 case OMAP_DSS_VIDEO2:
468 return 0x0010; 478 return 0x0010;
469 case OMAP_DSS_VIDEO3: 479 case OMAP_DSS_VIDEO3:
480 case OMAP_DSS_WB:
470 return 0x0070; 481 return 0x0070;
471 default: 482 default:
472 BUG(); 483 BUG();
@@ -486,6 +497,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
486 return 0x04DC; 497 return 0x04DC;
487 case OMAP_DSS_VIDEO3: 498 case OMAP_DSS_VIDEO3:
488 return 0x032C; 499 return 0x032C;
500 case OMAP_DSS_WB:
501 return 0x0310;
489 default: 502 default:
490 BUG(); 503 BUG();
491 return 0; 504 return 0;
@@ -501,6 +514,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
501 case OMAP_DSS_VIDEO2: 514 case OMAP_DSS_VIDEO2:
502 return 0x0014; 515 return 0x0014;
503 case OMAP_DSS_VIDEO3: 516 case OMAP_DSS_VIDEO3:
517 case OMAP_DSS_WB:
504 return 0x008C; 518 return 0x008C;
505 default: 519 default:
506 BUG(); 520 BUG();
@@ -517,6 +531,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
517 case OMAP_DSS_VIDEO2: 531 case OMAP_DSS_VIDEO2:
518 return 0x0018; 532 return 0x0018;
519 case OMAP_DSS_VIDEO3: 533 case OMAP_DSS_VIDEO3:
534 case OMAP_DSS_WB:
520 return 0x0088; 535 return 0x0088;
521 default: 536 default:
522 BUG(); 537 BUG();
@@ -533,6 +548,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
533 case OMAP_DSS_VIDEO2: 548 case OMAP_DSS_VIDEO2:
534 return 0x001C; 549 return 0x001C;
535 case OMAP_DSS_VIDEO3: 550 case OMAP_DSS_VIDEO3:
551 case OMAP_DSS_WB:
536 return 0x00A4; 552 return 0x00A4;
537 default: 553 default:
538 BUG(); 554 BUG();
@@ -549,6 +565,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
549 case OMAP_DSS_VIDEO2: 565 case OMAP_DSS_VIDEO2:
550 return 0x0020; 566 return 0x0020;
551 case OMAP_DSS_VIDEO3: 567 case OMAP_DSS_VIDEO3:
568 case OMAP_DSS_WB:
552 return 0x0098; 569 return 0x0098;
553 default: 570 default:
554 BUG(); 571 BUG();
@@ -598,6 +615,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
598 case OMAP_DSS_VIDEO2: 615 case OMAP_DSS_VIDEO2:
599 return 0x0024; 616 return 0x0024;
600 case OMAP_DSS_VIDEO3: 617 case OMAP_DSS_VIDEO3:
618 case OMAP_DSS_WB:
601 return 0x0090; 619 return 0x0090;
602 default: 620 default:
603 BUG(); 621 BUG();
@@ -617,6 +635,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
617 return 0x055C; 635 return 0x055C;
618 case OMAP_DSS_VIDEO3: 636 case OMAP_DSS_VIDEO3:
619 return 0x0424; 637 return 0x0424;
638 case OMAP_DSS_WB:
639 return 0x290;
620 default: 640 default:
621 BUG(); 641 BUG();
622 return 0; 642 return 0;
@@ -633,6 +653,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
633 case OMAP_DSS_VIDEO2: 653 case OMAP_DSS_VIDEO2:
634 return 0x0028; 654 return 0x0028;
635 case OMAP_DSS_VIDEO3: 655 case OMAP_DSS_VIDEO3:
656 case OMAP_DSS_WB:
636 return 0x0094; 657 return 0x0094;
637 default: 658 default:
638 BUG(); 659 BUG();
@@ -651,6 +672,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
651 case OMAP_DSS_VIDEO2: 672 case OMAP_DSS_VIDEO2:
652 return 0x002C; 673 return 0x002C;
653 case OMAP_DSS_VIDEO3: 674 case OMAP_DSS_VIDEO3:
675 case OMAP_DSS_WB:
654 return 0x0000; 676 return 0x0000;
655 default: 677 default:
656 BUG(); 678 BUG();
@@ -670,6 +692,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
670 return 0x0560; 692 return 0x0560;
671 case OMAP_DSS_VIDEO3: 693 case OMAP_DSS_VIDEO3:
672 return 0x0428; 694 return 0x0428;
695 case OMAP_DSS_WB:
696 return 0x0294;
673 default: 697 default:
674 BUG(); 698 BUG();
675 return 0; 699 return 0;
@@ -686,6 +710,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
686 case OMAP_DSS_VIDEO2: 710 case OMAP_DSS_VIDEO2:
687 return 0x0030; 711 return 0x0030;
688 case OMAP_DSS_VIDEO3: 712 case OMAP_DSS_VIDEO3:
713 case OMAP_DSS_WB:
689 return 0x0004; 714 return 0x0004;
690 default: 715 default:
691 BUG(); 716 BUG();
@@ -705,6 +730,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
705 return 0x0564; 730 return 0x0564;
706 case OMAP_DSS_VIDEO3: 731 case OMAP_DSS_VIDEO3:
707 return 0x042C; 732 return 0x042C;
733 case OMAP_DSS_WB:
734 return 0x0298;
708 default: 735 default:
709 BUG(); 736 BUG();
710 return 0; 737 return 0;
@@ -722,6 +749,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
722 case OMAP_DSS_VIDEO2: 749 case OMAP_DSS_VIDEO2:
723 return 0x0034 + i * 0x8; 750 return 0x0034 + i * 0x8;
724 case OMAP_DSS_VIDEO3: 751 case OMAP_DSS_VIDEO3:
752 case OMAP_DSS_WB:
725 return 0x0010 + i * 0x8; 753 return 0x0010 + i * 0x8;
726 default: 754 default:
727 BUG(); 755 BUG();
@@ -742,6 +770,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
742 return 0x0568 + i * 0x8; 770 return 0x0568 + i * 0x8;
743 case OMAP_DSS_VIDEO3: 771 case OMAP_DSS_VIDEO3:
744 return 0x0430 + i * 0x8; 772 return 0x0430 + i * 0x8;
773 case OMAP_DSS_WB:
774 return 0x02A0 + i * 0x8;
745 default: 775 default:
746 BUG(); 776 BUG();
747 return 0; 777 return 0;
@@ -759,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
759 case OMAP_DSS_VIDEO2: 789 case OMAP_DSS_VIDEO2:
760 return 0x0038 + i * 0x8; 790 return 0x0038 + i * 0x8;
761 case OMAP_DSS_VIDEO3: 791 case OMAP_DSS_VIDEO3:
792 case OMAP_DSS_WB:
762 return 0x0014 + i * 0x8; 793 return 0x0014 + i * 0x8;
763 default: 794 default:
764 BUG(); 795 BUG();
@@ -779,6 +810,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
779 return 0x056C + i * 0x8; 810 return 0x056C + i * 0x8;
780 case OMAP_DSS_VIDEO3: 811 case OMAP_DSS_VIDEO3:
781 return 0x0434 + i * 0x8; 812 return 0x0434 + i * 0x8;
813 case OMAP_DSS_WB:
814 return 0x02A4 + i * 0x8;
782 default: 815 default:
783 BUG(); 816 BUG();
784 return 0; 817 return 0;
@@ -795,6 +828,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
795 case OMAP_DSS_VIDEO1: 828 case OMAP_DSS_VIDEO1:
796 case OMAP_DSS_VIDEO2: 829 case OMAP_DSS_VIDEO2:
797 case OMAP_DSS_VIDEO3: 830 case OMAP_DSS_VIDEO3:
831 case OMAP_DSS_WB:
798 return 0x0074 + i * 0x4; 832 return 0x0074 + i * 0x4;
799 default: 833 default:
800 BUG(); 834 BUG();
@@ -814,6 +848,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
814 case OMAP_DSS_VIDEO2: 848 case OMAP_DSS_VIDEO2:
815 return 0x00B4 + i * 0x4; 849 return 0x00B4 + i * 0x4;
816 case OMAP_DSS_VIDEO3: 850 case OMAP_DSS_VIDEO3:
851 case OMAP_DSS_WB:
817 return 0x0050 + i * 0x4; 852 return 0x0050 + i * 0x4;
818 default: 853 default:
819 BUG(); 854 BUG();
@@ -834,6 +869,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
834 return 0x05A8 + i * 0x4; 869 return 0x05A8 + i * 0x4;
835 case OMAP_DSS_VIDEO3: 870 case OMAP_DSS_VIDEO3:
836 return 0x0470 + i * 0x4; 871 return 0x0470 + i * 0x4;
872 case OMAP_DSS_WB:
873 return 0x02E0 + i * 0x4;
837 default: 874 default:
838 BUG(); 875 BUG();
839 return 0; 876 return 0;
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 5bd957e85505..ccf8550fafde 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -142,7 +142,11 @@ static ssize_t display_timings_store(struct device *dev,
142 if (r) 142 if (r)
143 return r; 143 return r;
144 144
145 dssdev->driver->disable(dssdev);
145 dssdev->driver->set_timings(dssdev, &t); 146 dssdev->driver->set_timings(dssdev, &t);
147 r = dssdev->driver->enable(dssdev);
148 if (r)
149 return r;
146 150
147 return size; 151 return size;
148} 152}
@@ -316,26 +320,117 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
316} 320}
317EXPORT_SYMBOL(omapdss_default_get_timings); 321EXPORT_SYMBOL(omapdss_default_get_timings);
318 322
319void dss_init_device(struct platform_device *pdev, 323/*
324 * Connect dssdev to a manager if the manager is free or if force is specified.
325 * Connect all overlays to that manager if they are free or if force is
326 * specified.
327 */
328static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
329{
330 struct omap_dss_output *out;
331 struct omap_overlay_manager *mgr;
332 int i, r;
333
334 out = omapdss_get_output_from_dssdev(dssdev);
335
336 WARN_ON(dssdev->output);
337 WARN_ON(out->device);
338
339 r = omapdss_output_set_device(out, dssdev);
340 if (r) {
341 DSSERR("failed to connect output to new device\n");
342 return r;
343 }
344
345 mgr = omap_dss_get_overlay_manager(dssdev->channel);
346
347 if (mgr->output && !force)
348 return 0;
349
350 if (mgr->output)
351 mgr->unset_output(mgr);
352
353 r = mgr->set_output(mgr, out);
354 if (r) {
355 DSSERR("failed to connect manager to output of new device\n");
356
357 /* remove the output-device connection we just made */
358 omapdss_output_unset_device(out);
359 return r;
360 }
361
362 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
363 struct omap_overlay *ovl = omap_dss_get_overlay(i);
364
365 if (!ovl->manager || force) {
366 if (ovl->manager)
367 ovl->unset_manager(ovl);
368
369 r = ovl->set_manager(ovl, mgr);
370 if (r) {
371 DSSERR("failed to set initial overlay\n");
372 return r;
373 }
374 }
375 }
376
377 return 0;
378}
379
380static void dss_uninit_connections(struct omap_dss_device *dssdev)
381{
382 if (dssdev->output) {
383 struct omap_overlay_manager *mgr = dssdev->output->manager;
384
385 if (mgr)
386 mgr->unset_output(mgr);
387
388 omapdss_output_unset_device(dssdev->output);
389 }
390}
391
392int dss_init_device(struct platform_device *pdev,
320 struct omap_dss_device *dssdev) 393 struct omap_dss_device *dssdev)
321{ 394{
322 struct device_attribute *attr; 395 struct device_attribute *attr;
323 int i; 396 int i, r;
324 int r; 397 const char *def_disp_name = dss_get_default_display_name();
398 bool force;
399
400 force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
401 dss_init_connections(dssdev, force);
325 402
326 /* create device sysfs files */ 403 /* create device sysfs files */
327 i = 0; 404 i = 0;
328 while ((attr = display_sysfs_attrs[i++]) != NULL) { 405 while ((attr = display_sysfs_attrs[i++]) != NULL) {
329 r = device_create_file(&dssdev->dev, attr); 406 r = device_create_file(&dssdev->dev, attr);
330 if (r) 407 if (r) {
408 for (i = i - 2; i >= 0; i--) {
409 attr = display_sysfs_attrs[i];
410 device_remove_file(&dssdev->dev, attr);
411 }
412
413 dss_uninit_connections(dssdev);
414
331 DSSERR("failed to create sysfs file\n"); 415 DSSERR("failed to create sysfs file\n");
416 return r;
417 }
332 } 418 }
333 419
334 /* create display? sysfs links */ 420 /* create display? sysfs links */
335 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj, 421 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
336 dev_name(&dssdev->dev)); 422 dev_name(&dssdev->dev));
337 if (r) 423 if (r) {
424 while ((attr = display_sysfs_attrs[i++]) != NULL)
425 device_remove_file(&dssdev->dev, attr);
426
427 dss_uninit_connections(dssdev);
428
338 DSSERR("failed to create sysfs display link\n"); 429 DSSERR("failed to create sysfs display link\n");
430 return r;
431 }
432
433 return 0;
339} 434}
340 435
341void dss_uninit_device(struct platform_device *pdev, 436void dss_uninit_device(struct platform_device *pdev,
@@ -349,8 +444,7 @@ void dss_uninit_device(struct platform_device *pdev,
349 while ((attr = display_sysfs_attrs[i++]) != NULL) 444 while ((attr = display_sysfs_attrs[i++]) != NULL)
350 device_remove_file(&dssdev->dev, attr); 445 device_remove_file(&dssdev->dev, attr);
351 446
352 if (dssdev->manager) 447 dss_uninit_connections(dssdev);
353 dssdev->manager->unset_device(dssdev->manager);
354} 448}
355 449
356static int dss_suspend_device(struct device *dev, void *data) 450static int dss_suspend_device(struct device *dev, void *data)
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 3266be23fc0d..56748cf8760e 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -29,17 +29,24 @@
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/regulator/consumer.h> 31#include <linux/regulator/consumer.h>
32#include <linux/string.h>
32 33
33#include <video/omapdss.h> 34#include <video/omapdss.h>
34#include <plat/cpu.h>
35 35
36#include "dss.h" 36#include "dss.h"
37#include "dss_features.h"
37 38
38static struct { 39static struct {
39 struct regulator *vdds_dsi_reg; 40 struct regulator *vdds_dsi_reg;
40 struct platform_device *dsidev; 41 struct platform_device *dsidev;
41 42
43 struct mutex lock;
44
45 struct omap_video_timings timings;
42 struct dss_lcd_mgr_config mgr_config; 46 struct dss_lcd_mgr_config mgr_config;
47 int data_lines;
48
49 struct omap_dss_output output;
43} dpi; 50} dpi;
44 51
45static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) 52static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
@@ -121,7 +128,8 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
121 128
122static int dpi_set_mode(struct omap_dss_device *dssdev) 129static int dpi_set_mode(struct omap_dss_device *dssdev)
123{ 130{
124 struct omap_video_timings *t = &dssdev->panel.timings; 131 struct omap_video_timings *t = &dpi.timings;
132 struct omap_overlay_manager *mgr = dssdev->output->manager;
125 int lck_div = 0, pck_div = 0; 133 int lck_div = 0, pck_div = 0;
126 unsigned long fck = 0; 134 unsigned long fck = 0;
127 unsigned long pck; 135 unsigned long pck;
@@ -146,37 +154,44 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
146 t->pixel_clock = pck; 154 t->pixel_clock = pck;
147 } 155 }
148 156
149 dss_mgr_set_timings(dssdev->manager, t); 157 dss_mgr_set_timings(mgr, t);
150 158
151 return 0; 159 return 0;
152} 160}
153 161
154static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) 162static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
155{ 163{
164 struct omap_overlay_manager *mgr = dssdev->output->manager;
165
156 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 166 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
157 167
158 dpi.mgr_config.stallmode = false; 168 dpi.mgr_config.stallmode = false;
159 dpi.mgr_config.fifohandcheck = false; 169 dpi.mgr_config.fifohandcheck = false;
160 170
161 dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines; 171 dpi.mgr_config.video_port_width = dpi.data_lines;
162 172
163 dpi.mgr_config.lcden_sig_polarity = 0; 173 dpi.mgr_config.lcden_sig_polarity = 0;
164 174
165 dss_mgr_set_lcd_config(dssdev->manager, &dpi.mgr_config); 175 dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
166} 176}
167 177
168int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) 178int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
169{ 179{
180 struct omap_dss_output *out = dssdev->output;
170 int r; 181 int r;
171 182
172 if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) { 183 mutex_lock(&dpi.lock);
184
185 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
173 DSSERR("no VDSS_DSI regulator\n"); 186 DSSERR("no VDSS_DSI regulator\n");
174 return -ENODEV; 187 r = -ENODEV;
188 goto err_no_reg;
175 } 189 }
176 190
177 if (dssdev->manager == NULL) { 191 if (out == NULL || out->manager == NULL) {
178 DSSERR("failed to enable display: no manager\n"); 192 DSSERR("failed to enable display: no output/manager\n");
179 return -ENODEV; 193 r = -ENODEV;
194 goto err_no_out_mgr;
180 } 195 }
181 196
182 r = omap_dss_start_device(dssdev); 197 r = omap_dss_start_device(dssdev);
@@ -185,7 +200,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
185 goto err_start_dev; 200 goto err_start_dev;
186 } 201 }
187 202
188 if (cpu_is_omap34xx()) { 203 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
189 r = regulator_enable(dpi.vdds_dsi_reg); 204 r = regulator_enable(dpi.vdds_dsi_reg);
190 if (r) 205 if (r)
191 goto err_reg_enable; 206 goto err_reg_enable;
@@ -195,6 +210,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
195 if (r) 210 if (r)
196 goto err_get_dispc; 211 goto err_get_dispc;
197 212
213 r = dss_dpi_select_source(dssdev->channel);
214 if (r)
215 goto err_src_sel;
216
198 if (dpi_use_dsi_pll(dssdev)) { 217 if (dpi_use_dsi_pll(dssdev)) {
199 r = dsi_runtime_get(dpi.dsidev); 218 r = dsi_runtime_get(dpi.dsidev);
200 if (r) 219 if (r)
@@ -213,10 +232,12 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
213 232
214 mdelay(2); 233 mdelay(2);
215 234
216 r = dss_mgr_enable(dssdev->manager); 235 r = dss_mgr_enable(out->manager);
217 if (r) 236 if (r)
218 goto err_mgr_enable; 237 goto err_mgr_enable;
219 238
239 mutex_unlock(&dpi.lock);
240
220 return 0; 241 return 0;
221 242
222err_mgr_enable: 243err_mgr_enable:
@@ -227,20 +248,28 @@ err_dsi_pll_init:
227 if (dpi_use_dsi_pll(dssdev)) 248 if (dpi_use_dsi_pll(dssdev))
228 dsi_runtime_put(dpi.dsidev); 249 dsi_runtime_put(dpi.dsidev);
229err_get_dsi: 250err_get_dsi:
251err_src_sel:
230 dispc_runtime_put(); 252 dispc_runtime_put();
231err_get_dispc: 253err_get_dispc:
232 if (cpu_is_omap34xx()) 254 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
233 regulator_disable(dpi.vdds_dsi_reg); 255 regulator_disable(dpi.vdds_dsi_reg);
234err_reg_enable: 256err_reg_enable:
235 omap_dss_stop_device(dssdev); 257 omap_dss_stop_device(dssdev);
236err_start_dev: 258err_start_dev:
259err_no_out_mgr:
260err_no_reg:
261 mutex_unlock(&dpi.lock);
237 return r; 262 return r;
238} 263}
239EXPORT_SYMBOL(omapdss_dpi_display_enable); 264EXPORT_SYMBOL(omapdss_dpi_display_enable);
240 265
241void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) 266void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
242{ 267{
243 dss_mgr_disable(dssdev->manager); 268 struct omap_overlay_manager *mgr = dssdev->output->manager;
269
270 mutex_lock(&dpi.lock);
271
272 dss_mgr_disable(mgr);
244 273
245 if (dpi_use_dsi_pll(dssdev)) { 274 if (dpi_use_dsi_pll(dssdev)) {
246 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 275 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
@@ -250,44 +279,39 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
250 279
251 dispc_runtime_put(); 280 dispc_runtime_put();
252 281
253 if (cpu_is_omap34xx()) 282 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
254 regulator_disable(dpi.vdds_dsi_reg); 283 regulator_disable(dpi.vdds_dsi_reg);
255 284
256 omap_dss_stop_device(dssdev); 285 omap_dss_stop_device(dssdev);
286
287 mutex_unlock(&dpi.lock);
257} 288}
258EXPORT_SYMBOL(omapdss_dpi_display_disable); 289EXPORT_SYMBOL(omapdss_dpi_display_disable);
259 290
260void dpi_set_timings(struct omap_dss_device *dssdev, 291void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
261 struct omap_video_timings *timings) 292 struct omap_video_timings *timings)
262{ 293{
263 int r;
264
265 DSSDBG("dpi_set_timings\n"); 294 DSSDBG("dpi_set_timings\n");
266 dssdev->panel.timings = *timings;
267 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
268 r = dispc_runtime_get();
269 if (r)
270 return;
271 295
272 dpi_set_mode(dssdev); 296 mutex_lock(&dpi.lock);
273 297
274 dispc_runtime_put(); 298 dpi.timings = *timings;
275 } else { 299
276 dss_mgr_set_timings(dssdev->manager, timings); 300 mutex_unlock(&dpi.lock);
277 }
278} 301}
279EXPORT_SYMBOL(dpi_set_timings); 302EXPORT_SYMBOL(omapdss_dpi_set_timings);
280 303
281int dpi_check_timings(struct omap_dss_device *dssdev, 304int dpi_check_timings(struct omap_dss_device *dssdev,
282 struct omap_video_timings *timings) 305 struct omap_video_timings *timings)
283{ 306{
284 int r; 307 int r;
308 struct omap_overlay_manager *mgr = dssdev->output->manager;
285 int lck_div, pck_div; 309 int lck_div, pck_div;
286 unsigned long fck; 310 unsigned long fck;
287 unsigned long pck; 311 unsigned long pck;
288 struct dispc_clock_info dispc_cinfo; 312 struct dispc_clock_info dispc_cinfo;
289 313
290 if (dss_mgr_check_timings(dssdev->manager, timings)) 314 if (dss_mgr_check_timings(mgr, timings))
291 return -EINVAL; 315 return -EINVAL;
292 316
293 if (timings->pixel_clock == 0) 317 if (timings->pixel_clock == 0)
@@ -325,11 +349,22 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
325} 349}
326EXPORT_SYMBOL(dpi_check_timings); 350EXPORT_SYMBOL(dpi_check_timings);
327 351
352void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
353{
354 mutex_lock(&dpi.lock);
355
356 dpi.data_lines = data_lines;
357
358 mutex_unlock(&dpi.lock);
359}
360EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
361
328static int __init dpi_init_display(struct omap_dss_device *dssdev) 362static int __init dpi_init_display(struct omap_dss_device *dssdev)
329{ 363{
330 DSSDBG("init_display\n"); 364 DSSDBG("init_display\n");
331 365
332 if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { 366 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
367 dpi.vdds_dsi_reg == NULL) {
333 struct regulator *vdds_dsi; 368 struct regulator *vdds_dsi;
334 369
335 vdds_dsi = dss_get_vdds_dsi(); 370 vdds_dsi = dss_get_vdds_dsi();
@@ -351,10 +386,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
351 return 0; 386 return 0;
352} 387}
353 388
354static void __init dpi_probe_pdata(struct platform_device *pdev) 389static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
355{ 390{
356 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 391 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
357 int i, r; 392 const char *def_disp_name = dss_get_default_display_name();
393 struct omap_dss_device *def_dssdev;
394 int i;
395
396 def_dssdev = NULL;
358 397
359 for (i = 0; i < pdata->num_devices; ++i) { 398 for (i = 0; i < pdata->num_devices; ++i) {
360 struct omap_dss_device *dssdev = pdata->devices[i]; 399 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -362,21 +401,75 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
362 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI) 401 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
363 continue; 402 continue;
364 403
365 r = dpi_init_display(dssdev); 404 if (def_dssdev == NULL)
366 if (r) { 405 def_dssdev = dssdev;
367 DSSERR("device %s init failed: %d\n", dssdev->name, r); 406
368 continue; 407 if (def_disp_name != NULL &&
408 strcmp(dssdev->name, def_disp_name) == 0) {
409 def_dssdev = dssdev;
410 break;
369 } 411 }
412 }
370 413
371 r = omap_dss_register_device(dssdev, &pdev->dev, i); 414 return def_dssdev;
372 if (r) 415}
373 DSSERR("device %s register failed: %d\n", 416
374 dssdev->name, r); 417static void __init dpi_probe_pdata(struct platform_device *dpidev)
418{
419 struct omap_dss_device *plat_dssdev;
420 struct omap_dss_device *dssdev;
421 int r;
422
423 plat_dssdev = dpi_find_dssdev(dpidev);
424
425 if (!plat_dssdev)
426 return;
427
428 dssdev = dss_alloc_and_init_device(&dpidev->dev);
429 if (!dssdev)
430 return;
431
432 dss_copy_device_pdata(dssdev, plat_dssdev);
433
434 r = dpi_init_display(dssdev);
435 if (r) {
436 DSSERR("device %s init failed: %d\n", dssdev->name, r);
437 dss_put_device(dssdev);
438 return;
439 }
440
441 r = dss_add_device(dssdev);
442 if (r) {
443 DSSERR("device %s register failed: %d\n", dssdev->name, r);
444 dss_put_device(dssdev);
445 return;
375 } 446 }
376} 447}
377 448
449static void __init dpi_init_output(struct platform_device *pdev)
450{
451 struct omap_dss_output *out = &dpi.output;
452
453 out->pdev = pdev;
454 out->id = OMAP_DSS_OUTPUT_DPI;
455 out->type = OMAP_DISPLAY_TYPE_DPI;
456
457 dss_register_output(out);
458}
459
460static void __exit dpi_uninit_output(struct platform_device *pdev)
461{
462 struct omap_dss_output *out = &dpi.output;
463
464 dss_unregister_output(out);
465}
466
378static int __init omap_dpi_probe(struct platform_device *pdev) 467static int __init omap_dpi_probe(struct platform_device *pdev)
379{ 468{
469 mutex_init(&dpi.lock);
470
471 dpi_init_output(pdev);
472
380 dpi_probe_pdata(pdev); 473 dpi_probe_pdata(pdev);
381 474
382 return 0; 475 return 0;
@@ -384,7 +477,9 @@ static int __init omap_dpi_probe(struct platform_device *pdev)
384 477
385static int __exit omap_dpi_remove(struct platform_device *pdev) 478static int __exit omap_dpi_remove(struct platform_device *pdev)
386{ 479{
387 omap_dss_unregister_child_devices(&pdev->dev); 480 dss_unregister_child_devices(&pdev->dev);
481
482 dpi_uninit_output(pdev);
388 483
389 return 0; 484 return 0;
390} 485}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index b07e8864f82f..e37e6d868acd 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -41,7 +41,6 @@
41 41
42#include <video/omapdss.h> 42#include <video/omapdss.h>
43#include <video/mipi_display.h> 43#include <video/mipi_display.h>
44#include <plat/clock.h>
45 44
46#include "dss.h" 45#include "dss.h"
47#include "dss_features.h" 46#include "dss_features.h"
@@ -333,6 +332,12 @@ struct dsi_data {
333 unsigned scp_clk_refcount; 332 unsigned scp_clk_refcount;
334 333
335 struct dss_lcd_mgr_config mgr_config; 334 struct dss_lcd_mgr_config mgr_config;
335 struct omap_video_timings timings;
336 enum omap_dss_dsi_pixel_format pix_fmt;
337 enum omap_dss_dsi_mode mode;
338 struct omap_dss_dsi_videomode_timings vm_timings;
339
340 struct omap_dss_output output;
336}; 341};
337 342
338struct dsi_packet_sent_handler_data { 343struct dsi_packet_sent_handler_data {
@@ -340,8 +345,6 @@ struct dsi_packet_sent_handler_data {
340 struct completion *completion; 345 struct completion *completion;
341}; 346};
342 347
343static struct platform_device *dsi_pdev_map[MAX_NUM_DSI];
344
345#ifdef DEBUG 348#ifdef DEBUG
346static bool dsi_perf; 349static bool dsi_perf;
347module_param(dsi_perf, bool, 0644); 350module_param(dsi_perf, bool, 0644);
@@ -354,12 +357,19 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside
354 357
355static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) 358static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
356{ 359{
357 return dsi_pdev_map[dssdev->phy.dsi.module]; 360 return dssdev->output->pdev;
358} 361}
359 362
360struct platform_device *dsi_get_dsidev_from_id(int module) 363struct platform_device *dsi_get_dsidev_from_id(int module)
361{ 364{
362 return dsi_pdev_map[module]; 365 struct omap_dss_output *out;
366 enum omap_dss_output_id id;
367
368 id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
369
370 out = omap_dss_get_output(id);
371
372 return out->pdev;
363} 373}
364 374
365static inline void dsi_write_reg(struct platform_device *dsidev, 375static inline void dsi_write_reg(struct platform_device *dsidev,
@@ -1450,6 +1460,148 @@ found:
1450 return 0; 1460 return 0;
1451} 1461}
1452 1462
1463static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
1464 unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
1465{
1466 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1467 struct dsi_clock_info cur, best;
1468
1469 DSSDBG("dsi_pll_calc_ddrfreq\n");
1470
1471 memset(&best, 0, sizeof(best));
1472 memset(&cur, 0, sizeof(cur));
1473
1474 cur.clkin = clk_get_rate(dsi->sys_clk);
1475
1476 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
1477 cur.fint = cur.clkin / cur.regn;
1478
1479 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
1480 continue;
1481
1482 /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
1483 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
1484 unsigned long a, b;
1485
1486 a = 2 * cur.regm * (cur.clkin/1000);
1487 b = cur.regn;
1488 cur.clkin4ddr = a / b * 1000;
1489
1490 if (cur.clkin4ddr > 1800 * 1000 * 1000)
1491 break;
1492
1493 if (abs(cur.clkin4ddr - req_clkin4ddr) <
1494 abs(best.clkin4ddr - req_clkin4ddr)) {
1495 best = cur;
1496 DSSDBG("best %ld\n", best.clkin4ddr);
1497 }
1498
1499 if (cur.clkin4ddr == req_clkin4ddr)
1500 goto found;
1501 }
1502 }
1503found:
1504 if (cinfo)
1505 *cinfo = best;
1506
1507 return 0;
1508}
1509
1510static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
1511 struct dsi_clock_info *cinfo)
1512{
1513 unsigned long max_dsi_fck;
1514
1515 max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
1516
1517 cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
1518 cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
1519}
1520
1521static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
1522 unsigned long req_pck, struct dsi_clock_info *cinfo,
1523 struct dispc_clock_info *dispc_cinfo)
1524{
1525 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1526 unsigned regm_dispc, best_regm_dispc;
1527 unsigned long dispc_clk, best_dispc_clk;
1528 int min_fck_per_pck;
1529 unsigned long max_dss_fck;
1530 struct dispc_clock_info best_dispc;
1531 bool match;
1532
1533 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1534
1535 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
1536
1537 if (min_fck_per_pck &&
1538 req_pck * min_fck_per_pck > max_dss_fck) {
1539 DSSERR("Requested pixel clock not possible with the current "
1540 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
1541 "the constraint off.\n");
1542 min_fck_per_pck = 0;
1543 }
1544
1545retry:
1546 best_regm_dispc = 0;
1547 best_dispc_clk = 0;
1548 memset(&best_dispc, 0, sizeof(best_dispc));
1549 match = false;
1550
1551 for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
1552 struct dispc_clock_info cur_dispc;
1553
1554 dispc_clk = cinfo->clkin4ddr / regm_dispc;
1555
1556 /* this will narrow down the search a bit,
1557 * but still give pixclocks below what was
1558 * requested */
1559 if (dispc_clk < req_pck)
1560 break;
1561
1562 if (dispc_clk > max_dss_fck)
1563 continue;
1564
1565 if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
1566 continue;
1567
1568 match = true;
1569
1570 dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
1571
1572 if (abs(cur_dispc.pck - req_pck) <
1573 abs(best_dispc.pck - req_pck)) {
1574 best_regm_dispc = regm_dispc;
1575 best_dispc_clk = dispc_clk;
1576 best_dispc = cur_dispc;
1577
1578 if (cur_dispc.pck == req_pck)
1579 goto found;
1580 }
1581 }
1582
1583 if (!match) {
1584 if (min_fck_per_pck) {
1585 DSSERR("Could not find suitable clock settings.\n"
1586 "Turning FCK/PCK constraint off and"
1587 "trying again.\n");
1588 min_fck_per_pck = 0;
1589 goto retry;
1590 }
1591
1592 DSSERR("Could not find suitable clock settings.\n");
1593
1594 return -EINVAL;
1595 }
1596found:
1597 cinfo->regm_dispc = best_regm_dispc;
1598 cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
1599
1600 *dispc_cinfo = best_dispc;
1601
1602 return 0;
1603}
1604
1453int dsi_pll_set_clock_div(struct platform_device *dsidev, 1605int dsi_pll_set_clock_div(struct platform_device *dsidev,
1454 struct dsi_clock_info *cinfo) 1606 struct dsi_clock_info *cinfo)
1455{ 1607{
@@ -1526,21 +1678,27 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1526 1678
1527 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); 1679 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
1528 1680
1681 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1682
1529 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { 1683 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
1530 f = cinfo->fint < 1000000 ? 0x3 : 1684 f = cinfo->fint < 1000000 ? 0x3 :
1531 cinfo->fint < 1250000 ? 0x4 : 1685 cinfo->fint < 1250000 ? 0x4 :
1532 cinfo->fint < 1500000 ? 0x5 : 1686 cinfo->fint < 1500000 ? 0x5 :
1533 cinfo->fint < 1750000 ? 0x6 : 1687 cinfo->fint < 1750000 ? 0x6 :
1534 0x7; 1688 0x7;
1535 }
1536 1689
1537 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1538
1539 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
1540 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ 1690 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1691 } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
1692 f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
1693
1694 l = FLD_MOD(l, f, 4, 1); /* PLL_SELFREQDCO */
1695 }
1696
1541 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ 1697 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1542 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ 1698 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1543 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ 1699 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1700 if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
1701 l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */
1544 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); 1702 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1545 1703
1546 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ 1704 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
@@ -2004,15 +2162,16 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2004 return 1194 * 3; /* 1194x24 bits */ 2162 return 1194 * 3; /* 1194x24 bits */
2005 case 6: 2163 case 6:
2006 return 1365 * 3; /* 1365x24 bits */ 2164 return 1365 * 3; /* 1365x24 bits */
2165 case 7:
2166 return 1920 * 3; /* 1920x24 bits */
2007 default: 2167 default:
2008 BUG(); 2168 BUG();
2009 return 0; 2169 return 0;
2010 } 2170 }
2011} 2171}
2012 2172
2013static int dsi_set_lane_config(struct omap_dss_device *dssdev) 2173static int dsi_set_lane_config(struct platform_device *dsidev)
2014{ 2174{
2015 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2016 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2175 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2017 static const u8 offsets[] = { 0, 4, 8, 12, 16 }; 2176 static const u8 offsets[] = { 0, 4, 8, 12, 16 };
2018 static const enum dsi_lane_function functions[] = { 2177 static const enum dsi_lane_function functions[] = {
@@ -2136,9 +2295,16 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2136 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r); 2295 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);
2137 2296
2138 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); 2297 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
2139 r = FLD_MOD(r, tlpx_half, 22, 16); 2298 r = FLD_MOD(r, tlpx_half, 20, 16);
2140 r = FLD_MOD(r, tclk_trail, 15, 8); 2299 r = FLD_MOD(r, tclk_trail, 15, 8);
2141 r = FLD_MOD(r, tclk_zero, 7, 0); 2300 r = FLD_MOD(r, tclk_zero, 7, 0);
2301
2302 if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
2303 r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */
2304 r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
2305 r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */
2306 }
2307
2142 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r); 2308 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
2143 2309
2144 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); 2310 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
@@ -2147,10 +2313,9 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2147} 2313}
2148 2314
2149/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */ 2315/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
2150static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, 2316static void dsi_cio_enable_lane_override(struct platform_device *dsidev,
2151 unsigned mask_p, unsigned mask_n) 2317 unsigned mask_p, unsigned mask_n)
2152{ 2318{
2153 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2154 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2319 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2155 int i; 2320 int i;
2156 u32 l; 2321 u32 l;
@@ -2197,9 +2362,8 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
2197 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17); 2362 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);
2198} 2363}
2199 2364
2200static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) 2365static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
2201{ 2366{
2202 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2203 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2367 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2204 int t, i; 2368 int t, i;
2205 bool in_use[DSI_MAX_NR_LANES]; 2369 bool in_use[DSI_MAX_NR_LANES];
@@ -2247,9 +2411,8 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
2247} 2411}
2248 2412
2249/* return bitmask of enabled lanes, lane0 being the lsb */ 2413/* return bitmask of enabled lanes, lane0 being the lsb */
2250static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) 2414static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
2251{ 2415{
2252 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2253 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2416 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2254 unsigned mask = 0; 2417 unsigned mask = 0;
2255 int i; 2418 int i;
@@ -2262,16 +2425,15 @@ static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
2262 return mask; 2425 return mask;
2263} 2426}
2264 2427
2265static int dsi_cio_init(struct omap_dss_device *dssdev) 2428static int dsi_cio_init(struct platform_device *dsidev)
2266{ 2429{
2267 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2268 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2430 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2269 int r; 2431 int r;
2270 u32 l; 2432 u32 l;
2271 2433
2272 DSSDBGF(); 2434 DSSDBGF();
2273 2435
2274 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); 2436 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2275 if (r) 2437 if (r)
2276 return r; 2438 return r;
2277 2439
@@ -2288,7 +2450,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2288 goto err_scp_clk_dom; 2450 goto err_scp_clk_dom;
2289 } 2451 }
2290 2452
2291 r = dsi_set_lane_config(dssdev); 2453 r = dsi_set_lane_config(dsidev);
2292 if (r) 2454 if (r)
2293 goto err_scp_clk_dom; 2455 goto err_scp_clk_dom;
2294 2456
@@ -2323,7 +2485,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2323 mask_p |= 1 << i; 2485 mask_p |= 1 << i;
2324 } 2486 }
2325 2487
2326 dsi_cio_enable_lane_override(dssdev, mask_p, 0); 2488 dsi_cio_enable_lane_override(dsidev, mask_p, 0);
2327 } 2489 }
2328 2490
2329 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); 2491 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
@@ -2340,7 +2502,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2340 dsi_if_enable(dsidev, false); 2502 dsi_if_enable(dsidev, false);
2341 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ 2503 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
2342 2504
2343 r = dsi_cio_wait_tx_clk_esc_reset(dssdev); 2505 r = dsi_cio_wait_tx_clk_esc_reset(dsidev);
2344 if (r) 2506 if (r)
2345 goto err_tx_clk_esc_rst; 2507 goto err_tx_clk_esc_rst;
2346 2508
@@ -2360,10 +2522,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2360 2522
2361 dsi_cio_timings(dsidev); 2523 dsi_cio_timings(dsidev);
2362 2524
2363 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 2525 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
2364 /* DDR_CLK_ALWAYS_ON */ 2526 /* DDR_CLK_ALWAYS_ON */
2365 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 2527 REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
2366 dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); 2528 dsi->vm_timings.ddr_clk_always_on, 13, 13);
2367 } 2529 }
2368 2530
2369 dsi->ulps_enabled = false; 2531 dsi->ulps_enabled = false;
@@ -2381,13 +2543,12 @@ err_cio_pwr:
2381 dsi_cio_disable_lane_override(dsidev); 2543 dsi_cio_disable_lane_override(dsidev);
2382err_scp_clk_dom: 2544err_scp_clk_dom:
2383 dsi_disable_scp_clk(dsidev); 2545 dsi_disable_scp_clk(dsidev);
2384 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); 2546 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2385 return r; 2547 return r;
2386} 2548}
2387 2549
2388static void dsi_cio_uninit(struct omap_dss_device *dssdev) 2550static void dsi_cio_uninit(struct platform_device *dsidev)
2389{ 2551{
2390 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2391 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2552 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2392 2553
2393 /* DDR_CLK_ALWAYS_ON */ 2554 /* DDR_CLK_ALWAYS_ON */
@@ -2395,7 +2556,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev)
2395 2556
2396 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); 2557 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2397 dsi_disable_scp_clk(dsidev); 2558 dsi_disable_scp_clk(dsidev);
2398 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); 2559 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2399} 2560}
2400 2561
2401static void dsi_config_tx_fifo(struct platform_device *dsidev, 2562static void dsi_config_tx_fifo(struct platform_device *dsidev,
@@ -2685,6 +2846,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2685 bool enable) 2846 bool enable)
2686{ 2847{
2687 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2848 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2849 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2688 2850
2689 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); 2851 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
2690 2852
@@ -2701,7 +2863,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2701 dsi_force_tx_stop_mode_io(dsidev); 2863 dsi_force_tx_stop_mode_io(dsidev);
2702 2864
2703 /* start the DDR clock by sending a NULL packet */ 2865 /* start the DDR clock by sending a NULL packet */
2704 if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable) 2866 if (dsi->vm_timings.ddr_clk_always_on && enable)
2705 dsi_vc_send_null(dssdev, channel); 2867 dsi_vc_send_null(dssdev, channel);
2706} 2868}
2707EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); 2869EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
@@ -2987,10 +3149,9 @@ int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
2987} 3149}
2988EXPORT_SYMBOL(dsi_vc_send_null); 3150EXPORT_SYMBOL(dsi_vc_send_null);
2989 3151
2990static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, 3152static int dsi_vc_write_nosync_common(struct platform_device *dsidev,
2991 int channel, u8 *data, int len, enum dss_dsi_content_type type) 3153 int channel, u8 *data, int len, enum dss_dsi_content_type type)
2992{ 3154{
2993 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2994 int r; 3155 int r;
2995 3156
2996 if (len == 0) { 3157 if (len == 0) {
@@ -3021,7 +3182,9 @@ static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,
3021int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, 3182int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
3022 u8 *data, int len) 3183 u8 *data, int len)
3023{ 3184{
3024 return dsi_vc_write_nosync_common(dssdev, channel, data, len, 3185 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3186
3187 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3025 DSS_DSI_CONTENT_DCS); 3188 DSS_DSI_CONTENT_DCS);
3026} 3189}
3027EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); 3190EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
@@ -3029,7 +3192,9 @@ EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
3029int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, 3192int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
3030 u8 *data, int len) 3193 u8 *data, int len)
3031{ 3194{
3032 return dsi_vc_write_nosync_common(dssdev, channel, data, len, 3195 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3196
3197 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3033 DSS_DSI_CONTENT_GENERIC); 3198 DSS_DSI_CONTENT_GENERIC);
3034} 3199}
3035EXPORT_SYMBOL(dsi_vc_generic_write_nosync); 3200EXPORT_SYMBOL(dsi_vc_generic_write_nosync);
@@ -3040,7 +3205,7 @@ static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
3040 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3205 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3041 int r; 3206 int r;
3042 3207
3043 r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type); 3208 r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type);
3044 if (r) 3209 if (r)
3045 goto err; 3210 goto err;
3046 3211
@@ -3118,10 +3283,9 @@ int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
3118} 3283}
3119EXPORT_SYMBOL(dsi_vc_generic_write_2); 3284EXPORT_SYMBOL(dsi_vc_generic_write_2);
3120 3285
3121static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, 3286static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,
3122 int channel, u8 dcs_cmd) 3287 int channel, u8 dcs_cmd)
3123{ 3288{
3124 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3125 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3289 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3126 int r; 3290 int r;
3127 3291
@@ -3139,10 +3303,9 @@ static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,
3139 return 0; 3303 return 0;
3140} 3304}
3141 3305
3142static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, 3306static int dsi_vc_generic_send_read_request(struct platform_device *dsidev,
3143 int channel, u8 *reqdata, int reqlen) 3307 int channel, u8 *reqdata, int reqlen)
3144{ 3308{
3145 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3146 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3309 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3147 u16 data; 3310 u16 data;
3148 u8 data_type; 3311 u8 data_type;
@@ -3291,7 +3454,7 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3291 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3454 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3292 int r; 3455 int r;
3293 3456
3294 r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd); 3457 r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);
3295 if (r) 3458 if (r)
3296 goto err; 3459 goto err;
3297 3460
@@ -3322,7 +3485,7 @@ static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
3322 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3485 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3323 int r; 3486 int r;
3324 3487
3325 r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); 3488 r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen);
3326 if (r) 3489 if (r)
3327 return r; 3490 return r;
3328 3491
@@ -3604,15 +3767,15 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
3604 (total_ticks * 1000) / (fck / 1000 / 1000)); 3767 (total_ticks * 1000) / (fck / 1000 / 1000));
3605} 3768}
3606 3769
3607static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) 3770static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
3608{ 3771{
3609 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3772 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3610 int num_line_buffers; 3773 int num_line_buffers;
3611 3774
3612 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 3775 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3613 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 3776 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3614 unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 3777 unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
3615 struct omap_video_timings *timings = &dssdev->panel.timings; 3778 struct omap_video_timings *timings = &dsi->timings;
3616 /* 3779 /*
3617 * Don't use line buffers if width is greater than the video 3780 * Don't use line buffers if width is greater than the video
3618 * port's line buffer size 3781 * port's line buffer size
@@ -3630,11 +3793,11 @@ static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
3630 REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12); 3793 REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
3631} 3794}
3632 3795
3633static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) 3796static void dsi_config_vp_sync_events(struct platform_device *dsidev)
3634{ 3797{
3635 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3798 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3636 bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; 3799 bool vsync_end = dsi->vm_timings.vp_vsync_end;
3637 bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; 3800 bool hsync_end = dsi->vm_timings.vp_hsync_end;
3638 u32 r; 3801 u32 r;
3639 3802
3640 r = dsi_read_reg(dsidev, DSI_CTRL); 3803 r = dsi_read_reg(dsidev, DSI_CTRL);
@@ -3648,13 +3811,13 @@ static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
3648 dsi_write_reg(dsidev, DSI_CTRL, r); 3811 dsi_write_reg(dsidev, DSI_CTRL, r);
3649} 3812}
3650 3813
3651static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) 3814static void dsi_config_blanking_modes(struct platform_device *dsidev)
3652{ 3815{
3653 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3816 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3654 int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode; 3817 int blanking_mode = dsi->vm_timings.blanking_mode;
3655 int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode; 3818 int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
3656 int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode; 3819 int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
3657 int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode; 3820 int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
3658 u32 r; 3821 u32 r;
3659 3822
3660 /* 3823 /*
@@ -3741,8 +3904,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3741 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; 3904 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
3742 int tclk_trail, ths_exit, exiths_clk; 3905 int tclk_trail, ths_exit, exiths_clk;
3743 bool ddr_alwon; 3906 bool ddr_alwon;
3744 struct omap_video_timings *timings = &dssdev->panel.timings; 3907 struct omap_video_timings *timings = &dsi->timings;
3745 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 3908 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3746 int ndl = dsi->num_lanes_used - 1; 3909 int ndl = dsi->num_lanes_used - 1;
3747 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1; 3910 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
3748 int hsa_interleave_hs = 0, hsa_interleave_lp = 0; 3911 int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
@@ -3852,6 +4015,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3852static int dsi_proto_config(struct omap_dss_device *dssdev) 4015static int dsi_proto_config(struct omap_dss_device *dssdev)
3853{ 4016{
3854 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4017 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4018 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3855 u32 r; 4019 u32 r;
3856 int buswidth = 0; 4020 int buswidth = 0;
3857 4021
@@ -3871,7 +4035,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3871 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); 4035 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
3872 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); 4036 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
3873 4037
3874 switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) { 4038 switch (dsi_get_pixel_size(dsi->pix_fmt)) {
3875 case 16: 4039 case 16:
3876 buswidth = 0; 4040 buswidth = 0;
3877 break; 4041 break;
@@ -3903,11 +4067,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3903 4067
3904 dsi_write_reg(dsidev, DSI_CTRL, r); 4068 dsi_write_reg(dsidev, DSI_CTRL, r);
3905 4069
3906 dsi_config_vp_num_line_buffers(dssdev); 4070 dsi_config_vp_num_line_buffers(dsidev);
3907 4071
3908 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4072 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3909 dsi_config_vp_sync_events(dssdev); 4073 dsi_config_vp_sync_events(dsidev);
3910 dsi_config_blanking_modes(dssdev); 4074 dsi_config_blanking_modes(dsidev);
3911 dsi_config_cmd_mode_interleaving(dssdev); 4075 dsi_config_cmd_mode_interleaving(dssdev);
3912 } 4076 }
3913 4077
@@ -3919,9 +4083,8 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3919 return 0; 4083 return 0;
3920} 4084}
3921 4085
3922static void dsi_proto_timings(struct omap_dss_device *dssdev) 4086static void dsi_proto_timings(struct platform_device *dsidev)
3923{ 4087{
3924 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3925 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4088 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3926 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; 4089 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
3927 unsigned tclk_pre, tclk_post; 4090 unsigned tclk_pre, tclk_post;
@@ -3941,7 +4104,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3941 ths_exit = FLD_GET(r, 7, 0); 4104 ths_exit = FLD_GET(r, 7, 0);
3942 4105
3943 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); 4106 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
3944 tlpx = FLD_GET(r, 22, 16) * 2; 4107 tlpx = FLD_GET(r, 20, 16) * 2;
3945 tclk_trail = FLD_GET(r, 15, 8); 4108 tclk_trail = FLD_GET(r, 15, 8);
3946 tclk_zero = FLD_GET(r, 7, 0); 4109 tclk_zero = FLD_GET(r, 7, 0);
3947 4110
@@ -3984,18 +4147,18 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3984 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", 4147 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
3985 enter_hs_mode_lat, exit_hs_mode_lat); 4148 enter_hs_mode_lat, exit_hs_mode_lat);
3986 4149
3987 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4150 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3988 /* TODO: Implement a video mode check_timings function */ 4151 /* TODO: Implement a video mode check_timings function */
3989 int hsa = dssdev->panel.dsi_vm_data.hsa; 4152 int hsa = dsi->vm_timings.hsa;
3990 int hfp = dssdev->panel.dsi_vm_data.hfp; 4153 int hfp = dsi->vm_timings.hfp;
3991 int hbp = dssdev->panel.dsi_vm_data.hbp; 4154 int hbp = dsi->vm_timings.hbp;
3992 int vsa = dssdev->panel.dsi_vm_data.vsa; 4155 int vsa = dsi->vm_timings.vsa;
3993 int vfp = dssdev->panel.dsi_vm_data.vfp; 4156 int vfp = dsi->vm_timings.vfp;
3994 int vbp = dssdev->panel.dsi_vm_data.vbp; 4157 int vbp = dsi->vm_timings.vbp;
3995 int window_sync = dssdev->panel.dsi_vm_data.window_sync; 4158 int window_sync = dsi->vm_timings.window_sync;
3996 bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; 4159 bool hsync_end = dsi->vm_timings.vp_hsync_end;
3997 struct omap_video_timings *timings = &dssdev->panel.timings; 4160 struct omap_video_timings *timings = &dsi->timings;
3998 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 4161 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3999 int tl, t_he, width_bytes; 4162 int tl, t_he, width_bytes;
4000 4163
4001 t_he = hsync_end ? 4164 t_he = hsync_end ?
@@ -4100,16 +4263,84 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
4100} 4263}
4101EXPORT_SYMBOL(omapdss_dsi_configure_pins); 4264EXPORT_SYMBOL(omapdss_dsi_configure_pins);
4102 4265
4103int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) 4266int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
4267 unsigned long ddr_clk, unsigned long lp_clk)
4104{ 4268{
4105 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4269 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4270 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4271 struct dsi_clock_info cinfo;
4272 struct dispc_clock_info dispc_cinfo;
4273 unsigned lp_clk_div;
4274 unsigned long dsi_fclk;
4106 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 4275 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
4276 unsigned long pck;
4277 int r;
4278
4279 DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
4280
4281 mutex_lock(&dsi->lock);
4282
4283 /* Calculate PLL output clock */
4284 r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
4285 if (r)
4286 goto err;
4287
4288 /* Calculate PLL's DSI clock */
4289 dsi_pll_calc_dsi_fck(dsidev, &cinfo);
4290
4291 /* Calculate PLL's DISPC clock and pck & lck divs */
4292 pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
4293 DSSDBG("finding dispc dividers for pck %lu\n", pck);
4294 r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
4295 if (r)
4296 goto err;
4297
4298 /* Calculate LP clock */
4299 dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
4300 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
4301
4302 dssdev->clocks.dsi.regn = cinfo.regn;
4303 dssdev->clocks.dsi.regm = cinfo.regm;
4304 dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
4305 dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
4306
4307 dssdev->clocks.dsi.lp_clk_div = lp_clk_div;
4308
4309 dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
4310 dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
4311
4312 dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
4313
4314 dssdev->clocks.dispc.channel.lcd_clk_src =
4315 dsi->module_id == 0 ?
4316 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
4317 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
4318
4319 dssdev->clocks.dsi.dsi_fclk_src =
4320 dsi->module_id == 0 ?
4321 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
4322 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
4323
4324 mutex_unlock(&dsi->lock);
4325 return 0;
4326err:
4327 mutex_unlock(&dsi->lock);
4328 return r;
4329}
4330EXPORT_SYMBOL(omapdss_dsi_set_clocks);
4331
4332int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4333{
4334 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4335 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4336 struct omap_overlay_manager *mgr = dssdev->output->manager;
4337 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
4107 u8 data_type; 4338 u8 data_type;
4108 u16 word_count; 4339 u16 word_count;
4109 int r; 4340 int r;
4110 4341
4111 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4342 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4112 switch (dssdev->panel.dsi_pix_fmt) { 4343 switch (dsi->pix_fmt) {
4113 case OMAP_DSS_DSI_FMT_RGB888: 4344 case OMAP_DSS_DSI_FMT_RGB888:
4114 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; 4345 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
4115 break; 4346 break;
@@ -4133,7 +4364,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4133 /* MODE, 1 = video mode */ 4364 /* MODE, 1 = video mode */
4134 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); 4365 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
4135 4366
4136 word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); 4367 word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
4137 4368
4138 dsi_vc_write_long_header(dsidev, channel, data_type, 4369 dsi_vc_write_long_header(dsidev, channel, data_type,
4139 word_count, 0); 4370 word_count, 0);
@@ -4142,9 +4373,9 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4142 dsi_if_enable(dsidev, true); 4373 dsi_if_enable(dsidev, true);
4143 } 4374 }
4144 4375
4145 r = dss_mgr_enable(dssdev->manager); 4376 r = dss_mgr_enable(mgr);
4146 if (r) { 4377 if (r) {
4147 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4378 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4148 dsi_if_enable(dsidev, false); 4379 dsi_if_enable(dsidev, false);
4149 dsi_vc_enable(dsidev, channel, false); 4380 dsi_vc_enable(dsidev, channel, false);
4150 } 4381 }
@@ -4159,8 +4390,10 @@ EXPORT_SYMBOL(dsi_enable_video_output);
4159void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) 4390void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
4160{ 4391{
4161 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4392 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4393 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4394 struct omap_overlay_manager *mgr = dssdev->output->manager;
4162 4395
4163 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4396 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4164 dsi_if_enable(dsidev, false); 4397 dsi_if_enable(dsidev, false);
4165 dsi_vc_enable(dsidev, channel, false); 4398 dsi_vc_enable(dsidev, channel, false);
4166 4399
@@ -4171,15 +4404,15 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
4171 dsi_if_enable(dsidev, true); 4404 dsi_if_enable(dsidev, true);
4172 } 4405 }
4173 4406
4174 dss_mgr_disable(dssdev->manager); 4407 dss_mgr_disable(mgr);
4175} 4408}
4176EXPORT_SYMBOL(dsi_disable_video_output); 4409EXPORT_SYMBOL(dsi_disable_video_output);
4177 4410
4178static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, 4411static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
4179 u16 w, u16 h)
4180{ 4412{
4181 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4413 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4182 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4414 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4415 struct omap_overlay_manager *mgr = dssdev->output->manager;
4183 unsigned bytespp; 4416 unsigned bytespp;
4184 unsigned bytespl; 4417 unsigned bytespl;
4185 unsigned bytespf; 4418 unsigned bytespf;
@@ -4190,12 +4423,14 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
4190 int r; 4423 int r;
4191 const unsigned channel = dsi->update_channel; 4424 const unsigned channel = dsi->update_channel;
4192 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 4425 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
4426 u16 w = dsi->timings.x_res;
4427 u16 h = dsi->timings.y_res;
4193 4428
4194 DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h); 4429 DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
4195 4430
4196 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); 4431 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
4197 4432
4198 bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; 4433 bytespp = dsi_get_pixel_size(dsi->pix_fmt) / 8;
4199 bytespl = w * bytespp; 4434 bytespl = w * bytespp;
4200 bytespf = bytespl * h; 4435 bytespf = bytespl * h;
4201 4436
@@ -4239,7 +4474,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
4239 msecs_to_jiffies(250)); 4474 msecs_to_jiffies(250));
4240 BUG_ON(r == 0); 4475 BUG_ON(r == 0);
4241 4476
4242 dss_mgr_start_update(dssdev->manager); 4477 dss_mgr_set_timings(mgr, &dsi->timings);
4478
4479 dss_mgr_start_update(mgr);
4243 4480
4244 if (dsi->te_enabled) { 4481 if (dsi->te_enabled) {
4245 /* disable LP_RX_TO, so that we can receive TE. Time to wait 4482 /* disable LP_RX_TO, so that we can receive TE. Time to wait
@@ -4297,8 +4534,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
4297 4534
4298static void dsi_framedone_irq_callback(void *data, u32 mask) 4535static void dsi_framedone_irq_callback(void *data, u32 mask)
4299{ 4536{
4300 struct omap_dss_device *dssdev = (struct omap_dss_device *) data; 4537 struct platform_device *dsidev = (struct platform_device *) data;
4301 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4302 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4538 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4303 4539
4304 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and 4540 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
@@ -4325,13 +4561,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
4325 dsi->framedone_callback = callback; 4561 dsi->framedone_callback = callback;
4326 dsi->framedone_data = data; 4562 dsi->framedone_data = data;
4327 4563
4328 dssdev->driver->get_resolution(dssdev, &dw, &dh); 4564 dw = dsi->timings.x_res;
4565 dh = dsi->timings.y_res;
4329 4566
4330#ifdef DEBUG 4567#ifdef DEBUG
4331 dsi->update_bytes = dw * dh * 4568 dsi->update_bytes = dw * dh *
4332 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; 4569 dsi_get_pixel_size(dsi->pix_fmt) / 8;
4333#endif 4570#endif
4334 dsi_update_screen_dispc(dssdev, dw, dh); 4571 dsi_update_screen_dispc(dssdev);
4335 4572
4336 return 0; 4573 return 0;
4337} 4574}
@@ -4367,28 +4604,22 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4367{ 4604{
4368 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4605 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4369 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4606 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4370 struct omap_video_timings timings; 4607 struct omap_overlay_manager *mgr = dssdev->output->manager;
4371 int r; 4608 int r;
4372 u32 irq = 0; 4609 u32 irq = 0;
4373 4610
4374 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4611 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4375 u16 dw, dh; 4612 dsi->timings.hsw = 1;
4376 4613 dsi->timings.hfp = 1;
4377 dssdev->driver->get_resolution(dssdev, &dw, &dh); 4614 dsi->timings.hbp = 1;
4378 4615 dsi->timings.vsw = 1;
4379 timings.x_res = dw; 4616 dsi->timings.vfp = 0;
4380 timings.y_res = dh; 4617 dsi->timings.vbp = 0;
4381 timings.hsw = 1;
4382 timings.hfp = 1;
4383 timings.hbp = 1;
4384 timings.vsw = 1;
4385 timings.vfp = 0;
4386 timings.vbp = 0;
4387 4618
4388 irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); 4619 irq = dispc_mgr_get_framedone_irq(mgr->id);
4389 4620
4390 r = omap_dispc_register_isr(dsi_framedone_irq_callback, 4621 r = omap_dispc_register_isr(dsi_framedone_irq_callback,
4391 (void *) dssdev, irq); 4622 (void *) dsidev, irq);
4392 if (r) { 4623 if (r) {
4393 DSSERR("can't get FRAMEDONE irq\n"); 4624 DSSERR("can't get FRAMEDONE irq\n");
4394 goto err; 4625 goto err;
@@ -4397,8 +4628,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4397 dsi->mgr_config.stallmode = true; 4628 dsi->mgr_config.stallmode = true;
4398 dsi->mgr_config.fifohandcheck = true; 4629 dsi->mgr_config.fifohandcheck = true;
4399 } else { 4630 } else {
4400 timings = dssdev->panel.timings;
4401
4402 dsi->mgr_config.stallmode = false; 4631 dsi->mgr_config.stallmode = false;
4403 dsi->mgr_config.fifohandcheck = false; 4632 dsi->mgr_config.fifohandcheck = false;
4404 } 4633 }
@@ -4407,14 +4636,14 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4407 * override interlace, logic level and edge related parameters in 4636 * override interlace, logic level and edge related parameters in
4408 * omap_video_timings with default values 4637 * omap_video_timings with default values
4409 */ 4638 */
4410 timings.interlace = false; 4639 dsi->timings.interlace = false;
4411 timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; 4640 dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4412 timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; 4641 dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4413 timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 4642 dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
4414 timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; 4643 dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
4415 timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; 4644 dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
4416 4645
4417 dss_mgr_set_timings(dssdev->manager, &timings); 4646 dss_mgr_set_timings(mgr, &dsi->timings);
4418 4647
4419 r = dsi_configure_dispc_clocks(dssdev); 4648 r = dsi_configure_dispc_clocks(dssdev);
4420 if (r) 4649 if (r)
@@ -4422,29 +4651,33 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4422 4651
4423 dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 4652 dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
4424 dsi->mgr_config.video_port_width = 4653 dsi->mgr_config.video_port_width =
4425 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 4654 dsi_get_pixel_size(dsi->pix_fmt);
4426 dsi->mgr_config.lcden_sig_polarity = 0; 4655 dsi->mgr_config.lcden_sig_polarity = 0;
4427 4656
4428 dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config); 4657 dss_mgr_set_lcd_config(mgr, &dsi->mgr_config);
4429 4658
4430 return 0; 4659 return 0;
4431err1: 4660err1:
4432 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) 4661 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4433 omap_dispc_unregister_isr(dsi_framedone_irq_callback, 4662 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4434 (void *) dssdev, irq); 4663 (void *) dsidev, irq);
4435err: 4664err:
4436 return r; 4665 return r;
4437} 4666}
4438 4667
4439static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) 4668static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
4440{ 4669{
4441 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4670 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4671 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4672 struct omap_overlay_manager *mgr = dssdev->output->manager;
4673
4674 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4442 u32 irq; 4675 u32 irq;
4443 4676
4444 irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); 4677 irq = dispc_mgr_get_framedone_irq(mgr->id);
4445 4678
4446 omap_dispc_unregister_isr(dsi_framedone_irq_callback, 4679 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4447 (void *) dssdev, irq); 4680 (void *) dsidev, irq);
4448 } 4681 }
4449} 4682}
4450 4683
@@ -4477,6 +4710,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4477{ 4710{
4478 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4711 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4479 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4712 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4713 struct omap_overlay_manager *mgr = dssdev->output->manager;
4480 int r; 4714 int r;
4481 4715
4482 r = dsi_pll_init(dsidev, true, true); 4716 r = dsi_pll_init(dsidev, true, true);
@@ -4489,18 +4723,18 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4489 4723
4490 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); 4724 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
4491 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); 4725 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
4492 dss_select_lcd_clk_source(dssdev->manager->id, 4726 dss_select_lcd_clk_source(mgr->id,
4493 dssdev->clocks.dispc.channel.lcd_clk_src); 4727 dssdev->clocks.dispc.channel.lcd_clk_src);
4494 4728
4495 DSSDBG("PLL OK\n"); 4729 DSSDBG("PLL OK\n");
4496 4730
4497 r = dsi_cio_init(dssdev); 4731 r = dsi_cio_init(dsidev);
4498 if (r) 4732 if (r)
4499 goto err2; 4733 goto err2;
4500 4734
4501 _dsi_print_reset_status(dsidev); 4735 _dsi_print_reset_status(dsidev);
4502 4736
4503 dsi_proto_timings(dssdev); 4737 dsi_proto_timings(dsidev);
4504 dsi_set_lp_clk_divisor(dssdev); 4738 dsi_set_lp_clk_divisor(dssdev);
4505 4739
4506 if (1) 4740 if (1)
@@ -4520,11 +4754,11 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4520 4754
4521 return 0; 4755 return 0;
4522err3: 4756err3:
4523 dsi_cio_uninit(dssdev); 4757 dsi_cio_uninit(dsidev);
4524err2: 4758err2:
4525 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4759 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4526 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4760 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4527 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); 4761 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4528 4762
4529err1: 4763err1:
4530 dsi_pll_uninit(dsidev, true); 4764 dsi_pll_uninit(dsidev, true);
@@ -4537,6 +4771,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4537{ 4771{
4538 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4772 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4539 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4773 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4774 struct omap_overlay_manager *mgr = dssdev->output->manager;
4540 4775
4541 if (enter_ulps && !dsi->ulps_enabled) 4776 if (enter_ulps && !dsi->ulps_enabled)
4542 dsi_enter_ulps(dsidev); 4777 dsi_enter_ulps(dsidev);
@@ -4550,8 +4785,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4550 4785
4551 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4786 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4552 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4787 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4553 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); 4788 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4554 dsi_cio_uninit(dssdev); 4789 dsi_cio_uninit(dsidev);
4555 dsi_pll_uninit(dsidev, disconnect_lanes); 4790 dsi_pll_uninit(dsidev, disconnect_lanes);
4556} 4791}
4557 4792
@@ -4559,6 +4794,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4559{ 4794{
4560 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4795 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4561 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4796 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4797 struct omap_dss_output *out = dssdev->output;
4562 int r = 0; 4798 int r = 0;
4563 4799
4564 DSSDBG("dsi_display_enable\n"); 4800 DSSDBG("dsi_display_enable\n");
@@ -4567,8 +4803,8 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4567 4803
4568 mutex_lock(&dsi->lock); 4804 mutex_lock(&dsi->lock);
4569 4805
4570 if (dssdev->manager == NULL) { 4806 if (out == NULL || out->manager == NULL) {
4571 DSSERR("failed to enable display: no manager\n"); 4807 DSSERR("failed to enable display: no output/manager\n");
4572 r = -ENODEV; 4808 r = -ENODEV;
4573 goto err_start_dev; 4809 goto err_start_dev;
4574 } 4810 }
@@ -4653,17 +4889,83 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
4653} 4889}
4654EXPORT_SYMBOL(omapdss_dsi_enable_te); 4890EXPORT_SYMBOL(omapdss_dsi_enable_te);
4655 4891
4656static int __init dsi_init_display(struct omap_dss_device *dssdev) 4892void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
4893 struct omap_video_timings *timings)
4657{ 4894{
4658 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4895 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4659 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4896 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4660 4897
4661 DSSDBG("DSI init\n"); 4898 mutex_lock(&dsi->lock);
4662 4899
4663 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4900 dsi->timings = *timings;
4664 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | 4901
4665 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; 4902 mutex_unlock(&dsi->lock);
4666 } 4903}
4904EXPORT_SYMBOL(omapdss_dsi_set_timings);
4905
4906void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
4907{
4908 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4909 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4910
4911 mutex_lock(&dsi->lock);
4912
4913 dsi->timings.x_res = w;
4914 dsi->timings.y_res = h;
4915
4916 mutex_unlock(&dsi->lock);
4917}
4918EXPORT_SYMBOL(omapdss_dsi_set_size);
4919
4920void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
4921 enum omap_dss_dsi_pixel_format fmt)
4922{
4923 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4924 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4925
4926 mutex_lock(&dsi->lock);
4927
4928 dsi->pix_fmt = fmt;
4929
4930 mutex_unlock(&dsi->lock);
4931}
4932EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
4933
4934void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
4935 enum omap_dss_dsi_mode mode)
4936{
4937 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4938 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4939
4940 mutex_lock(&dsi->lock);
4941
4942 dsi->mode = mode;
4943
4944 mutex_unlock(&dsi->lock);
4945}
4946EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
4947
4948void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
4949 struct omap_dss_dsi_videomode_timings *timings)
4950{
4951 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4952 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4953
4954 mutex_lock(&dsi->lock);
4955
4956 dsi->vm_timings = *timings;
4957
4958 mutex_unlock(&dsi->lock);
4959}
4960EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
4961
4962static int __init dsi_init_display(struct omap_dss_device *dssdev)
4963{
4964 struct platform_device *dsidev =
4965 dsi_get_dsidev_from_id(dssdev->phy.dsi.module);
4966 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4967
4968 DSSDBG("DSI init\n");
4667 4969
4668 if (dsi->vdds_dsi_reg == NULL) { 4970 if (dsi->vdds_dsi_reg == NULL) {
4669 struct regulator *vdds_dsi; 4971 struct regulator *vdds_dsi;
@@ -4806,11 +5108,15 @@ static void dsi_put_clocks(struct platform_device *dsidev)
4806 clk_put(dsi->sys_clk); 5108 clk_put(dsi->sys_clk);
4807} 5109}
4808 5110
4809static void __init dsi_probe_pdata(struct platform_device *dsidev) 5111static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
4810{ 5112{
4811 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5113 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
4812 struct omap_dss_board_info *pdata = dsidev->dev.platform_data; 5114 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
4813 int i, r; 5115 const char *def_disp_name = dss_get_default_display_name();
5116 struct omap_dss_device *def_dssdev;
5117 int i;
5118
5119 def_dssdev = NULL;
4814 5120
4815 for (i = 0; i < pdata->num_devices; ++i) { 5121 for (i = 0; i < pdata->num_devices; ++i) {
4816 struct omap_dss_device *dssdev = pdata->devices[i]; 5122 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -4821,19 +5127,73 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
4821 if (dssdev->phy.dsi.module != dsi->module_id) 5127 if (dssdev->phy.dsi.module != dsi->module_id)
4822 continue; 5128 continue;
4823 5129
4824 r = dsi_init_display(dssdev); 5130 if (def_dssdev == NULL)
4825 if (r) { 5131 def_dssdev = dssdev;
4826 DSSERR("device %s init failed: %d\n", dssdev->name, r); 5132
4827 continue; 5133 if (def_disp_name != NULL &&
5134 strcmp(dssdev->name, def_disp_name) == 0) {
5135 def_dssdev = dssdev;
5136 break;
4828 } 5137 }
5138 }
4829 5139
4830 r = omap_dss_register_device(dssdev, &dsidev->dev, i); 5140 return def_dssdev;
4831 if (r) 5141}
4832 DSSERR("device %s register failed: %d\n", 5142
4833 dssdev->name, r); 5143static void __init dsi_probe_pdata(struct platform_device *dsidev)
5144{
5145 struct omap_dss_device *plat_dssdev;
5146 struct omap_dss_device *dssdev;
5147 int r;
5148
5149 plat_dssdev = dsi_find_dssdev(dsidev);
5150
5151 if (!plat_dssdev)
5152 return;
5153
5154 dssdev = dss_alloc_and_init_device(&dsidev->dev);
5155 if (!dssdev)
5156 return;
5157
5158 dss_copy_device_pdata(dssdev, plat_dssdev);
5159
5160 r = dsi_init_display(dssdev);
5161 if (r) {
5162 DSSERR("device %s init failed: %d\n", dssdev->name, r);
5163 dss_put_device(dssdev);
5164 return;
5165 }
5166
5167 r = dss_add_device(dssdev);
5168 if (r) {
5169 DSSERR("device %s register failed: %d\n", dssdev->name, r);
5170 dss_put_device(dssdev);
5171 return;
4834 } 5172 }
4835} 5173}
4836 5174
5175static void __init dsi_init_output(struct platform_device *dsidev)
5176{
5177 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5178 struct omap_dss_output *out = &dsi->output;
5179
5180 out->pdev = dsidev;
5181 out->id = dsi->module_id == 0 ?
5182 OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
5183
5184 out->type = OMAP_DISPLAY_TYPE_DSI;
5185
5186 dss_register_output(out);
5187}
5188
5189static void __exit dsi_uninit_output(struct platform_device *dsidev)
5190{
5191 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5192 struct omap_dss_output *out = &dsi->output;
5193
5194 dss_unregister_output(out);
5195}
5196
4837/* DSI1 HW IP initialisation */ 5197/* DSI1 HW IP initialisation */
4838static int __init omap_dsihw_probe(struct platform_device *dsidev) 5198static int __init omap_dsihw_probe(struct platform_device *dsidev)
4839{ 5199{
@@ -4848,7 +5208,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
4848 5208
4849 dsi->module_id = dsidev->id; 5209 dsi->module_id = dsidev->id;
4850 dsi->pdev = dsidev; 5210 dsi->pdev = dsidev;
4851 dsi_pdev_map[dsi->module_id] = dsidev;
4852 dev_set_drvdata(&dsidev->dev, dsi); 5211 dev_set_drvdata(&dsidev->dev, dsi);
4853 5212
4854 spin_lock_init(&dsi->irq_lock); 5213 spin_lock_init(&dsi->irq_lock);
@@ -4928,6 +5287,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
4928 else 5287 else
4929 dsi->num_lanes_supported = 3; 5288 dsi->num_lanes_supported = 3;
4930 5289
5290 dsi_init_output(dsidev);
5291
4931 dsi_probe_pdata(dsidev); 5292 dsi_probe_pdata(dsidev);
4932 5293
4933 dsi_runtime_put(dsidev); 5294 dsi_runtime_put(dsidev);
@@ -4957,7 +5318,9 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
4957 5318
4958 WARN_ON(dsi->scp_clk_refcount > 0); 5319 WARN_ON(dsi->scp_clk_refcount > 0);
4959 5320
4960 omap_dss_unregister_child_devices(&dsidev->dev); 5321 dss_unregister_child_devices(&dsidev->dev);
5322
5323 dsi_uninit_output(dsidev);
4961 5324
4962 pm_runtime_disable(&dsidev->dev); 5325 pm_runtime_disable(&dsidev->dev);
4963 5326
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 04b4586113e3..2ab1c3e96553 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -31,11 +31,11 @@
31#include <linux/clk.h> 31#include <linux/clk.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/gfp.h>
34 35
35#include <video/omapdss.h> 36#include <video/omapdss.h>
36 37
37#include <plat/cpu.h> 38#include <plat/cpu.h>
38#include <plat/clock.h>
39 39
40#include "dss.h" 40#include "dss.h"
41#include "dss_features.h" 41#include "dss_features.h"
@@ -65,6 +65,13 @@ struct dss_reg {
65static int dss_runtime_get(void); 65static int dss_runtime_get(void);
66static void dss_runtime_put(void); 66static void dss_runtime_put(void);
67 67
68struct dss_features {
69 u8 fck_div_max;
70 u8 dss_fck_multiplier;
71 const char *clk_name;
72 int (*dpi_select_source)(enum omap_channel channel);
73};
74
68static struct { 75static struct {
69 struct platform_device *pdev; 76 struct platform_device *pdev;
70 void __iomem *base; 77 void __iomem *base;
@@ -83,6 +90,8 @@ static struct {
83 90
84 bool ctx_valid; 91 bool ctx_valid;
85 u32 ctx[DSS_SZ_REGS / sizeof(u32)]; 92 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
93
94 const struct dss_features *feat;
86} dss; 95} dss;
87 96
88static const char * const dss_generic_clk_source_names[] = { 97static const char * const dss_generic_clk_source_names[] = {
@@ -144,7 +153,7 @@ static void dss_restore_context(void)
144#undef SR 153#undef SR
145#undef RR 154#undef RR
146 155
147void dss_sdi_init(u8 datapairs) 156void dss_sdi_init(int datapairs)
148{ 157{
149 u32 l; 158 u32 l;
150 159
@@ -236,7 +245,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
236 return dss_generic_clk_source_names[clk_src]; 245 return dss_generic_clk_source_names[clk_src];
237} 246}
238 247
239
240void dss_dump_clocks(struct seq_file *s) 248void dss_dump_clocks(struct seq_file *s)
241{ 249{
242 unsigned long dpll4_ck_rate; 250 unsigned long dpll4_ck_rate;
@@ -259,18 +267,10 @@ void dss_dump_clocks(struct seq_file *s)
259 267
260 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); 268 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
261 269
262 if (cpu_is_omap3630() || cpu_is_omap44xx()) 270 seq_printf(s, "%s (%s) = %lu / %lu * %d = %lu\n",
263 seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", 271 fclk_name, fclk_real_name, dpll4_ck_rate,
264 fclk_name, fclk_real_name, 272 dpll4_ck_rate / dpll4_m4_ck_rate,
265 dpll4_ck_rate, 273 dss.feat->dss_fck_multiplier, fclk_rate);
266 dpll4_ck_rate / dpll4_m4_ck_rate,
267 fclk_rate);
268 else
269 seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
270 fclk_name, fclk_real_name,
271 dpll4_ck_rate,
272 dpll4_ck_rate / dpll4_m4_ck_rate,
273 fclk_rate);
274 } else { 274 } else {
275 seq_printf(s, "%s (%s) = %lu\n", 275 seq_printf(s, "%s (%s) = %lu\n",
276 fclk_name, fclk_real_name, 276 fclk_name, fclk_real_name,
@@ -431,31 +431,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
431 } 431 }
432} 432}
433 433
434/* calculate clock rates using dividers in cinfo */
435int dss_calc_clock_rates(struct dss_clock_info *cinfo)
436{
437 if (dss.dpll4_m4_ck) {
438 unsigned long prate;
439 u16 fck_div_max = 16;
440
441 if (cpu_is_omap3630() || cpu_is_omap44xx())
442 fck_div_max = 32;
443
444 if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
445 return -EINVAL;
446
447 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
448
449 cinfo->fck = prate / cinfo->fck_div;
450 } else {
451 if (cinfo->fck_div != 0)
452 return -EINVAL;
453 cinfo->fck = clk_get_rate(dss.dss_clk);
454 }
455
456 return 0;
457}
458
459int dss_set_clock_div(struct dss_clock_info *cinfo) 434int dss_set_clock_div(struct dss_clock_info *cinfo)
460{ 435{
461 if (dss.dpll4_m4_ck) { 436 if (dss.dpll4_m4_ck) {
@@ -478,26 +453,6 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
478 return 0; 453 return 0;
479} 454}
480 455
481int dss_get_clock_div(struct dss_clock_info *cinfo)
482{
483 cinfo->fck = clk_get_rate(dss.dss_clk);
484
485 if (dss.dpll4_m4_ck) {
486 unsigned long prate;
487
488 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
489
490 if (cpu_is_omap3630() || cpu_is_omap44xx())
491 cinfo->fck_div = prate / (cinfo->fck);
492 else
493 cinfo->fck_div = prate / (cinfo->fck / 2);
494 } else {
495 cinfo->fck_div = 0;
496 }
497
498 return 0;
499}
500
501unsigned long dss_get_dpll4_rate(void) 456unsigned long dss_get_dpll4_rate(void)
502{ 457{
503 if (dss.dpll4_m4_ck) 458 if (dss.dpll4_m4_ck)
@@ -515,7 +470,7 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
515 470
516 unsigned long fck, max_dss_fck; 471 unsigned long fck, max_dss_fck;
517 472
518 u16 fck_div, fck_div_max = 16; 473 u16 fck_div;
519 474
520 int match = 0; 475 int match = 0;
521 int min_fck_per_pck; 476 int min_fck_per_pck;
@@ -525,9 +480,8 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
525 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 480 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
526 481
527 fck = clk_get_rate(dss.dss_clk); 482 fck = clk_get_rate(dss.dss_clk);
528 if (req_pck == dss.cache_req_pck && 483 if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
529 ((cpu_is_omap34xx() && prate == dss.cache_prate) || 484 dss.cache_dss_cinfo.fck == fck) {
530 dss.cache_dss_cinfo.fck == fck)) {
531 DSSDBG("dispc clock info found from cache.\n"); 485 DSSDBG("dispc clock info found from cache.\n");
532 *dss_cinfo = dss.cache_dss_cinfo; 486 *dss_cinfo = dss.cache_dss_cinfo;
533 *dispc_cinfo = dss.cache_dispc_cinfo; 487 *dispc_cinfo = dss.cache_dispc_cinfo;
@@ -564,16 +518,10 @@ retry:
564 518
565 goto found; 519 goto found;
566 } else { 520 } else {
567 if (cpu_is_omap3630() || cpu_is_omap44xx()) 521 for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
568 fck_div_max = 32;
569
570 for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
571 struct dispc_clock_info cur_dispc; 522 struct dispc_clock_info cur_dispc;
572 523
573 if (fck_div_max == 32) 524 fck = prate / fck_div * dss.feat->dss_fck_multiplier;
574 fck = prate / fck_div;
575 else
576 fck = prate / fck_div * 2;
577 525
578 if (fck > max_dss_fck) 526 if (fck > max_dss_fck)
579 continue; 527 continue;
@@ -648,9 +596,18 @@ void dss_set_dac_pwrdn_bgz(bool enable)
648 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ 596 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
649} 597}
650 598
651void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) 599void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
652{ 600{
653 REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ 601 enum omap_display_type dp;
602 dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
603
604 /* Complain about invalid selections */
605 WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
606 WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
607
608 /* Select only if we have options */
609 if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
610 REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */
654} 611}
655 612
656enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) 613enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
@@ -661,9 +618,71 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
661 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0) 618 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
662 return DSS_VENC_TV_CLK; 619 return DSS_VENC_TV_CLK;
663 620
621 if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
622 return DSS_HDMI_M_PCLK;
623
664 return REG_GET(DSS_CONTROL, 15, 15); 624 return REG_GET(DSS_CONTROL, 15, 15);
665} 625}
666 626
627static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
628{
629 if (channel != OMAP_DSS_CHANNEL_LCD)
630 return -EINVAL;
631
632 return 0;
633}
634
635static int dss_dpi_select_source_omap4(enum omap_channel channel)
636{
637 int val;
638
639 switch (channel) {
640 case OMAP_DSS_CHANNEL_LCD2:
641 val = 0;
642 break;
643 case OMAP_DSS_CHANNEL_DIGIT:
644 val = 1;
645 break;
646 default:
647 return -EINVAL;
648 }
649
650 REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
651
652 return 0;
653}
654
655static int dss_dpi_select_source_omap5(enum omap_channel channel)
656{
657 int val;
658
659 switch (channel) {
660 case OMAP_DSS_CHANNEL_LCD:
661 val = 1;
662 break;
663 case OMAP_DSS_CHANNEL_LCD2:
664 val = 2;
665 break;
666 case OMAP_DSS_CHANNEL_LCD3:
667 val = 3;
668 break;
669 case OMAP_DSS_CHANNEL_DIGIT:
670 val = 0;
671 break;
672 default:
673 return -EINVAL;
674 }
675
676 REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
677
678 return 0;
679}
680
681int dss_dpi_select_source(enum omap_channel channel)
682{
683 return dss.feat->dpi_select_source(channel);
684}
685
667static int dss_get_clocks(void) 686static int dss_get_clocks(void)
668{ 687{
669 struct clk *clk; 688 struct clk *clk;
@@ -678,22 +697,11 @@ static int dss_get_clocks(void)
678 697
679 dss.dss_clk = clk; 698 dss.dss_clk = clk;
680 699
681 if (cpu_is_omap34xx()) { 700 clk = clk_get(NULL, dss.feat->clk_name);
682 clk = clk_get(NULL, "dpll4_m4_ck"); 701 if (IS_ERR(clk)) {
683 if (IS_ERR(clk)) { 702 DSSERR("Failed to get %s\n", dss.feat->clk_name);
684 DSSERR("Failed to get dpll4_m4_ck\n"); 703 r = PTR_ERR(clk);
685 r = PTR_ERR(clk); 704 goto err;
686 goto err;
687 }
688 } else if (cpu_is_omap44xx()) {
689 clk = clk_get(NULL, "dpll_per_m5x2_ck");
690 if (IS_ERR(clk)) {
691 DSSERR("Failed to get dpll_per_m5x2_ck\n");
692 r = PTR_ERR(clk);
693 goto err;
694 }
695 } else { /* omap24xx */
696 clk = NULL;
697 } 705 }
698 706
699 dss.dpll4_m4_ck = clk; 707 dss.dpll4_m4_ck = clk;
@@ -749,6 +757,71 @@ void dss_debug_dump_clocks(struct seq_file *s)
749} 757}
750#endif 758#endif
751 759
760static const struct dss_features omap24xx_dss_feats __initconst = {
761 .fck_div_max = 16,
762 .dss_fck_multiplier = 2,
763 .clk_name = NULL,
764 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
765};
766
767static const struct dss_features omap34xx_dss_feats __initconst = {
768 .fck_div_max = 16,
769 .dss_fck_multiplier = 2,
770 .clk_name = "dpll4_m4_ck",
771 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
772};
773
774static const struct dss_features omap3630_dss_feats __initconst = {
775 .fck_div_max = 32,
776 .dss_fck_multiplier = 1,
777 .clk_name = "dpll4_m4_ck",
778 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
779};
780
781static const struct dss_features omap44xx_dss_feats __initconst = {
782 .fck_div_max = 32,
783 .dss_fck_multiplier = 1,
784 .clk_name = "dpll_per_m5x2_ck",
785 .dpi_select_source = &dss_dpi_select_source_omap4,
786};
787
788static const struct dss_features omap54xx_dss_feats __initconst = {
789 .fck_div_max = 64,
790 .dss_fck_multiplier = 1,
791 .clk_name = "dpll_per_h12x2_ck",
792 .dpi_select_source = &dss_dpi_select_source_omap5,
793};
794
795static int __init dss_init_features(struct device *dev)
796{
797 const struct dss_features *src;
798 struct dss_features *dst;
799
800 dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
801 if (!dst) {
802 dev_err(dev, "Failed to allocate local DSS Features\n");
803 return -ENOMEM;
804 }
805
806 if (cpu_is_omap24xx())
807 src = &omap24xx_dss_feats;
808 else if (cpu_is_omap34xx())
809 src = &omap34xx_dss_feats;
810 else if (cpu_is_omap3630())
811 src = &omap3630_dss_feats;
812 else if (cpu_is_omap44xx())
813 src = &omap44xx_dss_feats;
814 else if (soc_is_omap54xx())
815 src = &omap54xx_dss_feats;
816 else
817 return -ENODEV;
818
819 memcpy(dst, src, sizeof(*dst));
820 dss.feat = dst;
821
822 return 0;
823}
824
752/* DSS HW IP initialisation */ 825/* DSS HW IP initialisation */
753static int __init omap_dsshw_probe(struct platform_device *pdev) 826static int __init omap_dsshw_probe(struct platform_device *pdev)
754{ 827{
@@ -758,6 +831,10 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
758 831
759 dss.pdev = pdev; 832 dss.pdev = pdev;
760 833
834 r = dss_init_features(&dss.pdev->dev);
835 if (r)
836 return r;
837
761 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); 838 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
762 if (!dss_mem) { 839 if (!dss_mem) {
763 DSSERR("can't get IORESOURCE_MEM DSS\n"); 840 DSSERR("can't get IORESOURCE_MEM DSS\n");
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index f67afe76f217..6728892f9dad 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -113,6 +113,17 @@ enum dss_dsi_content_type {
113 DSS_DSI_CONTENT_GENERIC, 113 DSS_DSI_CONTENT_GENERIC,
114}; 114};
115 115
116enum dss_writeback_channel {
117 DSS_WB_LCD1_MGR = 0,
118 DSS_WB_LCD2_MGR = 1,
119 DSS_WB_TV_MGR = 2,
120 DSS_WB_OVL0 = 3,
121 DSS_WB_OVL1 = 4,
122 DSS_WB_OVL2 = 5,
123 DSS_WB_OVL3 = 6,
124 DSS_WB_LCD3_MGR = 7,
125};
126
116struct dss_clock_info { 127struct dss_clock_info {
117 /* rates that we get with dividers below */ 128 /* rates that we get with dividers below */
118 unsigned long fck; 129 unsigned long fck;
@@ -175,6 +186,7 @@ struct seq_file;
175struct platform_device; 186struct platform_device;
176 187
177/* core */ 188/* core */
189const char *dss_get_default_display_name(void);
178struct bus_type *dss_get_bus(void); 190struct bus_type *dss_get_bus(void);
179struct regulator *dss_get_vdds_dsi(void); 191struct regulator *dss_get_vdds_dsi(void);
180struct regulator *dss_get_vdds_sdi(void); 192struct regulator *dss_get_vdds_sdi(void);
@@ -184,10 +196,13 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
184int dss_set_min_bus_tput(struct device *dev, unsigned long tput); 196int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
185int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); 197int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
186 198
187int omap_dss_register_device(struct omap_dss_device *dssdev, 199struct omap_dss_device *dss_alloc_and_init_device(struct device *parent);
188 struct device *parent, int disp_num); 200int dss_add_device(struct omap_dss_device *dssdev);
189void omap_dss_unregister_device(struct omap_dss_device *dssdev); 201void dss_unregister_device(struct omap_dss_device *dssdev);
190void omap_dss_unregister_child_devices(struct device *parent); 202void dss_unregister_child_devices(struct device *parent);
203void dss_put_device(struct omap_dss_device *dssdev);
204void dss_copy_device_pdata(struct omap_dss_device *dst,
205 const struct omap_dss_device *src);
191 206
192/* apply */ 207/* apply */
193void dss_apply_init(void); 208void dss_apply_init(void);
@@ -205,8 +220,11 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
205int dss_mgr_set_device(struct omap_overlay_manager *mgr, 220int dss_mgr_set_device(struct omap_overlay_manager *mgr,
206 struct omap_dss_device *dssdev); 221 struct omap_dss_device *dssdev);
207int dss_mgr_unset_device(struct omap_overlay_manager *mgr); 222int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
223int dss_mgr_set_output(struct omap_overlay_manager *mgr,
224 struct omap_dss_output *output);
225int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
208void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 226void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
209 struct omap_video_timings *timings); 227 const struct omap_video_timings *timings);
210void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, 228void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
211 const struct dss_lcd_mgr_config *config); 229 const struct dss_lcd_mgr_config *config);
212const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr); 230const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
@@ -222,12 +240,17 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
222 struct omap_overlay_manager *mgr); 240 struct omap_overlay_manager *mgr);
223int dss_ovl_unset_manager(struct omap_overlay *ovl); 241int dss_ovl_unset_manager(struct omap_overlay *ovl);
224 242
243/* output */
244void dss_register_output(struct omap_dss_output *out);
245void dss_unregister_output(struct omap_dss_output *out);
246struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev);
247
225/* display */ 248/* display */
226int dss_suspend_all_devices(void); 249int dss_suspend_all_devices(void);
227int dss_resume_all_devices(void); 250int dss_resume_all_devices(void);
228void dss_disable_all_devices(void); 251void dss_disable_all_devices(void);
229 252
230void dss_init_device(struct platform_device *pdev, 253int dss_init_device(struct platform_device *pdev,
231 struct omap_dss_device *dssdev); 254 struct omap_dss_device *dssdev);
232void dss_uninit_device(struct platform_device *pdev, 255void dss_uninit_device(struct platform_device *pdev,
233 struct omap_dss_device *dssdev); 256 struct omap_dss_device *dssdev);
@@ -254,22 +277,29 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id)
254 return false; 277 return false;
255} 278}
256 279
280int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
281 struct platform_device *pdev);
282void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
283
257/* overlay */ 284/* overlay */
258void dss_init_overlays(struct platform_device *pdev); 285void dss_init_overlays(struct platform_device *pdev);
259void dss_uninit_overlays(struct platform_device *pdev); 286void dss_uninit_overlays(struct platform_device *pdev);
260void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); 287void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
261void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
262int dss_ovl_simple_check(struct omap_overlay *ovl, 288int dss_ovl_simple_check(struct omap_overlay *ovl,
263 const struct omap_overlay_info *info); 289 const struct omap_overlay_info *info);
264int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, 290int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
265 const struct omap_video_timings *mgr_timings); 291 const struct omap_video_timings *mgr_timings);
266bool dss_ovl_use_replication(struct dss_lcd_mgr_config config, 292bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
267 enum omap_color_mode mode); 293 enum omap_color_mode mode);
294int dss_overlay_kobj_init(struct omap_overlay *ovl,
295 struct platform_device *pdev);
296void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
268 297
269/* DSS */ 298/* DSS */
270int dss_init_platform_driver(void) __init; 299int dss_init_platform_driver(void) __init;
271void dss_uninit_platform_driver(void); 300void dss_uninit_platform_driver(void);
272 301
302int dss_dpi_select_source(enum omap_channel channel);
273void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 303void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
274enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); 304enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
275const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 305const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
@@ -279,7 +309,7 @@ void dss_dump_clocks(struct seq_file *s);
279void dss_debug_dump_clocks(struct seq_file *s); 309void dss_debug_dump_clocks(struct seq_file *s);
280#endif 310#endif
281 311
282void dss_sdi_init(u8 datapairs); 312void dss_sdi_init(int datapairs);
283int dss_sdi_enable(void); 313int dss_sdi_enable(void);
284void dss_sdi_disable(void); 314void dss_sdi_disable(void);
285 315
@@ -296,9 +326,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
296void dss_set_dac_pwrdn_bgz(bool enable); 326void dss_set_dac_pwrdn_bgz(bool enable);
297 327
298unsigned long dss_get_dpll4_rate(void); 328unsigned long dss_get_dpll4_rate(void);
299int dss_calc_clock_rates(struct dss_clock_info *cinfo);
300int dss_set_clock_div(struct dss_clock_info *cinfo); 329int dss_set_clock_div(struct dss_clock_info *cinfo);
301int dss_get_clock_div(struct dss_clock_info *cinfo);
302int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, 330int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
303 struct dispc_clock_info *dispc_cinfo); 331 struct dispc_clock_info *dispc_cinfo);
304 332
@@ -427,8 +455,9 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
427void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, 455void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
428 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, 456 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
429 bool manual_update); 457 bool manual_update);
430int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 458int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
431 bool replication, const struct omap_video_timings *mgr_timings); 459 bool replication, const struct omap_video_timings *mgr_timings,
460 bool mem_to_mem);
432int dispc_ovl_enable(enum omap_plane plane, bool enable); 461int dispc_ovl_enable(enum omap_plane plane, bool enable);
433void dispc_ovl_set_channel_out(enum omap_plane plane, 462void dispc_ovl_set_channel_out(enum omap_plane plane,
434 enum omap_channel channel); 463 enum omap_channel channel);
@@ -457,6 +486,15 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
457void dispc_mgr_setup(enum omap_channel channel, 486void dispc_mgr_setup(enum omap_channel channel,
458 struct omap_overlay_manager_info *info); 487 struct omap_overlay_manager_info *info);
459 488
489u32 dispc_wb_get_framedone_irq(void);
490bool dispc_wb_go_busy(void);
491void dispc_wb_go(void);
492void dispc_wb_enable(bool enable);
493bool dispc_wb_is_enabled(void);
494void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
495int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
496 bool mem_to_mem, const struct omap_video_timings *timings);
497
460/* VENC */ 498/* VENC */
461#ifdef CONFIG_OMAP2_DSS_VENC 499#ifdef CONFIG_OMAP2_DSS_VENC
462int venc_init_platform_driver(void) __init; 500int venc_init_platform_driver(void) __init;
@@ -469,6 +507,20 @@ static inline unsigned long venc_get_pixel_clock(void)
469 return 0; 507 return 0;
470} 508}
471#endif 509#endif
510int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
511void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
512void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
513 struct omap_video_timings *timings);
514int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
515 struct omap_video_timings *timings);
516u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
517int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
518void omapdss_venc_set_type(struct omap_dss_device *dssdev,
519 enum omap_dss_venc_type type);
520void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
521 bool invert_polarity);
522int venc_panel_init(void);
523void venc_panel_exit(void);
472 524
473/* HDMI */ 525/* HDMI */
474#ifdef CONFIG_OMAP4_DSS_HDMI 526#ifdef CONFIG_OMAP4_DSS_HDMI
@@ -484,7 +536,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
484#endif 536#endif
485int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); 537int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
486void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); 538void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
487void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); 539void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
540 struct omap_video_timings *timings);
488int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 541int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
489 struct omap_video_timings *timings); 542 struct omap_video_timings *timings);
490int omapdss_hdmi_read_edid(u8 *buf, int len); 543int omapdss_hdmi_read_edid(u8 *buf, int len);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 938709724f0c..acbc1e1efba3 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -46,7 +46,9 @@ struct omap_dss_features {
46 46
47 const int num_mgrs; 47 const int num_mgrs;
48 const int num_ovls; 48 const int num_ovls;
49 const int num_wbs;
49 const enum omap_display_type *supported_displays; 50 const enum omap_display_type *supported_displays;
51 const enum omap_dss_output_id *supported_outputs;
50 const enum omap_color_mode *supported_color_modes; 52 const enum omap_color_mode *supported_color_modes;
51 const enum omap_overlay_caps *overlay_caps; 53 const enum omap_overlay_caps *overlay_caps;
52 const char * const *clksrc_names; 54 const char * const *clksrc_names;
@@ -106,6 +108,21 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
106 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, 108 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
107}; 109};
108 110
111static const struct dss_reg_field omap5_dss_reg_fields[] = {
112 [FEAT_REG_FIRHINC] = { 12, 0 },
113 [FEAT_REG_FIRVINC] = { 28, 16 },
114 [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
115 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
116 [FEAT_REG_FIFOSIZE] = { 15, 0 },
117 [FEAT_REG_HORIZONTALACCU] = { 10, 0 },
118 [FEAT_REG_VERTICALACCU] = { 26, 16 },
119 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 },
120 [FEAT_REG_DSIPLL_REGN] = { 8, 1 },
121 [FEAT_REG_DSIPLL_REGM] = { 20, 9 },
122 [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
123 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
124};
125
109static const enum omap_display_type omap2_dss_supported_displays[] = { 126static const enum omap_display_type omap2_dss_supported_displays[] = {
110 /* OMAP_DSS_CHANNEL_LCD */ 127 /* OMAP_DSS_CHANNEL_LCD */
111 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, 128 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
@@ -144,6 +161,76 @@ static const enum omap_display_type omap4_dss_supported_displays[] = {
144 OMAP_DISPLAY_TYPE_DSI, 161 OMAP_DISPLAY_TYPE_DSI,
145}; 162};
146 163
164static const enum omap_display_type omap5_dss_supported_displays[] = {
165 /* OMAP_DSS_CHANNEL_LCD */
166 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
167 OMAP_DISPLAY_TYPE_DSI,
168
169 /* OMAP_DSS_CHANNEL_DIGIT */
170 OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
171
172 /* OMAP_DSS_CHANNEL_LCD2 */
173 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
174 OMAP_DISPLAY_TYPE_DSI,
175};
176
177static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
178 /* OMAP_DSS_CHANNEL_LCD */
179 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
180
181 /* OMAP_DSS_CHANNEL_DIGIT */
182 OMAP_DSS_OUTPUT_VENC,
183};
184
185static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
186 /* OMAP_DSS_CHANNEL_LCD */
187 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
188 OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
189
190 /* OMAP_DSS_CHANNEL_DIGIT */
191 OMAP_DSS_OUTPUT_VENC,
192};
193
194static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
195 /* OMAP_DSS_CHANNEL_LCD */
196 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
197 OMAP_DSS_OUTPUT_DSI1,
198
199 /* OMAP_DSS_CHANNEL_DIGIT */
200 OMAP_DSS_OUTPUT_VENC,
201};
202
203static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
204 /* OMAP_DSS_CHANNEL_LCD */
205 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
206 OMAP_DSS_OUTPUT_DSI1,
207
208 /* OMAP_DSS_CHANNEL_DIGIT */
209 OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI |
210 OMAP_DSS_OUTPUT_DPI,
211
212 /* OMAP_DSS_CHANNEL_LCD2 */
213 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
214 OMAP_DSS_OUTPUT_DSI2,
215};
216
217static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
218 /* OMAP_DSS_CHANNEL_LCD */
219 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
220 OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
221
222 /* OMAP_DSS_CHANNEL_DIGIT */
223 OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI,
224
225 /* OMAP_DSS_CHANNEL_LCD2 */
226 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
227 OMAP_DSS_OUTPUT_DSI1,
228
229 /* OMAP_DSS_CHANNEL_LCD3 */
230 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
231 OMAP_DSS_OUTPUT_DSI2,
232};
233
147static const enum omap_color_mode omap2_dss_supported_color_modes[] = { 234static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
148 /* OMAP_DSS_GFX */ 235 /* OMAP_DSS_GFX */
149 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | 236 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
@@ -224,58 +311,80 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
224 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | 311 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
225 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | 312 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
226 OMAP_DSS_COLOR_RGBX32, 313 OMAP_DSS_COLOR_RGBX32,
314
315 /* OMAP_DSS_WB */
316 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
317 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
318 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
319 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
320 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
321 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
322 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
323 OMAP_DSS_COLOR_RGBX32,
227}; 324};
228 325
229static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { 326static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
230 /* OMAP_DSS_GFX */ 327 /* OMAP_DSS_GFX */
231 0, 328 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
232 329
233 /* OMAP_DSS_VIDEO1 */ 330 /* OMAP_DSS_VIDEO1 */
234 OMAP_DSS_OVL_CAP_SCALE, 331 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
332 OMAP_DSS_OVL_CAP_REPLICATION,
235 333
236 /* OMAP_DSS_VIDEO2 */ 334 /* OMAP_DSS_VIDEO2 */
237 OMAP_DSS_OVL_CAP_SCALE, 335 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
336 OMAP_DSS_OVL_CAP_REPLICATION,
238}; 337};
239 338
240static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { 339static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
241 /* OMAP_DSS_GFX */ 340 /* OMAP_DSS_GFX */
242 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, 341 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
342 OMAP_DSS_OVL_CAP_REPLICATION,
243 343
244 /* OMAP_DSS_VIDEO1 */ 344 /* OMAP_DSS_VIDEO1 */
245 OMAP_DSS_OVL_CAP_SCALE, 345 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
346 OMAP_DSS_OVL_CAP_REPLICATION,
246 347
247 /* OMAP_DSS_VIDEO2 */ 348 /* OMAP_DSS_VIDEO2 */
248 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, 349 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
350 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
249}; 351};
250 352
251static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { 353static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
252 /* OMAP_DSS_GFX */ 354 /* OMAP_DSS_GFX */
253 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, 355 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
356 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
254 357
255 /* OMAP_DSS_VIDEO1 */ 358 /* OMAP_DSS_VIDEO1 */
256 OMAP_DSS_OVL_CAP_SCALE, 359 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
360 OMAP_DSS_OVL_CAP_REPLICATION,
257 361
258 /* OMAP_DSS_VIDEO2 */ 362 /* OMAP_DSS_VIDEO2 */
259 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 363 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
260 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, 364 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
365 OMAP_DSS_OVL_CAP_REPLICATION,
261}; 366};
262 367
263static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { 368static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
264 /* OMAP_DSS_GFX */ 369 /* OMAP_DSS_GFX */
265 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | 370 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
266 OMAP_DSS_OVL_CAP_ZORDER, 371 OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
372 OMAP_DSS_OVL_CAP_REPLICATION,
267 373
268 /* OMAP_DSS_VIDEO1 */ 374 /* OMAP_DSS_VIDEO1 */
269 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 375 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
270 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 376 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
377 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
271 378
272 /* OMAP_DSS_VIDEO2 */ 379 /* OMAP_DSS_VIDEO2 */
273 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 380 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
274 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 381 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
382 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
275 383
276 /* OMAP_DSS_VIDEO3 */ 384 /* OMAP_DSS_VIDEO3 */
277 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 385 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
278 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 386 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
387 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
279}; 388};
280 389
281static const char * const omap2_dss_clk_source_names[] = { 390static const char * const omap2_dss_clk_source_names[] = {
@@ -298,6 +407,14 @@ static const char * const omap4_dss_clk_source_names[] = {
298 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2", 407 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
299}; 408};
300 409
410static const char * const omap5_dss_clk_source_names[] = {
411 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1",
412 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2",
413 [OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK",
414 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
415 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2",
416};
417
301static const struct dss_param_range omap2_dss_param_range[] = { 418static const struct dss_param_range omap2_dss_param_range[] = {
302 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, 419 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
303 [FEAT_PARAM_DSS_PCD] = { 2, 255 }, 420 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
@@ -326,6 +443,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
326 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, 443 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
327 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, 444 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
328 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 445 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
446 [FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
329 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 447 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
330 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, 448 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
331 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, 449 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
@@ -341,6 +459,23 @@ static const struct dss_param_range omap4_dss_param_range[] = {
341 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, 459 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
342 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, 460 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
343 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 461 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
462 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
463 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
464 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
465 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
466 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
467};
468
469static const struct dss_param_range omap5_dss_param_range[] = {
470 [FEAT_PARAM_DSS_FCK] = { 0, 200000000 },
471 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
472 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
473 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
474 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
475 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
476 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
477 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
478 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
344 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 479 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
345 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, 480 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
346 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, 481 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
@@ -373,6 +508,26 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {
373 FEAT_ALPHA_FIXED_ZORDER, 508 FEAT_ALPHA_FIXED_ZORDER,
374 FEAT_FIFO_MERGE, 509 FEAT_FIFO_MERGE,
375 FEAT_OMAP3_DSI_FIFO_BUG, 510 FEAT_OMAP3_DSI_FIFO_BUG,
511 FEAT_DPI_USES_VDDS_DSI,
512};
513
514static const enum dss_feat_id am35xx_dss_feat_list[] = {
515 FEAT_LCDENABLEPOL,
516 FEAT_LCDENABLESIGNAL,
517 FEAT_PCKFREEENABLE,
518 FEAT_FUNCGATED,
519 FEAT_LINEBUFFERSPLIT,
520 FEAT_ROWREPEATENABLE,
521 FEAT_RESIZECONF,
522 FEAT_DSI_PLL_FREQSEL,
523 FEAT_DSI_REVERSE_TXCLKESC,
524 FEAT_VENC_REQUIRES_TV_DAC_CLK,
525 FEAT_CPR,
526 FEAT_PRELOAD,
527 FEAT_FIR_COEF_V,
528 FEAT_ALPHA_FIXED_ZORDER,
529 FEAT_FIFO_MERGE,
530 FEAT_OMAP3_DSI_FIFO_BUG,
376}; 531};
377 532
378static const enum dss_feat_id omap3630_dss_feat_list[] = { 533static const enum dss_feat_id omap3630_dss_feat_list[] = {
@@ -447,6 +602,28 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {
447 FEAT_BURST_2D, 602 FEAT_BURST_2D,
448}; 603};
449 604
605static const enum dss_feat_id omap5_dss_feat_list[] = {
606 FEAT_MGR_LCD2,
607 FEAT_CORE_CLK_DIV,
608 FEAT_LCD_CLK_SRC,
609 FEAT_DSI_DCS_CMD_CONFIG_VC,
610 FEAT_DSI_VC_OCP_WIDTH,
611 FEAT_DSI_GNQ,
612 FEAT_HDMI_CTS_SWMODE,
613 FEAT_HDMI_AUDIO_USE_MCLK,
614 FEAT_HANDLE_UV_SEPARATE,
615 FEAT_ATTR2,
616 FEAT_CPR,
617 FEAT_PRELOAD,
618 FEAT_FIR_COEF_V,
619 FEAT_ALPHA_FREE_ZORDER,
620 FEAT_FIFO_MERGE,
621 FEAT_BURST_2D,
622 FEAT_DSI_PLL_SELFREQDCO,
623 FEAT_DSI_PLL_REFSEL,
624 FEAT_DSI_PHY_DCC,
625};
626
450/* OMAP2 DSS Features */ 627/* OMAP2 DSS Features */
451static const struct omap_dss_features omap2_dss_features = { 628static const struct omap_dss_features omap2_dss_features = {
452 .reg_fields = omap2_dss_reg_fields, 629 .reg_fields = omap2_dss_reg_fields,
@@ -458,6 +635,7 @@ static const struct omap_dss_features omap2_dss_features = {
458 .num_mgrs = 2, 635 .num_mgrs = 2,
459 .num_ovls = 3, 636 .num_ovls = 3,
460 .supported_displays = omap2_dss_supported_displays, 637 .supported_displays = omap2_dss_supported_displays,
638 .supported_outputs = omap2_dss_supported_outputs,
461 .supported_color_modes = omap2_dss_supported_color_modes, 639 .supported_color_modes = omap2_dss_supported_color_modes,
462 .overlay_caps = omap2_dss_overlay_caps, 640 .overlay_caps = omap2_dss_overlay_caps,
463 .clksrc_names = omap2_dss_clk_source_names, 641 .clksrc_names = omap2_dss_clk_source_names,
@@ -478,6 +656,31 @@ static const struct omap_dss_features omap3430_dss_features = {
478 .num_mgrs = 2, 656 .num_mgrs = 2,
479 .num_ovls = 3, 657 .num_ovls = 3,
480 .supported_displays = omap3430_dss_supported_displays, 658 .supported_displays = omap3430_dss_supported_displays,
659 .supported_outputs = omap3430_dss_supported_outputs,
660 .supported_color_modes = omap3_dss_supported_color_modes,
661 .overlay_caps = omap3430_dss_overlay_caps,
662 .clksrc_names = omap3_dss_clk_source_names,
663 .dss_params = omap3_dss_param_range,
664 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
665 .buffer_size_unit = 1,
666 .burst_size_unit = 8,
667};
668
669/*
670 * AM35xx DSS Features. This is basically OMAP3 DSS Features without the
671 * vdds_dsi regulator.
672 */
673static const struct omap_dss_features am35xx_dss_features = {
674 .reg_fields = omap3_dss_reg_fields,
675 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
676
677 .features = am35xx_dss_feat_list,
678 .num_features = ARRAY_SIZE(am35xx_dss_feat_list),
679
680 .num_mgrs = 2,
681 .num_ovls = 3,
682 .supported_displays = omap3430_dss_supported_displays,
683 .supported_outputs = omap3430_dss_supported_outputs,
481 .supported_color_modes = omap3_dss_supported_color_modes, 684 .supported_color_modes = omap3_dss_supported_color_modes,
482 .overlay_caps = omap3430_dss_overlay_caps, 685 .overlay_caps = omap3430_dss_overlay_caps,
483 .clksrc_names = omap3_dss_clk_source_names, 686 .clksrc_names = omap3_dss_clk_source_names,
@@ -497,6 +700,7 @@ static const struct omap_dss_features omap3630_dss_features = {
497 .num_mgrs = 2, 700 .num_mgrs = 2,
498 .num_ovls = 3, 701 .num_ovls = 3,
499 .supported_displays = omap3630_dss_supported_displays, 702 .supported_displays = omap3630_dss_supported_displays,
703 .supported_outputs = omap3630_dss_supported_outputs,
500 .supported_color_modes = omap3_dss_supported_color_modes, 704 .supported_color_modes = omap3_dss_supported_color_modes,
501 .overlay_caps = omap3630_dss_overlay_caps, 705 .overlay_caps = omap3630_dss_overlay_caps,
502 .clksrc_names = omap3_dss_clk_source_names, 706 .clksrc_names = omap3_dss_clk_source_names,
@@ -517,7 +721,9 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
517 721
518 .num_mgrs = 3, 722 .num_mgrs = 3,
519 .num_ovls = 4, 723 .num_ovls = 4,
724 .num_wbs = 1,
520 .supported_displays = omap4_dss_supported_displays, 725 .supported_displays = omap4_dss_supported_displays,
726 .supported_outputs = omap4_dss_supported_outputs,
521 .supported_color_modes = omap4_dss_supported_color_modes, 727 .supported_color_modes = omap4_dss_supported_color_modes,
522 .overlay_caps = omap4_dss_overlay_caps, 728 .overlay_caps = omap4_dss_overlay_caps,
523 .clksrc_names = omap4_dss_clk_source_names, 729 .clksrc_names = omap4_dss_clk_source_names,
@@ -537,7 +743,9 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
537 743
538 .num_mgrs = 3, 744 .num_mgrs = 3,
539 .num_ovls = 4, 745 .num_ovls = 4,
746 .num_wbs = 1,
540 .supported_displays = omap4_dss_supported_displays, 747 .supported_displays = omap4_dss_supported_displays,
748 .supported_outputs = omap4_dss_supported_outputs,
541 .supported_color_modes = omap4_dss_supported_color_modes, 749 .supported_color_modes = omap4_dss_supported_color_modes,
542 .overlay_caps = omap4_dss_overlay_caps, 750 .overlay_caps = omap4_dss_overlay_caps,
543 .clksrc_names = omap4_dss_clk_source_names, 751 .clksrc_names = omap4_dss_clk_source_names,
@@ -557,7 +765,9 @@ static const struct omap_dss_features omap4_dss_features = {
557 765
558 .num_mgrs = 3, 766 .num_mgrs = 3,
559 .num_ovls = 4, 767 .num_ovls = 4,
768 .num_wbs = 1,
560 .supported_displays = omap4_dss_supported_displays, 769 .supported_displays = omap4_dss_supported_displays,
770 .supported_outputs = omap4_dss_supported_outputs,
561 .supported_color_modes = omap4_dss_supported_color_modes, 771 .supported_color_modes = omap4_dss_supported_color_modes,
562 .overlay_caps = omap4_dss_overlay_caps, 772 .overlay_caps = omap4_dss_overlay_caps,
563 .clksrc_names = omap4_dss_clk_source_names, 773 .clksrc_names = omap4_dss_clk_source_names,
@@ -567,6 +777,27 @@ static const struct omap_dss_features omap4_dss_features = {
567 .burst_size_unit = 16, 777 .burst_size_unit = 16,
568}; 778};
569 779
780/* OMAP5 DSS Features */
781static const struct omap_dss_features omap5_dss_features = {
782 .reg_fields = omap5_dss_reg_fields,
783 .num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
784
785 .features = omap5_dss_feat_list,
786 .num_features = ARRAY_SIZE(omap5_dss_feat_list),
787
788 .num_mgrs = 3,
789 .num_ovls = 4,
790 .supported_displays = omap5_dss_supported_displays,
791 .supported_outputs = omap5_dss_supported_outputs,
792 .supported_color_modes = omap4_dss_supported_color_modes,
793 .overlay_caps = omap4_dss_overlay_caps,
794 .clksrc_names = omap5_dss_clk_source_names,
795 .dss_params = omap5_dss_param_range,
796 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
797 .buffer_size_unit = 16,
798 .burst_size_unit = 16,
799};
800
570#if defined(CONFIG_OMAP4_DSS_HDMI) 801#if defined(CONFIG_OMAP4_DSS_HDMI)
571/* HDMI OMAP4 Functions*/ 802/* HDMI OMAP4 Functions*/
572static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { 803static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
@@ -612,6 +843,11 @@ int dss_feat_get_num_ovls(void)
612 return omap_current_dss_features->num_ovls; 843 return omap_current_dss_features->num_ovls;
613} 844}
614 845
846int dss_feat_get_num_wbs(void)
847{
848 return omap_current_dss_features->num_wbs;
849}
850
615unsigned long dss_feat_get_param_min(enum dss_range_param param) 851unsigned long dss_feat_get_param_min(enum dss_range_param param)
616{ 852{
617 return omap_current_dss_features->dss_params[param].min; 853 return omap_current_dss_features->dss_params[param].min;
@@ -627,6 +863,11 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
627 return omap_current_dss_features->supported_displays[channel]; 863 return omap_current_dss_features->supported_displays[channel];
628} 864}
629 865
866enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
867{
868 return omap_current_dss_features->supported_outputs[channel];
869}
870
630enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) 871enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
631{ 872{
632 return omap_current_dss_features->supported_color_modes[plane]; 873 return omap_current_dss_features->supported_color_modes[plane];
@@ -694,8 +935,13 @@ void dss_features_init(void)
694 omap_current_dss_features = &omap2_dss_features; 935 omap_current_dss_features = &omap2_dss_features;
695 else if (cpu_is_omap3630()) 936 else if (cpu_is_omap3630())
696 omap_current_dss_features = &omap3630_dss_features; 937 omap_current_dss_features = &omap3630_dss_features;
697 else if (cpu_is_omap34xx()) 938 else if (cpu_is_omap34xx()) {
698 omap_current_dss_features = &omap3430_dss_features; 939 if (soc_is_am35xx()) {
940 omap_current_dss_features = &am35xx_dss_features;
941 } else {
942 omap_current_dss_features = &omap3430_dss_features;
943 }
944 }
699 else if (omap_rev() == OMAP4430_REV_ES1_0) 945 else if (omap_rev() == OMAP4430_REV_ES1_0)
700 omap_current_dss_features = &omap4430_es1_0_dss_features; 946 omap_current_dss_features = &omap4430_es1_0_dss_features;
701 else if (omap_rev() == OMAP4430_REV_ES2_0 || 947 else if (omap_rev() == OMAP4430_REV_ES2_0 ||
@@ -704,6 +950,8 @@ void dss_features_init(void)
704 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features; 950 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
705 else if (cpu_is_omap44xx()) 951 else if (cpu_is_omap44xx())
706 omap_current_dss_features = &omap4_dss_features; 952 omap_current_dss_features = &omap4_dss_features;
953 else if (soc_is_omap54xx())
954 omap_current_dss_features = &omap5_dss_features;
707 else 955 else
708 DSSWARN("Unsupported OMAP version"); 956 DSSWARN("Unsupported OMAP version");
709} 957}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 996ffcbfed58..9218113b5e88 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -50,6 +50,7 @@ enum dss_feat_id {
50 FEAT_DSI_VC_OCP_WIDTH, 50 FEAT_DSI_VC_OCP_WIDTH,
51 FEAT_DSI_REVERSE_TXCLKESC, 51 FEAT_DSI_REVERSE_TXCLKESC,
52 FEAT_DSI_GNQ, 52 FEAT_DSI_GNQ,
53 FEAT_DPI_USES_VDDS_DSI,
53 FEAT_HDMI_CTS_SWMODE, 54 FEAT_HDMI_CTS_SWMODE,
54 FEAT_HDMI_AUDIO_USE_MCLK, 55 FEAT_HDMI_AUDIO_USE_MCLK,
55 FEAT_HANDLE_UV_SEPARATE, 56 FEAT_HANDLE_UV_SEPARATE,
@@ -64,6 +65,9 @@ enum dss_feat_id {
64 /* An unknown HW bug causing the normal FIFO thresholds not to work */ 65 /* An unknown HW bug causing the normal FIFO thresholds not to work */
65 FEAT_OMAP3_DSI_FIFO_BUG, 66 FEAT_OMAP3_DSI_FIFO_BUG,
66 FEAT_BURST_2D, 67 FEAT_BURST_2D,
68 FEAT_DSI_PLL_SELFREQDCO,
69 FEAT_DSI_PLL_REFSEL,
70 FEAT_DSI_PHY_DCC,
67}; 71};
68 72
69/* DSS register field id */ 73/* DSS register field id */
@@ -91,6 +95,7 @@ enum dss_range_param {
91 FEAT_PARAM_DSIPLL_REGM_DSI, 95 FEAT_PARAM_DSIPLL_REGM_DSI,
92 FEAT_PARAM_DSIPLL_FINT, 96 FEAT_PARAM_DSIPLL_FINT,
93 FEAT_PARAM_DSIPLL_LPDIV, 97 FEAT_PARAM_DSIPLL_LPDIV,
98 FEAT_PARAM_DSI_FCK,
94 FEAT_PARAM_DOWNSCALE, 99 FEAT_PARAM_DOWNSCALE,
95 FEAT_PARAM_LINEWIDTH, 100 FEAT_PARAM_LINEWIDTH,
96 FEAT_PARAM_MGR_WIDTH, 101 FEAT_PARAM_MGR_WIDTH,
@@ -100,9 +105,11 @@ enum dss_range_param {
100/* DSS Feature Functions */ 105/* DSS Feature Functions */
101int dss_feat_get_num_mgrs(void); 106int dss_feat_get_num_mgrs(void);
102int dss_feat_get_num_ovls(void); 107int dss_feat_get_num_ovls(void);
108int dss_feat_get_num_wbs(void);
103unsigned long dss_feat_get_param_min(enum dss_range_param param); 109unsigned long dss_feat_get_param_min(enum dss_range_param param);
104unsigned long dss_feat_get_param_max(enum dss_range_param param); 110unsigned long dss_feat_get_param_max(enum dss_range_param param);
105enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); 111enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
112enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
106enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); 113enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
107enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); 114enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
108bool dss_feat_color_mode_supported(enum omap_plane plane, 115bool dss_feat_color_mode_supported(enum omap_plane plane,
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 060216fdc578..a48a7dd75b33 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -32,6 +32,8 @@
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/clk.h> 34#include <linux/clk.h>
35#include <linux/gpio.h>
36#include <linux/regulator/consumer.h>
35#include <video/omapdss.h> 37#include <video/omapdss.h>
36 38
37#include "ti_hdmi.h" 39#include "ti_hdmi.h"
@@ -61,6 +63,13 @@ static struct {
61 struct hdmi_ip_data ip_data; 63 struct hdmi_ip_data ip_data;
62 64
63 struct clk *sys_clk; 65 struct clk *sys_clk;
66 struct regulator *vdda_hdmi_dac_reg;
67
68 int ct_cp_hpd_gpio;
69 int ls_oe_gpio;
70 int hpd_gpio;
71
72 struct omap_dss_output output;
64} hdmi; 73} hdmi;
65 74
66/* 75/*
@@ -314,12 +323,47 @@ static void hdmi_runtime_put(void)
314 323
315static int __init hdmi_init_display(struct omap_dss_device *dssdev) 324static int __init hdmi_init_display(struct omap_dss_device *dssdev)
316{ 325{
326 int r;
327
328 struct gpio gpios[] = {
329 { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
330 { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
331 { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
332 };
333
317 DSSDBG("init_display\n"); 334 DSSDBG("init_display\n");
318 335
319 dss_init_hdmi_ip_ops(&hdmi.ip_data); 336 dss_init_hdmi_ip_ops(&hdmi.ip_data);
337
338 if (hdmi.vdda_hdmi_dac_reg == NULL) {
339 struct regulator *reg;
340
341 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
342
343 if (IS_ERR(reg)) {
344 DSSERR("can't get VDDA_HDMI_DAC regulator\n");
345 return PTR_ERR(reg);
346 }
347
348 hdmi.vdda_hdmi_dac_reg = reg;
349 }
350
351 r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
352 if (r)
353 return r;
354
320 return 0; 355 return 0;
321} 356}
322 357
358static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
359{
360 DSSDBG("uninit_display\n");
361
362 gpio_free(hdmi.ct_cp_hpd_gpio);
363 gpio_free(hdmi.ls_oe_gpio);
364 gpio_free(hdmi.hpd_gpio);
365}
366
323static const struct hdmi_config *hdmi_find_timing( 367static const struct hdmi_config *hdmi_find_timing(
324 const struct hdmi_config *timings_arr, 368 const struct hdmi_config *timings_arr,
325 int len) 369 int len)
@@ -459,32 +503,30 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
459static int hdmi_power_on(struct omap_dss_device *dssdev) 503static int hdmi_power_on(struct omap_dss_device *dssdev)
460{ 504{
461 int r; 505 int r;
462 const struct hdmi_config *timing;
463 struct omap_video_timings *p; 506 struct omap_video_timings *p;
507 struct omap_overlay_manager *mgr = dssdev->output->manager;
464 unsigned long phy; 508 unsigned long phy;
465 509
510 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
511 gpio_set_value(hdmi.ls_oe_gpio, 1);
512
513 /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
514 udelay(300);
515
516 r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
517 if (r)
518 goto err_vdac_enable;
519
466 r = hdmi_runtime_get(); 520 r = hdmi_runtime_get();
467 if (r) 521 if (r)
468 return r; 522 goto err_runtime_get;
469 523
470 dss_mgr_disable(dssdev->manager); 524 dss_mgr_disable(mgr);
471 525
472 p = &dssdev->panel.timings; 526 p = &hdmi.ip_data.cfg.timings;
473 527
474 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", 528 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
475 dssdev->panel.timings.x_res,
476 dssdev->panel.timings.y_res);
477 529
478 timing = hdmi_get_timings();
479 if (timing == NULL) {
480 /* HDMI code 4 corresponds to 640 * 480 VGA */
481 hdmi.ip_data.cfg.cm.code = 4;
482 /* DVI mode 1 corresponds to HDMI 0 to DVI */
483 hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
484 hdmi.ip_data.cfg = vesa_timings[0];
485 } else {
486 hdmi.ip_data.cfg = *timing;
487 }
488 phy = p->pixel_clock; 530 phy = p->pixel_clock;
489 531
490 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); 532 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
@@ -495,13 +537,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
495 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); 537 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
496 if (r) { 538 if (r) {
497 DSSDBG("Failed to lock PLL\n"); 539 DSSDBG("Failed to lock PLL\n");
498 goto err; 540 goto err_pll_enable;
499 } 541 }
500 542
501 r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); 543 r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
502 if (r) { 544 if (r) {
503 DSSDBG("Failed to start PHY\n"); 545 DSSDBG("Failed to start PHY\n");
504 goto err; 546 goto err_phy_enable;
505 } 547 }
506 548
507 hdmi.ip_data.ops->video_configure(&hdmi.ip_data); 549 hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
@@ -521,13 +563,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
521 dispc_enable_gamma_table(0); 563 dispc_enable_gamma_table(0);
522 564
523 /* tv size */ 565 /* tv size */
524 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); 566 dss_mgr_set_timings(mgr, p);
525 567
526 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); 568 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
527 if (r) 569 if (r)
528 goto err_vid_enable; 570 goto err_vid_enable;
529 571
530 r = dss_mgr_enable(dssdev->manager); 572 r = dss_mgr_enable(mgr);
531 if (r) 573 if (r)
532 goto err_mgr_enable; 574 goto err_mgr_enable;
533 575
@@ -537,20 +579,33 @@ err_mgr_enable:
537 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 579 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
538err_vid_enable: 580err_vid_enable:
539 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 581 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
582err_phy_enable:
540 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 583 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
541err: 584err_pll_enable:
542 hdmi_runtime_put(); 585 hdmi_runtime_put();
586err_runtime_get:
587 regulator_disable(hdmi.vdda_hdmi_dac_reg);
588err_vdac_enable:
589 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
590 gpio_set_value(hdmi.ls_oe_gpio, 0);
543 return -EIO; 591 return -EIO;
544} 592}
545 593
546static void hdmi_power_off(struct omap_dss_device *dssdev) 594static void hdmi_power_off(struct omap_dss_device *dssdev)
547{ 595{
548 dss_mgr_disable(dssdev->manager); 596 struct omap_overlay_manager *mgr = dssdev->output->manager;
597
598 dss_mgr_disable(mgr);
549 599
550 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 600 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
551 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 601 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
552 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 602 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
553 hdmi_runtime_put(); 603 hdmi_runtime_put();
604
605 regulator_disable(hdmi.vdda_hdmi_dac_reg);
606
607 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
608 gpio_set_value(hdmi.ls_oe_gpio, 0);
554} 609}
555 610
556int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 611int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -567,25 +622,22 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
567 622
568} 623}
569 624
570void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) 625void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
626 struct omap_video_timings *timings)
571{ 627{
572 struct hdmi_cm cm; 628 struct hdmi_cm cm;
629 const struct hdmi_config *t;
573 630
574 cm = hdmi_get_code(&dssdev->panel.timings); 631 mutex_lock(&hdmi.lock);
575 hdmi.ip_data.cfg.cm.code = cm.code;
576 hdmi.ip_data.cfg.cm.mode = cm.mode;
577 632
578 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 633 cm = hdmi_get_code(timings);
579 int r; 634 hdmi.ip_data.cfg.cm = cm;
580 635
581 hdmi_power_off(dssdev); 636 t = hdmi_get_timings();
637 if (t != NULL)
638 hdmi.ip_data.cfg = *t;
582 639
583 r = hdmi_power_on(dssdev); 640 mutex_unlock(&hdmi.lock);
584 if (r)
585 DSSERR("failed to power on device\n");
586 } else {
587 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
588 }
589} 641}
590 642
591static void hdmi_dump_regs(struct seq_file *s) 643static void hdmi_dump_regs(struct seq_file *s)
@@ -640,20 +692,20 @@ bool omapdss_hdmi_detect(void)
640 692
641int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) 693int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
642{ 694{
643 struct omap_dss_hdmi_data *priv = dssdev->data; 695 struct omap_dss_output *out = dssdev->output;
644 int r = 0; 696 int r = 0;
645 697
646 DSSDBG("ENTER hdmi_display_enable\n"); 698 DSSDBG("ENTER hdmi_display_enable\n");
647 699
648 mutex_lock(&hdmi.lock); 700 mutex_lock(&hdmi.lock);
649 701
650 if (dssdev->manager == NULL) { 702 if (out == NULL || out->manager == NULL) {
651 DSSERR("failed to enable display: no manager\n"); 703 DSSERR("failed to enable display: no output/manager\n");
652 r = -ENODEV; 704 r = -ENODEV;
653 goto err0; 705 goto err0;
654 } 706 }
655 707
656 hdmi.ip_data.hpd_gpio = priv->hpd_gpio; 708 hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
657 709
658 r = omap_dss_start_device(dssdev); 710 r = omap_dss_start_device(dssdev);
659 if (r) { 711 if (r) {
@@ -661,26 +713,15 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
661 goto err0; 713 goto err0;
662 } 714 }
663 715
664 if (dssdev->platform_enable) {
665 r = dssdev->platform_enable(dssdev);
666 if (r) {
667 DSSERR("failed to enable GPIO's\n");
668 goto err1;
669 }
670 }
671
672 r = hdmi_power_on(dssdev); 716 r = hdmi_power_on(dssdev);
673 if (r) { 717 if (r) {
674 DSSERR("failed to power on device\n"); 718 DSSERR("failed to power on device\n");
675 goto err2; 719 goto err1;
676 } 720 }
677 721
678 mutex_unlock(&hdmi.lock); 722 mutex_unlock(&hdmi.lock);
679 return 0; 723 return 0;
680 724
681err2:
682 if (dssdev->platform_disable)
683 dssdev->platform_disable(dssdev);
684err1: 725err1:
685 omap_dss_stop_device(dssdev); 726 omap_dss_stop_device(dssdev);
686err0: 727err0:
@@ -696,9 +737,6 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
696 737
697 hdmi_power_off(dssdev); 738 hdmi_power_off(dssdev);
698 739
699 if (dssdev->platform_disable)
700 dssdev->platform_disable(dssdev);
701
702 omap_dss_stop_device(dssdev); 740 omap_dss_stop_device(dssdev);
703 741
704 mutex_unlock(&hdmi.lock); 742 mutex_unlock(&hdmi.lock);
@@ -869,10 +907,14 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
869 907
870#endif 908#endif
871 909
872static void __init hdmi_probe_pdata(struct platform_device *pdev) 910static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
873{ 911{
874 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 912 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
875 int r, i; 913 const char *def_disp_name = dss_get_default_display_name();
914 struct omap_dss_device *def_dssdev;
915 int i;
916
917 def_dssdev = NULL;
876 918
877 for (i = 0; i < pdata->num_devices; ++i) { 919 for (i = 0; i < pdata->num_devices; ++i) {
878 struct omap_dss_device *dssdev = pdata->devices[i]; 920 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -880,17 +922,76 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
880 if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI) 922 if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
881 continue; 923 continue;
882 924
883 r = hdmi_init_display(dssdev); 925 if (def_dssdev == NULL)
884 if (r) { 926 def_dssdev = dssdev;
885 DSSERR("device %s init failed: %d\n", dssdev->name, r); 927
886 continue; 928 if (def_disp_name != NULL &&
929 strcmp(dssdev->name, def_disp_name) == 0) {
930 def_dssdev = dssdev;
931 break;
887 } 932 }
933 }
888 934
889 r = omap_dss_register_device(dssdev, &pdev->dev, i); 935 return def_dssdev;
890 if (r) 936}
891 DSSERR("device %s register failed: %d\n", 937
892 dssdev->name, r); 938static void __init hdmi_probe_pdata(struct platform_device *pdev)
939{
940 struct omap_dss_device *plat_dssdev;
941 struct omap_dss_device *dssdev;
942 struct omap_dss_hdmi_data *priv;
943 int r;
944
945 plat_dssdev = hdmi_find_dssdev(pdev);
946
947 if (!plat_dssdev)
948 return;
949
950 dssdev = dss_alloc_and_init_device(&pdev->dev);
951 if (!dssdev)
952 return;
953
954 dss_copy_device_pdata(dssdev, plat_dssdev);
955
956 priv = dssdev->data;
957
958 hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
959 hdmi.ls_oe_gpio = priv->ls_oe_gpio;
960 hdmi.hpd_gpio = priv->hpd_gpio;
961
962 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
963
964 r = hdmi_init_display(dssdev);
965 if (r) {
966 DSSERR("device %s init failed: %d\n", dssdev->name, r);
967 dss_put_device(dssdev);
968 return;
893 } 969 }
970
971 r = dss_add_device(dssdev);
972 if (r) {
973 DSSERR("device %s register failed: %d\n", dssdev->name, r);
974 dss_put_device(dssdev);
975 return;
976 }
977}
978
979static void __init hdmi_init_output(struct platform_device *pdev)
980{
981 struct omap_dss_output *out = &hdmi.output;
982
983 out->pdev = pdev;
984 out->id = OMAP_DSS_OUTPUT_HDMI;
985 out->type = OMAP_DISPLAY_TYPE_HDMI;
986
987 dss_register_output(out);
988}
989
990static void __exit hdmi_uninit_output(struct platform_device *pdev)
991{
992 struct omap_dss_output *out = &hdmi.output;
993
994 dss_unregister_output(out);
894} 995}
895 996
896/* HDMI HW IP initialisation */ 997/* HDMI HW IP initialisation */
@@ -929,23 +1030,37 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
929 hdmi.ip_data.core_av_offset = HDMI_CORE_AV; 1030 hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
930 hdmi.ip_data.pll_offset = HDMI_PLLCTRL; 1031 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
931 hdmi.ip_data.phy_offset = HDMI_PHY; 1032 hdmi.ip_data.phy_offset = HDMI_PHY;
1033
932 mutex_init(&hdmi.ip_data.lock); 1034 mutex_init(&hdmi.ip_data.lock);
933 1035
934 hdmi_panel_init(); 1036 hdmi_panel_init();
935 1037
936 dss_debugfs_create_file("hdmi", hdmi_dump_regs); 1038 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
937 1039
1040 hdmi_init_output(pdev);
1041
938 hdmi_probe_pdata(pdev); 1042 hdmi_probe_pdata(pdev);
939 1043
940 return 0; 1044 return 0;
941} 1045}
942 1046
1047static int __exit hdmi_remove_child(struct device *dev, void *data)
1048{
1049 struct omap_dss_device *dssdev = to_dss_device(dev);
1050 hdmi_uninit_display(dssdev);
1051 return 0;
1052}
1053
943static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) 1054static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
944{ 1055{
945 omap_dss_unregister_child_devices(&pdev->dev); 1056 device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
1057
1058 dss_unregister_child_devices(&pdev->dev);
946 1059
947 hdmi_panel_exit(); 1060 hdmi_panel_exit();
948 1061
1062 hdmi_uninit_output(pdev);
1063
949 pm_runtime_disable(&pdev->dev); 1064 pm_runtime_disable(&pdev->dev);
950 1065
951 hdmi_put_clocks(); 1066 hdmi_put_clocks();
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index e10844faadf9..69fb115bab32 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -41,17 +41,34 @@ static struct {
41 41
42static int hdmi_panel_probe(struct omap_dss_device *dssdev) 42static int hdmi_panel_probe(struct omap_dss_device *dssdev)
43{ 43{
44 /* Initialize default timings to VGA in DVI mode */
45 const struct omap_video_timings default_timings = {
46 .x_res = 640,
47 .y_res = 480,
48 .pixel_clock = 25175,
49 .hsw = 96,
50 .hfp = 16,
51 .hbp = 48,
52 .vsw = 2,
53 .vfp = 11,
54 .vbp = 31,
55
56 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
57 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
58
59 .interlace = false,
60 };
61
44 DSSDBG("ENTER hdmi_panel_probe\n"); 62 DSSDBG("ENTER hdmi_panel_probe\n");
45 63
46 dssdev->panel.timings = (struct omap_video_timings) 64 dssdev->panel.timings = default_timings;
47 { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
48 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
49 false,
50 };
51 65
52 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", 66 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
53 dssdev->panel.timings.x_res, 67 dssdev->panel.timings.x_res,
54 dssdev->panel.timings.y_res); 68 dssdev->panel.timings.y_res);
69
70 omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
71
55 return 0; 72 return 0;
56} 73}
57 74
@@ -228,6 +245,8 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
228 goto err; 245 goto err;
229 } 246 }
230 247
248 omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
249
231 r = omapdss_hdmi_display_enable(dssdev); 250 r = omapdss_hdmi_display_enable(dssdev);
232 if (r) { 251 if (r) {
233 DSSERR("failed to power on\n"); 252 DSSERR("failed to power on\n");
@@ -336,8 +355,8 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
336 */ 355 */
337 hdmi_panel_audio_disable(dssdev); 356 hdmi_panel_audio_disable(dssdev);
338 357
358 omapdss_hdmi_display_set_timing(dssdev, timings);
339 dssdev->panel.timings = *timings; 359 dssdev->panel.timings = *timings;
340 omapdss_hdmi_display_set_timing(dssdev);
341 360
342 mutex_unlock(&hdmi.lock); 361 mutex_unlock(&hdmi.lock);
343} 362}
diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c
new file mode 100644
index 000000000000..9a2fb59b6f89
--- /dev/null
+++ b/drivers/video/omap2/dss/manager-sysfs.c
@@ -0,0 +1,512 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "MANAGER"
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/jiffies.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
37}
38
39static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
40{
41 struct omap_dss_device *dssdev = mgr->get_device(mgr);
42
43 return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
44 dssdev->name : "<none>");
45}
46
47static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
48 const char *buf, size_t size)
49{
50 int r = 0;
51 size_t len = size;
52 struct omap_dss_device *dssdev = NULL;
53
54 int match(struct omap_dss_device *dssdev, void *data)
55 {
56 const char *str = data;
57 return sysfs_streq(dssdev->name, str);
58 }
59
60 if (buf[size-1] == '\n')
61 --len;
62
63 if (len > 0)
64 dssdev = omap_dss_find_device((void *)buf, match);
65
66 if (len > 0 && dssdev == NULL)
67 return -EINVAL;
68
69 if (dssdev)
70 DSSDBG("display %s found\n", dssdev->name);
71
72 if (mgr->output) {
73 r = mgr->unset_output(mgr);
74 if (r) {
75 DSSERR("failed to unset current output\n");
76 goto put_device;
77 }
78 }
79
80 if (dssdev) {
81 struct omap_dss_output *out = dssdev->output;
82
83 /*
84 * a registered device should have an output connected to it
85 * already
86 */
87 if (!out) {
88 DSSERR("device has no output connected to it\n");
89 goto put_device;
90 }
91
92 r = mgr->set_output(mgr, out);
93 if (r) {
94 DSSERR("failed to set manager output\n");
95 goto put_device;
96 }
97
98 r = mgr->apply(mgr);
99 if (r) {
100 DSSERR("failed to apply dispc config\n");
101 goto put_device;
102 }
103 }
104
105put_device:
106 if (dssdev)
107 omap_dss_put_device(dssdev);
108
109 return r ? r : size;
110}
111
112static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
113 char *buf)
114{
115 struct omap_overlay_manager_info info;
116
117 mgr->get_manager_info(mgr, &info);
118
119 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
120}
121
122static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
123 const char *buf, size_t size)
124{
125 struct omap_overlay_manager_info info;
126 u32 color;
127 int r;
128
129 r = kstrtouint(buf, 0, &color);
130 if (r)
131 return r;
132
133 mgr->get_manager_info(mgr, &info);
134
135 info.default_color = color;
136
137 r = mgr->set_manager_info(mgr, &info);
138 if (r)
139 return r;
140
141 r = mgr->apply(mgr);
142 if (r)
143 return r;
144
145 return size;
146}
147
148static const char *trans_key_type_str[] = {
149 "gfx-destination",
150 "video-source",
151};
152
153static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
154 char *buf)
155{
156 enum omap_dss_trans_key_type key_type;
157 struct omap_overlay_manager_info info;
158
159 mgr->get_manager_info(mgr, &info);
160
161 key_type = info.trans_key_type;
162 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
163
164 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
165}
166
167static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
168 const char *buf, size_t size)
169{
170 enum omap_dss_trans_key_type key_type;
171 struct omap_overlay_manager_info info;
172 int r;
173
174 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
175 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
176 if (sysfs_streq(buf, trans_key_type_str[key_type]))
177 break;
178 }
179
180 if (key_type == ARRAY_SIZE(trans_key_type_str))
181 return -EINVAL;
182
183 mgr->get_manager_info(mgr, &info);
184
185 info.trans_key_type = key_type;
186
187 r = mgr->set_manager_info(mgr, &info);
188 if (r)
189 return r;
190
191 r = mgr->apply(mgr);
192 if (r)
193 return r;
194
195 return size;
196}
197
198static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
199 char *buf)
200{
201 struct omap_overlay_manager_info info;
202
203 mgr->get_manager_info(mgr, &info);
204
205 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
206}
207
208static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
209 const char *buf, size_t size)
210{
211 struct omap_overlay_manager_info info;
212 u32 key_value;
213 int r;
214
215 r = kstrtouint(buf, 0, &key_value);
216 if (r)
217 return r;
218
219 mgr->get_manager_info(mgr, &info);
220
221 info.trans_key = key_value;
222
223 r = mgr->set_manager_info(mgr, &info);
224 if (r)
225 return r;
226
227 r = mgr->apply(mgr);
228 if (r)
229 return r;
230
231 return size;
232}
233
234static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
235 char *buf)
236{
237 struct omap_overlay_manager_info info;
238
239 mgr->get_manager_info(mgr, &info);
240
241 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
242}
243
244static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
245 const char *buf, size_t size)
246{
247 struct omap_overlay_manager_info info;
248 bool enable;
249 int r;
250
251 r = strtobool(buf, &enable);
252 if (r)
253 return r;
254
255 mgr->get_manager_info(mgr, &info);
256
257 info.trans_enabled = enable;
258
259 r = mgr->set_manager_info(mgr, &info);
260 if (r)
261 return r;
262
263 r = mgr->apply(mgr);
264 if (r)
265 return r;
266
267 return size;
268}
269
270static ssize_t manager_alpha_blending_enabled_show(
271 struct omap_overlay_manager *mgr, char *buf)
272{
273 struct omap_overlay_manager_info info;
274
275 mgr->get_manager_info(mgr, &info);
276
277 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
278
279 return snprintf(buf, PAGE_SIZE, "%d\n",
280 info.partial_alpha_enabled);
281}
282
283static ssize_t manager_alpha_blending_enabled_store(
284 struct omap_overlay_manager *mgr,
285 const char *buf, size_t size)
286{
287 struct omap_overlay_manager_info info;
288 bool enable;
289 int r;
290
291 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
292
293 r = strtobool(buf, &enable);
294 if (r)
295 return r;
296
297 mgr->get_manager_info(mgr, &info);
298
299 info.partial_alpha_enabled = enable;
300
301 r = mgr->set_manager_info(mgr, &info);
302 if (r)
303 return r;
304
305 r = mgr->apply(mgr);
306 if (r)
307 return r;
308
309 return size;
310}
311
312static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
313 char *buf)
314{
315 struct omap_overlay_manager_info info;
316
317 mgr->get_manager_info(mgr, &info);
318
319 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
320}
321
322static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
323 const char *buf, size_t size)
324{
325 struct omap_overlay_manager_info info;
326 int r;
327 bool enable;
328
329 if (!dss_has_feature(FEAT_CPR))
330 return -ENODEV;
331
332 r = strtobool(buf, &enable);
333 if (r)
334 return r;
335
336 mgr->get_manager_info(mgr, &info);
337
338 if (info.cpr_enable == enable)
339 return size;
340
341 info.cpr_enable = enable;
342
343 r = mgr->set_manager_info(mgr, &info);
344 if (r)
345 return r;
346
347 r = mgr->apply(mgr);
348 if (r)
349 return r;
350
351 return size;
352}
353
354static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
355 char *buf)
356{
357 struct omap_overlay_manager_info info;
358
359 mgr->get_manager_info(mgr, &info);
360
361 return snprintf(buf, PAGE_SIZE,
362 "%d %d %d %d %d %d %d %d %d\n",
363 info.cpr_coefs.rr,
364 info.cpr_coefs.rg,
365 info.cpr_coefs.rb,
366 info.cpr_coefs.gr,
367 info.cpr_coefs.gg,
368 info.cpr_coefs.gb,
369 info.cpr_coefs.br,
370 info.cpr_coefs.bg,
371 info.cpr_coefs.bb);
372}
373
374static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
375 const char *buf, size_t size)
376{
377 struct omap_overlay_manager_info info;
378 struct omap_dss_cpr_coefs coefs;
379 int r, i;
380 s16 *arr;
381
382 if (!dss_has_feature(FEAT_CPR))
383 return -ENODEV;
384
385 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
386 &coefs.rr, &coefs.rg, &coefs.rb,
387 &coefs.gr, &coefs.gg, &coefs.gb,
388 &coefs.br, &coefs.bg, &coefs.bb) != 9)
389 return -EINVAL;
390
391 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
392 coefs.gr, coefs.gg, coefs.gb,
393 coefs.br, coefs.bg, coefs.bb };
394
395 for (i = 0; i < 9; ++i) {
396 if (arr[i] < -512 || arr[i] > 511)
397 return -EINVAL;
398 }
399
400 mgr->get_manager_info(mgr, &info);
401
402 info.cpr_coefs = coefs;
403
404 r = mgr->set_manager_info(mgr, &info);
405 if (r)
406 return r;
407
408 r = mgr->apply(mgr);
409 if (r)
410 return r;
411
412 return size;
413}
414
415struct manager_attribute {
416 struct attribute attr;
417 ssize_t (*show)(struct omap_overlay_manager *, char *);
418 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
419};
420
421#define MANAGER_ATTR(_name, _mode, _show, _store) \
422 struct manager_attribute manager_attr_##_name = \
423 __ATTR(_name, _mode, _show, _store)
424
425static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
426static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
427 manager_display_show, manager_display_store);
428static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
429 manager_default_color_show, manager_default_color_store);
430static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
431 manager_trans_key_type_show, manager_trans_key_type_store);
432static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
433 manager_trans_key_value_show, manager_trans_key_value_store);
434static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
435 manager_trans_key_enabled_show,
436 manager_trans_key_enabled_store);
437static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
438 manager_alpha_blending_enabled_show,
439 manager_alpha_blending_enabled_store);
440static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
441 manager_cpr_enable_show,
442 manager_cpr_enable_store);
443static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
444 manager_cpr_coef_show,
445 manager_cpr_coef_store);
446
447
448static struct attribute *manager_sysfs_attrs[] = {
449 &manager_attr_name.attr,
450 &manager_attr_display.attr,
451 &manager_attr_default_color.attr,
452 &manager_attr_trans_key_type.attr,
453 &manager_attr_trans_key_value.attr,
454 &manager_attr_trans_key_enabled.attr,
455 &manager_attr_alpha_blending_enabled.attr,
456 &manager_attr_cpr_enable.attr,
457 &manager_attr_cpr_coef.attr,
458 NULL
459};
460
461static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
462 char *buf)
463{
464 struct omap_overlay_manager *manager;
465 struct manager_attribute *manager_attr;
466
467 manager = container_of(kobj, struct omap_overlay_manager, kobj);
468 manager_attr = container_of(attr, struct manager_attribute, attr);
469
470 if (!manager_attr->show)
471 return -ENOENT;
472
473 return manager_attr->show(manager, buf);
474}
475
476static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
477 const char *buf, size_t size)
478{
479 struct omap_overlay_manager *manager;
480 struct manager_attribute *manager_attr;
481
482 manager = container_of(kobj, struct omap_overlay_manager, kobj);
483 manager_attr = container_of(attr, struct manager_attribute, attr);
484
485 if (!manager_attr->store)
486 return -ENOENT;
487
488 return manager_attr->store(manager, buf, size);
489}
490
491static const struct sysfs_ops manager_sysfs_ops = {
492 .show = manager_attr_show,
493 .store = manager_attr_store,
494};
495
496static struct kobj_type manager_ktype = {
497 .sysfs_ops = &manager_sysfs_ops,
498 .default_attrs = manager_sysfs_attrs,
499};
500
501int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
502 struct platform_device *pdev)
503{
504 return kobject_init_and_add(&mgr->kobj, &manager_ktype,
505 &pdev->dev.kobj, "manager%d", mgr->id);
506}
507
508void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
509{
510 kobject_del(&mgr->kobj);
511 kobject_put(&mgr->kobj);
512}
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 53710fadc82d..c54d2f620ce3 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -36,463 +36,15 @@
36static int num_managers; 36static int num_managers;
37static struct omap_overlay_manager *managers; 37static struct omap_overlay_manager *managers;
38 38
39static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) 39static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
40{ 40{
41 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name); 41 return mgr->output ? mgr->output->device : NULL;
42} 42}
43 43
44static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
45{
46 return snprintf(buf, PAGE_SIZE, "%s\n",
47 mgr->device ? mgr->device->name : "<none>");
48}
49
50static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
51 const char *buf, size_t size)
52{
53 int r = 0;
54 size_t len = size;
55 struct omap_dss_device *dssdev = NULL;
56
57 int match(struct omap_dss_device *dssdev, void *data)
58 {
59 const char *str = data;
60 return sysfs_streq(dssdev->name, str);
61 }
62
63 if (buf[size-1] == '\n')
64 --len;
65
66 if (len > 0)
67 dssdev = omap_dss_find_device((void *)buf, match);
68
69 if (len > 0 && dssdev == NULL)
70 return -EINVAL;
71
72 if (dssdev)
73 DSSDBG("display %s found\n", dssdev->name);
74
75 if (mgr->device) {
76 r = mgr->unset_device(mgr);
77 if (r) {
78 DSSERR("failed to unset display\n");
79 goto put_device;
80 }
81 }
82
83 if (dssdev) {
84 r = mgr->set_device(mgr, dssdev);
85 if (r) {
86 DSSERR("failed to set manager\n");
87 goto put_device;
88 }
89
90 r = mgr->apply(mgr);
91 if (r) {
92 DSSERR("failed to apply dispc config\n");
93 goto put_device;
94 }
95 }
96
97put_device:
98 if (dssdev)
99 omap_dss_put_device(dssdev);
100
101 return r ? r : size;
102}
103
104static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
105 char *buf)
106{
107 struct omap_overlay_manager_info info;
108
109 mgr->get_manager_info(mgr, &info);
110
111 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
112}
113
114static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
115 const char *buf, size_t size)
116{
117 struct omap_overlay_manager_info info;
118 u32 color;
119 int r;
120
121 r = kstrtouint(buf, 0, &color);
122 if (r)
123 return r;
124
125 mgr->get_manager_info(mgr, &info);
126
127 info.default_color = color;
128
129 r = mgr->set_manager_info(mgr, &info);
130 if (r)
131 return r;
132
133 r = mgr->apply(mgr);
134 if (r)
135 return r;
136
137 return size;
138}
139
140static const char *trans_key_type_str[] = {
141 "gfx-destination",
142 "video-source",
143};
144
145static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
146 char *buf)
147{
148 enum omap_dss_trans_key_type key_type;
149 struct omap_overlay_manager_info info;
150
151 mgr->get_manager_info(mgr, &info);
152
153 key_type = info.trans_key_type;
154 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
155
156 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
157}
158
159static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
160 const char *buf, size_t size)
161{
162 enum omap_dss_trans_key_type key_type;
163 struct omap_overlay_manager_info info;
164 int r;
165
166 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
167 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
168 if (sysfs_streq(buf, trans_key_type_str[key_type]))
169 break;
170 }
171
172 if (key_type == ARRAY_SIZE(trans_key_type_str))
173 return -EINVAL;
174
175 mgr->get_manager_info(mgr, &info);
176
177 info.trans_key_type = key_type;
178
179 r = mgr->set_manager_info(mgr, &info);
180 if (r)
181 return r;
182
183 r = mgr->apply(mgr);
184 if (r)
185 return r;
186
187 return size;
188}
189
190static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
191 char *buf)
192{
193 struct omap_overlay_manager_info info;
194
195 mgr->get_manager_info(mgr, &info);
196
197 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
198}
199
200static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
201 const char *buf, size_t size)
202{
203 struct omap_overlay_manager_info info;
204 u32 key_value;
205 int r;
206
207 r = kstrtouint(buf, 0, &key_value);
208 if (r)
209 return r;
210
211 mgr->get_manager_info(mgr, &info);
212
213 info.trans_key = key_value;
214
215 r = mgr->set_manager_info(mgr, &info);
216 if (r)
217 return r;
218
219 r = mgr->apply(mgr);
220 if (r)
221 return r;
222
223 return size;
224}
225
226static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
227 char *buf)
228{
229 struct omap_overlay_manager_info info;
230
231 mgr->get_manager_info(mgr, &info);
232
233 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
234}
235
236static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
237 const char *buf, size_t size)
238{
239 struct omap_overlay_manager_info info;
240 bool enable;
241 int r;
242
243 r = strtobool(buf, &enable);
244 if (r)
245 return r;
246
247 mgr->get_manager_info(mgr, &info);
248
249 info.trans_enabled = enable;
250
251 r = mgr->set_manager_info(mgr, &info);
252 if (r)
253 return r;
254
255 r = mgr->apply(mgr);
256 if (r)
257 return r;
258
259 return size;
260}
261
262static ssize_t manager_alpha_blending_enabled_show(
263 struct omap_overlay_manager *mgr, char *buf)
264{
265 struct omap_overlay_manager_info info;
266
267 mgr->get_manager_info(mgr, &info);
268
269 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
270
271 return snprintf(buf, PAGE_SIZE, "%d\n",
272 info.partial_alpha_enabled);
273}
274
275static ssize_t manager_alpha_blending_enabled_store(
276 struct omap_overlay_manager *mgr,
277 const char *buf, size_t size)
278{
279 struct omap_overlay_manager_info info;
280 bool enable;
281 int r;
282
283 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
284
285 r = strtobool(buf, &enable);
286 if (r)
287 return r;
288
289 mgr->get_manager_info(mgr, &info);
290
291 info.partial_alpha_enabled = enable;
292
293 r = mgr->set_manager_info(mgr, &info);
294 if (r)
295 return r;
296
297 r = mgr->apply(mgr);
298 if (r)
299 return r;
300
301 return size;
302}
303
304static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
305 char *buf)
306{
307 struct omap_overlay_manager_info info;
308
309 mgr->get_manager_info(mgr, &info);
310
311 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
312}
313
314static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
315 const char *buf, size_t size)
316{
317 struct omap_overlay_manager_info info;
318 int r;
319 bool enable;
320
321 if (!dss_has_feature(FEAT_CPR))
322 return -ENODEV;
323
324 r = strtobool(buf, &enable);
325 if (r)
326 return r;
327
328 mgr->get_manager_info(mgr, &info);
329
330 if (info.cpr_enable == enable)
331 return size;
332
333 info.cpr_enable = enable;
334
335 r = mgr->set_manager_info(mgr, &info);
336 if (r)
337 return r;
338
339 r = mgr->apply(mgr);
340 if (r)
341 return r;
342
343 return size;
344}
345
346static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
347 char *buf)
348{
349 struct omap_overlay_manager_info info;
350
351 mgr->get_manager_info(mgr, &info);
352
353 return snprintf(buf, PAGE_SIZE,
354 "%d %d %d %d %d %d %d %d %d\n",
355 info.cpr_coefs.rr,
356 info.cpr_coefs.rg,
357 info.cpr_coefs.rb,
358 info.cpr_coefs.gr,
359 info.cpr_coefs.gg,
360 info.cpr_coefs.gb,
361 info.cpr_coefs.br,
362 info.cpr_coefs.bg,
363 info.cpr_coefs.bb);
364}
365
366static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
367 const char *buf, size_t size)
368{
369 struct omap_overlay_manager_info info;
370 struct omap_dss_cpr_coefs coefs;
371 int r, i;
372 s16 *arr;
373
374 if (!dss_has_feature(FEAT_CPR))
375 return -ENODEV;
376
377 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
378 &coefs.rr, &coefs.rg, &coefs.rb,
379 &coefs.gr, &coefs.gg, &coefs.gb,
380 &coefs.br, &coefs.bg, &coefs.bb) != 9)
381 return -EINVAL;
382
383 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
384 coefs.gr, coefs.gg, coefs.gb,
385 coefs.br, coefs.bg, coefs.bb };
386
387 for (i = 0; i < 9; ++i) {
388 if (arr[i] < -512 || arr[i] > 511)
389 return -EINVAL;
390 }
391
392 mgr->get_manager_info(mgr, &info);
393
394 info.cpr_coefs = coefs;
395
396 r = mgr->set_manager_info(mgr, &info);
397 if (r)
398 return r;
399
400 r = mgr->apply(mgr);
401 if (r)
402 return r;
403
404 return size;
405}
406
407struct manager_attribute {
408 struct attribute attr;
409 ssize_t (*show)(struct omap_overlay_manager *, char *);
410 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
411};
412
413#define MANAGER_ATTR(_name, _mode, _show, _store) \
414 struct manager_attribute manager_attr_##_name = \
415 __ATTR(_name, _mode, _show, _store)
416
417static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
418static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
419 manager_display_show, manager_display_store);
420static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
421 manager_default_color_show, manager_default_color_store);
422static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
423 manager_trans_key_type_show, manager_trans_key_type_store);
424static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
425 manager_trans_key_value_show, manager_trans_key_value_store);
426static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
427 manager_trans_key_enabled_show,
428 manager_trans_key_enabled_store);
429static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
430 manager_alpha_blending_enabled_show,
431 manager_alpha_blending_enabled_store);
432static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
433 manager_cpr_enable_show,
434 manager_cpr_enable_store);
435static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
436 manager_cpr_coef_show,
437 manager_cpr_coef_store);
438
439
440static struct attribute *manager_sysfs_attrs[] = {
441 &manager_attr_name.attr,
442 &manager_attr_display.attr,
443 &manager_attr_default_color.attr,
444 &manager_attr_trans_key_type.attr,
445 &manager_attr_trans_key_value.attr,
446 &manager_attr_trans_key_enabled.attr,
447 &manager_attr_alpha_blending_enabled.attr,
448 &manager_attr_cpr_enable.attr,
449 &manager_attr_cpr_coef.attr,
450 NULL
451};
452
453static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
454 char *buf)
455{
456 struct omap_overlay_manager *manager;
457 struct manager_attribute *manager_attr;
458
459 manager = container_of(kobj, struct omap_overlay_manager, kobj);
460 manager_attr = container_of(attr, struct manager_attribute, attr);
461
462 if (!manager_attr->show)
463 return -ENOENT;
464
465 return manager_attr->show(manager, buf);
466}
467
468static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
469 const char *buf, size_t size)
470{
471 struct omap_overlay_manager *manager;
472 struct manager_attribute *manager_attr;
473
474 manager = container_of(kobj, struct omap_overlay_manager, kobj);
475 manager_attr = container_of(attr, struct manager_attribute, attr);
476
477 if (!manager_attr->store)
478 return -ENOENT;
479
480 return manager_attr->store(manager, buf, size);
481}
482
483static const struct sysfs_ops manager_sysfs_ops = {
484 .show = manager_attr_show,
485 .store = manager_attr_store,
486};
487
488static struct kobj_type manager_ktype = {
489 .sysfs_ops = &manager_sysfs_ops,
490 .default_attrs = manager_sysfs_attrs,
491};
492
493static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) 44static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
494{ 45{
495 unsigned long timeout = msecs_to_jiffies(500); 46 unsigned long timeout = msecs_to_jiffies(500);
47 struct omap_dss_device *dssdev = mgr->get_device(mgr);
496 u32 irq; 48 u32 irq;
497 int r; 49 int r;
498 50
@@ -500,9 +52,9 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
500 if (r) 52 if (r)
501 return r; 53 return r;
502 54
503 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) 55 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
504 irq = DISPC_IRQ_EVSYNC_ODD; 56 irq = DISPC_IRQ_EVSYNC_ODD;
505 else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) 57 else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
506 irq = DISPC_IRQ_EVSYNC_EVEN; 58 irq = DISPC_IRQ_EVSYNC_EVEN;
507 else 59 else
508 irq = dispc_mgr_get_vsync_irq(mgr->id); 60 irq = dispc_mgr_get_vsync_irq(mgr->id);
@@ -547,23 +99,24 @@ int dss_init_overlay_managers(struct platform_device *pdev)
547 break; 99 break;
548 } 100 }
549 101
550 mgr->set_device = &dss_mgr_set_device; 102 mgr->set_output = &dss_mgr_set_output;
551 mgr->unset_device = &dss_mgr_unset_device; 103 mgr->unset_output = &dss_mgr_unset_output;
552 mgr->apply = &omap_dss_mgr_apply; 104 mgr->apply = &omap_dss_mgr_apply;
553 mgr->set_manager_info = &dss_mgr_set_info; 105 mgr->set_manager_info = &dss_mgr_set_info;
554 mgr->get_manager_info = &dss_mgr_get_info; 106 mgr->get_manager_info = &dss_mgr_get_info;
555 mgr->wait_for_go = &dss_mgr_wait_for_go; 107 mgr->wait_for_go = &dss_mgr_wait_for_go;
556 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync; 108 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
109 mgr->get_device = &dss_mgr_get_device;
557 110
558 mgr->caps = 0; 111 mgr->caps = 0;
559 mgr->supported_displays = 112 mgr->supported_displays =
560 dss_feat_get_supported_displays(mgr->id); 113 dss_feat_get_supported_displays(mgr->id);
114 mgr->supported_outputs =
115 dss_feat_get_supported_outputs(mgr->id);
561 116
562 INIT_LIST_HEAD(&mgr->overlays); 117 INIT_LIST_HEAD(&mgr->overlays);
563 118
564 r = kobject_init_and_add(&mgr->kobj, &manager_ktype, 119 r = dss_manager_kobj_init(mgr, pdev);
565 &pdev->dev.kobj, "manager%d", i);
566
567 if (r) 120 if (r)
568 DSSERR("failed to create sysfs file\n"); 121 DSSERR("failed to create sysfs file\n");
569 } 122 }
@@ -577,9 +130,7 @@ void dss_uninit_overlay_managers(struct platform_device *pdev)
577 130
578 for (i = 0; i < num_managers; ++i) { 131 for (i = 0; i < num_managers; ++i) {
579 struct omap_overlay_manager *mgr = &managers[i]; 132 struct omap_overlay_manager *mgr = &managers[i];
580 133 dss_manager_kobj_uninit(mgr);
581 kobject_del(&mgr->kobj);
582 kobject_put(&mgr->kobj);
583 } 134 }
584 135
585 kfree(managers); 136 kfree(managers);
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
new file mode 100644
index 000000000000..813f26682b7a
--- /dev/null
+++ b/drivers/video/omap2/dss/output.c
@@ -0,0 +1,148 @@
1/*
2 * Copyright (C) 2012 Texas Instruments Ltd
3 * Author: Archit Taneja <archit@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22
23#include <video/omapdss.h>
24
25#include "dss.h"
26
27static LIST_HEAD(output_list);
28static DEFINE_MUTEX(output_lock);
29
30int omapdss_output_set_device(struct omap_dss_output *out,
31 struct omap_dss_device *dssdev)
32{
33 int r;
34
35 mutex_lock(&output_lock);
36
37 if (out->device) {
38 DSSERR("output already has device %s connected to it\n",
39 out->device->name);
40 r = -EINVAL;
41 goto err;
42 }
43
44 if (out->type != dssdev->type) {
45 DSSERR("output type and display type don't match\n");
46 r = -EINVAL;
47 goto err;
48 }
49
50 out->device = dssdev;
51 dssdev->output = out;
52
53 mutex_unlock(&output_lock);
54
55 return 0;
56err:
57 mutex_unlock(&output_lock);
58
59 return r;
60}
61EXPORT_SYMBOL(omapdss_output_set_device);
62
63int omapdss_output_unset_device(struct omap_dss_output *out)
64{
65 int r;
66
67 mutex_lock(&output_lock);
68
69 if (!out->device) {
70 DSSERR("output doesn't have a device connected to it\n");
71 r = -EINVAL;
72 goto err;
73 }
74
75 if (out->device->state != OMAP_DSS_DISPLAY_DISABLED) {
76 DSSERR("device %s is not disabled, cannot unset device\n",
77 out->device->name);
78 r = -EINVAL;
79 goto err;
80 }
81
82 out->device->output = NULL;
83 out->device = NULL;
84
85 mutex_unlock(&output_lock);
86
87 return 0;
88err:
89 mutex_unlock(&output_lock);
90
91 return r;
92}
93EXPORT_SYMBOL(omapdss_output_unset_device);
94
95void dss_register_output(struct omap_dss_output *out)
96{
97 list_add_tail(&out->list, &output_list);
98}
99
100void dss_unregister_output(struct omap_dss_output *out)
101{
102 list_del(&out->list);
103}
104
105struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
106{
107 struct omap_dss_output *out;
108
109 list_for_each_entry(out, &output_list, list) {
110 if (out->id == id)
111 return out;
112 }
113
114 return NULL;
115}
116
117struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev)
118{
119 struct omap_dss_output *out = NULL;
120 enum omap_dss_output_id id;
121
122 switch (dssdev->type) {
123 case OMAP_DISPLAY_TYPE_DPI:
124 out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI);
125 break;
126 case OMAP_DISPLAY_TYPE_DBI:
127 out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI);
128 break;
129 case OMAP_DISPLAY_TYPE_SDI:
130 out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI);
131 break;
132 case OMAP_DISPLAY_TYPE_VENC:
133 out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC);
134 break;
135 case OMAP_DISPLAY_TYPE_HDMI:
136 out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI);
137 break;
138 case OMAP_DISPLAY_TYPE_DSI:
139 id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 :
140 OMAP_DSS_OUTPUT_DSI2;
141 out = omap_dss_get_output(id);
142 break;
143 default:
144 break;
145 }
146
147 return out;
148}
diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/omap2/dss/overlay-sysfs.c
new file mode 100644
index 000000000000..4cc5ddebfb34
--- /dev/null
+++ b/drivers/video/omap2/dss/overlay-sysfs.c
@@ -0,0 +1,456 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "OVERLAY"
22
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/sysfs.h>
26#include <linux/kobject.h>
27#include <linux/platform_device.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
37}
38
39static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
40{
41 return snprintf(buf, PAGE_SIZE, "%s\n",
42 ovl->manager ? ovl->manager->name : "<none>");
43}
44
45static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
46 size_t size)
47{
48 int i, r;
49 struct omap_overlay_manager *mgr = NULL;
50 struct omap_overlay_manager *old_mgr;
51 int len = size;
52
53 if (buf[size-1] == '\n')
54 --len;
55
56 if (len > 0) {
57 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
58 mgr = omap_dss_get_overlay_manager(i);
59
60 if (sysfs_streq(buf, mgr->name))
61 break;
62
63 mgr = NULL;
64 }
65 }
66
67 if (len > 0 && mgr == NULL)
68 return -EINVAL;
69
70 if (mgr)
71 DSSDBG("manager %s found\n", mgr->name);
72
73 if (mgr == ovl->manager)
74 return size;
75
76 old_mgr = ovl->manager;
77
78 r = dispc_runtime_get();
79 if (r)
80 return r;
81
82 /* detach old manager */
83 if (old_mgr) {
84 r = ovl->unset_manager(ovl);
85 if (r) {
86 DSSERR("detach failed\n");
87 goto err;
88 }
89
90 r = old_mgr->apply(old_mgr);
91 if (r)
92 goto err;
93 }
94
95 if (mgr) {
96 r = ovl->set_manager(ovl, mgr);
97 if (r) {
98 DSSERR("Failed to attach overlay\n");
99 goto err;
100 }
101
102 r = mgr->apply(mgr);
103 if (r)
104 goto err;
105 }
106
107 dispc_runtime_put();
108
109 return size;
110
111err:
112 dispc_runtime_put();
113 return r;
114}
115
116static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
117{
118 struct omap_overlay_info info;
119
120 ovl->get_overlay_info(ovl, &info);
121
122 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
123 info.width, info.height);
124}
125
126static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
127{
128 struct omap_overlay_info info;
129
130 ovl->get_overlay_info(ovl, &info);
131
132 return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
133}
134
135static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
136{
137 struct omap_overlay_info info;
138
139 ovl->get_overlay_info(ovl, &info);
140
141 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
142 info.pos_x, info.pos_y);
143}
144
145static ssize_t overlay_position_store(struct omap_overlay *ovl,
146 const char *buf, size_t size)
147{
148 int r;
149 char *last;
150 struct omap_overlay_info info;
151
152 ovl->get_overlay_info(ovl, &info);
153
154 info.pos_x = simple_strtoul(buf, &last, 10);
155 ++last;
156 if (last - buf >= size)
157 return -EINVAL;
158
159 info.pos_y = simple_strtoul(last, &last, 10);
160
161 r = ovl->set_overlay_info(ovl, &info);
162 if (r)
163 return r;
164
165 if (ovl->manager) {
166 r = ovl->manager->apply(ovl->manager);
167 if (r)
168 return r;
169 }
170
171 return size;
172}
173
174static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
175{
176 struct omap_overlay_info info;
177
178 ovl->get_overlay_info(ovl, &info);
179
180 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
181 info.out_width, info.out_height);
182}
183
184static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
185 const char *buf, size_t size)
186{
187 int r;
188 char *last;
189 struct omap_overlay_info info;
190
191 ovl->get_overlay_info(ovl, &info);
192
193 info.out_width = simple_strtoul(buf, &last, 10);
194 ++last;
195 if (last - buf >= size)
196 return -EINVAL;
197
198 info.out_height = simple_strtoul(last, &last, 10);
199
200 r = ovl->set_overlay_info(ovl, &info);
201 if (r)
202 return r;
203
204 if (ovl->manager) {
205 r = ovl->manager->apply(ovl->manager);
206 if (r)
207 return r;
208 }
209
210 return size;
211}
212
213static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
214{
215 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
216}
217
218static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
219 size_t size)
220{
221 int r;
222 bool enable;
223
224 r = strtobool(buf, &enable);
225 if (r)
226 return r;
227
228 if (enable)
229 r = ovl->enable(ovl);
230 else
231 r = ovl->disable(ovl);
232
233 if (r)
234 return r;
235
236 return size;
237}
238
239static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
240{
241 struct omap_overlay_info info;
242
243 ovl->get_overlay_info(ovl, &info);
244
245 return snprintf(buf, PAGE_SIZE, "%d\n",
246 info.global_alpha);
247}
248
249static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
250 const char *buf, size_t size)
251{
252 int r;
253 u8 alpha;
254 struct omap_overlay_info info;
255
256 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
257 return -ENODEV;
258
259 r = kstrtou8(buf, 0, &alpha);
260 if (r)
261 return r;
262
263 ovl->get_overlay_info(ovl, &info);
264
265 info.global_alpha = alpha;
266
267 r = ovl->set_overlay_info(ovl, &info);
268 if (r)
269 return r;
270
271 if (ovl->manager) {
272 r = ovl->manager->apply(ovl->manager);
273 if (r)
274 return r;
275 }
276
277 return size;
278}
279
280static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
281 char *buf)
282{
283 struct omap_overlay_info info;
284
285 ovl->get_overlay_info(ovl, &info);
286
287 return snprintf(buf, PAGE_SIZE, "%d\n",
288 info.pre_mult_alpha);
289}
290
291static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
292 const char *buf, size_t size)
293{
294 int r;
295 u8 alpha;
296 struct omap_overlay_info info;
297
298 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
299 return -ENODEV;
300
301 r = kstrtou8(buf, 0, &alpha);
302 if (r)
303 return r;
304
305 ovl->get_overlay_info(ovl, &info);
306
307 info.pre_mult_alpha = alpha;
308
309 r = ovl->set_overlay_info(ovl, &info);
310 if (r)
311 return r;
312
313 if (ovl->manager) {
314 r = ovl->manager->apply(ovl->manager);
315 if (r)
316 return r;
317 }
318
319 return size;
320}
321
322static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
323{
324 struct omap_overlay_info info;
325
326 ovl->get_overlay_info(ovl, &info);
327
328 return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
329}
330
331static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
332 const char *buf, size_t size)
333{
334 int r;
335 u8 zorder;
336 struct omap_overlay_info info;
337
338 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
339 return -ENODEV;
340
341 r = kstrtou8(buf, 0, &zorder);
342 if (r)
343 return r;
344
345 ovl->get_overlay_info(ovl, &info);
346
347 info.zorder = zorder;
348
349 r = ovl->set_overlay_info(ovl, &info);
350 if (r)
351 return r;
352
353 if (ovl->manager) {
354 r = ovl->manager->apply(ovl->manager);
355 if (r)
356 return r;
357 }
358
359 return size;
360}
361
362struct overlay_attribute {
363 struct attribute attr;
364 ssize_t (*show)(struct omap_overlay *, char *);
365 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
366};
367
368#define OVERLAY_ATTR(_name, _mode, _show, _store) \
369 struct overlay_attribute overlay_attr_##_name = \
370 __ATTR(_name, _mode, _show, _store)
371
372static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
373static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
374 overlay_manager_show, overlay_manager_store);
375static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
376static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
377static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
378 overlay_position_show, overlay_position_store);
379static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
380 overlay_output_size_show, overlay_output_size_store);
381static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
382 overlay_enabled_show, overlay_enabled_store);
383static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
384 overlay_global_alpha_show, overlay_global_alpha_store);
385static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
386 overlay_pre_mult_alpha_show,
387 overlay_pre_mult_alpha_store);
388static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
389 overlay_zorder_show, overlay_zorder_store);
390
391static struct attribute *overlay_sysfs_attrs[] = {
392 &overlay_attr_name.attr,
393 &overlay_attr_manager.attr,
394 &overlay_attr_input_size.attr,
395 &overlay_attr_screen_width.attr,
396 &overlay_attr_position.attr,
397 &overlay_attr_output_size.attr,
398 &overlay_attr_enabled.attr,
399 &overlay_attr_global_alpha.attr,
400 &overlay_attr_pre_mult_alpha.attr,
401 &overlay_attr_zorder.attr,
402 NULL
403};
404
405static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
406 char *buf)
407{
408 struct omap_overlay *overlay;
409 struct overlay_attribute *overlay_attr;
410
411 overlay = container_of(kobj, struct omap_overlay, kobj);
412 overlay_attr = container_of(attr, struct overlay_attribute, attr);
413
414 if (!overlay_attr->show)
415 return -ENOENT;
416
417 return overlay_attr->show(overlay, buf);
418}
419
420static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
421 const char *buf, size_t size)
422{
423 struct omap_overlay *overlay;
424 struct overlay_attribute *overlay_attr;
425
426 overlay = container_of(kobj, struct omap_overlay, kobj);
427 overlay_attr = container_of(attr, struct overlay_attribute, attr);
428
429 if (!overlay_attr->store)
430 return -ENOENT;
431
432 return overlay_attr->store(overlay, buf, size);
433}
434
435static const struct sysfs_ops overlay_sysfs_ops = {
436 .show = overlay_attr_show,
437 .store = overlay_attr_store,
438};
439
440static struct kobj_type overlay_ktype = {
441 .sysfs_ops = &overlay_sysfs_ops,
442 .default_attrs = overlay_sysfs_attrs,
443};
444
445int dss_overlay_kobj_init(struct omap_overlay *ovl,
446 struct platform_device *pdev)
447{
448 return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
449 &pdev->dev.kobj, "overlay%d", ovl->id);
450}
451
452void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
453{
454 kobject_del(&ovl->kobj);
455 kobject_put(&ovl->kobj);
456}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 952c6fad9a81..45f4994bc6b0 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -26,13 +26,11 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/sysfs.h> 28#include <linux/sysfs.h>
29#include <linux/kobject.h>
30#include <linux/platform_device.h> 29#include <linux/platform_device.h>
31#include <linux/delay.h> 30#include <linux/delay.h>
32#include <linux/slab.h> 31#include <linux/slab.h>
33 32
34#include <video/omapdss.h> 33#include <video/omapdss.h>
35#include <plat/cpu.h>
36 34
37#include "dss.h" 35#include "dss.h"
38#include "dss_features.h" 36#include "dss_features.h"
@@ -40,417 +38,13 @@
40static int num_overlays; 38static int num_overlays;
41static struct omap_overlay *overlays; 39static struct omap_overlay *overlays;
42 40
43static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) 41static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
44{ 42{
45 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); 43 return ovl->manager ?
44 (ovl->manager->output ? ovl->manager->output->device : NULL) :
45 NULL;
46} 46}
47 47
48static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
49{
50 return snprintf(buf, PAGE_SIZE, "%s\n",
51 ovl->manager ? ovl->manager->name : "<none>");
52}
53
54static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
55 size_t size)
56{
57 int i, r;
58 struct omap_overlay_manager *mgr = NULL;
59 struct omap_overlay_manager *old_mgr;
60 int len = size;
61
62 if (buf[size-1] == '\n')
63 --len;
64
65 if (len > 0) {
66 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
67 mgr = omap_dss_get_overlay_manager(i);
68
69 if (sysfs_streq(buf, mgr->name))
70 break;
71
72 mgr = NULL;
73 }
74 }
75
76 if (len > 0 && mgr == NULL)
77 return -EINVAL;
78
79 if (mgr)
80 DSSDBG("manager %s found\n", mgr->name);
81
82 if (mgr == ovl->manager)
83 return size;
84
85 old_mgr = ovl->manager;
86
87 r = dispc_runtime_get();
88 if (r)
89 return r;
90
91 /* detach old manager */
92 if (old_mgr) {
93 r = ovl->unset_manager(ovl);
94 if (r) {
95 DSSERR("detach failed\n");
96 goto err;
97 }
98
99 r = old_mgr->apply(old_mgr);
100 if (r)
101 goto err;
102 }
103
104 if (mgr) {
105 r = ovl->set_manager(ovl, mgr);
106 if (r) {
107 DSSERR("Failed to attach overlay\n");
108 goto err;
109 }
110
111 r = mgr->apply(mgr);
112 if (r)
113 goto err;
114 }
115
116 dispc_runtime_put();
117
118 return size;
119
120err:
121 dispc_runtime_put();
122 return r;
123}
124
125static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
126{
127 struct omap_overlay_info info;
128
129 ovl->get_overlay_info(ovl, &info);
130
131 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
132 info.width, info.height);
133}
134
135static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
136{
137 struct omap_overlay_info info;
138
139 ovl->get_overlay_info(ovl, &info);
140
141 return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
142}
143
144static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
145{
146 struct omap_overlay_info info;
147
148 ovl->get_overlay_info(ovl, &info);
149
150 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
151 info.pos_x, info.pos_y);
152}
153
154static ssize_t overlay_position_store(struct omap_overlay *ovl,
155 const char *buf, size_t size)
156{
157 int r;
158 char *last;
159 struct omap_overlay_info info;
160
161 ovl->get_overlay_info(ovl, &info);
162
163 info.pos_x = simple_strtoul(buf, &last, 10);
164 ++last;
165 if (last - buf >= size)
166 return -EINVAL;
167
168 info.pos_y = simple_strtoul(last, &last, 10);
169
170 r = ovl->set_overlay_info(ovl, &info);
171 if (r)
172 return r;
173
174 if (ovl->manager) {
175 r = ovl->manager->apply(ovl->manager);
176 if (r)
177 return r;
178 }
179
180 return size;
181}
182
183static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
184{
185 struct omap_overlay_info info;
186
187 ovl->get_overlay_info(ovl, &info);
188
189 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
190 info.out_width, info.out_height);
191}
192
193static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
194 const char *buf, size_t size)
195{
196 int r;
197 char *last;
198 struct omap_overlay_info info;
199
200 ovl->get_overlay_info(ovl, &info);
201
202 info.out_width = simple_strtoul(buf, &last, 10);
203 ++last;
204 if (last - buf >= size)
205 return -EINVAL;
206
207 info.out_height = simple_strtoul(last, &last, 10);
208
209 r = ovl->set_overlay_info(ovl, &info);
210 if (r)
211 return r;
212
213 if (ovl->manager) {
214 r = ovl->manager->apply(ovl->manager);
215 if (r)
216 return r;
217 }
218
219 return size;
220}
221
222static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
223{
224 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
225}
226
227static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
228 size_t size)
229{
230 int r;
231 bool enable;
232
233 r = strtobool(buf, &enable);
234 if (r)
235 return r;
236
237 if (enable)
238 r = ovl->enable(ovl);
239 else
240 r = ovl->disable(ovl);
241
242 if (r)
243 return r;
244
245 return size;
246}
247
248static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
249{
250 struct omap_overlay_info info;
251
252 ovl->get_overlay_info(ovl, &info);
253
254 return snprintf(buf, PAGE_SIZE, "%d\n",
255 info.global_alpha);
256}
257
258static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
259 const char *buf, size_t size)
260{
261 int r;
262 u8 alpha;
263 struct omap_overlay_info info;
264
265 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
266 return -ENODEV;
267
268 r = kstrtou8(buf, 0, &alpha);
269 if (r)
270 return r;
271
272 ovl->get_overlay_info(ovl, &info);
273
274 info.global_alpha = alpha;
275
276 r = ovl->set_overlay_info(ovl, &info);
277 if (r)
278 return r;
279
280 if (ovl->manager) {
281 r = ovl->manager->apply(ovl->manager);
282 if (r)
283 return r;
284 }
285
286 return size;
287}
288
289static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
290 char *buf)
291{
292 struct omap_overlay_info info;
293
294 ovl->get_overlay_info(ovl, &info);
295
296 return snprintf(buf, PAGE_SIZE, "%d\n",
297 info.pre_mult_alpha);
298}
299
300static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
301 const char *buf, size_t size)
302{
303 int r;
304 u8 alpha;
305 struct omap_overlay_info info;
306
307 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
308 return -ENODEV;
309
310 r = kstrtou8(buf, 0, &alpha);
311 if (r)
312 return r;
313
314 ovl->get_overlay_info(ovl, &info);
315
316 info.pre_mult_alpha = alpha;
317
318 r = ovl->set_overlay_info(ovl, &info);
319 if (r)
320 return r;
321
322 if (ovl->manager) {
323 r = ovl->manager->apply(ovl->manager);
324 if (r)
325 return r;
326 }
327
328 return size;
329}
330
331static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
332{
333 struct omap_overlay_info info;
334
335 ovl->get_overlay_info(ovl, &info);
336
337 return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
338}
339
340static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
341 const char *buf, size_t size)
342{
343 int r;
344 u8 zorder;
345 struct omap_overlay_info info;
346
347 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
348 return -ENODEV;
349
350 r = kstrtou8(buf, 0, &zorder);
351 if (r)
352 return r;
353
354 ovl->get_overlay_info(ovl, &info);
355
356 info.zorder = zorder;
357
358 r = ovl->set_overlay_info(ovl, &info);
359 if (r)
360 return r;
361
362 if (ovl->manager) {
363 r = ovl->manager->apply(ovl->manager);
364 if (r)
365 return r;
366 }
367
368 return size;
369}
370
371struct overlay_attribute {
372 struct attribute attr;
373 ssize_t (*show)(struct omap_overlay *, char *);
374 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
375};
376
377#define OVERLAY_ATTR(_name, _mode, _show, _store) \
378 struct overlay_attribute overlay_attr_##_name = \
379 __ATTR(_name, _mode, _show, _store)
380
381static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
382static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
383 overlay_manager_show, overlay_manager_store);
384static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
385static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
386static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
387 overlay_position_show, overlay_position_store);
388static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
389 overlay_output_size_show, overlay_output_size_store);
390static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
391 overlay_enabled_show, overlay_enabled_store);
392static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
393 overlay_global_alpha_show, overlay_global_alpha_store);
394static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
395 overlay_pre_mult_alpha_show,
396 overlay_pre_mult_alpha_store);
397static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
398 overlay_zorder_show, overlay_zorder_store);
399
400static struct attribute *overlay_sysfs_attrs[] = {
401 &overlay_attr_name.attr,
402 &overlay_attr_manager.attr,
403 &overlay_attr_input_size.attr,
404 &overlay_attr_screen_width.attr,
405 &overlay_attr_position.attr,
406 &overlay_attr_output_size.attr,
407 &overlay_attr_enabled.attr,
408 &overlay_attr_global_alpha.attr,
409 &overlay_attr_pre_mult_alpha.attr,
410 &overlay_attr_zorder.attr,
411 NULL
412};
413
414static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
415 char *buf)
416{
417 struct omap_overlay *overlay;
418 struct overlay_attribute *overlay_attr;
419
420 overlay = container_of(kobj, struct omap_overlay, kobj);
421 overlay_attr = container_of(attr, struct overlay_attribute, attr);
422
423 if (!overlay_attr->show)
424 return -ENOENT;
425
426 return overlay_attr->show(overlay, buf);
427}
428
429static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
430 const char *buf, size_t size)
431{
432 struct omap_overlay *overlay;
433 struct overlay_attribute *overlay_attr;
434
435 overlay = container_of(kobj, struct omap_overlay, kobj);
436 overlay_attr = container_of(attr, struct overlay_attribute, attr);
437
438 if (!overlay_attr->store)
439 return -ENOENT;
440
441 return overlay_attr->store(overlay, buf, size);
442}
443
444static const struct sysfs_ops overlay_sysfs_ops = {
445 .show = overlay_attr_show,
446 .store = overlay_attr_store,
447};
448
449static struct kobj_type overlay_ktype = {
450 .sysfs_ops = &overlay_sysfs_ops,
451 .default_attrs = overlay_sysfs_attrs,
452};
453
454int omap_dss_get_num_overlays(void) 48int omap_dss_get_num_overlays(void)
455{ 49{
456 return num_overlays; 50 return num_overlays;
@@ -507,97 +101,25 @@ void dss_init_overlays(struct platform_device *pdev)
507 ovl->set_overlay_info = &dss_ovl_set_info; 101 ovl->set_overlay_info = &dss_ovl_set_info;
508 ovl->get_overlay_info = &dss_ovl_get_info; 102 ovl->get_overlay_info = &dss_ovl_get_info;
509 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; 103 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
104 ovl->get_device = &dss_ovl_get_device;
510 105
511 ovl->caps = dss_feat_get_overlay_caps(ovl->id); 106 ovl->caps = dss_feat_get_overlay_caps(ovl->id);
512 ovl->supported_modes = 107 ovl->supported_modes =
513 dss_feat_get_supported_color_modes(ovl->id); 108 dss_feat_get_supported_color_modes(ovl->id);
514 109
515 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, 110 r = dss_overlay_kobj_init(ovl, pdev);
516 &pdev->dev.kobj, "overlay%d", i);
517
518 if (r) 111 if (r)
519 DSSERR("failed to create sysfs file\n"); 112 DSSERR("failed to create sysfs file\n");
520 } 113 }
521} 114}
522 115
523/* connect overlays to the new device, if not already connected. if force
524 * selected, connect always. */
525void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
526{
527 int i;
528 struct omap_overlay_manager *lcd_mgr;
529 struct omap_overlay_manager *tv_mgr;
530 struct omap_overlay_manager *lcd2_mgr = NULL;
531 struct omap_overlay_manager *lcd3_mgr = NULL;
532 struct omap_overlay_manager *mgr = NULL;
533
534 lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD);
535 tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_DIGIT);
536 if (dss_has_feature(FEAT_MGR_LCD3))
537 lcd3_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD3);
538 if (dss_has_feature(FEAT_MGR_LCD2))
539 lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD2);
540
541 if (dssdev->channel == OMAP_DSS_CHANNEL_LCD3) {
542 if (!lcd3_mgr->device || force) {
543 if (lcd3_mgr->device)
544 lcd3_mgr->unset_device(lcd3_mgr);
545 lcd3_mgr->set_device(lcd3_mgr, dssdev);
546 mgr = lcd3_mgr;
547 }
548 } else if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
549 if (!lcd2_mgr->device || force) {
550 if (lcd2_mgr->device)
551 lcd2_mgr->unset_device(lcd2_mgr);
552 lcd2_mgr->set_device(lcd2_mgr, dssdev);
553 mgr = lcd2_mgr;
554 }
555 } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
556 && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
557 if (!lcd_mgr->device || force) {
558 if (lcd_mgr->device)
559 lcd_mgr->unset_device(lcd_mgr);
560 lcd_mgr->set_device(lcd_mgr, dssdev);
561 mgr = lcd_mgr;
562 }
563 }
564
565 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
566 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
567 if (!tv_mgr->device || force) {
568 if (tv_mgr->device)
569 tv_mgr->unset_device(tv_mgr);
570 tv_mgr->set_device(tv_mgr, dssdev);
571 mgr = tv_mgr;
572 }
573 }
574
575 if (mgr) {
576 dispc_runtime_get();
577
578 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
579 struct omap_overlay *ovl;
580 ovl = omap_dss_get_overlay(i);
581 if (!ovl->manager || force) {
582 if (ovl->manager)
583 ovl->unset_manager(ovl);
584 ovl->set_manager(ovl, mgr);
585 }
586 }
587
588 dispc_runtime_put();
589 }
590}
591
592void dss_uninit_overlays(struct platform_device *pdev) 116void dss_uninit_overlays(struct platform_device *pdev)
593{ 117{
594 int i; 118 int i;
595 119
596 for (i = 0; i < num_overlays; ++i) { 120 for (i = 0; i < num_overlays; ++i) {
597 struct omap_overlay *ovl = &overlays[i]; 121 struct omap_overlay *ovl = &overlays[i];
598 122 dss_overlay_kobj_uninit(ovl);
599 kobject_del(&ovl->kobj);
600 kobject_put(&ovl->kobj);
601 } 123 }
602 124
603 kfree(overlays); 125 kfree(overlays);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 7c087424b634..7282e5af3e1a 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -111,6 +111,13 @@ static struct {
111 struct omap_dss_device *dssdev[2]; 111 struct omap_dss_device *dssdev[2];
112 112
113 struct semaphore bus_lock; 113 struct semaphore bus_lock;
114
115 struct omap_video_timings timings;
116 int pixel_size;
117 int data_lines;
118 struct rfbi_timings intf_timings;
119
120 struct omap_dss_output output;
114} rfbi; 121} rfbi;
115 122
116static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) 123static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
@@ -300,30 +307,23 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
300} 307}
301EXPORT_SYMBOL(omap_rfbi_write_pixels); 308EXPORT_SYMBOL(omap_rfbi_write_pixels);
302 309
303static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, 310static int rfbi_transfer_area(struct omap_dss_device *dssdev,
304 u16 height, void (*callback)(void *data), void *data) 311 void (*callback)(void *data), void *data)
305{ 312{
306 u32 l; 313 u32 l;
307 int r; 314 int r;
308 struct omap_video_timings timings = { 315 struct omap_overlay_manager *mgr = dssdev->output->manager;
309 .hsw = 1, 316 u16 width = rfbi.timings.x_res;
310 .hfp = 1, 317 u16 height = rfbi.timings.y_res;
311 .hbp = 1,
312 .vsw = 1,
313 .vfp = 0,
314 .vbp = 0,
315 .x_res = width,
316 .y_res = height,
317 };
318 318
319 /*BUG_ON(callback == 0);*/ 319 /*BUG_ON(callback == 0);*/
320 BUG_ON(rfbi.framedone_callback != NULL); 320 BUG_ON(rfbi.framedone_callback != NULL);
321 321
322 DSSDBG("rfbi_transfer_area %dx%d\n", width, height); 322 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
323 323
324 dss_mgr_set_timings(dssdev->manager, &timings); 324 dss_mgr_set_timings(mgr, &rfbi.timings);
325 325
326 r = dss_mgr_enable(dssdev->manager); 326 r = dss_mgr_enable(mgr);
327 if (r) 327 if (r)
328 return r; 328 return r;
329 329
@@ -770,62 +770,45 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
770 return 0; 770 return 0;
771} 771}
772 772
773int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, 773int omap_rfbi_configure(struct omap_dss_device *dssdev)
774 int data_lines)
775{ 774{
776 return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines); 775 return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
776 rfbi.data_lines);
777} 777}
778EXPORT_SYMBOL(omap_rfbi_configure); 778EXPORT_SYMBOL(omap_rfbi_configure);
779 779
780int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, 780int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
781 u16 *x, u16 *y, u16 *w, u16 *h) 781 void *data)
782{ 782{
783 u16 dw, dh; 783 return rfbi_transfer_area(dssdev, callback, data);
784 struct omap_video_timings timings = { 784}
785 .hsw = 1, 785EXPORT_SYMBOL(omap_rfbi_update);
786 .hfp = 1,
787 .hbp = 1,
788 .vsw = 1,
789 .vfp = 0,
790 .vbp = 0,
791 .x_res = *w,
792 .y_res = *h,
793 };
794
795 dssdev->driver->get_resolution(dssdev, &dw, &dh);
796
797 if (*x > dw || *y > dh)
798 return -EINVAL;
799
800 if (*x + *w > dw)
801 return -EINVAL;
802
803 if (*y + *h > dh)
804 return -EINVAL;
805
806 if (*w == 1)
807 return -EINVAL;
808
809 if (*w == 0 || *h == 0)
810 return -EINVAL;
811
812 dss_mgr_set_timings(dssdev->manager, &timings);
813 786
814 return 0; 787void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
788{
789 rfbi.timings.x_res = w;
790 rfbi.timings.y_res = h;
815} 791}
816EXPORT_SYMBOL(omap_rfbi_prepare_update); 792EXPORT_SYMBOL(omapdss_rfbi_set_size);
817 793
818int omap_rfbi_update(struct omap_dss_device *dssdev, 794void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
819 u16 x, u16 y, u16 w, u16 h,
820 void (*callback)(void *), void *data)
821{ 795{
822 int r; 796 rfbi.pixel_size = pixel_size;
797}
798EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
823 799
824 r = rfbi_transfer_area(dssdev, w, h, callback, data); 800void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
801{
802 rfbi.data_lines = data_lines;
803}
804EXPORT_SYMBOL(omapdss_rfbi_set_data_lines);
825 805
826 return r; 806void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
807 struct rfbi_timings *timings)
808{
809 rfbi.intf_timings = *timings;
827} 810}
828EXPORT_SYMBOL(omap_rfbi_update); 811EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);
829 812
830static void rfbi_dump_regs(struct seq_file *s) 813static void rfbi_dump_regs(struct seq_file *s)
831{ 814{
@@ -869,6 +852,7 @@ static void rfbi_dump_regs(struct seq_file *s)
869 852
870static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) 853static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
871{ 854{
855 struct omap_overlay_manager *mgr = dssdev->output->manager;
872 struct dss_lcd_mgr_config mgr_config; 856 struct dss_lcd_mgr_config mgr_config;
873 857
874 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI; 858 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
@@ -877,18 +861,40 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
877 /* Do we need fifohandcheck for RFBI? */ 861 /* Do we need fifohandcheck for RFBI? */
878 mgr_config.fifohandcheck = false; 862 mgr_config.fifohandcheck = false;
879 863
880 mgr_config.video_port_width = dssdev->ctrl.pixel_size; 864 mgr_config.video_port_width = rfbi.pixel_size;
881 mgr_config.lcden_sig_polarity = 0; 865 mgr_config.lcden_sig_polarity = 0;
882 866
883 dss_mgr_set_lcd_config(dssdev->manager, &mgr_config); 867 dss_mgr_set_lcd_config(mgr, &mgr_config);
868
869 /*
870 * Set rfbi.timings with default values, the x_res and y_res fields
871 * are expected to be already configured by the panel driver via
872 * omapdss_rfbi_set_size()
873 */
874 rfbi.timings.hsw = 1;
875 rfbi.timings.hfp = 1;
876 rfbi.timings.hbp = 1;
877 rfbi.timings.vsw = 1;
878 rfbi.timings.vfp = 0;
879 rfbi.timings.vbp = 0;
880
881 rfbi.timings.interlace = false;
882 rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
883 rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
884 rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
885 rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
886 rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
887
888 dss_mgr_set_timings(mgr, &rfbi.timings);
884} 889}
885 890
886int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) 891int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
887{ 892{
893 struct omap_dss_output *out = dssdev->output;
888 int r; 894 int r;
889 895
890 if (dssdev->manager == NULL) { 896 if (out == NULL || out->manager == NULL) {
891 DSSERR("failed to enable display: no manager\n"); 897 DSSERR("failed to enable display: no output/manager\n");
892 return -ENODEV; 898 return -ENODEV;
893 } 899 }
894 900
@@ -911,13 +917,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
911 917
912 rfbi_config_lcd_manager(dssdev); 918 rfbi_config_lcd_manager(dssdev);
913 919
914 rfbi_configure(dssdev->phy.rfbi.channel, 920 rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
915 dssdev->ctrl.pixel_size, 921 rfbi.data_lines);
916 dssdev->phy.rfbi.data_lines);
917
918 rfbi_set_timings(dssdev->phy.rfbi.channel,
919 &dssdev->ctrl.rfbi_timings);
920 922
923 rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
921 924
922 return 0; 925 return 0;
923err1: 926err1:
@@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable);
941static int __init rfbi_init_display(struct omap_dss_device *dssdev) 944static int __init rfbi_init_display(struct omap_dss_device *dssdev)
942{ 945{
943 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; 946 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
944 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
945 return 0; 947 return 0;
946} 948}
947 949
948static void __init rfbi_probe_pdata(struct platform_device *pdev) 950static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
949{ 951{
950 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 952 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
951 int i, r; 953 const char *def_disp_name = dss_get_default_display_name();
954 struct omap_dss_device *def_dssdev;
955 int i;
956
957 def_dssdev = NULL;
952 958
953 for (i = 0; i < pdata->num_devices; ++i) { 959 for (i = 0; i < pdata->num_devices; ++i) {
954 struct omap_dss_device *dssdev = pdata->devices[i]; 960 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -956,17 +962,67 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)
956 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI) 962 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
957 continue; 963 continue;
958 964
959 r = rfbi_init_display(dssdev); 965 if (def_dssdev == NULL)
960 if (r) { 966 def_dssdev = dssdev;
961 DSSERR("device %s init failed: %d\n", dssdev->name, r); 967
962 continue; 968 if (def_disp_name != NULL &&
969 strcmp(dssdev->name, def_disp_name) == 0) {
970 def_dssdev = dssdev;
971 break;
963 } 972 }
973 }
974
975 return def_dssdev;
976}
977
978static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
979{
980 struct omap_dss_device *plat_dssdev;
981 struct omap_dss_device *dssdev;
982 int r;
983
984 plat_dssdev = rfbi_find_dssdev(rfbidev);
985
986 if (!plat_dssdev)
987 return;
988
989 dssdev = dss_alloc_and_init_device(&rfbidev->dev);
990 if (!dssdev)
991 return;
992
993 dss_copy_device_pdata(dssdev, plat_dssdev);
964 994
965 r = omap_dss_register_device(dssdev, &pdev->dev, i); 995 r = rfbi_init_display(dssdev);
966 if (r) 996 if (r) {
967 DSSERR("device %s register failed: %d\n", 997 DSSERR("device %s init failed: %d\n", dssdev->name, r);
968 dssdev->name, r); 998 dss_put_device(dssdev);
999 return;
969 } 1000 }
1001
1002 r = dss_add_device(dssdev);
1003 if (r) {
1004 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1005 dss_put_device(dssdev);
1006 return;
1007 }
1008}
1009
1010static void __init rfbi_init_output(struct platform_device *pdev)
1011{
1012 struct omap_dss_output *out = &rfbi.output;
1013
1014 out->pdev = pdev;
1015 out->id = OMAP_DSS_OUTPUT_DBI;
1016 out->type = OMAP_DISPLAY_TYPE_DBI;
1017
1018 dss_register_output(out);
1019}
1020
1021static void __exit rfbi_uninit_output(struct platform_device *pdev)
1022{
1023 struct omap_dss_output *out = &rfbi.output;
1024
1025 dss_unregister_output(out);
970} 1026}
971 1027
972/* RFBI HW IP initialisation */ 1028/* RFBI HW IP initialisation */
@@ -1020,6 +1076,8 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)
1020 1076
1021 dss_debugfs_create_file("rfbi", rfbi_dump_regs); 1077 dss_debugfs_create_file("rfbi", rfbi_dump_regs);
1022 1078
1079 rfbi_init_output(pdev);
1080
1023 rfbi_probe_pdata(pdev); 1081 rfbi_probe_pdata(pdev);
1024 1082
1025 return 0; 1083 return 0;
@@ -1031,8 +1089,12 @@ err_runtime_get:
1031 1089
1032static int __exit omap_rfbihw_remove(struct platform_device *pdev) 1090static int __exit omap_rfbihw_remove(struct platform_device *pdev)
1033{ 1091{
1034 omap_dss_unregister_child_devices(&pdev->dev); 1092 dss_unregister_child_devices(&pdev->dev);
1093
1094 rfbi_uninit_output(pdev);
1095
1035 pm_runtime_disable(&pdev->dev); 1096 pm_runtime_disable(&pdev->dev);
1097
1036 return 0; 1098 return 0;
1037} 1099}
1038 1100
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index f43bfe17b3b6..7760851f6e5d 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -25,6 +25,7 @@
25#include <linux/regulator/consumer.h> 25#include <linux/regulator/consumer.h>
26#include <linux/export.h> 26#include <linux/export.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/string.h>
28 29
29#include <video/omapdss.h> 30#include <video/omapdss.h>
30#include "dss.h" 31#include "dss.h"
@@ -34,10 +35,16 @@ static struct {
34 struct regulator *vdds_sdi_reg; 35 struct regulator *vdds_sdi_reg;
35 36
36 struct dss_lcd_mgr_config mgr_config; 37 struct dss_lcd_mgr_config mgr_config;
38 struct omap_video_timings timings;
39 int datapairs;
40
41 struct omap_dss_output output;
37} sdi; 42} sdi;
38 43
39static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) 44static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
40{ 45{
46 struct omap_overlay_manager *mgr = dssdev->output->manager;
47
41 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 48 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
42 49
43 sdi.mgr_config.stallmode = false; 50 sdi.mgr_config.stallmode = false;
@@ -46,19 +53,20 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
46 sdi.mgr_config.video_port_width = 24; 53 sdi.mgr_config.video_port_width = 24;
47 sdi.mgr_config.lcden_sig_polarity = 1; 54 sdi.mgr_config.lcden_sig_polarity = 1;
48 55
49 dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config); 56 dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
50} 57}
51 58
52int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) 59int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
53{ 60{
54 struct omap_video_timings *t = &dssdev->panel.timings; 61 struct omap_dss_output *out = dssdev->output;
62 struct omap_video_timings *t = &sdi.timings;
55 struct dss_clock_info dss_cinfo; 63 struct dss_clock_info dss_cinfo;
56 struct dispc_clock_info dispc_cinfo; 64 struct dispc_clock_info dispc_cinfo;
57 unsigned long pck; 65 unsigned long pck;
58 int r; 66 int r;
59 67
60 if (dssdev->manager == NULL) { 68 if (out == NULL || out->manager == NULL) {
61 DSSERR("failed to enable display: no manager\n"); 69 DSSERR("failed to enable display: no output/manager\n");
62 return -ENODEV; 70 return -ENODEV;
63 } 71 }
64 72
@@ -77,8 +85,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
77 goto err_get_dispc; 85 goto err_get_dispc;
78 86
79 /* 15.5.9.1.2 */ 87 /* 15.5.9.1.2 */
80 dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 88 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
81 dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 89 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
82 90
83 r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); 91 r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
84 if (r) 92 if (r)
@@ -97,7 +105,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
97 } 105 }
98 106
99 107
100 dss_mgr_set_timings(dssdev->manager, t); 108 dss_mgr_set_timings(out->manager, t);
101 109
102 r = dss_set_clock_div(&dss_cinfo); 110 r = dss_set_clock_div(&dss_cinfo);
103 if (r) 111 if (r)
@@ -116,16 +124,15 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
116 * need to care about the shadow register mechanism for pck-free. The 124 * need to care about the shadow register mechanism for pck-free. The
117 * exact reason for this is unknown. 125 * exact reason for this is unknown.
118 */ 126 */
119 dispc_mgr_set_clock_div(dssdev->manager->id, 127 dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
120 &sdi.mgr_config.clock_info);
121 128
122 dss_sdi_init(dssdev->phy.sdi.datapairs); 129 dss_sdi_init(sdi.datapairs);
123 r = dss_sdi_enable(); 130 r = dss_sdi_enable();
124 if (r) 131 if (r)
125 goto err_sdi_enable; 132 goto err_sdi_enable;
126 mdelay(2); 133 mdelay(2);
127 134
128 r = dss_mgr_enable(dssdev->manager); 135 r = dss_mgr_enable(out->manager);
129 if (r) 136 if (r)
130 goto err_mgr_enable; 137 goto err_mgr_enable;
131 138
@@ -148,7 +155,9 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
148 155
149void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) 156void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
150{ 157{
151 dss_mgr_disable(dssdev->manager); 158 struct omap_overlay_manager *mgr = dssdev->output->manager;
159
160 dss_mgr_disable(mgr);
152 161
153 dss_sdi_disable(); 162 dss_sdi_disable();
154 163
@@ -160,6 +169,19 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
160} 169}
161EXPORT_SYMBOL(omapdss_sdi_display_disable); 170EXPORT_SYMBOL(omapdss_sdi_display_disable);
162 171
172void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
173 struct omap_video_timings *timings)
174{
175 sdi.timings = *timings;
176}
177EXPORT_SYMBOL(omapdss_sdi_set_timings);
178
179void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
180{
181 sdi.datapairs = datapairs;
182}
183EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
184
163static int __init sdi_init_display(struct omap_dss_device *dssdev) 185static int __init sdi_init_display(struct omap_dss_device *dssdev)
164{ 186{
165 DSSDBG("SDI init\n"); 187 DSSDBG("SDI init\n");
@@ -180,10 +202,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
180 return 0; 202 return 0;
181} 203}
182 204
183static void __init sdi_probe_pdata(struct platform_device *pdev) 205static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
184{ 206{
185 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 207 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
186 int i, r; 208 const char *def_disp_name = dss_get_default_display_name();
209 struct omap_dss_device *def_dssdev;
210 int i;
211
212 def_dssdev = NULL;
187 213
188 for (i = 0; i < pdata->num_devices; ++i) { 214 for (i = 0; i < pdata->num_devices; ++i) {
189 struct omap_dss_device *dssdev = pdata->devices[i]; 215 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -191,21 +217,73 @@ static void __init sdi_probe_pdata(struct platform_device *pdev)
191 if (dssdev->type != OMAP_DISPLAY_TYPE_SDI) 217 if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
192 continue; 218 continue;
193 219
194 r = sdi_init_display(dssdev); 220 if (def_dssdev == NULL)
195 if (r) { 221 def_dssdev = dssdev;
196 DSSERR("device %s init failed: %d\n", dssdev->name, r); 222
197 continue; 223 if (def_disp_name != NULL &&
224 strcmp(dssdev->name, def_disp_name) == 0) {
225 def_dssdev = dssdev;
226 break;
198 } 227 }
228 }
229
230 return def_dssdev;
231}
232
233static void __init sdi_probe_pdata(struct platform_device *sdidev)
234{
235 struct omap_dss_device *plat_dssdev;
236 struct omap_dss_device *dssdev;
237 int r;
238
239 plat_dssdev = sdi_find_dssdev(sdidev);
199 240
200 r = omap_dss_register_device(dssdev, &pdev->dev, i); 241 if (!plat_dssdev)
201 if (r) 242 return;
202 DSSERR("device %s register failed: %d\n", 243
203 dssdev->name, r); 244 dssdev = dss_alloc_and_init_device(&sdidev->dev);
245 if (!dssdev)
246 return;
247
248 dss_copy_device_pdata(dssdev, plat_dssdev);
249
250 r = sdi_init_display(dssdev);
251 if (r) {
252 DSSERR("device %s init failed: %d\n", dssdev->name, r);
253 dss_put_device(dssdev);
254 return;
204 } 255 }
256
257 r = dss_add_device(dssdev);
258 if (r) {
259 DSSERR("device %s register failed: %d\n", dssdev->name, r);
260 dss_put_device(dssdev);
261 return;
262 }
263}
264
265static void __init sdi_init_output(struct platform_device *pdev)
266{
267 struct omap_dss_output *out = &sdi.output;
268
269 out->pdev = pdev;
270 out->id = OMAP_DSS_OUTPUT_SDI;
271 out->type = OMAP_DISPLAY_TYPE_SDI;
272
273 dss_register_output(out);
274}
275
276static void __exit sdi_uninit_output(struct platform_device *pdev)
277{
278 struct omap_dss_output *out = &sdi.output;
279
280 dss_unregister_output(out);
205} 281}
206 282
207static int __init omap_sdi_probe(struct platform_device *pdev) 283static int __init omap_sdi_probe(struct platform_device *pdev)
208{ 284{
285 sdi_init_output(pdev);
286
209 sdi_probe_pdata(pdev); 287 sdi_probe_pdata(pdev);
210 288
211 return 0; 289 return 0;
@@ -213,7 +291,9 @@ static int __init omap_sdi_probe(struct platform_device *pdev)
213 291
214static int __exit omap_sdi_remove(struct platform_device *pdev) 292static int __exit omap_sdi_remove(struct platform_device *pdev)
215{ 293{
216 omap_dss_unregister_child_devices(&pdev->dev); 294 dss_unregister_child_devices(&pdev->dev);
295
296 sdi_uninit_output(pdev);
217 297
218 return 0; 298 return 0;
219} 299}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 3a220877461a..56efa3bb465d 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -36,7 +36,6 @@
36#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
37 37
38#include <video/omapdss.h> 38#include <video/omapdss.h>
39#include <plat/cpu.h>
40 39
41#include "dss.h" 40#include "dss.h"
42#include "dss_features.h" 41#include "dss_features.h"
@@ -300,6 +299,12 @@ static struct {
300 struct regulator *vdda_dac_reg; 299 struct regulator *vdda_dac_reg;
301 300
302 struct clk *tv_dac_clk; 301 struct clk *tv_dac_clk;
302
303 struct omap_video_timings timings;
304 enum omap_dss_venc_type type;
305 bool invert_polarity;
306
307 struct omap_dss_output output;
303} venc; 308} venc;
304 309
305static inline void venc_write_reg(int idx, u32 val) 310static inline void venc_write_reg(int idx, u32 val)
@@ -424,65 +429,67 @@ static const struct venc_config *venc_timings_to_config(
424 429
425static int venc_power_on(struct omap_dss_device *dssdev) 430static int venc_power_on(struct omap_dss_device *dssdev)
426{ 431{
432 struct omap_overlay_manager *mgr = dssdev->output->manager;
427 u32 l; 433 u32 l;
428 int r; 434 int r;
429 435
436 r = venc_runtime_get();
437 if (r)
438 goto err0;
439
430 venc_reset(); 440 venc_reset();
431 venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); 441 venc_write_config(venc_timings_to_config(&venc.timings));
432 442
433 dss_set_venc_output(dssdev->phy.venc.type); 443 dss_set_venc_output(venc.type);
434 dss_set_dac_pwrdn_bgz(1); 444 dss_set_dac_pwrdn_bgz(1);
435 445
436 l = 0; 446 l = 0;
437 447
438 if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) 448 if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
439 l |= 1 << 1; 449 l |= 1 << 1;
440 else /* S-Video */ 450 else /* S-Video */
441 l |= (1 << 0) | (1 << 2); 451 l |= (1 << 0) | (1 << 2);
442 452
443 if (dssdev->phy.venc.invert_polarity == false) 453 if (venc.invert_polarity == false)
444 l |= 1 << 3; 454 l |= 1 << 3;
445 455
446 venc_write_reg(VENC_OUTPUT_CONTROL, l); 456 venc_write_reg(VENC_OUTPUT_CONTROL, l);
447 457
448 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); 458 dss_mgr_set_timings(mgr, &venc.timings);
449 459
450 r = regulator_enable(venc.vdda_dac_reg); 460 r = regulator_enable(venc.vdda_dac_reg);
451 if (r) 461 if (r)
452 goto err; 462 goto err1;
453
454 if (dssdev->platform_enable)
455 dssdev->platform_enable(dssdev);
456 463
457 r = dss_mgr_enable(dssdev->manager); 464 r = dss_mgr_enable(mgr);
458 if (r) 465 if (r)
459 goto err; 466 goto err2;
460 467
461 return 0; 468 return 0;
462 469
463err: 470err2:
471 regulator_disable(venc.vdda_dac_reg);
472err1:
464 venc_write_reg(VENC_OUTPUT_CONTROL, 0); 473 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
465 dss_set_dac_pwrdn_bgz(0); 474 dss_set_dac_pwrdn_bgz(0);
466 475
467 if (dssdev->platform_disable) 476 venc_runtime_put();
468 dssdev->platform_disable(dssdev); 477err0:
469
470 regulator_disable(venc.vdda_dac_reg);
471
472 return r; 478 return r;
473} 479}
474 480
475static void venc_power_off(struct omap_dss_device *dssdev) 481static void venc_power_off(struct omap_dss_device *dssdev)
476{ 482{
483 struct omap_overlay_manager *mgr = dssdev->output->manager;
484
477 venc_write_reg(VENC_OUTPUT_CONTROL, 0); 485 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
478 dss_set_dac_pwrdn_bgz(0); 486 dss_set_dac_pwrdn_bgz(0);
479 487
480 dss_mgr_disable(dssdev->manager); 488 dss_mgr_disable(mgr);
481
482 if (dssdev->platform_disable)
483 dssdev->platform_disable(dssdev);
484 489
485 regulator_disable(venc.vdda_dac_reg); 490 regulator_disable(venc.vdda_dac_reg);
491
492 venc_runtime_put();
486} 493}
487 494
488unsigned long venc_get_pixel_clock(void) 495unsigned long venc_get_pixel_clock(void)
@@ -491,171 +498,83 @@ unsigned long venc_get_pixel_clock(void)
491 return 13500000; 498 return 13500000;
492} 499}
493 500
494static ssize_t display_output_type_show(struct device *dev, 501int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
495 struct device_attribute *attr, char *buf)
496{ 502{
497 struct omap_dss_device *dssdev = to_dss_device(dev); 503 struct omap_dss_output *out = dssdev->output;
498 const char *ret; 504 int r;
499
500 switch (dssdev->phy.venc.type) {
501 case OMAP_DSS_VENC_TYPE_COMPOSITE:
502 ret = "composite";
503 break;
504 case OMAP_DSS_VENC_TYPE_SVIDEO:
505 ret = "svideo";
506 break;
507 default:
508 return -EINVAL;
509 }
510
511 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
512}
513 505
514static ssize_t display_output_type_store(struct device *dev, 506 DSSDBG("venc_display_enable\n");
515 struct device_attribute *attr, const char *buf, size_t size)
516{
517 struct omap_dss_device *dssdev = to_dss_device(dev);
518 enum omap_dss_venc_type new_type;
519
520 if (sysfs_streq("composite", buf))
521 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
522 else if (sysfs_streq("svideo", buf))
523 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
524 else
525 return -EINVAL;
526 507
527 mutex_lock(&venc.venc_lock); 508 mutex_lock(&venc.venc_lock);
528 509
529 if (dssdev->phy.venc.type != new_type) { 510 if (out == NULL || out->manager == NULL) {
530 dssdev->phy.venc.type = new_type; 511 DSSERR("Failed to enable display: no output/manager\n");
531 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 512 r = -ENODEV;
532 venc_power_off(dssdev); 513 goto err0;
533 venc_power_on(dssdev);
534 }
535 } 514 }
536 515
537 mutex_unlock(&venc.venc_lock);
538
539 return size;
540}
541
542static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
543 display_output_type_show, display_output_type_store);
544
545/* driver */
546static int venc_panel_probe(struct omap_dss_device *dssdev)
547{
548 dssdev->panel.timings = omap_dss_pal_timings;
549
550 return device_create_file(&dssdev->dev, &dev_attr_output_type);
551}
552
553static void venc_panel_remove(struct omap_dss_device *dssdev)
554{
555 device_remove_file(&dssdev->dev, &dev_attr_output_type);
556}
557
558static int venc_panel_enable(struct omap_dss_device *dssdev)
559{
560 int r = 0;
561
562 DSSDBG("venc_enable_display\n");
563
564 mutex_lock(&venc.venc_lock);
565
566 r = omap_dss_start_device(dssdev); 516 r = omap_dss_start_device(dssdev);
567 if (r) { 517 if (r) {
568 DSSERR("failed to start device\n"); 518 DSSERR("failed to start device\n");
569 goto err0; 519 goto err0;
570 } 520 }
571 521
572 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { 522 if (dssdev->platform_enable)
573 r = -EINVAL; 523 dssdev->platform_enable(dssdev);
574 goto err1;
575 }
576 524
577 r = venc_runtime_get();
578 if (r)
579 goto err1;
580 525
581 r = venc_power_on(dssdev); 526 r = venc_power_on(dssdev);
582 if (r) 527 if (r)
583 goto err2; 528 goto err1;
584 529
585 venc.wss_data = 0; 530 venc.wss_data = 0;
586 531
587 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
588
589 mutex_unlock(&venc.venc_lock); 532 mutex_unlock(&venc.venc_lock);
533
590 return 0; 534 return 0;
591err2:
592 venc_runtime_put();
593err1: 535err1:
536 if (dssdev->platform_disable)
537 dssdev->platform_disable(dssdev);
594 omap_dss_stop_device(dssdev); 538 omap_dss_stop_device(dssdev);
595err0: 539err0:
596 mutex_unlock(&venc.venc_lock); 540 mutex_unlock(&venc.venc_lock);
597
598 return r; 541 return r;
599} 542}
600 543
601static void venc_panel_disable(struct omap_dss_device *dssdev) 544void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
602{ 545{
603 DSSDBG("venc_disable_display\n"); 546 DSSDBG("venc_display_disable\n");
604 547
605 mutex_lock(&venc.venc_lock); 548 mutex_lock(&venc.venc_lock);
606 549
607 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
608 goto end;
609
610 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
611 /* suspended is the same as disabled with venc */
612 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
613 goto end;
614 }
615
616 venc_power_off(dssdev); 550 venc_power_off(dssdev);
617 551
618 venc_runtime_put();
619
620 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
621
622 omap_dss_stop_device(dssdev); 552 omap_dss_stop_device(dssdev);
623end:
624 mutex_unlock(&venc.venc_lock);
625}
626 553
627static int venc_panel_suspend(struct omap_dss_device *dssdev) 554 if (dssdev->platform_disable)
628{ 555 dssdev->platform_disable(dssdev);
629 venc_panel_disable(dssdev);
630 return 0;
631}
632 556
633static int venc_panel_resume(struct omap_dss_device *dssdev) 557 mutex_unlock(&venc.venc_lock);
634{
635 return venc_panel_enable(dssdev);
636} 558}
637 559
638static void venc_set_timings(struct omap_dss_device *dssdev, 560void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
639 struct omap_video_timings *timings) 561 struct omap_video_timings *timings)
640{ 562{
641 DSSDBG("venc_set_timings\n"); 563 DSSDBG("venc_set_timings\n");
642 564
565 mutex_lock(&venc.venc_lock);
566
643 /* Reset WSS data when the TV standard changes. */ 567 /* Reset WSS data when the TV standard changes. */
644 if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings))) 568 if (memcmp(&venc.timings, timings, sizeof(*timings)))
645 venc.wss_data = 0; 569 venc.wss_data = 0;
646 570
647 dssdev->panel.timings = *timings; 571 venc.timings = *timings;
648 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 572
649 /* turn the venc off and on to get new timings to use */ 573 mutex_unlock(&venc.venc_lock);
650 venc_panel_disable(dssdev);
651 venc_panel_enable(dssdev);
652 } else {
653 dss_mgr_set_timings(dssdev->manager, timings);
654 }
655} 574}
656 575
657static int venc_check_timings(struct omap_dss_device *dssdev, 576int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
658 struct omap_video_timings *timings) 577 struct omap_video_timings *timings)
659{ 578{
660 DSSDBG("venc_check_timings\n"); 579 DSSDBG("venc_check_timings\n");
661 580
@@ -668,13 +587,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
668 return -EINVAL; 587 return -EINVAL;
669} 588}
670 589
671static u32 venc_get_wss(struct omap_dss_device *dssdev) 590u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)
672{ 591{
673 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 592 /* Invert due to VENC_L21_WC_CTL:INV=1 */
674 return (venc.wss_data >> 8) ^ 0xfffff; 593 return (venc.wss_data >> 8) ^ 0xfffff;
675} 594}
676 595
677static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) 596int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
678{ 597{
679 const struct venc_config *config; 598 const struct venc_config *config;
680 int r; 599 int r;
@@ -683,7 +602,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
683 602
684 mutex_lock(&venc.venc_lock); 603 mutex_lock(&venc.venc_lock);
685 604
686 config = venc_timings_to_config(&dssdev->panel.timings); 605 config = venc_timings_to_config(&venc.timings);
687 606
688 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 607 /* Invert due to VENC_L21_WC_CTL:INV=1 */
689 venc.wss_data = (wss ^ 0xfffff) << 8; 608 venc.wss_data = (wss ^ 0xfffff) << 8;
@@ -703,30 +622,25 @@ err:
703 return r; 622 return r;
704} 623}
705 624
706static struct omap_dss_driver venc_driver = { 625void omapdss_venc_set_type(struct omap_dss_device *dssdev,
707 .probe = venc_panel_probe, 626 enum omap_dss_venc_type type)
708 .remove = venc_panel_remove, 627{
628 mutex_lock(&venc.venc_lock);
709 629
710 .enable = venc_panel_enable, 630 venc.type = type;
711 .disable = venc_panel_disable,
712 .suspend = venc_panel_suspend,
713 .resume = venc_panel_resume,
714 631
715 .get_resolution = omapdss_default_get_resolution, 632 mutex_unlock(&venc.venc_lock);
716 .get_recommended_bpp = omapdss_default_get_recommended_bpp, 633}
717 634
718 .set_timings = venc_set_timings, 635void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
719 .check_timings = venc_check_timings, 636 bool invert_polarity)
637{
638 mutex_lock(&venc.venc_lock);
720 639
721 .get_wss = venc_get_wss, 640 venc.invert_polarity = invert_polarity;
722 .set_wss = venc_set_wss,
723 641
724 .driver = { 642 mutex_unlock(&venc.venc_lock);
725 .name = "venc", 643}
726 .owner = THIS_MODULE,
727 },
728};
729/* driver end */
730 644
731static int __init venc_init_display(struct omap_dss_device *dssdev) 645static int __init venc_init_display(struct omap_dss_device *dssdev)
732{ 646{
@@ -752,11 +666,6 @@ static void venc_dump_regs(struct seq_file *s)
752{ 666{
753#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 667#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
754 668
755 if (cpu_is_omap44xx()) {
756 seq_printf(s, "VENC currently disabled on OMAP44xx\n");
757 return;
758 }
759
760 if (venc_runtime_get()) 669 if (venc_runtime_get())
761 return; 670 return;
762 671
@@ -832,10 +741,14 @@ static void venc_put_clocks(void)
832 clk_put(venc.tv_dac_clk); 741 clk_put(venc.tv_dac_clk);
833} 742}
834 743
835static void __init venc_probe_pdata(struct platform_device *pdev) 744static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
836{ 745{
837 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 746 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
838 int r, i; 747 const char *def_disp_name = dss_get_default_display_name();
748 struct omap_dss_device *def_dssdev;
749 int i;
750
751 def_dssdev = NULL;
839 752
840 for (i = 0; i < pdata->num_devices; ++i) { 753 for (i = 0; i < pdata->num_devices; ++i) {
841 struct omap_dss_device *dssdev = pdata->devices[i]; 754 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -843,17 +756,69 @@ static void __init venc_probe_pdata(struct platform_device *pdev)
843 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) 756 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
844 continue; 757 continue;
845 758
846 r = venc_init_display(dssdev); 759 if (def_dssdev == NULL)
847 if (r) { 760 def_dssdev = dssdev;
848 DSSERR("device %s init failed: %d\n", dssdev->name, r); 761
849 continue; 762 if (def_disp_name != NULL &&
763 strcmp(dssdev->name, def_disp_name) == 0) {
764 def_dssdev = dssdev;
765 break;
850 } 766 }
767 }
768
769 return def_dssdev;
770}
771
772static void __init venc_probe_pdata(struct platform_device *vencdev)
773{
774 struct omap_dss_device *plat_dssdev;
775 struct omap_dss_device *dssdev;
776 int r;
777
778 plat_dssdev = venc_find_dssdev(vencdev);
851 779
852 r = omap_dss_register_device(dssdev, &pdev->dev, i); 780 if (!plat_dssdev)
853 if (r) 781 return;
854 DSSERR("device %s register failed: %d\n", 782
855 dssdev->name, r); 783 dssdev = dss_alloc_and_init_device(&vencdev->dev);
784 if (!dssdev)
785 return;
786
787 dss_copy_device_pdata(dssdev, plat_dssdev);
788
789 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
790
791 r = venc_init_display(dssdev);
792 if (r) {
793 DSSERR("device %s init failed: %d\n", dssdev->name, r);
794 dss_put_device(dssdev);
795 return;
856 } 796 }
797
798 r = dss_add_device(dssdev);
799 if (r) {
800 DSSERR("device %s register failed: %d\n", dssdev->name, r);
801 dss_put_device(dssdev);
802 return;
803 }
804}
805
806static void __init venc_init_output(struct platform_device *pdev)
807{
808 struct omap_dss_output *out = &venc.output;
809
810 out->pdev = pdev;
811 out->id = OMAP_DSS_OUTPUT_VENC;
812 out->type = OMAP_DISPLAY_TYPE_VENC;
813
814 dss_register_output(out);
815}
816
817static void __exit venc_uninit_output(struct platform_device *pdev)
818{
819 struct omap_dss_output *out = &venc.output;
820
821 dss_unregister_output(out);
857} 822}
858 823
859/* VENC HW IP initialisation */ 824/* VENC HW IP initialisation */
@@ -897,17 +862,19 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
897 862
898 venc_runtime_put(); 863 venc_runtime_put();
899 864
900 r = omap_dss_register_driver(&venc_driver); 865 r = venc_panel_init();
901 if (r) 866 if (r)
902 goto err_reg_panel_driver; 867 goto err_panel_init;
903 868
904 dss_debugfs_create_file("venc", venc_dump_regs); 869 dss_debugfs_create_file("venc", venc_dump_regs);
905 870
871 venc_init_output(pdev);
872
906 venc_probe_pdata(pdev); 873 venc_probe_pdata(pdev);
907 874
908 return 0; 875 return 0;
909 876
910err_reg_panel_driver: 877err_panel_init:
911err_runtime_get: 878err_runtime_get:
912 pm_runtime_disable(&pdev->dev); 879 pm_runtime_disable(&pdev->dev);
913 venc_put_clocks(); 880 venc_put_clocks();
@@ -916,14 +883,16 @@ err_runtime_get:
916 883
917static int __exit omap_venchw_remove(struct platform_device *pdev) 884static int __exit omap_venchw_remove(struct platform_device *pdev)
918{ 885{
919 omap_dss_unregister_child_devices(&pdev->dev); 886 dss_unregister_child_devices(&pdev->dev);
920 887
921 if (venc.vdda_dac_reg != NULL) { 888 if (venc.vdda_dac_reg != NULL) {
922 regulator_put(venc.vdda_dac_reg); 889 regulator_put(venc.vdda_dac_reg);
923 venc.vdda_dac_reg = NULL; 890 venc.vdda_dac_reg = NULL;
924 } 891 }
925 892
926 omap_dss_unregister_driver(&venc_driver); 893 venc_panel_exit();
894
895 venc_uninit_output(pdev);
927 896
928 pm_runtime_disable(&pdev->dev); 897 pm_runtime_disable(&pdev->dev);
929 venc_put_clocks(); 898 venc_put_clocks();
@@ -971,16 +940,10 @@ static struct platform_driver omap_venchw_driver = {
971 940
972int __init venc_init_platform_driver(void) 941int __init venc_init_platform_driver(void)
973{ 942{
974 if (cpu_is_omap44xx())
975 return 0;
976
977 return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe); 943 return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
978} 944}
979 945
980void __exit venc_uninit_platform_driver(void) 946void __exit venc_uninit_platform_driver(void)
981{ 947{
982 if (cpu_is_omap44xx())
983 return;
984
985 platform_driver_unregister(&omap_venchw_driver); 948 platform_driver_unregister(&omap_venchw_driver);
986} 949}
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
new file mode 100644
index 000000000000..d55b8784ecfd
--- /dev/null
+++ b/drivers/video/omap2/dss/venc_panel.c
@@ -0,0 +1,251 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * VENC panel driver
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <linux/mutex.h>
24#include <linux/module.h>
25
26#include <video/omapdss.h>
27
28#include "dss.h"
29
30static struct {
31 struct mutex lock;
32} venc_panel;
33
34static ssize_t display_output_type_show(struct device *dev,
35 struct device_attribute *attr, char *buf)
36{
37 struct omap_dss_device *dssdev = to_dss_device(dev);
38 const char *ret;
39
40 switch (dssdev->phy.venc.type) {
41 case OMAP_DSS_VENC_TYPE_COMPOSITE:
42 ret = "composite";
43 break;
44 case OMAP_DSS_VENC_TYPE_SVIDEO:
45 ret = "svideo";
46 break;
47 default:
48 return -EINVAL;
49 }
50
51 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
52}
53
54static ssize_t display_output_type_store(struct device *dev,
55 struct device_attribute *attr, const char *buf, size_t size)
56{
57 struct omap_dss_device *dssdev = to_dss_device(dev);
58 enum omap_dss_venc_type new_type;
59
60 if (sysfs_streq("composite", buf))
61 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
62 else if (sysfs_streq("svideo", buf))
63 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
64 else
65 return -EINVAL;
66
67 mutex_lock(&venc_panel.lock);
68
69 if (dssdev->phy.venc.type != new_type) {
70 dssdev->phy.venc.type = new_type;
71 omapdss_venc_set_type(dssdev, new_type);
72 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
73 omapdss_venc_display_disable(dssdev);
74 omapdss_venc_display_enable(dssdev);
75 }
76 }
77
78 mutex_unlock(&venc_panel.lock);
79
80 return size;
81}
82
83static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
84 display_output_type_show, display_output_type_store);
85
86static int venc_panel_probe(struct omap_dss_device *dssdev)
87{
88 /* set default timings to PAL */
89 const struct omap_video_timings default_timings = {
90 .x_res = 720,
91 .y_res = 574,
92 .pixel_clock = 13500,
93 .hsw = 64,
94 .hfp = 12,
95 .hbp = 68,
96 .vsw = 5,
97 .vfp = 5,
98 .vbp = 41,
99
100 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
101 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
102
103 .interlace = true,
104 };
105
106 mutex_init(&venc_panel.lock);
107
108 dssdev->panel.timings = default_timings;
109
110 return device_create_file(&dssdev->dev, &dev_attr_output_type);
111}
112
113static void venc_panel_remove(struct omap_dss_device *dssdev)
114{
115 device_remove_file(&dssdev->dev, &dev_attr_output_type);
116}
117
118static int venc_panel_enable(struct omap_dss_device *dssdev)
119{
120 int r;
121
122 dev_dbg(&dssdev->dev, "venc_panel_enable\n");
123
124 mutex_lock(&venc_panel.lock);
125
126 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
127 r = -EINVAL;
128 goto err;
129 }
130
131 omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
132 omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
133 omapdss_venc_invert_vid_out_polarity(dssdev,
134 dssdev->phy.venc.invert_polarity);
135
136 r = omapdss_venc_display_enable(dssdev);
137 if (r)
138 goto err;
139
140 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
141
142 mutex_unlock(&venc_panel.lock);
143
144 return 0;
145err:
146 mutex_unlock(&venc_panel.lock);
147
148 return r;
149}
150
151static void venc_panel_disable(struct omap_dss_device *dssdev)
152{
153 dev_dbg(&dssdev->dev, "venc_panel_disable\n");
154
155 mutex_lock(&venc_panel.lock);
156
157 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
158 goto end;
159
160 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
161 /* suspended is the same as disabled with venc */
162 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
163 goto end;
164 }
165
166 omapdss_venc_display_disable(dssdev);
167
168 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
169end:
170 mutex_unlock(&venc_panel.lock);
171}
172
173static int venc_panel_suspend(struct omap_dss_device *dssdev)
174{
175 venc_panel_disable(dssdev);
176 return 0;
177}
178
179static int venc_panel_resume(struct omap_dss_device *dssdev)
180{
181 return venc_panel_enable(dssdev);
182}
183
184static void venc_panel_set_timings(struct omap_dss_device *dssdev,
185 struct omap_video_timings *timings)
186{
187 dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
188
189 mutex_lock(&venc_panel.lock);
190
191 omapdss_venc_set_timings(dssdev, timings);
192 dssdev->panel.timings = *timings;
193
194 mutex_unlock(&venc_panel.lock);
195}
196
197static int venc_panel_check_timings(struct omap_dss_device *dssdev,
198 struct omap_video_timings *timings)
199{
200 dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
201
202 return omapdss_venc_check_timings(dssdev, timings);
203}
204
205static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
206{
207 dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
208
209 return omapdss_venc_get_wss(dssdev);
210}
211
212static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
213{
214 dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
215
216 return omapdss_venc_set_wss(dssdev, wss);
217}
218
219static struct omap_dss_driver venc_driver = {
220 .probe = venc_panel_probe,
221 .remove = venc_panel_remove,
222
223 .enable = venc_panel_enable,
224 .disable = venc_panel_disable,
225 .suspend = venc_panel_suspend,
226 .resume = venc_panel_resume,
227
228 .get_resolution = omapdss_default_get_resolution,
229 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
230
231 .set_timings = venc_panel_set_timings,
232 .check_timings = venc_panel_check_timings,
233
234 .get_wss = venc_panel_get_wss,
235 .set_wss = venc_panel_set_wss,
236
237 .driver = {
238 .name = "venc",
239 .owner = THIS_MODULE,
240 },
241};
242
243int venc_panel_init(void)
244{
245 return omap_dss_register_driver(&venc_driver);
246}
247
248void venc_panel_exit(void)
249{
250 omap_dss_unregister_driver(&venc_driver);
251}
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index c6cf372d22c5..606b89f12351 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -599,6 +599,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
599 struct omapfb_info *ofbi = FB2OFB(fbi); 599 struct omapfb_info *ofbi = FB2OFB(fbi);
600 struct omapfb2_device *fbdev = ofbi->fbdev; 600 struct omapfb2_device *fbdev = ofbi->fbdev;
601 struct omap_dss_device *display = fb2display(fbi); 601 struct omap_dss_device *display = fb2display(fbi);
602 struct omap_overlay_manager *mgr;
602 603
603 union { 604 union {
604 struct omapfb_update_window_old uwnd_o; 605 struct omapfb_update_window_old uwnd_o;
@@ -786,12 +787,14 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
786 787
787 case OMAPFB_WAITFORVSYNC: 788 case OMAPFB_WAITFORVSYNC:
788 DBG("ioctl WAITFORVSYNC\n"); 789 DBG("ioctl WAITFORVSYNC\n");
789 if (!display) { 790 if (!display && !display->output && !display->output->manager) {
790 r = -EINVAL; 791 r = -EINVAL;
791 break; 792 break;
792 } 793 }
793 794
794 r = display->manager->wait_for_vsync(display->manager); 795 mgr = display->output->manager;
796
797 r = mgr->wait_for_vsync(mgr);
795 break; 798 break;
796 799
797 case OMAPFB_WAITFORGO: 800 case OMAPFB_WAITFORGO:
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index fc671d3d8004..b103793516db 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1592,6 +1592,20 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1592 return 0; 1592 return 0;
1593} 1593}
1594 1594
1595static void omapfb_clear_fb(struct fb_info *fbi)
1596{
1597 const struct fb_fillrect rect = {
1598 .dx = 0,
1599 .dy = 0,
1600 .width = fbi->var.xres_virtual,
1601 .height = fbi->var.yres_virtual,
1602 .color = 0,
1603 .rop = ROP_COPY,
1604 };
1605
1606 cfb_fillrect(fbi, &rect);
1607}
1608
1595int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) 1609int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1596{ 1610{
1597 struct omapfb_info *ofbi = FB2OFB(fbi); 1611 struct omapfb_info *ofbi = FB2OFB(fbi);
@@ -1661,6 +1675,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1661 goto err; 1675 goto err;
1662 } 1676 }
1663 1677
1678 omapfb_clear_fb(fbi);
1679
1664 return 0; 1680 return 0;
1665err: 1681err:
1666 omapfb_free_fbmem(fbi); 1682 omapfb_free_fbmem(fbi);
@@ -1945,6 +1961,16 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1945 } 1961 }
1946 } 1962 }
1947 1963
1964 for (i = 0; i < fbdev->num_fbs; i++) {
1965 struct fb_info *fbi = fbdev->fbs[i];
1966 struct omapfb_info *ofbi = FB2OFB(fbi);
1967
1968 if (ofbi->region->size == 0)
1969 continue;
1970
1971 omapfb_clear_fb(fbi);
1972 }
1973
1948 DBG("fb_infos initialized\n"); 1974 DBG("fb_infos initialized\n");
1949 1975
1950 for (i = 0; i < fbdev->num_fbs; i++) { 1976 for (i = 0; i < fbdev->num_fbs; i++) {
@@ -2353,6 +2379,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
2353 struct omap_overlay *ovl; 2379 struct omap_overlay *ovl;
2354 struct omap_dss_device *def_display; 2380 struct omap_dss_device *def_display;
2355 struct omap_dss_device *dssdev; 2381 struct omap_dss_device *dssdev;
2382 struct omap_dss_device *ovl_device;
2356 2383
2357 DBG("omapfb_probe\n"); 2384 DBG("omapfb_probe\n");
2358 2385
@@ -2426,8 +2453,9 @@ static int __init omapfb_probe(struct platform_device *pdev)
2426 /* gfx overlay should be the default one. find a display 2453 /* gfx overlay should be the default one. find a display
2427 * connected to that, and use it as default display */ 2454 * connected to that, and use it as default display */
2428 ovl = omap_dss_get_overlay(0); 2455 ovl = omap_dss_get_overlay(0);
2429 if (ovl->manager && ovl->manager->device) { 2456 ovl_device = ovl->get_device(ovl);
2430 def_display = ovl->manager->device; 2457 if (ovl_device) {
2458 def_display = ovl_device;
2431 } else { 2459 } else {
2432 dev_warn(&pdev->dev, "cannot find default display\n"); 2460 dev_warn(&pdev->dev, "cannot find default display\n");
2433 def_display = NULL; 2461 def_display = NULL;
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 30361a09aecd..5ced9b334d35 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -148,8 +148,9 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
148 148
149 /* XXX: returns the display connected to first attached overlay */ 149 /* XXX: returns the display connected to first attached overlay */
150 for (i = 0; i < ofbi->num_overlays; i++) { 150 for (i = 0; i < ofbi->num_overlays; i++) {
151 if (ofbi->overlays[i]->manager) 151 struct omap_overlay *ovl = ofbi->overlays[i];
152 return ofbi->overlays[i]->manager->device; 152
153 return ovl->get_device(ovl);
153 } 154 }
154 155
155 return NULL; 156 return NULL;
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
index 87e421e25afe..f2b15c4a75bc 100644
--- a/drivers/video/omap2/vram.c
+++ b/drivers/video/omap2/vram.c
@@ -34,7 +34,6 @@
34#include <asm/setup.h> 34#include <asm/setup.h>
35 35
36#include <plat/vram.h> 36#include <plat/vram.h>
37#include <plat/dma.h>
38 37
39#ifdef DEBUG 38#ifdef DEBUG
40#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__) 39#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
@@ -250,59 +249,6 @@ int omap_vram_reserve(unsigned long paddr, size_t size)
250} 249}
251EXPORT_SYMBOL(omap_vram_reserve); 250EXPORT_SYMBOL(omap_vram_reserve);
252 251
253static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
254{
255 struct completion *compl = data;
256 complete(compl);
257}
258
259static int _omap_vram_clear(u32 paddr, unsigned pages)
260{
261 struct completion compl;
262 unsigned elem_count;
263 unsigned frame_count;
264 int r;
265 int lch;
266
267 init_completion(&compl);
268
269 r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
270 _omap_vram_dma_cb,
271 &compl, &lch);
272 if (r) {
273 pr_err("VRAM: request_dma failed for memory clear\n");
274 return -EBUSY;
275 }
276
277 elem_count = pages * PAGE_SIZE / 4;
278 frame_count = 1;
279
280 omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
281 elem_count, frame_count,
282 OMAP_DMA_SYNC_ELEMENT,
283 0, 0);
284
285 omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
286 paddr, 0, 0);
287
288 omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
289
290 omap_start_dma(lch);
291
292 if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
293 omap_stop_dma(lch);
294 pr_err("VRAM: dma timeout while clearing memory\n");
295 r = -EIO;
296 goto err;
297 }
298
299 r = 0;
300err:
301 omap_free_dma(lch);
302
303 return r;
304}
305
306static int _omap_vram_alloc(unsigned pages, unsigned long *paddr) 252static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
307{ 253{
308 struct vram_region *rm; 254 struct vram_region *rm;
@@ -337,8 +283,6 @@ found:
337 283
338 *paddr = start; 284 *paddr = start;
339 285
340 _omap_vram_clear(start, pages);
341
342 return 0; 286 return 0;
343 } 287 }
344 288