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:
@@ -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;
|
||||
|
Reference in New Issue
Block a user