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

Configure Feed

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

at v3.12 314 lines 7.7 kB view raw
1/* 2 * linux/drivers/video/omap2/dss/display.c 3 * 4 * Copyright (C) 2009 Nokia Corporation 5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 6 * 7 * Some code and ideas taken from drivers/video/omap/ driver 8 * by Imre Deak. 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 as published by 12 * the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 * more details. 18 * 19 * You should have received a copy of the GNU General Public License along with 20 * this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23#define DSS_SUBSYS_NAME "DISPLAY" 24 25#include <linux/kernel.h> 26#include <linux/module.h> 27#include <linux/jiffies.h> 28#include <linux/platform_device.h> 29 30#include <video/omapdss.h> 31#include "dss.h" 32#include "dss_features.h" 33 34void omapdss_default_get_resolution(struct omap_dss_device *dssdev, 35 u16 *xres, u16 *yres) 36{ 37 *xres = dssdev->panel.timings.x_res; 38 *yres = dssdev->panel.timings.y_res; 39} 40EXPORT_SYMBOL(omapdss_default_get_resolution); 41 42int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) 43{ 44 switch (dssdev->type) { 45 case OMAP_DISPLAY_TYPE_DPI: 46 if (dssdev->phy.dpi.data_lines == 24) 47 return 24; 48 else 49 return 16; 50 51 case OMAP_DISPLAY_TYPE_DBI: 52 if (dssdev->ctrl.pixel_size == 24) 53 return 24; 54 else 55 return 16; 56 case OMAP_DISPLAY_TYPE_DSI: 57 if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16) 58 return 24; 59 else 60 return 16; 61 case OMAP_DISPLAY_TYPE_VENC: 62 case OMAP_DISPLAY_TYPE_SDI: 63 case OMAP_DISPLAY_TYPE_HDMI: 64 case OMAP_DISPLAY_TYPE_DVI: 65 return 24; 66 default: 67 BUG(); 68 return 0; 69 } 70} 71EXPORT_SYMBOL(omapdss_default_get_recommended_bpp); 72 73void omapdss_default_get_timings(struct omap_dss_device *dssdev, 74 struct omap_video_timings *timings) 75{ 76 *timings = dssdev->panel.timings; 77} 78EXPORT_SYMBOL(omapdss_default_get_timings); 79 80int dss_suspend_all_devices(void) 81{ 82 struct omap_dss_device *dssdev = NULL; 83 84 for_each_dss_dev(dssdev) { 85 if (!dssdev->driver) 86 continue; 87 88 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 89 dssdev->driver->disable(dssdev); 90 dssdev->activate_after_resume = true; 91 } else { 92 dssdev->activate_after_resume = false; 93 } 94 } 95 96 return 0; 97} 98 99int dss_resume_all_devices(void) 100{ 101 struct omap_dss_device *dssdev = NULL; 102 103 for_each_dss_dev(dssdev) { 104 if (!dssdev->driver) 105 continue; 106 107 if (dssdev->activate_after_resume) { 108 dssdev->driver->enable(dssdev); 109 dssdev->activate_after_resume = false; 110 } 111 } 112 113 return 0; 114} 115 116void dss_disable_all_devices(void) 117{ 118 struct omap_dss_device *dssdev = NULL; 119 120 for_each_dss_dev(dssdev) { 121 if (!dssdev->driver) 122 continue; 123 124 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 125 dssdev->driver->disable(dssdev); 126 } 127} 128 129static LIST_HEAD(panel_list); 130static DEFINE_MUTEX(panel_list_mutex); 131static int disp_num_counter; 132 133int omapdss_register_display(struct omap_dss_device *dssdev) 134{ 135 struct omap_dss_driver *drv = dssdev->driver; 136 137 snprintf(dssdev->alias, sizeof(dssdev->alias), 138 "display%d", disp_num_counter++); 139 140 if (drv && drv->get_resolution == NULL) 141 drv->get_resolution = omapdss_default_get_resolution; 142 if (drv && drv->get_recommended_bpp == NULL) 143 drv->get_recommended_bpp = omapdss_default_get_recommended_bpp; 144 if (drv && drv->get_timings == NULL) 145 drv->get_timings = omapdss_default_get_timings; 146 147 mutex_lock(&panel_list_mutex); 148 list_add_tail(&dssdev->panel_list, &panel_list); 149 mutex_unlock(&panel_list_mutex); 150 return 0; 151} 152EXPORT_SYMBOL(omapdss_register_display); 153 154void omapdss_unregister_display(struct omap_dss_device *dssdev) 155{ 156 mutex_lock(&panel_list_mutex); 157 list_del(&dssdev->panel_list); 158 mutex_unlock(&panel_list_mutex); 159} 160EXPORT_SYMBOL(omapdss_unregister_display); 161 162struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev) 163{ 164 if (!try_module_get(dssdev->owner)) 165 return NULL; 166 167 if (get_device(dssdev->dev) == NULL) { 168 module_put(dssdev->owner); 169 return NULL; 170 } 171 172 return dssdev; 173} 174EXPORT_SYMBOL(omap_dss_get_device); 175 176void omap_dss_put_device(struct omap_dss_device *dssdev) 177{ 178 put_device(dssdev->dev); 179 module_put(dssdev->owner); 180} 181EXPORT_SYMBOL(omap_dss_put_device); 182 183/* 184 * ref count of the found device is incremented. 185 * ref count of from-device is decremented. 186 */ 187struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from) 188{ 189 struct list_head *l; 190 struct omap_dss_device *dssdev; 191 192 mutex_lock(&panel_list_mutex); 193 194 if (list_empty(&panel_list)) { 195 dssdev = NULL; 196 goto out; 197 } 198 199 if (from == NULL) { 200 dssdev = list_first_entry(&panel_list, struct omap_dss_device, 201 panel_list); 202 omap_dss_get_device(dssdev); 203 goto out; 204 } 205 206 omap_dss_put_device(from); 207 208 list_for_each(l, &panel_list) { 209 dssdev = list_entry(l, struct omap_dss_device, panel_list); 210 if (dssdev == from) { 211 if (list_is_last(l, &panel_list)) { 212 dssdev = NULL; 213 goto out; 214 } 215 216 dssdev = list_entry(l->next, struct omap_dss_device, 217 panel_list); 218 omap_dss_get_device(dssdev); 219 goto out; 220 } 221 } 222 223 WARN(1, "'from' dssdev not found\n"); 224 225 dssdev = NULL; 226out: 227 mutex_unlock(&panel_list_mutex); 228 return dssdev; 229} 230EXPORT_SYMBOL(omap_dss_get_next_device); 231 232struct omap_dss_device *omap_dss_find_device(void *data, 233 int (*match)(struct omap_dss_device *dssdev, void *data)) 234{ 235 struct omap_dss_device *dssdev = NULL; 236 237 while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) { 238 if (match(dssdev, data)) 239 return dssdev; 240 } 241 242 return NULL; 243} 244EXPORT_SYMBOL(omap_dss_find_device); 245 246void videomode_to_omap_video_timings(const struct videomode *vm, 247 struct omap_video_timings *ovt) 248{ 249 memset(ovt, 0, sizeof(*ovt)); 250 251 ovt->pixel_clock = vm->pixelclock / 1000; 252 ovt->x_res = vm->hactive; 253 ovt->hbp = vm->hback_porch; 254 ovt->hfp = vm->hfront_porch; 255 ovt->hsw = vm->hsync_len; 256 ovt->y_res = vm->vactive; 257 ovt->vbp = vm->vback_porch; 258 ovt->vfp = vm->vfront_porch; 259 ovt->vsw = vm->vsync_len; 260 261 ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ? 262 OMAPDSS_SIG_ACTIVE_HIGH : 263 OMAPDSS_SIG_ACTIVE_LOW; 264 ovt->hsync_level = vm->flags & DISPLAY_FLAGS_HSYNC_HIGH ? 265 OMAPDSS_SIG_ACTIVE_HIGH : 266 OMAPDSS_SIG_ACTIVE_LOW; 267 ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ? 268 OMAPDSS_SIG_ACTIVE_HIGH : 269 OMAPDSS_SIG_ACTIVE_HIGH; 270 ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ? 271 OMAPDSS_DRIVE_SIG_RISING_EDGE : 272 OMAPDSS_DRIVE_SIG_FALLING_EDGE; 273 274 ovt->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; 275} 276EXPORT_SYMBOL(videomode_to_omap_video_timings); 277 278void omap_video_timings_to_videomode(const struct omap_video_timings *ovt, 279 struct videomode *vm) 280{ 281 memset(vm, 0, sizeof(*vm)); 282 283 vm->pixelclock = ovt->pixel_clock * 1000; 284 285 vm->hactive = ovt->x_res; 286 vm->hback_porch = ovt->hbp; 287 vm->hfront_porch = ovt->hfp; 288 vm->hsync_len = ovt->hsw; 289 vm->vactive = ovt->y_res; 290 vm->vback_porch = ovt->vbp; 291 vm->vfront_porch = ovt->vfp; 292 vm->vsync_len = ovt->vsw; 293 294 if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH) 295 vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH; 296 else 297 vm->flags |= DISPLAY_FLAGS_HSYNC_LOW; 298 299 if (ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH) 300 vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH; 301 else 302 vm->flags |= DISPLAY_FLAGS_VSYNC_LOW; 303 304 if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH) 305 vm->flags |= DISPLAY_FLAGS_DE_HIGH; 306 else 307 vm->flags |= DISPLAY_FLAGS_DE_LOW; 308 309 if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE) 310 vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; 311 else 312 vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE; 313} 314EXPORT_SYMBOL(omap_video_timings_to_videomode);