diff options
| author | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2012-10-10 02:16:30 +0000 |
|---|---|---|
| committer | Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | 2012-10-10 02:16:30 +0000 |
| commit | 0febd3bccff3ac005a570180209e44fb7de188df (patch) | |
| tree | 2af5177fb8fef95900f68c64121ad6bdc78d8761 /drivers/video/omap2/dss/rfbi.c | |
| parent | 8d93241b923bcb6a60994f8ed20fda8cc06d0fda (diff) | |
| parent | 13b1ba7de8d0ecc42e4f9c002d5b0c1a48f05e58 (diff) | |
Merge tag 'omapdss-for-3.7' of git://gitorious.org/linux-omap-dss2/linux into fbdev-next
Omapdss driver changes for the 3.7 merge window.
Notable changes:
* Basic writeback support for DISPC level. Writeback is not yet usable, though,
as we need higher level code to actually expose the writeback feature to
userspace.
* Rewriting the omapdss output drivers. We're trying to remove the hard links
between the omapdss and the panels, and this rewrite work moves us closer to
that goal.
* Cleanup and restructuring patches that have been made while working on device
tree support for omapdss. Device tree support is still some way ahead, but
these patches are good cleanups in themselves.
* Basic OMAP5 DSS support for DPI and DSI outputs.
* Workaround for the problem that GFX overlay's fifo is too small for high
resolution scenarios, causing underflows.
* Cleanups that remove dependencies to omap platform code.
Diffstat (limited to 'drivers/video/omap2/dss/rfbi.c')
| -rw-r--r-- | drivers/video/omap2/dss/rfbi.c | 222 |
1 files changed, 142 insertions, 80 deletions
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 7c087424b634..7282e5af3e1a 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -111,6 +111,13 @@ static struct { struct omap_dss_device *dssdev[2]; struct semaphore bus_lock; + + struct omap_video_timings timings; + int pixel_size; + int data_lines; + struct rfbi_timings intf_timings; + + struct omap_dss_output output; } rfbi; static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) @@ -300,30 +307,23 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, } EXPORT_SYMBOL(omap_rfbi_write_pixels); -static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, - u16 height, void (*callback)(void *data), void *data) +static int rfbi_transfer_area(struct omap_dss_device *dssdev, + void (*callback)(void *data), void *data) { u32 l; int r; - struct omap_video_timings timings = { - .hsw = 1, - .hfp = 1, - .hbp = 1, - .vsw = 1, - .vfp = 0, - .vbp = 0, - .x_res = width, - .y_res = height, - }; + struct omap_overlay_manager *mgr = dssdev->output->manager; + u16 width = rfbi.timings.x_res; + u16 height = rfbi.timings.y_res; /*BUG_ON(callback == 0);*/ BUG_ON(rfbi.framedone_callback != NULL); DSSDBG("rfbi_transfer_area %dx%d\n", width, height); - dss_mgr_set_timings(dssdev->manager, &timings); + dss_mgr_set_timings(mgr, &rfbi.timings); - r = dss_mgr_enable(dssdev->manager); + r = dss_mgr_enable(mgr); if (r) return r; @@ -770,62 +770,45 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines) return 0; } -int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, - int data_lines) +int omap_rfbi_configure(struct omap_dss_device *dssdev) { - return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines); + return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size, + rfbi.data_lines); } EXPORT_SYMBOL(omap_rfbi_configure); -int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, - u16 *x, u16 *y, u16 *w, u16 *h) +int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *), + void *data) { - u16 dw, dh; - struct omap_video_timings timings = { - .hsw = 1, - .hfp = 1, - .hbp = 1, - .vsw = 1, - .vfp = 0, - .vbp = 0, - .x_res = *w, - .y_res = *h, - }; - - dssdev->driver->get_resolution(dssdev, &dw, &dh); - - if (*x > dw || *y > dh) - return -EINVAL; - - if (*x + *w > dw) - return -EINVAL; - - if (*y + *h > dh) - return -EINVAL; - - if (*w == 1) - return -EINVAL; - - if (*w == 0 || *h == 0) - return -EINVAL; - - dss_mgr_set_timings(dssdev->manager, &timings); + return rfbi_transfer_area(dssdev, callback, data); +} +EXPORT_SYMBOL(omap_rfbi_update); - return 0; +void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) +{ + rfbi.timings.x_res = w; + rfbi.timings.y_res = h; } -EXPORT_SYMBOL(omap_rfbi_prepare_update); +EXPORT_SYMBOL(omapdss_rfbi_set_size); -int omap_rfbi_update(struct omap_dss_device *dssdev, - u16 x, u16 y, u16 w, u16 h, - void (*callback)(void *), void *data) +void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size) { - int r; + rfbi.pixel_size = pixel_size; +} +EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size); - r = rfbi_transfer_area(dssdev, w, h, callback, data); +void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) +{ + rfbi.data_lines = data_lines; +} +EXPORT_SYMBOL(omapdss_rfbi_set_data_lines); - return r; +void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, + struct rfbi_timings *timings) +{ + rfbi.intf_timings = *timings; } -EXPORT_SYMBOL(omap_rfbi_update); +EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings); static void rfbi_dump_regs(struct seq_file *s) { @@ -869,6 +852,7 @@ static void rfbi_dump_regs(struct seq_file *s) static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) { + struct omap_overlay_manager *mgr = dssdev->output->manager; struct dss_lcd_mgr_config mgr_config; mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI; @@ -877,18 +861,40 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) /* Do we need fifohandcheck for RFBI? */ mgr_config.fifohandcheck = false; - mgr_config.video_port_width = dssdev->ctrl.pixel_size; + mgr_config.video_port_width = rfbi.pixel_size; mgr_config.lcden_sig_polarity = 0; - dss_mgr_set_lcd_config(dssdev->manager, &mgr_config); + dss_mgr_set_lcd_config(mgr, &mgr_config); + + /* + * Set rfbi.timings with default values, the x_res and y_res fields + * are expected to be already configured by the panel driver via + * omapdss_rfbi_set_size() + */ + rfbi.timings.hsw = 1; + rfbi.timings.hfp = 1; + rfbi.timings.hbp = 1; + rfbi.timings.vsw = 1; + rfbi.timings.vfp = 0; + rfbi.timings.vbp = 0; + + rfbi.timings.interlace = false; + rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; + rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; + rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; + rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; + + dss_mgr_set_timings(mgr, &rfbi.timings); } int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) { + struct omap_dss_output *out = dssdev->output; int r; - if (dssdev->manager == NULL) { - DSSERR("failed to enable display: no manager\n"); + if (out == NULL || out->manager == NULL) { + DSSERR("failed to enable display: no output/manager\n"); return -ENODEV; } @@ -911,13 +917,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) rfbi_config_lcd_manager(dssdev); - rfbi_configure(dssdev->phy.rfbi.channel, - dssdev->ctrl.pixel_size, - dssdev->phy.rfbi.data_lines); - - rfbi_set_timings(dssdev->phy.rfbi.channel, - &dssdev->ctrl.rfbi_timings); + rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size, + rfbi.data_lines); + rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings); return 0; err1: @@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable); static int __init rfbi_init_display(struct omap_dss_device *dssdev) { rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; - dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; return 0; } -static void __init rfbi_probe_pdata(struct platform_device *pdev) +static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; - int i, r; + const char *def_disp_name = dss_get_default_display_name(); + struct omap_dss_device *def_dssdev; + int i; + + def_dssdev = NULL; for (i = 0; i < pdata->num_devices; ++i) { struct omap_dss_device *dssdev = pdata->devices[i]; @@ -956,17 +962,67 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev) if (dssdev->type != OMAP_DISPLAY_TYPE_DBI) continue; - r = rfbi_init_display(dssdev); - if (r) { - DSSERR("device %s init failed: %d\n", dssdev->name, r); - continue; + if (def_dssdev == NULL) + def_dssdev = dssdev; + + if (def_disp_name != NULL && + strcmp(dssdev->name, def_disp_name) == 0) { + def_dssdev = dssdev; + break; } + } + + return def_dssdev; +} + +static void __init rfbi_probe_pdata(struct platform_device *rfbidev) +{ + struct omap_dss_device *plat_dssdev; + struct omap_dss_device *dssdev; + int r; + + plat_dssdev = rfbi_find_dssdev(rfbidev); + + if (!plat_dssdev) + return; + + dssdev = dss_alloc_and_init_device(&rfbidev->dev); + if (!dssdev) + return; + + dss_copy_device_pdata(dssdev, plat_dssdev); - r = omap_dss_register_device(dssdev, &pdev->dev, i); - if (r) - DSSERR("device %s register failed: %d\n", - dssdev->name, r); + r = rfbi_init_display(dssdev); + if (r) { + DSSERR("device %s init failed: %d\n", dssdev->name, r); + dss_put_device(dssdev); + return; } + + r = dss_add_device(dssdev); + if (r) { + DSSERR("device %s register failed: %d\n", dssdev->name, r); + dss_put_device(dssdev); + return; + } +} + +static void __init rfbi_init_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &rfbi.output; + + out->pdev = pdev; + out->id = OMAP_DSS_OUTPUT_DBI; + out->type = OMAP_DISPLAY_TYPE_DBI; + + dss_register_output(out); +} + +static void __exit rfbi_uninit_output(struct platform_device *pdev) +{ + struct omap_dss_output *out = &rfbi.output; + + dss_unregister_output(out); } /* RFBI HW IP initialisation */ @@ -1020,6 +1076,8 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev) dss_debugfs_create_file("rfbi", rfbi_dump_regs); + rfbi_init_output(pdev); + rfbi_probe_pdata(pdev); return 0; @@ -1031,8 +1089,12 @@ err_runtime_get: static int __exit omap_rfbihw_remove(struct platform_device *pdev) { - omap_dss_unregister_child_devices(&pdev->dev); + dss_unregister_child_devices(&pdev->dev); + + rfbi_uninit_output(pdev); + pm_runtime_disable(&pdev->dev); + return 0; } |
