diff options
Diffstat (limited to 'drivers/video/omap2/dss/venc_panel.c')
-rw-r--r-- | drivers/video/omap2/dss/venc_panel.c | 251 |
1 files changed, 251 insertions, 0 deletions
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 | |||
30 | static struct { | ||
31 | struct mutex lock; | ||
32 | } venc_panel; | ||
33 | |||
34 | static 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 | |||
54 | static 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 | |||
83 | static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR, | ||
84 | display_output_type_show, display_output_type_store); | ||
85 | |||
86 | static 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 | |||
113 | static void venc_panel_remove(struct omap_dss_device *dssdev) | ||
114 | { | ||
115 | device_remove_file(&dssdev->dev, &dev_attr_output_type); | ||
116 | } | ||
117 | |||
118 | static 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; | ||
145 | err: | ||
146 | mutex_unlock(&venc_panel.lock); | ||
147 | |||
148 | return r; | ||
149 | } | ||
150 | |||
151 | static 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; | ||
169 | end: | ||
170 | mutex_unlock(&venc_panel.lock); | ||
171 | } | ||
172 | |||
173 | static int venc_panel_suspend(struct omap_dss_device *dssdev) | ||
174 | { | ||
175 | venc_panel_disable(dssdev); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int venc_panel_resume(struct omap_dss_device *dssdev) | ||
180 | { | ||
181 | return venc_panel_enable(dssdev); | ||
182 | } | ||
183 | |||
184 | static 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 | |||
197 | static 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 | |||
205 | static 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 | |||
212 | static 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 | |||
219 | static 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 | |||
243 | int venc_panel_init(void) | ||
244 | { | ||
245 | return omap_dss_register_driver(&venc_driver); | ||
246 | } | ||
247 | |||
248 | void venc_panel_exit(void) | ||
249 | { | ||
250 | omap_dss_unregister_driver(&venc_driver); | ||
251 | } | ||