Merge branch 'fbdev-3.10-fixes' of git://gitorious.org/linux-omap-dss2/linux into...
authorJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Wed, 29 May 2013 09:00:34 +0000 (17:00 +0800)
committerJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Wed, 29 May 2013 09:00:34 +0000 (17:00 +0800)
Pull Tomi fixes for ps3fb and omap2

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
1  2 
drivers/gpu/drm/omapdrm/omap_drv.c
drivers/media/platform/omap/omap_vout.c
drivers/video/omap2/dss/core.c
drivers/video/omap2/omapfb/omapfb-main.c
include/video/omapdss.h

index 9c53c25e5201763a4673734d5ce32d72043f5a35,902074bbd1f43c6bfd698510a8f1e18db9f48130..826586ffbe835d94983f779b372149d92143b863
@@@ -74,53 -74,54 +74,53 @@@ static int get_connector_type(struct om
        }
  }
  
 +static bool channel_used(struct drm_device *dev, enum omap_channel channel)
 +{
 +      struct omap_drm_private *priv = dev->dev_private;
 +      int i;
 +
 +      for (i = 0; i < priv->num_crtcs; i++) {
 +              struct drm_crtc *crtc = priv->crtcs[i];
 +
 +              if (omap_crtc_channel(crtc) == channel)
 +                      return true;
 +      }
 +
 +      return false;
 +}
 +
  static int omap_modeset_init(struct drm_device *dev)
  {
        struct omap_drm_private *priv = dev->dev_private;
        struct omap_dss_device *dssdev = NULL;
        int num_ovls = dss_feat_get_num_ovls();
 -      int id;
 +      int num_mgrs = dss_feat_get_num_mgrs();
 +      int num_crtcs;
 +      int i, id = 0;
  
        drm_mode_config_init(dev);
  
        omap_drm_irq_install(dev);
  
        /*
 -       * Create private planes and CRTCs for the last NUM_CRTCs overlay
 -       * plus manager:
 +       * We usually don't want to create a CRTC for each manager, at least
 +       * not until we have a way to expose private planes to userspace.
 +       * Otherwise there would not be enough video pipes left for drm planes.
 +       * We use the num_crtc argument to limit the number of crtcs we create.
         */
 -      for (id = 0; id < min(num_crtc, num_ovls); id++) {
 -              struct drm_plane *plane;
 -              struct drm_crtc *crtc;
 -
 -              plane = omap_plane_init(dev, id, true);
 -              crtc = omap_crtc_init(dev, plane, pipe2chan(id), id);
 +      num_crtcs = min3(num_crtc, num_mgrs, num_ovls);
  
 -              BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
 -              priv->crtcs[id] = crtc;
 -              priv->num_crtcs++;
 -
 -              priv->planes[id] = plane;
 -              priv->num_planes++;
 -      }
 -
 -      /*
 -       * Create normal planes for the remaining overlays:
 -       */
 -      for (; id < num_ovls; id++) {
 -              struct drm_plane *plane = omap_plane_init(dev, id, false);
 -
 -              BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
 -              priv->planes[priv->num_planes++] = plane;
 -      }
 +      dssdev = NULL;
  
        for_each_dss_dev(dssdev) {
                struct drm_connector *connector;
                struct drm_encoder *encoder;
 +              enum omap_channel channel;
  
                if (!dssdev->driver) {
                        dev_warn(dev->dev, "%s has no driver.. skipping it\n",
                                        dssdev->name);
 -                      return 0;
 +                      continue;
                }
  
                if (!(dssdev->driver->get_timings ||
                        dev_warn(dev->dev, "%s driver does not support "
                                "get_timings or read_edid.. skipping it!\n",
                                dssdev->name);
 -                      return 0;
 +                      continue;
                }
  
                encoder = omap_encoder_init(dev, dssdev);
  
                drm_mode_connector_attach_encoder(connector, encoder);
  
 +              /*
 +               * if we have reached the limit of the crtcs we are allowed to
 +               * create, let's not try to look for a crtc for this
 +               * panel/encoder and onwards, we will, of course, populate the
 +               * the possible_crtcs field for all the encoders with the final
 +               * set of crtcs we create
 +               */
 +              if (id == num_crtcs)
 +                      continue;
 +
 +              /*
 +               * get the recommended DISPC channel for this encoder. For now,
 +               * we only try to get create a crtc out of the recommended, the
 +               * other possible channels to which the encoder can connect are
 +               * not considered.
 +               */
 +              channel = dssdev->output->dispc_channel;
 +
 +              /*
 +               * if this channel hasn't already been taken by a previously
 +               * allocated crtc, we create a new crtc for it
 +               */
 +              if (!channel_used(dev, channel)) {
 +                      struct drm_plane *plane;
 +                      struct drm_crtc *crtc;
 +
 +                      plane = omap_plane_init(dev, id, true);
 +                      crtc = omap_crtc_init(dev, plane, channel, id);
 +
 +                      BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
 +                      priv->crtcs[id] = crtc;
 +                      priv->num_crtcs++;
 +
 +                      priv->planes[id] = plane;
 +                      priv->num_planes++;
 +
 +                      id++;
 +              }
 +      }
 +
 +      /*
 +       * we have allocated crtcs according to the need of the panels/encoders,
 +       * adding more crtcs here if needed
 +       */
 +      for (; id < num_crtcs; id++) {
 +
 +              /* find a free manager for this crtc */
 +              for (i = 0; i < num_mgrs; i++) {
 +                      if (!channel_used(dev, i)) {
 +                              struct drm_plane *plane;
 +                              struct drm_crtc *crtc;
 +
 +                              plane = omap_plane_init(dev, id, true);
 +                              crtc = omap_crtc_init(dev, plane, i, id);
 +
 +                              BUG_ON(priv->num_crtcs >=
 +                                      ARRAY_SIZE(priv->crtcs));
 +
 +                              priv->crtcs[id] = crtc;
 +                              priv->num_crtcs++;
 +
 +                              priv->planes[id] = plane;
 +                              priv->num_planes++;
 +
 +                              break;
 +                      } else {
 +                              continue;
 +                      }
 +              }
 +
 +              if (i == num_mgrs) {
 +                      /* this shouldn't really happen */
 +                      dev_err(dev->dev, "no managers left for crtc\n");
 +                      return -ENOMEM;
 +              }
 +      }
 +
 +      /*
 +       * Create normal planes for the remaining overlays:
 +       */
 +      for (; id < num_ovls; id++) {
 +              struct drm_plane *plane = omap_plane_init(dev, id, false);
 +
 +              BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
 +              priv->planes[priv->num_planes++] = plane;
 +      }
 +
 +      for (i = 0; i < priv->num_encoders; i++) {
 +              struct drm_encoder *encoder = priv->encoders[i];
 +              struct omap_dss_device *dssdev =
 +                                      omap_encoder_get_dssdev(encoder);
 +
                /* figure out which crtc's we can connect the encoder to: */
                encoder->possible_crtcs = 0;
                for (id = 0; id < priv->num_crtcs; id++) {
 -                      enum omap_dss_output_id supported_outputs =
 -                                      dss_feat_get_supported_outputs(pipe2chan(id));
 +                      struct drm_crtc *crtc = priv->crtcs[id];
 +                      enum omap_channel crtc_channel;
 +                      enum omap_dss_output_id supported_outputs;
 +
 +                      crtc_channel = omap_crtc_channel(crtc);
 +                      supported_outputs =
 +                              dss_feat_get_supported_outputs(crtc_channel);
 +
                        if (supported_outputs & dssdev->output->id)
                                encoder->possible_crtcs |= (1 << id);
                }
        }
  
 +      DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n",
 +              priv->num_planes, priv->num_crtcs, priv->num_encoders,
 +              priv->num_connectors);
 +
        dev->mode_config.min_width = 32;
        dev->mode_config.min_height = 32;
  
@@@ -404,7 -303,7 +404,7 @@@ static int ioctl_gem_info(struct drm_de
        return ret;
  }
  
 -struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
 +static struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
        DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH),
        DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH),
@@@ -649,6 -548,9 +649,9 @@@ static void pdev_shutdown(struct platfo
  
  static int pdev_probe(struct platform_device *device)
  {
+       if (omapdss_is_initialized() == false)
+               return -EPROBE_DEFER;
        DBG("%s", device->name);
        return drm_platform_init(&omap_drm_driver, device);
  }
@@@ -668,7 -570,7 +671,7 @@@ static const struct dev_pm_ops omapdrm_
  };
  #endif
  
 -struct platform_driver pdev = {
 +static struct platform_driver pdev = {
                .driver = {
                        .name = DRIVER_NAME,
                        .owner = THIS_MODULE,
index 477268a2415fd06d58e47eddc5e157b4940fd8c3,0a489bd29d6bf077222b14d13b56d1162d24f6f6..d338b19da544c92e8e1c73c66092ca96575bcb59
@@@ -648,12 -648,9 +648,12 @@@ static void omap_vout_isr(void *arg, un
  
        /* First save the configuration in ovelray structure */
        ret = omapvid_init(vout, addr);
 -      if (ret)
 +      if (ret) {
                printk(KERN_ERR VOUT_NAME
                        "failed to set overlay info\n");
 +              goto vout_isr_err;
 +      }
 +
        /* Enable the pipeline and set the Go bit */
        ret = omapvid_apply_changes(vout);
        if (ret)
@@@ -1663,16 -1660,13 +1663,16 @@@ static int vidioc_streamon(struct file 
        mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
                | DISPC_IRQ_VSYNC2;
  
 -      omap_dispc_register_isr(omap_vout_isr, vout, mask);
 -
        /* First save the configuration in ovelray structure */
        ret = omapvid_init(vout, addr);
 -      if (ret)
 +      if (ret) {
                v4l2_err(&vout->vid_dev->v4l2_dev,
                                "failed to set overlay info\n");
 +              goto streamon_err1;
 +      }
 +
 +      omap_dispc_register_isr(omap_vout_isr, vout, mask);
 +
        /* Enable the pipeline and set the Go bit */
        ret = omapvid_apply_changes(vout);
        if (ret)
@@@ -2150,6 -2144,9 +2150,9 @@@ static int __init omap_vout_probe(struc
        struct omap_dss_device *def_display;
        struct omap2video_device *vid_dev = NULL;
  
+       if (omapdss_is_initialized() == false)
+               return -EPROBE_DEFER;
        ret = omapdss_compat_init();
        if (ret) {
                dev_err(&pdev->dev, "failed to init dss\n");
index 60cc6fee654815444c21d46909351f0e15af6b10,f49ddb9e7c8273fd33371011418ac6831bc290b3..c9c2252e371945939dcf0b5e1f667359cd7ba42d
@@@ -53,6 -53,8 +53,8 @@@ static char *def_disp_name
  module_param_named(def_disp, def_disp_name, charp, 0);
  MODULE_PARM_DESC(def_disp, "default display name");
  
+ static bool dss_initialized;
  const char *omapdss_get_default_display_name(void)
  {
        return core.default_display_name;
@@@ -66,6 -68,12 +68,12 @@@ enum omapdss_version omapdss_get_versio
  }
  EXPORT_SYMBOL(omapdss_get_version);
  
+ bool omapdss_is_initialized(void)
+ {
+       return dss_initialized;
+ }
+ EXPORT_SYMBOL(omapdss_is_initialized);
  struct platform_device *dss_get_core_pdev(void)
  {
        return core.pdev;
@@@ -181,7 -189,10 +189,7 @@@ int dss_debugfs_create_file(const char 
        d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
                        write, &dss_debug_fops);
  
 -      if (IS_ERR(d))
 -              return PTR_ERR(d);
 -
 -      return 0;
 +      return PTR_RET(d);
  }
  #else /* CONFIG_OMAP2_DSS_DEBUGFS */
  static inline int dss_initialize_debugfs(void)
@@@ -603,6 -614,8 +611,8 @@@ static int __init omap_dss_init(void
                return r;
        }
  
+       dss_initialized = true;
        return 0;
  }
  
@@@ -633,7 -646,15 +643,15 @@@ static int __init omap_dss_init(void
  
  static int __init omap_dss_init2(void)
  {
-       return omap_dss_register_drivers();
+       int r;
+       r = omap_dss_register_drivers();
+       if (r)
+               return r;
+       dss_initialized = true;
+       return 0;
  }
  
  core_initcall(omap_dss_init);
index c84bb8a4d0c4c1b7b1433fb97f6e55796d067434,bb5f9fee365929fd44ee3aaffeba77a1ce45cccf..856917b3361665137d676fda89f1c0f426ae41c2
@@@ -2372,7 -2372,7 +2372,7 @@@ static int omapfb_init_connections(stru
                struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
                struct omap_dss_output *out = dssdev->output;
  
 -              mgr = omap_dss_get_overlay_manager(dssdev->channel);
 +              mgr = omap_dss_get_overlay_manager(out->dispc_channel);
  
                if (!mgr || !out)
                        continue;
        return 0;
  }
  
 -static int __init omapfb_probe(struct platform_device *pdev)
 +static int omapfb_probe(struct platform_device *pdev)
  {
        struct omapfb2_device *fbdev = NULL;
        int r = 0;
  
        DBG("omapfb_probe\n");
  
+       if (omapdss_is_initialized() == false)
+               return -EPROBE_DEFER;
        if (pdev->num_resources != 0) {
                dev_err(&pdev->dev, "probed for an unknown device\n");
                r = -ENODEV;
  
        if (fbdev->num_displays == 0) {
                dev_err(&pdev->dev, "no displays\n");
 -              r = -EINVAL;
 +              r = -EPROBE_DEFER;
                goto cleanup;
        }
  
@@@ -2579,7 -2582,6 +2582,7 @@@ static int __exit omapfb_remove(struct 
  }
  
  static struct platform_driver omapfb_driver = {
 +      .probe          = omapfb_probe,
        .remove         = __exit_p(omapfb_remove),
        .driver         = {
                .name   = "omapfb",
        },
  };
  
 -static int __init omapfb_init(void)
 -{
 -      DBG("omapfb_init\n");
 -
 -      if (platform_driver_probe(&omapfb_driver, omapfb_probe)) {
 -              printk(KERN_ERR "failed to register omapfb driver\n");
 -              return -ENODEV;
 -      }
 -
 -      return 0;
 -}
 -
 -static void __exit omapfb_exit(void)
 -{
 -      DBG("omapfb_exit\n");
 -      platform_driver_unregister(&omapfb_driver);
 -}
 -
  module_param_named(mode, def_mode, charp, 0);
  module_param_named(vram, def_vram, charp, 0);
  module_param_named(rotate, def_rotate, int, 0);
  module_param_named(vrfb, def_vrfb, bool, 0);
  module_param_named(mirror, def_mirror, bool, 0);
  
 -/* late_initcall to let panel/ctrl drivers loaded first.
 - * I guess better option would be a more dynamic approach,
 - * so that omapfb reacts to new panels when they are loaded */
 -late_initcall(omapfb_init);
 -/*module_init(omapfb_init);*/
 -module_exit(omapfb_exit);
 +module_platform_driver(omapfb_driver);
  
  MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
  MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
diff --combined include/video/omapdss.h
index 62ca9a77c1d65dff76823857e895f61280893a1b,9b52340ec3ff31988634c05c89b308e092b1ef69..aeb4e9a0c5d1c1e4dbd484286983bc3eada936df
@@@ -257,31 -257,10 +257,31 @@@ void rfbi_bus_unlock(void)
  
  /* DSI */
  
 +enum omap_dss_dsi_trans_mode {
 +      /* Sync Pulses: both sync start and end packets sent */
 +      OMAP_DSS_DSI_PULSE_MODE,
 +      /* Sync Events: only sync start packets sent */
 +      OMAP_DSS_DSI_EVENT_MODE,
 +      /* Burst: only sync start packets sent, pixels are time compressed */
 +      OMAP_DSS_DSI_BURST_MODE,
 +};
 +
  struct omap_dss_dsi_videomode_timings {
 +      unsigned long hsclk;
 +
 +      unsigned ndl;
 +      unsigned bitspp;
 +
 +      /* pixels */
 +      u16 hact;
 +      /* lines */
 +      u16 vact;
 +
        /* DSI video mode blanking data */
        /* Unit: byte clock cycles */
 +      u16 hss;
        u16 hsa;
 +      u16 hse;
        u16 hfp;
        u16 hbp;
        /* Unit: line clocks */
        int hbp_blanking_mode;
        int hfp_blanking_mode;
  
 -      /* Video port sync events */
 -      bool vp_vsync_end;
 -      bool vp_hsync_end;
 +      enum omap_dss_dsi_trans_mode trans_mode;
  
        bool ddr_clk_always_on;
        int window_sync;
  };
  
 +struct omap_dss_dsi_config {
 +      enum omap_dss_dsi_mode mode;
 +      enum omap_dss_dsi_pixel_format pixel_format;
 +      const struct omap_video_timings *timings;
 +
 +      unsigned long hs_clk_min, hs_clk_max;
 +      unsigned long lp_clk_min, lp_clk_max;
 +
 +      bool ddr_clk_always_on;
 +      enum omap_dss_dsi_trans_mode trans_mode;
 +};
 +
  void dsi_bus_lock(struct omap_dss_device *dssdev);
  void dsi_bus_unlock(struct omap_dss_device *dssdev);
  int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
@@@ -572,14 -541,9 +572,14 @@@ struct omap_dss_writeback_info 
  struct omap_dss_output {
        struct list_head list;
  
 +      const char *name;
 +
        /* display type supported by the output */
        enum omap_display_type type;
  
 +      /* DISPC channel for this output */
 +      enum omap_channel dispc_channel;
 +
        /* output instance */
        enum omap_dss_output_id id;
  
@@@ -597,7 -561,6 +597,7 @@@ struct omap_dss_device 
  
        enum omap_display_type type;
  
 +      /* obsolete, to be removed */
        enum omap_channel channel;
  
        union {
                } venc;
        } phy;
  
 -      struct {
 -              struct {
 -                      struct {
 -                              u16 lck_div;
 -                              u16 pck_div;
 -                              enum omap_dss_clk_source lcd_clk_src;
 -                      } channel;
 -
 -                      enum omap_dss_clk_source dispc_fclk_src;
 -              } dispc;
 -
 -              struct {
 -                      /* regn is one greater than TRM's REGN value */
 -                      u16 regn;
 -                      u16 regm;
 -                      u16 regm_dispc;
 -                      u16 regm_dsi;
 -
 -                      u16 lp_clk_div;
 -                      enum omap_dss_clk_source dsi_fclk_src;
 -              } dsi;
 -
 -              struct {
 -                      /* regn is one greater than TRM's REGN value */
 -                      u16 regn;
 -                      u16 regm2;
 -              } hdmi;
 -      } clocks;
 -
        struct {
                struct omap_video_timings timings;
  
                enum omap_dss_dsi_pixel_format dsi_pix_fmt;
                enum omap_dss_dsi_mode dsi_mode;
 -              struct omap_dss_dsi_videomode_timings dsi_vm_timings;
        } panel;
  
        struct {
@@@ -748,6 -741,7 +748,7 @@@ struct omap_dss_driver 
  };
  
  enum omapdss_version omapdss_get_version(void);
+ bool omapdss_is_initialized(void);
  
  int omap_dss_register_driver(struct omap_dss_driver *);
  void omap_dss_unregister_driver(struct omap_dss_driver *);
@@@ -836,8 -830,15 +837,8 @@@ int dispc_ovl_setup(enum omap_plane pla
  void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
                bool enable);
  int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
 -void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
 -              struct omap_video_timings *timings);
 -void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h);
 -void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
 -              enum omap_dss_dsi_pixel_format fmt);
 -void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
 -              enum omap_dss_dsi_mode mode);
 -void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
 -              struct omap_dss_dsi_videomode_timings *timings);
 +int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
 +              const struct omap_dss_dsi_config *config);
  
  int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
                void (*callback)(int, void *), void *data);
@@@ -846,6 -847,8 +847,6 @@@ int omap_dsi_set_vc_id(struct omap_dss_
  void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
  int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
                const struct omap_dsi_pin_config *pin_cfg);
 -int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
 -              unsigned long ddr_clk, unsigned long lp_clk);
  
  int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
  void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,