This commit is based on the following commit by Fabio Estevam:
  4344429 video: mxsfb: Introduce regulator support

Cc: Jean-Christophe Plagniol-Villard <[email protected]>
Cc: Tomi Valkeinen <[email protected]>
Cc: [email protected]
Cc: Sascha Hauer <[email protected]>
Cc: [email protected]
Cc: Eric BĂ©nard <[email protected]>
Signed-off-by: Denis Carikli <[email protected]>
---
ChangeLog v3->v4:
- Some code style fixes.
- Improved error handling in eremap.

ChangeLog v2->v3:
- The prints are now replaced with non line wrapped prints.
- The regulator retrival has been adapted to the new DT bindings which looks
  more like the IPUv3 ones.
- The regulator_is_enabled checks were kept, because regulator_disable do not
  do such check.
---
 drivers/video/mx3fb.c |   71 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 75087c8..fd8df64 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -27,6 +27,7 @@
 #include <linux/clk.h>
 #include <linux/mutex.h>
 #include <linux/dma/ipu-dma.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/platform_data/dma-imx.h>
 #include <linux/platform_data/video-mx3fb.h>
@@ -269,6 +270,7 @@ struct mx3fb_info {
        struct dma_async_tx_descriptor  *txd;
        dma_cookie_t                    cookie;
        struct scatterlist              sg[2];
+       struct regulator                *reg_lcd;
 
        struct fb_var_screeninfo        cur_var; /* current var info */
 };
@@ -1005,6 +1007,7 @@ static void __blank(int blank, struct fb_info *fbi)
        struct mx3fb_info *mx3_fbi = fbi->par;
        struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
        int was_blank = mx3_fbi->blank;
+       int ret;
 
        mx3_fbi->blank = blank;
 
@@ -1023,6 +1026,15 @@ static void __blank(int blank, struct fb_info *fbi)
        case FB_BLANK_HSYNC_SUSPEND:
        case FB_BLANK_NORMAL:
                sdc_set_brightness(mx3fb, 0);
+               if (mx3_fbi->reg_lcd) {
+                       if (regulator_is_enabled(mx3_fbi->reg_lcd)) {
+                               ret = regulator_disable(mx3_fbi->reg_lcd);
+                               if (ret)
+                                       dev_warn(fbi->device,
+                                                "lcd regulator disable failed 
with error: %d\n",
+                                                ret);
+                       }
+               }
                memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
                /* Give LCD time to update - enough for 50 and 60 Hz */
                msleep(25);
@@ -1030,6 +1042,15 @@ static void __blank(int blank, struct fb_info *fbi)
                break;
        case FB_BLANK_UNBLANK:
                sdc_enable_channel(mx3_fbi);
+               if (mx3_fbi->reg_lcd) {
+                       if (!regulator_is_enabled(mx3_fbi->reg_lcd)) {
+                               ret = regulator_enable(mx3_fbi->reg_lcd);
+                               if (ret)
+                                       dev_warn(fbi->device,
+                                                "lcd regulator enable failed 
with error: %d\n",
+                                                ret);
+                       }
+               }
                sdc_set_brightness(mx3fb, mx3fb->backlight_level);
                break;
        }
@@ -1206,6 +1227,7 @@ static int mx3fb_suspend(struct platform_device *pdev, 
pm_message_t state)
 {
        struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
        struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
+       int ret;
 
        console_lock();
        fb_set_suspend(mx3fb->fbi, 1);
@@ -1214,7 +1236,15 @@ static int mx3fb_suspend(struct platform_device *pdev, 
pm_message_t state)
        if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
                sdc_disable_channel(mx3_fbi);
                sdc_set_brightness(mx3fb, 0);
-
+               if (mx3_fbi->reg_lcd) {
+                       if (regulator_is_enabled(mx3_fbi->reg_lcd)) {
+                               ret = regulator_disable(mx3_fbi->reg_lcd);
+                               if (ret)
+                                       dev_warn(&pdev->dev,
+                                                "lcd regulator disable failed 
with error: %d\n",
+                                                ret);
+                       }
+               }
        }
        return 0;
 }
@@ -1226,10 +1256,20 @@ static int mx3fb_resume(struct platform_device *pdev)
 {
        struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
        struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
+       int ret;
 
        if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
                sdc_enable_channel(mx3_fbi);
                sdc_set_brightness(mx3fb, mx3fb->backlight_level);
+               if (mx3_fbi->reg_lcd) {
+                       if (!regulator_is_enabled(mx3_fbi->reg_lcd)) {
+                               ret = regulator_enable(mx3_fbi->reg_lcd);
+                               if (ret)
+                                       dev_warn(&pdev->dev,
+                                                "lcd regulator enable failed 
with error: %d\n",
+                                                ret);
+                       }
+               }
        }
 
        console_lock();
@@ -1373,6 +1413,7 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct 
idmac_channel *ichan)
        struct mx3fb_platform_data *mx3fb_pdata = dev->platform_data;
        struct device_node *np = dev->of_node;
        const char *name;
+       const char *regulator_name;
        const char *ipu_disp_format;
        unsigned int irq;
        struct fb_info *fbi;
@@ -1389,6 +1430,9 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct 
idmac_channel *ichan)
                        return -EINVAL;
                }
 
+               of_property_read_string(display_np, "regulator-name",
+                                       &regulator_name);
+
                of_property_read_string(display_np, "interface-pix-fmt",
                                        &ipu_disp_format);
                if (!ipu_disp_format) {
@@ -1503,6 +1547,25 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct 
idmac_channel *ichan)
        if (ret < 0)
                goto erfb;
 
+       /* In dt mode,
+        * using devm_regulator_get would require that the proprety referencing
+        * the regulator phandle has to be inside the mx3fb node.
+        */
+       if (np) {
+               if (regulator_name)
+                       mx3fbi->reg_lcd = regulator_get(NULL, regulator_name);
+       } else {
+               mx3fbi->reg_lcd = devm_regulator_get(dev, "lcd");
+       }
+
+       if (IS_ERR(mx3fbi->reg_lcd)) {
+               dev_warn(mx3fb->dev, "Operating without regulator \"lcd\"\n");
+               mx3fbi->reg_lcd = NULL;
+       } else {
+               dev_info(mx3fb->dev, "Using \"%s\" Regulator\n",
+                        regulator_name);
+       }
+
        return 0;
 
 erfb:
@@ -1569,6 +1632,7 @@ static int mx3fb_probe(struct platform_device *pdev)
        dma_cap_mask_t mask;
        struct dma_chan *chan;
        struct dma_chan_request rq;
+       struct mx3fb_info *mx3_fbi;
 
        /*
         * Display Interface (DI) and Synchronous Display Controller (SDC)
@@ -1624,6 +1688,11 @@ ersdc0:
        dmaengine_put();
        iounmap(mx3fb->reg_base);
 eremap:
+       if (mx3fb->fbi) {
+               mx3_fbi = mx3fb->fbi->par;
+               if (mx3_fbi->reg_lcd)
+                       regulator_put(mx3_fbi->reg_lcd);
+       }
        kfree(mx3fb);
        dev_err(dev, "mx3fb: failed to register fb\n");
        return ret;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to