Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/fbdev-2.6

* 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
  ...
This commit is contained in:
Linus Torvalds
2011-01-13 10:39:14 -08:00
42 changed files with 2122 additions and 1180 deletions

View File

@@ -222,6 +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 +739,7 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
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;
@@ -801,6 +802,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
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);
@@ -808,37 +812,56 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
/* 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;
}
@@ -856,9 +879,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
* 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 +1124,7 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
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 */
@@ -1122,22 +1146,21 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
/* 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);
@@ -1145,7 +1168,7 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
}
} else {
/* New monitor or have to wake up */
fb_set_suspend(hdmi->info, 0);
fb_set_suspend(info, 0);
}
release_console_sem();
@@ -1175,13 +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)
{
@@ -1191,7 +1207,7 @@ static int sh_hdmi_notify(struct notifier_block *nb,
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) {
@@ -1210,11 +1226,11 @@ static int sh_hdmi_notify(struct notifier_block *nb,
* 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 +1328,9 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
goto ecodec;
}
hdmi->notifier.notifier_call = sh_hdmi_notify;
fb_register_client(&hdmi->notifier);
return 0;
ecodec:
@@ -1342,6 +1361,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
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;