MLK-14548: video: fb: hdmi: Allow Sil902 init regardless of fb registration time
authorCristina Ciocan <cristina-mihaela.ciocan@nxp.com>
Thu, 20 Apr 2017 10:48:50 +0000 (13:48 +0300)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:22:02 +0000 (15:22 -0500)
When a new fb is registered, a FB_EVENT_FB_REGISTERED event is sent to
any registered fb client. Upon event receipt, the Sil902 HDMI transmitter
saves the fb info structure address for future use and schedules a cable
state check in order to setup and power up/down the device.

The current Sil902 driver registers as fb client at the end of the probe
function, thus events from fb core will only be received after the probe()
call. If a framebuffer is registered before Sil902's probe() is called,
the HDMI transmitter will not have knowledge of the framebuffer.

This patch moves the Sil902 fb client registration step into an __init
function and saves the fb info in case any registration event is received
prior to the probe() call. When the probe() is called, check for any
registration event and act accordingly.

Sil902's init function class is called after the frame buffer core's init
function class.

Signed-off-by: Cristina Ciocan <cristina-mihaela.ciocan@nxp.com>
drivers/video/fbdev/mxc/mxsfb_sii902x.c

index c3c4a18..aa4a8bb 100644 (file)
@@ -60,6 +60,8 @@ struct sii902x_data {
 static void sii902x_poweron(void);
 static void sii902x_poweroff(void);
 
+static int sii902x_in_init_state;
+
 #ifdef DEBUG
 static void dump_fb_videomode(struct fb_videomode *m)
 {
@@ -329,6 +331,13 @@ static int sii902x_fb_event(struct notifier_block *nb, unsigned long val, void *
 
        dev_dbg(&sii902x.client->dev, "%s event=0x%lx\n", __func__, val);
 
+       if (sii902x_in_init_state) {
+               if (val == FB_EVENT_FB_REGISTERED && !sii902x.fbi)
+                       sii902x.fbi = fbi;
+
+               return 0;
+       }
+
        switch (val) {
        case FB_EVENT_FB_REGISTERED:
                if (sii902x.fbi == NULL)
@@ -387,6 +396,7 @@ static int sii902x_probe(struct i2c_client *client,
 {
        int i, dat, ret;
        struct fb_info edid_fbi;
+       struct fb_info *init_fbi = sii902x.fbi;
 
        memset(&sii902x, 0, sizeof(sii902x));
 
@@ -465,7 +475,15 @@ static int sii902x_probe(struct i2c_client *client,
        }
 
        mxsfb_get_of_property();
-       fb_register_client(&nb);
+
+       if (init_fbi) {
+               sii902x.fbi = init_fbi;
+
+               /* Manually trigger a plugin/plugout interrupter to check cable state */
+               schedule_delayed_work(&(sii902x.det_work), msecs_to_jiffies(50));
+       }
+
+       sii902x_in_init_state = 0;
 
        return 0;
 }
@@ -499,6 +517,14 @@ static void sii902x_poweroff(void)
        return;
 }
 
+static int __init sii902x_init(void)
+{
+       sii902x_in_init_state = 1;
+
+       return fb_register_client(&nb);
+}
+fs_initcall_sync(sii902x_init);
+
 static const struct i2c_device_id sii902x_id[] = {
        { DRV_NAME, 0},
        { },