]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Jan 2011 18:39:14 +0000 (10:39 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Jan 2011 18:39:14 +0000 (10:39 -0800)
* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6: (29 commits)
  video: move SH_MIPI_DSI/SH_LCD_MIPI_DSI to the top of menu
  fbdev: Implement simple blanking in pseudocolor modes for vt8500lcdfb
  video: imx: Update the manufacturer's name
  nuc900fb: don't treat NULL clk as an error
  s3c2410fb: don't treat NULL clk as an error
  video: tidy up modedb formatting.
  video: matroxfb: Correct video option in comments and kernel config help.
  fbdev: sh_mobile_hdmi: simplify pointer handling
  fbdev: sh_mobile_hdmi: framebuffer notifiers have to be registered
  fbdev: sh_mobile_hdmi: add command line option to use the preferred EDID mode
  OMAP: DSS2: Introduce omap_channel as an omap_dss_device parameter, add new overlay manager.
  OMAP: DSS2: Use dss_features to handle DISPC bits removed on OMAP4
  OMAP: DSS2: LCD2 Channel Changes for DISPC
  OMAP: DSS2: Change remaining DISPC functions for new omap_channel argument
  OMAP: DSS2: Introduce omap_channel argument to DISPC functions used by interface drivers
  OMAP: DSS2: Represent DISPC register defines with channel as parameter
  OMAP: DSS2: Add dss_features for omap4 and overlay manager related features
  OMAP: DSS2: Clean up DISPC color mode validation checks
  OMAP: DSS2: Add back authors of panel-generic.c based drivers
  OMAP: DSS2: remove generic DPI panel driver duplicated panel drivers
  ...

1  2 
drivers/video/sh_mobile_hdmi.c

index e7594e145c96561ef221165f8ff9a6862d7dfd2a,e3eb77dfbf22411ca3553bd7817d57f453a91b41..74d9f546a2e8012b50ee4503fdebdb50297ce4fa
@@@ -22,7 -22,6 +22,7 @@@
  #include <linux/slab.h>
  #include <linux/types.h>
  #include <linux/workqueue.h>
 +#include <sound/soc.h>
  #include <sound/soc-dapm.h>
  #include <sound/initval.h>
  
@@@ -222,6 -221,7 +222,7 @@@ struct sh_hdmi 
        struct delayed_work edid_work;
        struct fb_var_screeninfo var;
        struct fb_monspecs monspec;
+       struct notifier_block notifier;
  };
  
  static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
@@@ -738,7 -738,7 +739,7 @@@ static int sh_hdmi_read_edid(struct sh_
        struct fb_modelist *modelist = NULL;
        unsigned int f_width = 0, f_height = 0, f_refresh = 0;
        unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
-       bool exact_match = false;
+       bool scanning = false, preferred_bad = false;
        u8 edid[128];
        char *forced;
        int i;
                if (i < 2) {
                        f_width = 0;
                        f_height = 0;
+               } else {
+                       /* The user wants us to use the EDID data */
+                       scanning = true;
                }
                dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
                        f_width, f_height, f_refresh);
  
        /* Walk monitor modes to find the best or the exact match */
        for (i = 0, mode = hdmi->monspec.modedb;
-            f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
+            i < hdmi->monspec.modedb_len && scanning;
             i++, mode++) {
                unsigned long rate_error;
  
-               /* No interest in unmatching modes */
-               if (f_width != mode->xres || f_height != mode->yres)
+               if (!f_width && !f_height) {
+                       /*
+                        * A parameter string "video=sh_mobile_lcdc:0x0" means
+                        * use the preferred EDID mode. If it is rejected by
+                        * .fb_check_var(), keep looking, until an acceptable
+                        * one is found.
+                        */
+                       if ((mode->flag & FB_MODE_IS_FIRST) || preferred_bad)
+                               scanning = false;
+                       else
+                               continue;
+               } else if (f_width != mode->xres || f_height != mode->yres) {
+                       /* No interest in unmatching modes */
                        continue;
+               }
  
                rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate);
  
-               if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
-                       /*
-                        * Exact match if either the refresh rate matches or it
-                        * hasn't been specified and we've found a mode, for
-                        * which we can configure the clock precisely
-                        */
-                       exact_match = true;
-               else if (found && found_rate_error <= rate_error)
-                       /*
-                        * We otherwise search for the closest matching clock
-                        * rate - either if no refresh rate has been specified
-                        * or we cannot find an exactly matching one
-                        */
-                       continue;
+               if (scanning) {
+                       if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
+                               /*
+                                * Exact match if either the refresh rate
+                                * matches or it hasn't been specified and we've
+                                * found a mode, for which we can configure the
+                                * clock precisely
+                                */
+                               scanning = false;
+                       else if (found && found_rate_error <= rate_error)
+                               /*
+                                * We otherwise search for the closest matching
+                                * clock rate - either if no refresh rate has
+                                * been specified or we cannot find an exactly
+                                * matching one
+                                */
+                               continue;
+               }
  
                /* Check if supported: sufficient fb memory, supported clock-rate */
                fb_videomode_to_var(var, mode);
  
+               var->bits_per_pixel = info->var.bits_per_pixel;
                if (info && info->fbops->fb_check_var &&
                    info->fbops->fb_check_var(var, info)) {
-                       exact_match = false;
+                       scanning = true;
+                       preferred_bad = true;
                        continue;
                }
  
         * driver, and passing ->info with HDMI platform data.
         */
        if (info && !found) {
-               modelist = hdmi->info->modelist.next &&
-                       !list_empty(&hdmi->info->modelist) ?
-                       list_entry(hdmi->info->modelist.next,
+               modelist = info->modelist.next &&
+                       !list_empty(&info->modelist) ?
+                       list_entry(info->modelist.next,
                                   struct fb_modelist, list) :
                        NULL;
  
@@@ -1101,6 -1123,7 +1124,7 @@@ static void sh_hdmi_edid_work_fn(struc
        mutex_lock(&hdmi->mutex);
  
        if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
+               struct fb_info *info = hdmi->info;
                unsigned long parent_rate = 0, hdmi_rate;
  
                /* A device has been plugged in */
                /* Switched to another (d) power-save mode */
                msleep(10);
  
-               if (!hdmi->info)
+               if (!info)
                        goto out;
  
-               ch = hdmi->info->par;
+               ch = info->par;
  
                acquire_console_sem();
  
                /* HDMI plug in */
                if (!sh_hdmi_must_reconfigure(hdmi) &&
-                   hdmi->info->state == FBINFO_STATE_RUNNING) {
+                   info->state == FBINFO_STATE_RUNNING) {
                        /*
                         * First activation with the default monitor - just turn
                         * on, if we run a resume here, the logo disappears
                         */
-                       if (lock_fb_info(hdmi->info)) {
-                               struct fb_info *info = hdmi->info;
+                       if (lock_fb_info(info)) {
                                info->var.width = hdmi->var.width;
                                info->var.height = hdmi->var.height;
                                sh_hdmi_display_on(hdmi, info);
                        }
                } else {
                        /* New monitor or have to wake up */
-                       fb_set_suspend(hdmi->info, 0);
+                       fb_set_suspend(info, 0);
                }
  
                release_console_sem();
@@@ -1175,13 -1197,6 +1198,6 @@@ out
        dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, pdata->lcd_dev);
  }
  
- static int sh_hdmi_notify(struct notifier_block *nb,
-                         unsigned long action, void *data);
- static struct notifier_block sh_hdmi_notifier = {
-       .notifier_call = sh_hdmi_notify,
- };
  static int sh_hdmi_notify(struct notifier_block *nb,
                          unsigned long action, void *data)
  {
        struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
        struct sh_hdmi *hdmi = board_cfg->board_data;
  
-       if (nb != &sh_hdmi_notifier || !hdmi || hdmi->info != info)
+       if (!hdmi || nb != &hdmi->notifier || hdmi->info != info)
                return NOTIFY_DONE;
  
        switch(action) {
                 * temporarily, synchronise with the work queue and re-acquire
                 * the info->lock.
                 */
-               unlock_fb_info(hdmi->info);
+               unlock_fb_info(info);
                mutex_lock(&hdmi->mutex);
                hdmi->info = NULL;
                mutex_unlock(&hdmi->mutex);
-               lock_fb_info(hdmi->info);
+               lock_fb_info(info);
                return NOTIFY_OK;
        }
        return NOTIFY_DONE;
@@@ -1312,6 -1327,9 +1328,9 @@@ static int __init sh_hdmi_probe(struct 
                goto ecodec;
        }
  
+       hdmi->notifier.notifier_call = sh_hdmi_notify;
+       fb_register_client(&hdmi->notifier);
        return 0;
  
  ecodec:
@@@ -1342,6 -1360,8 +1361,8 @@@ static int __exit sh_hdmi_remove(struc
  
        snd_soc_unregister_codec(&pdev->dev);
  
+       fb_unregister_client(&hdmi->notifier);
        board_cfg->display_on = NULL;
        board_cfg->display_off = NULL;
        board_cfg->board_data = NULL;