Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
venc_panel.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 Nokia Corporation
3  * Author: Tomi Valkeinen <[email protected]>
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) {
42  ret = "composite";
43  break;
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))
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) {
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);
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 */
163  goto end;
164  }
165 
167 
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 
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 }