]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
sh_mobile_hdmi: Use sh_mobile_lcdc_entity::channel to access fb_info
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Sun, 18 Sep 2011 10:25:21 +0000 (12:25 +0200)
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Mon, 12 Mar 2012 21:40:51 +0000 (22:40 +0100)
The fb_info parameter passed to the display_on operation will be
removed, don't use it.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
drivers/video/sh_mobile_hdmi.c

index 3f4e4a4c1cd82f5dd3f690d97939fad56f022dac..bd885ee78d54d6de0e3f048881e543bbd2b48809 100644 (file)
@@ -219,16 +219,12 @@ struct sh_hdmi {
        u8 edid_blocks;
        struct clk *hdmi_clk;
        struct device *dev;
-       struct fb_info *info;
-       struct mutex mutex;             /* Protect the info pointer */
        struct delayed_work edid_work;
        struct fb_var_screeninfo var;
        struct fb_monspecs monspec;
-       struct notifier_block notifier;
 };
 
 #define entity_to_sh_hdmi(e)   container_of(e, struct sh_hdmi, entity)
-#define notifier_to_hdmi(n)    container_of(n, struct sh_hdmi, notifier)
 
 static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
 {
@@ -737,10 +733,11 @@ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
 static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
                             unsigned long *parent_rate)
 {
+       struct fb_info *info = hdmi->entity.lcdc
+                            ? hdmi->entity.lcdc->info : NULL;
        struct fb_var_screeninfo tmpvar;
        struct fb_var_screeninfo *var = &tmpvar;
        const struct fb_videomode *mode, *found = NULL;
-       struct fb_info *info = hdmi->info;
        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... */
@@ -1012,13 +1009,10 @@ static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity,
         * FB_EVENT_FB_UNBIND notify is also called with info->lock held
         */
        struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
-       struct sh_mobile_lcdc_chan *ch = info->par;
+       struct sh_mobile_lcdc_chan *ch = entity->lcdc;
 
        dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__, hdmi, info->state);
 
-       /* No need to lock */
-       hdmi->info = info;
-
        /*
         * hp_state can be set to
         * HDMI_HOTPLUG_DISCONNECTED:   on monitor unplug
@@ -1040,7 +1034,6 @@ static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity,
        return 0;
 }
 
-/* locking: called with info->lock held */
 static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity)
 {
        struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
@@ -1057,15 +1050,14 @@ static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = {
 
 static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
 {
-       struct fb_info *info = hdmi->info;
-       struct sh_mobile_lcdc_chan *ch = info->par;
+       struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
        struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var;
        struct fb_videomode mode1, mode2;
 
        fb_var_to_videomode(&mode1, old_var);
        fb_var_to_videomode(&mode2, new_var);
 
-       dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
+       dev_dbg(hdmi->dev, "Old %ux%u, new %ux%u\n",
                mode1.xres, mode1.yres, mode2.xres, mode2.yres);
 
        if (fb_mode_is_equal(&mode1, &mode2)) {
@@ -1075,7 +1067,7 @@ static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
                return false;
        }
 
-       dev_dbg(info->dev, "Switching %u -> %u lines\n",
+       dev_dbg(hdmi->dev, "Switching %u -> %u lines\n",
                mode1.yres, mode2.yres);
        *old_var = *new_var;
 
@@ -1121,17 +1113,13 @@ static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
 static void sh_hdmi_edid_work_fn(struct work_struct *work)
 {
        struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
+       struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
        struct fb_info *info;
-       struct sh_mobile_lcdc_chan *ch;
        int ret;
 
        dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, hdmi,
                hdmi->hp_state);
 
-       mutex_lock(&hdmi->mutex);
-
-       info = hdmi->info;
-
        if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
                unsigned long parent_rate = 0, hdmi_rate;
 
@@ -1151,10 +1139,10 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
                /* Switched to another (d) power-save mode */
                msleep(10);
 
-               if (!info)
+               if (ch == NULL)
                        goto out;
 
-               ch = info->par;
+               info = ch->info;
 
                if (lock_fb_info(info)) {
                        console_lock();
@@ -1179,9 +1167,11 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
                }
        } else {
                ret = 0;
-               if (!info)
+               if (ch == NULL)
                        goto out;
 
+               info = ch->info;
+
                hdmi->monspec.modedb_len = 0;
                fb_destroy_modedb(hdmi->monspec.modedb);
                hdmi->monspec.modedb = NULL;
@@ -1200,47 +1190,10 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
 out:
        if (ret < 0 && ret != -EAGAIN)
                hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
-       mutex_unlock(&hdmi->mutex);
 
        dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi);
 }
 
-static int sh_hdmi_notify(struct notifier_block *nb,
-                         unsigned long action, void *data)
-{
-       struct fb_event *event = data;
-       struct fb_info *info = event->info;
-       struct sh_hdmi *hdmi = notifier_to_hdmi(nb);
-
-       if (hdmi->info != info)
-               return NOTIFY_DONE;
-
-       switch(action) {
-       case FB_EVENT_FB_REGISTERED:
-               /* Unneeded, activation taken care by sh_hdmi_display_on() */
-               break;
-       case FB_EVENT_FB_UNREGISTERED:
-               /*
-                * We are called from unregister_framebuffer() with the
-                * info->lock held. This is bad for us, because we can race with
-                * the scheduled work, which has to call fb_set_suspend(), which
-                * takes info->lock internally, so, sh_hdmi_edid_work_fn()
-                * cannot take and hold info->lock for the whole function
-                * duration. Using an additional lock creates a classical AB-BA
-                * lock up. Therefore, we have to release the info->lock
-                * temporarily, synchronise with the work queue and re-acquire
-                * the info->lock.
-                */
-               unlock_fb_info(info);
-               mutex_lock(&hdmi->mutex);
-               hdmi->info = NULL;
-               mutex_unlock(&hdmi->mutex);
-               lock_fb_info(info);
-               return NOTIFY_OK;
-       }
-       return NOTIFY_DONE;
-}
-
 static int __init sh_hdmi_probe(struct platform_device *pdev)
 {
        struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
@@ -1258,8 +1211,6 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       mutex_init(&hdmi->mutex);
-
        hdmi->dev = &pdev->dev;
        hdmi->entity.owner = THIS_MODULE;
        hdmi->entity.ops = &sh_hdmi_ops;
@@ -1327,9 +1278,6 @@ 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:
@@ -1345,7 +1293,6 @@ ereqreg:
 erate:
        clk_put(hdmi->hdmi_clk);
 egetclk:
-       mutex_destroy(&hdmi->mutex);
        kfree(hdmi);
 
        return ret;
@@ -1359,8 +1306,6 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
 
        snd_soc_unregister_codec(&pdev->dev);
 
-       fb_unregister_client(&hdmi->notifier);
-
        /* No new work will be scheduled, wait for running ISR */
        free_irq(irq, hdmi);
        /* Wait for already scheduled work */
@@ -1371,7 +1316,6 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
        clk_put(hdmi->hdmi_clk);
        iounmap(hdmi->base);
        release_mem_region(res->start, resource_size(res));
-       mutex_destroy(&hdmi->mutex);
        kfree(hdmi);
 
        return 0;