diff options
Diffstat (limited to 'drivers/video/omap2/omapfb/omapfb-main.c')
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 231 |
1 files changed, 131 insertions, 100 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 505ec6672049..505bc12a3031 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/omapfb.h> | 31 | #include <linux/omapfb.h> |
32 | 32 | ||
33 | #include <plat/display.h> | 33 | #include <video/omapdss.h> |
34 | #include <plat/vram.h> | 34 | #include <plat/vram.h> |
35 | #include <plat/vrfb.h> | 35 | #include <plat/vrfb.h> |
36 | 36 | ||
@@ -702,8 +702,16 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) | |||
702 | var->xres, var->yres, | 702 | var->xres, var->yres, |
703 | var->xres_virtual, var->yres_virtual); | 703 | var->xres_virtual, var->yres_virtual); |
704 | 704 | ||
705 | var->height = -1; | 705 | if (display && display->driver->get_dimensions) { |
706 | var->width = -1; | 706 | u32 w, h; |
707 | display->driver->get_dimensions(display, &w, &h); | ||
708 | var->width = DIV_ROUND_CLOSEST(w, 1000); | ||
709 | var->height = DIV_ROUND_CLOSEST(h, 1000); | ||
710 | } else { | ||
711 | var->height = -1; | ||
712 | var->width = -1; | ||
713 | } | ||
714 | |||
707 | var->grayscale = 0; | 715 | var->grayscale = 0; |
708 | 716 | ||
709 | if (display && display->driver->get_timings) { | 717 | if (display && display->driver->get_timings) { |
@@ -749,35 +757,6 @@ static int omapfb_open(struct fb_info *fbi, int user) | |||
749 | 757 | ||
750 | static int omapfb_release(struct fb_info *fbi, int user) | 758 | static int omapfb_release(struct fb_info *fbi, int user) |
751 | { | 759 | { |
752 | #if 0 | ||
753 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
754 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
755 | struct omap_dss_device *display = fb2display(fbi); | ||
756 | |||
757 | DBG("Closing fb with plane index %d\n", ofbi->id); | ||
758 | |||
759 | omapfb_lock(fbdev); | ||
760 | |||
761 | if (display && display->get_update_mode && display->update) { | ||
762 | /* XXX this update should be removed, I think. But it's | ||
763 | * good for debugging */ | ||
764 | if (display->get_update_mode(display) == | ||
765 | OMAP_DSS_UPDATE_MANUAL) { | ||
766 | u16 w, h; | ||
767 | |||
768 | if (display->sync) | ||
769 | display->sync(display); | ||
770 | |||
771 | display->get_resolution(display, &w, &h); | ||
772 | display->update(display, 0, 0, w, h); | ||
773 | } | ||
774 | } | ||
775 | |||
776 | if (display && display->sync) | ||
777 | display->sync(display); | ||
778 | |||
779 | omapfb_unlock(fbdev); | ||
780 | #endif | ||
781 | return 0; | 760 | return 0; |
782 | } | 761 | } |
783 | 762 | ||
@@ -1263,7 +1242,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1263 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1242 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1264 | struct omapfb2_device *fbdev = ofbi->fbdev; | 1243 | struct omapfb2_device *fbdev = ofbi->fbdev; |
1265 | struct omap_dss_device *display = fb2display(fbi); | 1244 | struct omap_dss_device *display = fb2display(fbi); |
1266 | int do_update = 0; | ||
1267 | int r = 0; | 1245 | int r = 0; |
1268 | 1246 | ||
1269 | if (!display) | 1247 | if (!display) |
@@ -1279,11 +1257,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1279 | if (display->driver->resume) | 1257 | if (display->driver->resume) |
1280 | r = display->driver->resume(display); | 1258 | r = display->driver->resume(display); |
1281 | 1259 | ||
1282 | if (r == 0 && display->driver->get_update_mode && | ||
1283 | display->driver->get_update_mode(display) == | ||
1284 | OMAP_DSS_UPDATE_MANUAL) | ||
1285 | do_update = 1; | ||
1286 | |||
1287 | break; | 1260 | break; |
1288 | 1261 | ||
1289 | case FB_BLANK_NORMAL: | 1262 | case FB_BLANK_NORMAL: |
@@ -1307,13 +1280,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
1307 | exit: | 1280 | exit: |
1308 | omapfb_unlock(fbdev); | 1281 | omapfb_unlock(fbdev); |
1309 | 1282 | ||
1310 | if (r == 0 && do_update && display->driver->update) { | ||
1311 | u16 w, h; | ||
1312 | display->driver->get_resolution(display, &w, &h); | ||
1313 | |||
1314 | r = display->driver->update(display, 0, 0, w, h); | ||
1315 | } | ||
1316 | |||
1317 | return r; | 1283 | return r; |
1318 | } | 1284 | } |
1319 | 1285 | ||
@@ -2030,9 +1996,9 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
2030 | static int omapfb_mode_to_timings(const char *mode_str, | 1996 | static int omapfb_mode_to_timings(const char *mode_str, |
2031 | struct omap_video_timings *timings, u8 *bpp) | 1997 | struct omap_video_timings *timings, u8 *bpp) |
2032 | { | 1998 | { |
2033 | struct fb_info fbi; | 1999 | struct fb_info *fbi; |
2034 | struct fb_var_screeninfo var; | 2000 | struct fb_var_screeninfo *var; |
2035 | struct fb_ops fbops; | 2001 | struct fb_ops *fbops; |
2036 | int r; | 2002 | int r; |
2037 | 2003 | ||
2038 | #ifdef CONFIG_OMAP2_DSS_VENC | 2004 | #ifdef CONFIG_OMAP2_DSS_VENC |
@@ -2050,39 +2016,66 @@ static int omapfb_mode_to_timings(const char *mode_str, | |||
2050 | /* this is quite a hack, but I wanted to use the modedb and for | 2016 | /* this is quite a hack, but I wanted to use the modedb and for |
2051 | * that we need fb_info and var, so we create dummy ones */ | 2017 | * that we need fb_info and var, so we create dummy ones */ |
2052 | 2018 | ||
2053 | memset(&fbi, 0, sizeof(fbi)); | 2019 | *bpp = 0; |
2054 | memset(&var, 0, sizeof(var)); | 2020 | fbi = NULL; |
2055 | memset(&fbops, 0, sizeof(fbops)); | 2021 | var = NULL; |
2056 | fbi.fbops = &fbops; | 2022 | fbops = NULL; |
2057 | |||
2058 | r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24); | ||
2059 | |||
2060 | if (r != 0) { | ||
2061 | timings->pixel_clock = PICOS2KHZ(var.pixclock); | ||
2062 | timings->hbp = var.left_margin; | ||
2063 | timings->hfp = var.right_margin; | ||
2064 | timings->vbp = var.upper_margin; | ||
2065 | timings->vfp = var.lower_margin; | ||
2066 | timings->hsw = var.hsync_len; | ||
2067 | timings->vsw = var.vsync_len; | ||
2068 | timings->x_res = var.xres; | ||
2069 | timings->y_res = var.yres; | ||
2070 | |||
2071 | switch (var.bits_per_pixel) { | ||
2072 | case 16: | ||
2073 | *bpp = 16; | ||
2074 | break; | ||
2075 | case 24: | ||
2076 | case 32: | ||
2077 | default: | ||
2078 | *bpp = 24; | ||
2079 | break; | ||
2080 | } | ||
2081 | 2023 | ||
2082 | return 0; | 2024 | fbi = kzalloc(sizeof(*fbi), GFP_KERNEL); |
2083 | } else { | 2025 | if (fbi == NULL) { |
2084 | return -EINVAL; | 2026 | r = -ENOMEM; |
2027 | goto err; | ||
2028 | } | ||
2029 | |||
2030 | var = kzalloc(sizeof(*var), GFP_KERNEL); | ||
2031 | if (var == NULL) { | ||
2032 | r = -ENOMEM; | ||
2033 | goto err; | ||
2034 | } | ||
2035 | |||
2036 | fbops = kzalloc(sizeof(*fbops), GFP_KERNEL); | ||
2037 | if (fbops == NULL) { | ||
2038 | r = -ENOMEM; | ||
2039 | goto err; | ||
2040 | } | ||
2041 | |||
2042 | fbi->fbops = fbops; | ||
2043 | |||
2044 | r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24); | ||
2045 | if (r == 0) { | ||
2046 | r = -EINVAL; | ||
2047 | goto err; | ||
2048 | } | ||
2049 | |||
2050 | timings->pixel_clock = PICOS2KHZ(var->pixclock); | ||
2051 | timings->hbp = var->left_margin; | ||
2052 | timings->hfp = var->right_margin; | ||
2053 | timings->vbp = var->upper_margin; | ||
2054 | timings->vfp = var->lower_margin; | ||
2055 | timings->hsw = var->hsync_len; | ||
2056 | timings->vsw = var->vsync_len; | ||
2057 | timings->x_res = var->xres; | ||
2058 | timings->y_res = var->yres; | ||
2059 | |||
2060 | switch (var->bits_per_pixel) { | ||
2061 | case 16: | ||
2062 | *bpp = 16; | ||
2063 | break; | ||
2064 | case 24: | ||
2065 | case 32: | ||
2066 | default: | ||
2067 | *bpp = 24; | ||
2068 | break; | ||
2085 | } | 2069 | } |
2070 | |||
2071 | r = 0; | ||
2072 | |||
2073 | err: | ||
2074 | kfree(fbi); | ||
2075 | kfree(var); | ||
2076 | kfree(fbops); | ||
2077 | |||
2078 | return r; | ||
2086 | } | 2079 | } |
2087 | 2080 | ||
2088 | static int omapfb_set_def_mode(struct omapfb2_device *fbdev, | 2081 | static int omapfb_set_def_mode(struct omapfb2_device *fbdev, |
@@ -2185,6 +2178,61 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) | |||
2185 | return r; | 2178 | return r; |
2186 | } | 2179 | } |
2187 | 2180 | ||
2181 | static int omapfb_init_display(struct omapfb2_device *fbdev, | ||
2182 | struct omap_dss_device *dssdev) | ||
2183 | { | ||
2184 | struct omap_dss_driver *dssdrv = dssdev->driver; | ||
2185 | int r; | ||
2186 | |||
2187 | r = dssdrv->enable(dssdev); | ||
2188 | if (r) { | ||
2189 | dev_warn(fbdev->dev, "Failed to enable display '%s'\n", | ||
2190 | dssdev->name); | ||
2191 | return r; | ||
2192 | } | ||
2193 | |||
2194 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | ||
2195 | u16 w, h; | ||
2196 | if (dssdrv->enable_te) { | ||
2197 | r = dssdrv->enable_te(dssdev, 1); | ||
2198 | if (r) { | ||
2199 | dev_err(fbdev->dev, "Failed to set TE\n"); | ||
2200 | return r; | ||
2201 | } | ||
2202 | } | ||
2203 | |||
2204 | if (dssdrv->set_update_mode) { | ||
2205 | r = dssdrv->set_update_mode(dssdev, | ||
2206 | OMAP_DSS_UPDATE_MANUAL); | ||
2207 | if (r) { | ||
2208 | dev_err(fbdev->dev, | ||
2209 | "Failed to set update mode\n"); | ||
2210 | return r; | ||
2211 | } | ||
2212 | } | ||
2213 | |||
2214 | dssdrv->get_resolution(dssdev, &w, &h); | ||
2215 | r = dssdrv->update(dssdev, 0, 0, w, h); | ||
2216 | if (r) { | ||
2217 | dev_err(fbdev->dev, | ||
2218 | "Failed to update display\n"); | ||
2219 | return r; | ||
2220 | } | ||
2221 | } else { | ||
2222 | if (dssdrv->set_update_mode) { | ||
2223 | r = dssdrv->set_update_mode(dssdev, | ||
2224 | OMAP_DSS_UPDATE_AUTO); | ||
2225 | if (r) { | ||
2226 | dev_err(fbdev->dev, | ||
2227 | "Failed to set update mode\n"); | ||
2228 | return r; | ||
2229 | } | ||
2230 | } | ||
2231 | } | ||
2232 | |||
2233 | return 0; | ||
2234 | } | ||
2235 | |||
2188 | static int omapfb_probe(struct platform_device *pdev) | 2236 | static int omapfb_probe(struct platform_device *pdev) |
2189 | { | 2237 | { |
2190 | struct omapfb2_device *fbdev = NULL; | 2238 | struct omapfb2_device *fbdev = NULL; |
@@ -2284,30 +2332,13 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2284 | } | 2332 | } |
2285 | 2333 | ||
2286 | if (def_display) { | 2334 | if (def_display) { |
2287 | struct omap_dss_driver *dssdrv = def_display->driver; | 2335 | r = omapfb_init_display(fbdev, def_display); |
2288 | |||
2289 | r = def_display->driver->enable(def_display); | ||
2290 | if (r) { | 2336 | if (r) { |
2291 | dev_warn(fbdev->dev, "Failed to enable display '%s'\n", | 2337 | dev_err(fbdev->dev, |
2292 | def_display->name); | 2338 | "failed to initialize default " |
2339 | "display\n"); | ||
2293 | goto cleanup; | 2340 | goto cleanup; |
2294 | } | 2341 | } |
2295 | |||
2296 | if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | ||
2297 | u16 w, h; | ||
2298 | if (dssdrv->enable_te) | ||
2299 | dssdrv->enable_te(def_display, 1); | ||
2300 | if (dssdrv->set_update_mode) | ||
2301 | dssdrv->set_update_mode(def_display, | ||
2302 | OMAP_DSS_UPDATE_MANUAL); | ||
2303 | |||
2304 | dssdrv->get_resolution(def_display, &w, &h); | ||
2305 | def_display->driver->update(def_display, 0, 0, w, h); | ||
2306 | } else { | ||
2307 | if (dssdrv->set_update_mode) | ||
2308 | dssdrv->set_update_mode(def_display, | ||
2309 | OMAP_DSS_UPDATE_AUTO); | ||
2310 | } | ||
2311 | } | 2342 | } |
2312 | 2343 | ||
2313 | DBG("create sysfs for fbs\n"); | 2344 | DBG("create sysfs for fbs\n"); |