diff --git a/Documentation/devicetree/bindings/video/fsl,imx-fb.txt b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt new file mode 100644 index 000000000000..46da08db186a --- /dev/null +++ b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt @@ -0,0 +1,51 @@ +Freescale imx21 Framebuffer + +This framebuffer driver supports devices imx1, imx21, imx25, and imx27. + +Required properties: +- compatible : "fsl,-fb", chip should be imx1 or imx21 +- reg : Should contain 1 register ranges(address and length) +- interrupts : One interrupt of the fb dev + +Required nodes: +- display: Phandle to a display node as described in + Documentation/devicetree/bindings/video/display-timing.txt + Additional, the display node has to define properties: + - bits-per-pixel: Bits per pixel + - fsl,pcr: LCDC PCR value + +Optional properties: +- fsl,dmacr: DMA Control Register value. This is optional. By default, the + register is not modified as recommended by the datasheet. +- fsl,lscr1: LCDC Sharp Configuration Register value. + +Example: + + imxfb: fb@10021000 { + compatible = "fsl,imx21-fb"; + interrupts = <61>; + reg = <0x10021000 0x1000>; + display = <&display0>; + }; + + ... + + display0: display0 { + model = "Primeview-PD050VL1"; + native-mode = <&timing_disp0>; + bits-per-pixel = <16>; + fsl,pcr = <0xf0c88080>; /* non-standard but required */ + display-timings { + timing_disp0: 640x480 { + hactive = <640>; + vactive = <480>; + hback-porch = <112>; + hfront-porch = <36>; + hsync-len = <32>; + vback-porch = <33>; + vfront-porch = <33>; + vsync-len = <2>; + clock-frequency = <25000000>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt index 3d0060cff062..7a125427ff4b 100644 --- a/Documentation/devicetree/bindings/video/ssd1307fb.txt +++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt @@ -1,13 +1,17 @@ * Solomon SSD1307 Framebuffer Driver Required properties: - - compatible: Should be "solomon,ssd1307fb-". The only supported bus for - now is i2c. + - compatible: Should be "solomon,fb-". The only supported bus for + now is i2c, and the supported chips are ssd1306 and ssd1307. - reg: Should contain address of the controller on the I2C bus. Most likely 0x3c or 0x3d - pwm: Should contain the pwm to use according to the OF device tree PWM - specification [0] + specification [0]. Only required for the ssd1307. - reset-gpios: Should contain the GPIO used to reset the OLED display + - solomon,height: Height in pixel of the screen driven by the controller + - solomon,width: Width in pixel of the screen driven by the controller + - solomon,page-offset: Offset of pages (band of 8 pixels) that the screen is + mapped to. Optional properties: - reset-active-low: Is the reset gpio is active on physical low? diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 79b200aee18a..4cec678dba94 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -40,7 +40,7 @@ struct omap_crtc { * mgr->id.) Eventually this will be replaced w/ something * more common-panel-framework-y */ - struct omap_overlay_manager mgr; + struct omap_overlay_manager *mgr; struct omap_video_timings timings; bool enabled; @@ -90,7 +90,32 @@ uint32_t pipe2vbl(struct drm_crtc *crtc) * job of sequencing the setup of the video pipe in the proper order */ +/* ovl-mgr-id -> crtc */ +static struct omap_crtc *omap_crtcs[8]; + /* we can probably ignore these until we support command-mode panels: */ +static int omap_crtc_connect(struct omap_overlay_manager *mgr, + struct omap_dss_device *dst) +{ + if (mgr->output) + return -EINVAL; + + if ((mgr->supported_outputs & dst->id) == 0) + return -EINVAL; + + dst->manager = mgr; + mgr->output = dst; + + return 0; +} + +static void omap_crtc_disconnect(struct omap_overlay_manager *mgr, + struct omap_dss_device *dst) +{ + mgr->output->manager = NULL; + mgr->output = NULL; +} + static void omap_crtc_start_update(struct omap_overlay_manager *mgr) { } @@ -107,7 +132,7 @@ static void omap_crtc_disable(struct omap_overlay_manager *mgr) static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, const struct omap_video_timings *timings) { - struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr); + struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; DBG("%s", omap_crtc->name); omap_crtc->timings = *timings; omap_crtc->full_update = true; @@ -116,7 +141,7 @@ static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr, const struct dss_lcd_mgr_config *config) { - struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr); + struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; DBG("%s", omap_crtc->name); dispc_mgr_set_lcd_config(omap_crtc->channel, config); } @@ -135,6 +160,8 @@ static void omap_crtc_unregister_framedone_handler( } static const struct dss_mgr_ops mgr_ops = { + .connect = omap_crtc_connect, + .disconnect = omap_crtc_disconnect, .start_update = omap_crtc_start_update, .enable = omap_crtc_enable, .disable = omap_crtc_disable, @@ -569,7 +596,7 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) } else { if (encoder) { omap_encoder_set_enabled(encoder, false); - omap_encoder_update(encoder, &omap_crtc->mgr, + omap_encoder_update(encoder, omap_crtc->mgr, &omap_crtc->timings); omap_encoder_set_enabled(encoder, true); omap_crtc->full_update = false; @@ -595,6 +622,11 @@ static const char *channel_names[] = { [OMAP_DSS_CHANNEL_LCD2] = "lcd2", }; +void omap_crtc_pre_init(void) +{ + dss_install_mgr_ops(&mgr_ops); +} + /* initialize crtc */ struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id) @@ -635,9 +667,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, omap_irq_register(dev, &omap_crtc->error_irq); /* temporary: */ - omap_crtc->mgr.id = channel; - - dss_install_mgr_ops(&mgr_ops); + omap_crtc->mgr = omap_dss_get_overlay_manager(channel); /* TODO: fix hard-coded setup.. add properties! */ info = &omap_crtc->info; @@ -651,6 +681,8 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, omap_plane_install_properties(omap_crtc->plane, &crtc->base); + omap_crtcs[channel] = omap_crtc; + return crtc; fail: diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 826586ffbe83..a3004f12b9a3 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -65,10 +65,8 @@ static int get_connector_type(struct omap_dss_device *dssdev) switch (dssdev->type) { case OMAP_DISPLAY_TYPE_HDMI: return DRM_MODE_CONNECTOR_HDMIA; - case OMAP_DISPLAY_TYPE_DPI: - if (!strcmp(dssdev->name, "dvi")) - return DRM_MODE_CONNECTOR_DVID; - /* fallthrough */ + case OMAP_DISPLAY_TYPE_DVI: + return DRM_MODE_CONNECTOR_DVID; default: return DRM_MODE_CONNECTOR_Unknown; } @@ -97,6 +95,9 @@ static int omap_modeset_init(struct drm_device *dev) int num_mgrs = dss_feat_get_num_mgrs(); int num_crtcs; int i, id = 0; + int r; + + omap_crtc_pre_init(); drm_mode_config_init(dev); @@ -116,6 +117,7 @@ static int omap_modeset_init(struct drm_device *dev) struct drm_connector *connector; struct drm_encoder *encoder; enum omap_channel channel; + struct omap_overlay_manager *mgr; if (!dssdev->driver) { dev_warn(dev->dev, "%s has no driver.. skipping it\n", @@ -131,6 +133,13 @@ static int omap_modeset_init(struct drm_device *dev) continue; } + r = dssdev->driver->connect(dssdev); + if (r) { + dev_err(dev->dev, "could not connect display: %s\n", + dssdev->name); + continue; + } + encoder = omap_encoder_init(dev, dssdev); if (!encoder) { @@ -172,8 +181,9 @@ static int omap_modeset_init(struct drm_device *dev) * other possible channels to which the encoder can connect are * not considered. */ - channel = dssdev->output->dispc_channel; + mgr = omapdss_find_mgr_from_display(dssdev); + channel = mgr->id; /* * if this channel hasn't already been taken by a previously * allocated crtc, we create a new crtc for it @@ -247,6 +257,9 @@ static int omap_modeset_init(struct drm_device *dev) struct drm_encoder *encoder = priv->encoders[i]; struct omap_dss_device *dssdev = omap_encoder_get_dssdev(encoder); + struct omap_dss_device *output; + + output = omapdss_find_output_from_display(dssdev); /* figure out which crtc's we can connect the encoder to: */ encoder->possible_crtcs = 0; @@ -259,9 +272,11 @@ static int omap_modeset_init(struct drm_device *dev) supported_outputs = dss_feat_get_supported_outputs(crtc_channel); - if (supported_outputs & dssdev->output->id) + if (supported_outputs & output->id) encoder->possible_crtcs |= (1 << id); } + + omap_dss_put_device(output); } DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n", diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 215a20dd340c..14f17da2ce25 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -157,6 +157,7 @@ const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc); enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); int omap_crtc_apply(struct drm_crtc *crtc, struct omap_drm_apply *apply); +void omap_crtc_pre_init(void); struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 2e937bdace6f..4cf1e1dd5621 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -367,6 +367,8 @@ config FB_IMX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select FB_MODE_HELPERS + select VIDEOMODE_HELPERS config FB_CYBER2000 tristate "CyberPro 2000/2010/5000 support" @@ -2188,7 +2190,7 @@ config FB_PS3_DEFAULT_SIZE_M config FB_XILINX tristate "Xilinx frame buffer support" - depends on FB && (XILINX_VIRTEX || MICROBLAZE) + depends on FB && (XILINX_VIRTEX || MICROBLAZE || ARCH_ZYNQ) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 8c55011313dc..a4dfe8cb0a0a 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -2016,7 +2016,7 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent) aty128_init_engine(par); - par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); + par->pm_reg = pdev->pm_cap; par->pdev = pdev; par->asleep = 0; par->lock_blank = 0; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 4f27fdc58d84..a89c15de9f45 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -434,8 +435,8 @@ static int correct_chipset(struct atyfb_par *par) const char *name; int i; - for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--) - if (par->pci_id == aty_chips[i].pci_id) + for (i = ARRAY_SIZE(aty_chips); i > 0; i--) + if (par->pci_id == aty_chips[i - 1].pci_id) break; if (i < 0) @@ -531,8 +532,8 @@ static int correct_chipset(struct atyfb_par *par) return 0; } -static char ram_dram[] = "DRAM"; -static char ram_resv[] = "RESV"; +static char ram_dram[] __maybe_unused = "DRAM"; +static char ram_resv[] __maybe_unused = "RESV"; #ifdef CONFIG_FB_ATY_GX static char ram_vram[] = "VRAM"; #endif /* CONFIG_FB_ATY_GX */ diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 92bda5848516..f7091ece580d 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2805,7 +2805,7 @@ static void radeonfb_early_resume(void *data) void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep) { /* Find PM registers in config space if any*/ - rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM); + rinfo->pm_reg = rinfo->pdev->pm_cap; /* Enable/Disable dynamic clocks: TODO add sysfs access */ if (rinfo->family == CHIP_FAMILY_RS480) diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index ebeb9715f061..a54ccdc4d661 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -577,7 +577,6 @@ failed: if (fbdev->info.cmap.len != 0) { fb_dealloc_cmap(&fbdev->info.cmap); } - platform_set_drvdata(dev, NULL); return -ENODEV; } diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 2726a5b66741..87f288bfc58c 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -681,7 +681,6 @@ out3: out2: free_dma(CH_EPPI0); out1: - platform_set_drvdata(pdev, NULL); return ret; } diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c index 29d8c0443a1f..b594a58ff21d 100644 --- a/drivers/video/bfin-lq035q1-fb.c +++ b/drivers/video/bfin-lq035q1-fb.c @@ -170,16 +170,19 @@ static int lq035q1_spidev_remove(struct spi_device *spi) return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT); } -#ifdef CONFIG_PM -static int lq035q1_spidev_suspend(struct spi_device *spi, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int lq035q1_spidev_suspend(struct device *dev) { + struct spi_device *spi = to_spi_device(dev); + return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT); } -static int lq035q1_spidev_resume(struct spi_device *spi) +static int lq035q1_spidev_resume(struct device *dev) { - int ret; + struct spi_device *spi = to_spi_device(dev); struct spi_control *ctl = spi_get_drvdata(spi); + int ret; ret = lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode); if (ret) @@ -187,9 +190,13 @@ static int lq035q1_spidev_resume(struct spi_device *spi) return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON); } + +static SIMPLE_DEV_PM_OPS(lq035q1_spidev_pm_ops, lq035q1_spidev_suspend, + lq035q1_spidev_resume); +#define LQ035Q1_SPIDEV_PM_OPS (&lq035q1_spidev_pm_ops) + #else -# define lq035q1_spidev_suspend NULL -# define lq035q1_spidev_resume NULL +#define LQ035Q1_SPIDEV_PM_OPS NULL #endif /* Power down all displays on reboot, poweroff or halt */ @@ -708,8 +715,7 @@ static int bfin_lq035q1_probe(struct platform_device *pdev) info->spidrv.probe = lq035q1_spidev_probe; info->spidrv.remove = lq035q1_spidev_remove; info->spidrv.shutdown = lq035q1_spidev_shutdown; - info->spidrv.suspend = lq035q1_spidev_suspend; - info->spidrv.resume = lq035q1_spidev_resume; + info->spidrv.driver.pm = LQ035Q1_SPIDEV_PM_OPS; ret = spi_register_driver(&info->spidrv); if (ret < 0) { @@ -759,7 +765,6 @@ static int bfin_lq035q1_probe(struct platform_device *pdev) out2: free_dma(CH_PPI); out1: - platform_set_drvdata(pdev, NULL); return ret; } @@ -788,7 +793,6 @@ static int bfin_lq035q1_remove(struct platform_device *pdev) bfin_lq035q1_free_ports(info->disp_info->ppi_mode == USE_RGB565_16_BIT_PPI); - platform_set_drvdata(pdev, NULL); framebuffer_release(fbinfo); dev_info(&pdev->dev, "unregistered LCD driver\n"); diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index d46da01c31ae..48c0c4e38a62 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -578,7 +578,6 @@ out3: out2: free_dma(CH_PPI); out1: - platform_set_drvdata(pdev, NULL); return ret; } @@ -608,7 +607,6 @@ static int bfin_t350mcqb_remove(struct platform_device *pdev) bfin_t350mcqb_request_ports(0); - platform_set_drvdata(pdev, NULL); framebuffer_release(fbinfo); printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n"); diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c index ee1ee5401544..28a837dfddd1 100644 --- a/drivers/video/ep93xx-fb.c +++ b/drivers/video/ep93xx-fb.c @@ -595,7 +595,6 @@ failed_videomem: fb_dealloc_cmap(&info->cmap); failed_cmap: kfree(info); - platform_set_drvdata(pdev, NULL); return err; } @@ -614,7 +613,6 @@ static int ep93xxfb_remove(struct platform_device *pdev) fbi->mach_info->teardown(pdev); kfree(info); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 098bfc64cfb9..36e1fe21b9b5 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1305,7 +1305,9 @@ static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, err |= copy_to_user(fix32->reserved, fix->reserved, sizeof(fix->reserved)); - return err; + if (err) + return -EFAULT; + return 0; } static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, @@ -1881,7 +1883,7 @@ static int ofonly __read_mostly; * * NOTE: Needed to maintain backwards compatibility */ -int fb_get_options(char *name, char **option) +int fb_get_options(const char *name, char **option) { char *opt, *options = NULL; int retval = 0; diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 6c278056fc60..6dd72250111e 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -469,7 +469,7 @@ static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s) unsigned long val; if (s) { - if (!strict_strtoul(s, 10, &val) && (val <= 2)) + if (!kstrtoul(s, 10, &val) && (val <= 2)) port = (enum fsl_diu_monitor_port) val; else if (strncmp(s, "lvds", 4) == 0) port = FSL_DIU_PORT_LVDS; @@ -1853,7 +1853,7 @@ static int __init fsl_diu_setup(char *options) if (!strncmp(opt, "monitor=", 8)) { monitor_port = fsl_diu_name_to_port(opt + 8); } else if (!strncmp(opt, "bpp=", 4)) { - if (!strict_strtoul(opt + 4, 10, &val)) + if (!kstrtoul(opt + 4, 10, &val)) default_bpp = val; } else fb_mode = opt; diff --git a/drivers/video/i740fb.c b/drivers/video/i740fb.c index cfd0c52e8f73..6c4838818950 100644 --- a/drivers/video/i740fb.c +++ b/drivers/video/i740fb.c @@ -1302,7 +1302,7 @@ static int __init i740fb_setup(char *options) } #endif -int __init i740fb_init(void) +static int __init i740fb_init(void) { #ifndef MODULE char *option = NULL; diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 0abf2bf20836..38733ac2b698 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -31,6 +31,12 @@ #include #include #include +#include +#include + +#include