Merge git://git.kernel.org/pub/scm/linux/kernel/git/nico/orion into fixes
[pandora-kernel.git] / drivers / video / omap2 / dss / hdmi_omap4_panel.c
1 /*
2  * hdmi_omap4_panel.c
3  *
4  * HDMI library support functions for TI OMAP4 processors.
5  *
6  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
7  * Authors:     Mythri P k <mythripk@ti.com>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License version 2 as published by
11  * the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <linux/kernel.h>
23 #include <linux/err.h>
24 #include <linux/io.h>
25 #include <linux/mutex.h>
26 #include <linux/module.h>
27 #include <plat/display.h>
28
29 #include "dss.h"
30
31 static struct {
32         struct mutex hdmi_lock;
33 } hdmi;
34
35
36 static int hdmi_panel_probe(struct omap_dss_device *dssdev)
37 {
38         DSSDBG("ENTER hdmi_panel_probe\n");
39
40         dssdev->panel.config = OMAP_DSS_LCD_TFT |
41                         OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
42
43         /*
44          * Initialize the timings to 640 * 480
45          * This is only for framebuffer update not for TV timing setting
46          * Setting TV timing will be done only on enable
47          */
48         dssdev->panel.timings.x_res = 640;
49         dssdev->panel.timings.y_res = 480;
50
51         DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
52                 dssdev->panel.timings.x_res,
53                 dssdev->panel.timings.y_res);
54         return 0;
55 }
56
57 static void hdmi_panel_remove(struct omap_dss_device *dssdev)
58 {
59
60 }
61
62 static int hdmi_panel_enable(struct omap_dss_device *dssdev)
63 {
64         int r = 0;
65         DSSDBG("ENTER hdmi_panel_enable\n");
66
67         mutex_lock(&hdmi.hdmi_lock);
68
69         if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
70                 r = -EINVAL;
71                 goto err;
72         }
73
74         r = omapdss_hdmi_display_enable(dssdev);
75         if (r) {
76                 DSSERR("failed to power on\n");
77                 goto err;
78         }
79
80         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
81
82 err:
83         mutex_unlock(&hdmi.hdmi_lock);
84
85         return r;
86 }
87
88 static void hdmi_panel_disable(struct omap_dss_device *dssdev)
89 {
90         mutex_lock(&hdmi.hdmi_lock);
91
92         if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
93                 omapdss_hdmi_display_disable(dssdev);
94
95         dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
96
97         mutex_unlock(&hdmi.hdmi_lock);
98 }
99
100 static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
101 {
102         int r = 0;
103
104         mutex_lock(&hdmi.hdmi_lock);
105
106         if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
107                 r = -EINVAL;
108                 goto err;
109         }
110
111         dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
112
113         omapdss_hdmi_display_disable(dssdev);
114
115 err:
116         mutex_unlock(&hdmi.hdmi_lock);
117
118         return r;
119 }
120
121 static int hdmi_panel_resume(struct omap_dss_device *dssdev)
122 {
123         int r = 0;
124
125         mutex_lock(&hdmi.hdmi_lock);
126
127         if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
128                 r = -EINVAL;
129                 goto err;
130         }
131
132         r = omapdss_hdmi_display_enable(dssdev);
133         if (r) {
134                 DSSERR("failed to power on\n");
135                 goto err;
136         }
137
138         dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
139
140 err:
141         mutex_unlock(&hdmi.hdmi_lock);
142
143         return r;
144 }
145
146 static void hdmi_get_timings(struct omap_dss_device *dssdev,
147                         struct omap_video_timings *timings)
148 {
149         mutex_lock(&hdmi.hdmi_lock);
150
151         *timings = dssdev->panel.timings;
152
153         mutex_unlock(&hdmi.hdmi_lock);
154 }
155
156 static void hdmi_set_timings(struct omap_dss_device *dssdev,
157                         struct omap_video_timings *timings)
158 {
159         DSSDBG("hdmi_set_timings\n");
160
161         mutex_lock(&hdmi.hdmi_lock);
162
163         dssdev->panel.timings = *timings;
164
165         if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
166                 /* turn the hdmi off and on to get new timings to use */
167                 omapdss_hdmi_display_disable(dssdev);
168                 omapdss_hdmi_display_set_timing(dssdev);
169         }
170
171         mutex_unlock(&hdmi.hdmi_lock);
172 }
173
174 static int hdmi_check_timings(struct omap_dss_device *dssdev,
175                         struct omap_video_timings *timings)
176 {
177         int r = 0;
178
179         DSSDBG("hdmi_check_timings\n");
180
181         mutex_lock(&hdmi.hdmi_lock);
182
183         r = omapdss_hdmi_display_check_timing(dssdev, timings);
184         if (r) {
185                 DSSERR("Timing cannot be applied\n");
186                 goto err;
187         }
188 err:
189         mutex_unlock(&hdmi.hdmi_lock);
190         return r;
191 }
192
193 static struct omap_dss_driver hdmi_driver = {
194         .probe          = hdmi_panel_probe,
195         .remove         = hdmi_panel_remove,
196         .enable         = hdmi_panel_enable,
197         .disable        = hdmi_panel_disable,
198         .suspend        = hdmi_panel_suspend,
199         .resume         = hdmi_panel_resume,
200         .get_timings    = hdmi_get_timings,
201         .set_timings    = hdmi_set_timings,
202         .check_timings  = hdmi_check_timings,
203         .driver                 = {
204                 .name   = "hdmi_panel",
205                 .owner  = THIS_MODULE,
206         },
207 };
208
209 int hdmi_panel_init(void)
210 {
211         mutex_init(&hdmi.hdmi_lock);
212
213         omap_dss_register_driver(&hdmi_driver);
214
215         return 0;
216 }
217
218 void hdmi_panel_exit(void)
219 {
220         omap_dss_unregister_driver(&hdmi_driver);
221
222 }