summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev/mx3fb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-08 22:31:16 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-08 22:31:16 +0400
commit3f17ea6dea8ba5668873afa54628a91aaa3fb1c0 (patch)
treeafbeb2accd4c2199ddd705ae943995b143a0af02 /drivers/video/fbdev/mx3fb.c
parent1860e379875dfe7271c649058aeddffe5afd9d0d (diff)
parent1a5700bc2d10cd379a795fd2bb377a190af5acd4 (diff)
downloadlinux-3f17ea6dea8ba5668873afa54628a91aaa3fb1c0.tar.xz
Merge branch 'next' (accumulated 3.16 merge window patches) into master
Now that 3.15 is released, this merges the 'next' branch into 'master', bringing us to the normal situation where my 'master' branch is the merge window. * accumulated work in next: (6809 commits) ufs: sb mutex merge + mutex_destroy powerpc: update comments for generic idle conversion cris: update comments for generic idle conversion idle: remove cpu_idle() forward declarations nbd: zero from and len fields in NBD_CMD_DISCONNECT. mm: convert some level-less printks to pr_* MAINTAINERS: adi-buildroot-devel is moderated MAINTAINERS: add linux-api for review of API/ABI changes mm/kmemleak-test.c: use pr_fmt for logging fs/dlm/debug_fs.c: replace seq_printf by seq_puts fs/dlm/lockspace.c: convert simple_str to kstr fs/dlm/config.c: convert simple_str to kstr mm: mark remap_file_pages() syscall as deprecated mm: memcontrol: remove unnecessary memcg argument from soft limit functions mm: memcontrol: clean up memcg zoneinfo lookup mm/memblock.c: call kmemleak directly from memblock_(alloc|free) mm/mempool.c: update the kmemleak stack trace for mempool allocations lib/radix-tree.c: update the kmemleak stack trace for radix tree allocations mm: introduce kmemleak_update_trace() mm/kmemleak.c: use %u to print ->checksum ...
Diffstat (limited to 'drivers/video/fbdev/mx3fb.c')
-rw-r--r--drivers/video/fbdev/mx3fb.c85
1 files changed, 82 insertions, 3 deletions
diff --git a/drivers/video/fbdev/mx3fb.c b/drivers/video/fbdev/mx3fb.c
index 142e860fb527..c645a0a0c341 100644
--- a/drivers/video/fbdev/mx3fb.c
+++ b/drivers/video/fbdev/mx3fb.c
@@ -27,6 +27,7 @@
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/dma/ipu-dma.h>
+#include <linux/backlight.h>
#include <linux/platform_data/dma-imx.h>
#include <linux/platform_data/video-mx3fb.h>
@@ -241,6 +242,7 @@ struct mx3fb_data {
void __iomem *reg_base;
spinlock_t lock;
struct device *dev;
+ struct backlight_device *bl;
uint32_t h_start_width;
uint32_t v_start_width;
@@ -271,6 +273,71 @@ struct mx3fb_info {
struct fb_var_screeninfo cur_var; /* current var info */
};
+static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value);
+static u32 sdc_get_brightness(struct mx3fb_data *mx3fb);
+
+static int mx3fb_bl_get_brightness(struct backlight_device *bl)
+{
+ struct mx3fb_data *fbd = bl_get_data(bl);
+
+ return sdc_get_brightness(fbd);
+}
+
+static int mx3fb_bl_update_status(struct backlight_device *bl)
+{
+ struct mx3fb_data *fbd = bl_get_data(bl);
+ int brightness = bl->props.brightness;
+
+ if (bl->props.power != FB_BLANK_UNBLANK)
+ brightness = 0;
+ if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ fbd->backlight_level = (fbd->backlight_level & ~0xFF) | brightness;
+
+ sdc_set_brightness(fbd, fbd->backlight_level);
+
+ return 0;
+}
+
+static const struct backlight_ops mx3fb_lcdc_bl_ops = {
+ .update_status = mx3fb_bl_update_status,
+ .get_brightness = mx3fb_bl_get_brightness,
+};
+
+static void mx3fb_init_backlight(struct mx3fb_data *fbd)
+{
+ struct backlight_properties props;
+ struct backlight_device *bl;
+
+ if (fbd->bl)
+ return;
+
+ memset(&props, 0, sizeof(struct backlight_properties));
+ props.max_brightness = 0xff;
+ props.type = BACKLIGHT_RAW;
+ sdc_set_brightness(fbd, fbd->backlight_level);
+
+ bl = backlight_device_register("mx3fb-bl", fbd->dev, fbd,
+ &mx3fb_lcdc_bl_ops, &props);
+ if (IS_ERR(bl)) {
+ dev_err(fbd->dev, "error %ld on backlight register\n",
+ PTR_ERR(bl));
+ return;
+ }
+
+ fbd->bl = bl;
+ bl->props.power = FB_BLANK_UNBLANK;
+ bl->props.fb_blank = FB_BLANK_UNBLANK;
+ bl->props.brightness = mx3fb_bl_get_brightness(bl);
+}
+
+static void mx3fb_exit_backlight(struct mx3fb_data *fbd)
+{
+ if (fbd->bl)
+ backlight_device_unregister(fbd->bl);
+}
+
static void mx3fb_dma_done(void *);
/* Used fb-mode and bpp. Can be set on kernel command line, therefore file-static. */
@@ -628,6 +695,16 @@ static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t a
return 0;
}
+static u32 sdc_get_brightness(struct mx3fb_data *mx3fb)
+{
+ u32 brightness;
+
+ brightness = mx3fb_read_reg(mx3fb, SDC_PWM_CTRL);
+ brightness = (brightness >> 16) & 0xFF;
+
+ return brightness;
+}
+
static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
{
dev_dbg(mx3fb->dev, "%s: value = %d\n", __func__, value);
@@ -1496,7 +1573,7 @@ static int mx3fb_probe(struct platform_device *pdev)
if (!sdc_reg)
return -EINVAL;
- mx3fb = kzalloc(sizeof(*mx3fb), GFP_KERNEL);
+ mx3fb = devm_kzalloc(&pdev->dev, sizeof(*mx3fb), GFP_KERNEL);
if (!mx3fb)
return -ENOMEM;
@@ -1534,6 +1611,8 @@ static int mx3fb_probe(struct platform_device *pdev)
if (ret < 0)
goto eisdc0;
+ mx3fb_init_backlight(mx3fb);
+
return 0;
eisdc0:
@@ -1542,7 +1621,6 @@ ersdc0:
dmaengine_put();
iounmap(mx3fb->reg_base);
eremap:
- kfree(mx3fb);
dev_err(dev, "mx3fb: failed to register fb\n");
return ret;
}
@@ -1557,11 +1635,12 @@ static int mx3fb_remove(struct platform_device *dev)
chan = &mx3_fbi->idmac_channel->dma_chan;
release_fbi(fbi);
+ mx3fb_exit_backlight(mx3fb);
+
dma_release_channel(chan);
dmaengine_put();
iounmap(mx3fb->reg_base);
- kfree(mx3fb);
return 0;
}