* [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan
@ 2011-12-13 14:02 Laurent Pinchart
2011-12-16 9:40 ` [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to Guennadi Liakhovetski
2011-12-16 10:22 ` [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan Laurent Pinchart
0 siblings, 2 replies; 3+ messages in thread
From: Laurent Pinchart @ 2011-12-13 14:02 UTC (permalink / raw)
To: linux-fbdev
The callback implements 3 notification events:
- SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT notifies the LCDC that the
display has been connected
- SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT notifies the LCDC that the
display has been disconnected
- SH_MOBILE_LCDC_EVENT_DISPLAY_MODE notifies that LCDC that a display
mode has been detected
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/video/sh_mobile_lcdcfb.c | 81 ++++++++++++++++++++++++++++++++++++++
drivers/video/sh_mobile_lcdcfb.h | 10 +++++
2 files changed, 91 insertions(+), 0 deletions(-)
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 4b03aa5..21e5f10 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -363,6 +363,86 @@ static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch)
ch->tx_dev->ops->display_off(ch->tx_dev);
}
+static bool
+sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
+ const struct fb_var_screeninfo *new_var)
+{
+ struct fb_var_screeninfo *old_var = &ch->display_var;
+ struct fb_videomode old_mode;
+ struct fb_videomode new_mode;
+
+ fb_var_to_videomode(&old_mode, old_var);
+ fb_var_to_videomode(&new_mode, new_var);
+
+ dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n",
+ old_mode.xres, old_mode.yres, new_mode.xres, new_mode.yres);
+
+ if (fb_mode_is_equal(&old_mode, &new_mode)) {
+ /* It can be a different monitor with an equal video-mode */
+ old_var->width = new_var->width;
+ old_var->height = new_var->height;
+ return false;
+ }
+
+ dev_dbg(ch->info->dev, "Switching %u -> %u lines\n",
+ old_mode.yres, new_mode.yres);
+ *old_var = *new_var;
+
+ return true;
+}
+
+static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
+ enum sh_mobile_lcdc_entity_event event,
+ struct fb_var_screeninfo *var)
+{
+ struct fb_info *info = ch->info;
+ int ret = 0;
+
+ switch (event) {
+ case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
+ /* HDMI plug in */
+ if (lock_fb_info(info)) {
+ console_lock();
+
+ if (!sh_mobile_lcdc_must_reconfigure(ch, var) &&
+ info->state = FBINFO_STATE_RUNNING) {
+ /* First activation with the default monitor.
+ * Just turn on, if we run a resume here, the
+ * logo disappears.
+ */
+ info->var.width = var->width;
+ info->var.height = var->height;
+ sh_mobile_lcdc_display_on(ch);
+ } else {
+ /* New monitor or have to wake up */
+ fb_set_suspend(info, 0);
+ }
+
+ console_unlock();
+ unlock_fb_info(info);
+ }
+ break;
+
+ case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
+ /* HDMI disconnect */
+ if (lock_fb_info(info)) {
+ console_lock();
+ fb_set_suspend(info, 1);
+ console_unlock();
+ unlock_fb_info(info);
+ }
+ break;
+
+ case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
+ /* Validate a proposed new mode */
+ var->bits_per_pixel = info->var.bits_per_pixel;
+ ret = info->fbops->fb_check_var(var, info);
+ break;
+ }
+
+ return ret;
+}
+
/* -----------------------------------------------------------------------------
* Format helpers
*/
@@ -1591,6 +1671,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
int i;
mutex_init(&ch->open_lock);
+ ch->notify = sh_mobile_lcdc_display_notify;
/* Allocate the frame buffer device. */
ch->info = framebuffer_alloc(0, priv->dev);
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index 6fb956c..e2eb7af 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -30,6 +30,12 @@ struct sh_mobile_lcdc_entity_ops {
void (*display_off)(struct sh_mobile_lcdc_entity *entity);
};
+enum sh_mobile_lcdc_entity_event {
+ SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
+ SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
+ SH_MOBILE_LCDC_EVENT_DISPLAY_MODE,
+};
+
struct sh_mobile_lcdc_entity {
struct module *owner;
const struct sh_mobile_lcdc_entity_ops *ops;
@@ -70,6 +76,10 @@ struct sh_mobile_lcdc_chan {
unsigned long base_addr_y;
unsigned long base_addr_c;
unsigned int pitch;
+
+ int (*notify)(struct sh_mobile_lcdc_chan *ch,
+ enum sh_mobile_lcdc_entity_event event,
+ struct fb_var_screeninfo *var);
};
#endif
--
1.7.3.4
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to
2011-12-13 14:02 [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan Laurent Pinchart
@ 2011-12-16 9:40 ` Guennadi Liakhovetski
2011-12-16 10:22 ` [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan Laurent Pinchart
1 sibling, 0 replies; 3+ messages in thread
From: Guennadi Liakhovetski @ 2011-12-16 9:40 UTC (permalink / raw)
To: linux-fbdev
On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> The callback implements 3 notification events:
>
> - SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT notifies the LCDC that the
> display has been connected
> - SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT notifies the LCDC that the
> display has been disconnected
> - SH_MOBILE_LCDC_EVENT_DISPLAY_MODE notifies that LCDC that a display
> mode has been detected
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> drivers/video/sh_mobile_lcdcfb.c | 81 ++++++++++++++++++++++++++++++++++++++
> drivers/video/sh_mobile_lcdcfb.h | 10 +++++
> 2 files changed, 91 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
> index 4b03aa5..21e5f10 100644
> --- a/drivers/video/sh_mobile_lcdcfb.c
> +++ b/drivers/video/sh_mobile_lcdcfb.c
> @@ -363,6 +363,86 @@ static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch)
> ch->tx_dev->ops->display_off(ch->tx_dev);
> }
>
> +static bool
> +sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
> + const struct fb_var_screeninfo *new_var)
> +{
> + struct fb_var_screeninfo *old_var = &ch->display_var;
> + struct fb_videomode old_mode;
> + struct fb_videomode new_mode;
> +
> + fb_var_to_videomode(&old_mode, old_var);
> + fb_var_to_videomode(&new_mode, new_var);
> +
> + dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n",
> + old_mode.xres, old_mode.yres, new_mode.xres, new_mode.yres);
> +
> + if (fb_mode_is_equal(&old_mode, &new_mode)) {
> + /* It can be a different monitor with an equal video-mode */
> + old_var->width = new_var->width;
> + old_var->height = new_var->height;
> + return false;
> + }
> +
> + dev_dbg(ch->info->dev, "Switching %u -> %u lines\n",
> + old_mode.yres, new_mode.yres);
> + *old_var = *new_var;
> +
> + return true;
> +}
> +
> +static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
> + enum sh_mobile_lcdc_entity_event event,
> + struct fb_var_screeninfo *var)
> +{
> + struct fb_info *info = ch->info;
> + int ret = 0;
> +
> + switch (event) {
> + case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
> + /* HDMI plug in */
> + if (lock_fb_info(info)) {
> + console_lock();
> +
> + if (!sh_mobile_lcdc_must_reconfigure(ch, var) &&
> + info->state = FBINFO_STATE_RUNNING) {
> + /* First activation with the default monitor.
> + * Just turn on, if we run a resume here, the
> + * logo disappears.
> + */
> + info->var.width = var->width;
> + info->var.height = var->height;
> + sh_mobile_lcdc_display_on(ch);
> + } else {
> + /* New monitor or have to wake up */
> + fb_set_suspend(info, 0);
> + }
> +
> + console_unlock();
> + unlock_fb_info(info);
> + }
> + break;
> +
> + case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
> + /* HDMI disconnect */
> + if (lock_fb_info(info)) {
> + console_lock();
> + fb_set_suspend(info, 1);
> + console_unlock();
> + unlock_fb_info(info);
> + }
> + break;
> +
> + case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
> + /* Validate a proposed new mode */
> + var->bits_per_pixel = info->var.bits_per_pixel;
> + ret = info->fbops->fb_check_var(var, info);
You can call sh_mobile_lcdc_check_var() directly here too, right?
Thanks
Guennadi
> + break;
> + }
> +
> + return ret;
> +}
> +
> /* -----------------------------------------------------------------------------
> * Format helpers
> */
> @@ -1591,6 +1671,7 @@ sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
> int i;
>
> mutex_init(&ch->open_lock);
> + ch->notify = sh_mobile_lcdc_display_notify;
>
> /* Allocate the frame buffer device. */
> ch->info = framebuffer_alloc(0, priv->dev);
> diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
> index 6fb956c..e2eb7af 100644
> --- a/drivers/video/sh_mobile_lcdcfb.h
> +++ b/drivers/video/sh_mobile_lcdcfb.h
> @@ -30,6 +30,12 @@ struct sh_mobile_lcdc_entity_ops {
> void (*display_off)(struct sh_mobile_lcdc_entity *entity);
> };
>
> +enum sh_mobile_lcdc_entity_event {
> + SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
> + SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
> + SH_MOBILE_LCDC_EVENT_DISPLAY_MODE,
> +};
> +
> struct sh_mobile_lcdc_entity {
> struct module *owner;
> const struct sh_mobile_lcdc_entity_ops *ops;
> @@ -70,6 +76,10 @@ struct sh_mobile_lcdc_chan {
> unsigned long base_addr_y;
> unsigned long base_addr_c;
> unsigned int pitch;
> +
> + int (*notify)(struct sh_mobile_lcdc_chan *ch,
> + enum sh_mobile_lcdc_entity_event event,
> + struct fb_var_screeninfo *var);
> };
>
> #endif
> --
> 1.7.3.4
>
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan
2011-12-13 14:02 [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan Laurent Pinchart
2011-12-16 9:40 ` [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to Guennadi Liakhovetski
@ 2011-12-16 10:22 ` Laurent Pinchart
1 sibling, 0 replies; 3+ messages in thread
From: Laurent Pinchart @ 2011-12-16 10:22 UTC (permalink / raw)
To: linux-fbdev
Hi Guennadi,
On Friday 16 December 2011 10:40:48 Guennadi Liakhovetski wrote:
> On Tue, 13 Dec 2011, Laurent Pinchart wrote:
> > The callback implements 3 notification events:
> >
> > - SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT notifies the LCDC that the
> > display has been connected
> >
> > - SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT notifies the LCDC that the
> > display has been disconnected
> >
> > - SH_MOBILE_LCDC_EVENT_DISPLAY_MODE notifies that LCDC that a display
> > mode has been detected
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >
> > diff --git a/drivers/video/sh_mobile_lcdcfb.c
> > b/drivers/video/sh_mobile_lcdcfb.c index 4b03aa5..21e5f10 100644
> > --- a/drivers/video/sh_mobile_lcdcfb.c
> > +++ b/drivers/video/sh_mobile_lcdcfb.c
> > @@ -363,6 +363,86 @@ static void sh_mobile_lcdc_display_off(struct
[snip]
> > +static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
> > + enum sh_mobile_lcdc_entity_event event,
> > + struct fb_var_screeninfo *var)
> > +{
> > + struct fb_info *info = ch->info;
> > + int ret = 0;
> > +
> > + switch (event) {
> > + case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
> > + /* HDMI plug in */
> > + if (lock_fb_info(info)) {
> > + console_lock();
> > +
> > + if (!sh_mobile_lcdc_must_reconfigure(ch, var) &&
> > + info->state = FBINFO_STATE_RUNNING) {
> > + /* First activation with the default monitor.
> > + * Just turn on, if we run a resume here, the
> > + * logo disappears.
> > + */
> > + info->var.width = var->width;
> > + info->var.height = var->height;
> > + sh_mobile_lcdc_display_on(ch);
> > + } else {
> > + /* New monitor or have to wake up */
> > + fb_set_suspend(info, 0);
> > + }
> > +
> > + console_unlock();
> > + unlock_fb_info(info);
> > + }
> > + break;
> > +
> > + case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
> > + /* HDMI disconnect */
> > + if (lock_fb_info(info)) {
> > + console_lock();
> > + fb_set_suspend(info, 1);
> > + console_unlock();
> > + unlock_fb_info(info);
> > + }
> > + break;
> > +
> > + case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
> > + /* Validate a proposed new mode */
> > + var->bits_per_pixel = info->var.bits_per_pixel;
> > + ret = info->fbops->fb_check_var(var, info);
>
> You can call sh_mobile_lcdc_check_var() directly here too, right?
This was a way to avoid a forward declaration. You would prefer a forward
declaration, right ? :-) I think you would be right.
> > + break;
> > + }
> > +
> > + return ret;
> > +}
> > +
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-12-16 10:22 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-13 14:02 [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan Laurent Pinchart
2011-12-16 9:40 ` [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to Guennadi Liakhovetski
2011-12-16 10:22 ` [PATCH 25/57] sh_mobile_lcdc: Add display notify callback to sh_mobile_lcdc_chan Laurent Pinchart
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).