Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9-rc4 232 lines 5.3 kB view raw
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 omapdss_venc_display_disable(dssdev); 161 162 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 163end: 164 mutex_unlock(&venc_panel.lock); 165} 166 167static void venc_panel_set_timings(struct omap_dss_device *dssdev, 168 struct omap_video_timings *timings) 169{ 170 dev_dbg(&dssdev->dev, "venc_panel_set_timings\n"); 171 172 mutex_lock(&venc_panel.lock); 173 174 omapdss_venc_set_timings(dssdev, timings); 175 dssdev->panel.timings = *timings; 176 177 mutex_unlock(&venc_panel.lock); 178} 179 180static int venc_panel_check_timings(struct omap_dss_device *dssdev, 181 struct omap_video_timings *timings) 182{ 183 dev_dbg(&dssdev->dev, "venc_panel_check_timings\n"); 184 185 return omapdss_venc_check_timings(dssdev, timings); 186} 187 188static u32 venc_panel_get_wss(struct omap_dss_device *dssdev) 189{ 190 dev_dbg(&dssdev->dev, "venc_panel_get_wss\n"); 191 192 return omapdss_venc_get_wss(dssdev); 193} 194 195static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss) 196{ 197 dev_dbg(&dssdev->dev, "venc_panel_set_wss\n"); 198 199 return omapdss_venc_set_wss(dssdev, wss); 200} 201 202static struct omap_dss_driver venc_driver = { 203 .probe = venc_panel_probe, 204 .remove = venc_panel_remove, 205 206 .enable = venc_panel_enable, 207 .disable = venc_panel_disable, 208 209 .get_resolution = omapdss_default_get_resolution, 210 .get_recommended_bpp = omapdss_default_get_recommended_bpp, 211 212 .set_timings = venc_panel_set_timings, 213 .check_timings = venc_panel_check_timings, 214 215 .get_wss = venc_panel_get_wss, 216 .set_wss = venc_panel_set_wss, 217 218 .driver = { 219 .name = "venc", 220 .owner = THIS_MODULE, 221 }, 222}; 223 224int venc_panel_init(void) 225{ 226 return omap_dss_register_driver(&venc_driver); 227} 228 229void venc_panel_exit(void) 230{ 231 omap_dss_unregister_driver(&venc_driver); 232}