* Re: [PATCH v10 2/6] backlight: Add support Skyworks SKY81452 backlight driver
From: Oliver Neukum @ 2014-12-03 10:02 UTC (permalink / raw)
To: gyungoh
Cc: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
pawel.moll, mark.rutland, ijc+devicetree, galak, trivial, akpm,
jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
matti.vaittinen, broonie, jason, heiko, shawn.guo,
florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-3-git-send-email-jack.yoo@skyworksinc.com>
On Wed, 2014-12-03 at 16:05 +0900, gyungoh@gmail.com wrote:
> +static ssize_t sky81452_bl_store_enable(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t
> count)
> +{
> + struct regmap *regmap = bl_get_data(to_backlight_device(dev));
> + unsigned long value;
> + int ret;
> +
> + ret = kstrtoul(buf, 16, &value);
> + if (IS_ERR_VALUE(ret))
> + return ret;
> +
> + ret = regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
> + value << CTZ(SKY81452_EN));
No range checking for value?
> + if (IS_ERR_VALUE(ret))
> + return ret;
> +
> + return count;
> +}
Regards
Oliver
--
Oliver Neukum <oneukum@suse.de>
^ permalink raw reply
* Re: [PATCHv2 0/4] LS1021A: Add dcfb framebuffer driver support.
From: Arnd Bergmann @ 2014-12-03 9:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>
On Wednesday 03 December 2014 17:15:58 Xiubo Li wrote:
> Framebuffer driver for the Freescale SoC Display Controller.
>
>
> Change in V2:
> - Use the native-mode timing as default.
> - Add to_fsl_private().
<standard reply>
We try to not have any new framebuffer drivers. Please consider making
this a DRM/KMS driver instead.
</standard reply>
Arnd
^ permalink raw reply
* [PATCHv2 4/4] ARM: ls1021a: dts: Add and enable dt node for dcfb.
From: Xiubo Li @ 2014-12-03 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>
On LS1021A TWR board, the TFT LCD panel is WQVGA "480x272", and
the bpp is 24.
Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
arch/arm/boot/dts/ls1021a-twr.dts | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
index a2c591e..3602286 100644
--- a/arch/arm/boot/dts/ls1021a-twr.dts
+++ b/arch/arm/boot/dts/ls1021a-twr.dts
@@ -58,6 +58,32 @@
};
};
+&dcfb {
+ display = <&display>;
+ status = "okay";
+
+ display: display@0 {
+ bits-per-pixel = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: nl4827hc19 {
+ clock-frequency = <10870000>;
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <2>;
+ hfront-porch = <2>;
+ vback-porch = <2>;
+ vfront-porch = <2>;
+ hsync-len = <41>;
+ vsync-len = <4>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
+ };
+};
+
&dspi1 {
bus-num = <0>;
status = "okay";
--
2.1.0.27.g96db324
^ permalink raw reply related
* [PATCHv2 3/4] ARM: ls1021a: dtsi: Add dt node support for dcfb.
From: Xiubo Li @ 2014-12-03 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>
On LS1021A SoC, the dcfb device is in BE mode.
Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
arch/arm/boot/dts/ls1021a.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index c70bb27..740a04e 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -383,6 +383,16 @@
<&platform_clk 1>;
};
+ dcfb: dcfb@2ce0000 {
+ compatible = "fsl,ls1021a-dcfb";
+ reg = <0x0 0x2ce0000 0x0 0x10000>;
+ clocks = <&platform_clk 0>;
+ clock-names = "dcfb";
+ scfg-controller = <&scfg>;
+ big-endian;
+ status = "disabled";
+ };
+
mdio0: mdio@2d24000 {
compatible = "gianfar";
device_type = "mdio";
--
2.1.0.27.g96db324
^ permalink raw reply related
* [PATCHv2 2/4] video: fsl-dcfb: Add devicetree binding support
From: Xiubo Li @ 2014-12-03 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>
Add devicetree binding support for fsl-dcfb framebuffer driver. It
uses the generic display bindings and helper functions.
Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
.../devicetree/bindings/video/fsl,dcfb.txt | 52 ++++++++++++++++++++++
1 file changed, 52 insertions(+)
create mode 100644 Documentation/devicetree/bindings/video/fsl,dcfb.txt
diff --git a/Documentation/devicetree/bindings/video/fsl,dcfb.txt b/Documentation/devicetree/bindings/video/fsl,dcfb.txt
new file mode 100644
index 0000000..2f3d02b
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/fsl,dcfb.txt
@@ -0,0 +1,52 @@
+* Freescale Simple Display Controller FB Driver
+
+== For dcfb node =+Required properties:
+- compatible: Should be one of "fsl,ls1021a-dcfb".
+- reg: Address and length of the register set for dcfb.
+- clocks: From common clock binding: handle to dcfb clock.
+- clock-names: From common clock binding: Shall be "dcfb".
+- display: The phandle to display node.
+
+Optional properties:
+- scfg-controller: The phandle of scfg node.
+
+== For display sub-node =+Required properties:
+- bits-per-pixel: <16> for RGB565,
+ <24> for RGB888,
+ <32> for RGB8888.
+
+Required timing node for dispplay sub-node:
+- display-timings: Refer to binding doc display-timing.txt for details.
+
+Examples:
+dcfb: dcfb@2ce0000 {
+ compatible = "fsl,ls1021a-dcfb";
+ reg = <0x0 0x2ce0000 0x0 0x10000>;
+ clocks = <&platform_clk 0>;
+ clock-names = "dcfb";
+ scfg-controller = <&scfg>;
+ display = <&display>;
+
+ display: display@0 {
+ bits-per-pixel = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: nl4827hc19 {
+ clock-frequency = <10870000>;
+ hactive = <480>;
+ vactive = <272>;
+ hback-porch = <2>;
+ hfront-porch = <2>;
+ vback-porch = <1>;
+ vfront-porch = <1>;
+ hsync-len = <41>;
+ vsync-len = <2>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
+ };
+};
--
2.1.0.27.g96db324
^ permalink raw reply related
* [PATCHv2 1/4] video: fsl-dcfb: Add dcfb framebuffer driver for LS1021A platform
From: Xiubo Li @ 2014-12-03 9:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1417598162-40433-1-git-send-email-Li.Xiubo@freescale.com>
The Display Controller module is a system master that fetches graphics
stored in internal/external memory and displays them on a TFT LCD panel.
A wide range of panel sizes is supported and the timing of the interface
signals is configurable.
The dcfb has these features:
o Full RGB888 output to TFT LCD panel.
o Optional output to system memory dependent on implementation.
o Supports Programmable panel size upto a maximum of 2032x2047. The actual
resolution supported depends upon the pixel clock and bus bandwidth
available.
o Gamma correction with 8-bit resolution on each color component.
o Dedicated memory blocks to store a cursor and Color Look Up Tables(CLUTs).
o Temporal Dithering.
Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
drivers/video/fbdev/Kconfig | 19 +
drivers/video/fbdev/Makefile | 1 +
drivers/video/fbdev/fsl-dcfb.c | 814 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 834 insertions(+)
create mode 100644 drivers/video/fbdev/fsl-dcfb.c
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 4916c97..460fe39 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -1948,6 +1948,25 @@ config FB_MBX_DEBUG
If unsure, say N.
+config FB_FSL_DCFB
+ tristate "Freescale Display Control Framebuffer Support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
+ select REGMAP_MMIO
+ ---help---
+ Framebuffer driver for the Freescale SoC Display Control.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want).
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/kbuild/modules.txt>.
+
+ If unsure, say N.
+
config FB_FSL_DIU
tristate "Freescale DIU framebuffer support"
depends on FB && FSL_SOC
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index 1979aff..9015138 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -109,6 +109,7 @@ obj-$(CONFIG_FB_SH7760) += sh7760fb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
obj-$(CONFIG_FB_S3C) += s3c-fb.o
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
+obj-$(CONFIG_FB_FSL_DCFB) += fsl-dcfb.o
obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
diff --git a/drivers/video/fbdev/fsl-dcfb.c b/drivers/video/fbdev/fsl-dcfb.c
new file mode 100644
index 0000000..c3843bf
--- /dev/null
+++ b/drivers/video/fbdev/fsl-dcfb.c
@@ -0,0 +1,814 @@
+/*
+ * Copyright 2012-2014 Freescale Semiconductor, Inc.
+ *
+ * Freescale Dispaly Controller Framebuffer Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fb.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+
+#define FSL_SCFG_CTRL 0x28
+#define FSL_SCFG_PIXEL_EN BIT(31)
+
+#define FSL_DCFB_MODE 0x10
+#define FSL_DCFB_BGND 0x14
+#define FSL_DCFB_FIX_SIZE 0x18
+#define FSL_DCFB_HSYN 0x1c
+#define FSL_DCFB_VSYN 0x20
+#define FSL_DCFB_SP 0x24
+#define FSL_DCFB_TS 0x28
+#define FSL_DCFB_DIV_RATIO 0x54
+#define FSL_DCFB_UPDATE 0xcc
+#define FSL_DCFB_VAR_SIZE 0x200
+#define FSL_DCFB_POS 0x204
+#define FSL_DCFB_BASE 0x208
+#define FSL_DCFB_CTRL 0x20c
+#define FSL_DCFB_CKMAX 0x210
+#define FSL_DCFB_CKMIN 0x214
+#define FSL_DCFB_FCOLOR 0x21c
+#define FSL_DCFB_BCOLOR 0x220
+#define FSL_DCFB_SKIP 0x224
+#define FSL_DCFB_MAX 0x300
+
+#define FSL_DCFB_HSYN_BP(x) ((x) << 22)
+#define FSL_DCFB_HSYN_PW(x) ((x) << 11)
+#define FSL_DCFB_HSYN_FP(x) (x)
+#define FSL_DCFB_VSYN_BP(x) ((x) << 22)
+#define FSL_DCFB_VSYN_PW(x) ((x) << 11)
+#define FSL_DCFB_VSYN_FP(x) (x)
+
+#define FSL_DCFB_SP_VS BIT(1)
+#define FSL_DCFB_SP_HS BIT(0)
+
+#define FSL_DCFB_TS_LBV(x) ((x) << 16)
+#define FSL_DCFB_TS_OBH(x) ((x) << 8)
+#define FSL_DCFB_TS_OBL(x) (x)
+
+#define FSL_DCFB_UPDATE_MODE BIT(31)
+#define FSL_DCFB_UPDATE_READREG BIT(30)
+
+#define FSL_DCFB_VAR_SIZE_H(x) ((x) << 16)
+#define FSL_DCFB_VAR_SIZE_W(x) (x)
+
+#define FSL_DCFB_POSY(x) ((x) << 16)
+#define FSL_DCFB_POSX(x) (x)
+
+#define FSL_DCFB_CTRL_EN BIT(31)
+#define FSL_DCFB_CTRL_TILE_EN BIT(30)
+#define FSL_DCFB_CTRL_DATA_SEL_CLUT BIT(29)
+#define FSL_DCFB_CTRL_SAFETY_EN BIT(28)
+#define FSL_DCFB_CTRL_TRANS(x) ((x) << 20)
+#define FSL_DCFB_CTRL_BPP(x) ((x) << 16)
+#define FSL_DCFB_CTRL_RLE_EN BIT(15)
+#define FSL_DCFB_CTRL_LUOFFS(x) ((x) << 4)
+#define FSL_DCFB_CTRL_BB_ON BIT(2)
+
+#define FSL_DCFB_CKMAX_R(x) ((x) << 16)
+#define FSL_DCFB_CKMAX_G(x) ((x) << 8)
+#define FSL_DCFB_CKMAX_B(x) (x)
+
+#define FSL_DCFB_CKMIN_R(x) ((x) << 16)
+#define FSL_DCFB_CKMIN_G(x) ((x) << 8)
+#define FSL_DCFB_CKMIN_B(x) (x)
+
+#define FSL_DCFB_TILE_SIZE_W(x) ((x) << 16)
+#define FSL_DCFB_TILE_SIZE_H(x) (x)
+
+#define FSL_DCFB_FCOLOR_OFF(x) (x)
+#define FSL_DCFB_BCOLOR_OFF(x) (x)
+
+#define FSL_DCFB_MODE_BITER(x) ((x) << 20)
+#define FSL_DCFB_MODE_RASTER_EN BIT(14)
+#define FSL_DCFB_MODE_MODE(x) (x)
+#define FSL_DCFB_MODE_MODE_MASK 0x03
+
+#define FSL_DCFB_BGND_R(x) ((x) << 16)
+#define FSL_DCFB_BGND_G(x) ((x) << 8)
+#define FSL_DCFB_BGND_B(x) (x)
+
+#define FSL_DCFB_FIX_SIZE_Y(x) ((x) << 16)
+#define FSL_DCFB_FIX_SIZE_X(x) (x)
+
+enum fsl_dcfb_fmt {
+ FSL_DCFB_RGB565 = 4,
+ FSL_DCFB_RGB888,
+ FSL_DCFB_ARGB8888,
+};
+
+enum fsl_dcfb_mode {
+ FSL_DCFB_MOD_OFF = 0,
+ FSL_DCFB_MOD_NORMAL,
+ FSL_DCFB_MOD_TEST,
+ FSL_DCFB_MOD_COLORBAR,
+};
+
+struct fsl_dcfb_fb_private {
+ struct fb_info *fsl_dcfb_info;
+ struct device *dev;
+ struct regmap *regmap;
+ struct clk *clk;
+};
+
+struct fsl_dcfb_fb_info {
+ unsigned long pseudo_palette[16];
+ unsigned int count;
+ struct fsl_dcfb_fb_private *parent;
+};
+
+static inline struct fsl_dcfb_fb_private *to_fsl_private(struct fb_info *info)
+{
+ struct fsl_dcfb_fb_info *fsl_info = info->par;
+
+ return (struct fsl_dcfb_fb_private *)fsl_info->parent;
+}
+
+static int fsl_dcfb_get_bpp(unsigned int bits_per_pixel)
+{
+ int bpp;
+
+ switch (bits_per_pixel) {
+ case 16:
+ bpp = FSL_DCFB_RGB565;
+ break;
+ case 24:
+ bpp = FSL_DCFB_RGB888;
+ break;
+ case 32:
+ bpp = FSL_DCFB_ARGB8888;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return bpp;
+}
+
+static int fsl_dcfb_set_panel(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+ int bpp;
+
+ regmap_write(dcfb->regmap, FSL_DCFB_VAR_SIZE,
+ FSL_DCFB_VAR_SIZE_H(var->yres) |
+ FSL_DCFB_VAR_SIZE_W(var->xres));
+ regmap_write(dcfb->regmap, FSL_DCFB_POS,
+ FSL_DCFB_POSY(0) | FSL_DCFB_POSX(0));
+
+ regmap_write(dcfb->regmap, FSL_DCFB_BASE, info->fix.smem_start);
+
+ bpp = fsl_dcfb_get_bpp(var->bits_per_pixel);
+ if (bpp < 0) {
+ dev_err(dcfb->dev, "unsupported color depth: %u\n",
+ var->bits_per_pixel);
+ return bpp;
+ }
+
+ regmap_write(dcfb->regmap, FSL_DCFB_CTRL, FSL_DCFB_CTRL_EN |
+ FSL_DCFB_CTRL_TRANS(0xFF) | FSL_DCFB_CTRL_BPP(bpp));
+ regmap_write(dcfb->regmap, FSL_DCFB_CKMAX, FSL_DCFB_CKMAX_R(0xFF) |
+ FSL_DCFB_CKMAX_G(0xFF) | FSL_DCFB_CKMAX_B(0xFF));
+ regmap_write(dcfb->regmap, FSL_DCFB_CKMIN, FSL_DCFB_CKMIN_R(0) |
+ FSL_DCFB_CKMIN_G(0) | FSL_DCFB_CKMIN_B(0));
+
+ regmap_write(dcfb->regmap, FSL_DCFB_FCOLOR, FSL_DCFB_FCOLOR_OFF(0));
+ regmap_write(dcfb->regmap, FSL_DCFB_BCOLOR, FSL_DCFB_BCOLOR_OFF(0));
+
+ regmap_write(dcfb->regmap, FSL_DCFB_UPDATE, FSL_DCFB_UPDATE_READREG);
+
+ return 0;
+}
+
+static int fsl_dcfb_reset_panel(struct fsl_dcfb_fb_private *dcfb)
+{
+ regmap_write(dcfb->regmap, FSL_DCFB_VAR_SIZE, 0x0);
+ regmap_write(dcfb->regmap, FSL_DCFB_POS, 0x0);
+ regmap_write(dcfb->regmap, FSL_DCFB_BASE, 0x0);
+ regmap_write(dcfb->regmap, FSL_DCFB_CTRL, 0x0);
+ regmap_write(dcfb->regmap, FSL_DCFB_CKMAX, 0x0);
+ regmap_write(dcfb->regmap, FSL_DCFB_CKMIN, 0x0);
+ regmap_write(dcfb->regmap, FSL_DCFB_FCOLOR, 0x0);
+ regmap_write(dcfb->regmap, FSL_DCFB_BCOLOR, 0x0);
+ regmap_write(dcfb->regmap, FSL_DCFB_SKIP, 0x0);
+
+ regmap_write(dcfb->regmap, FSL_DCFB_UPDATE, FSL_DCFB_UPDATE_READREG);
+
+ return 0;
+}
+
+static void fsl_dcfb_modeset(struct fsl_dcfb_fb_private *dcfb,
+ enum fsl_dcfb_mode mode)
+{
+ regmap_update_bits(dcfb->regmap, FSL_DCFB_MODE,
+ FSL_DCFB_MODE_MODE_MASK,
+ FSL_DCFB_MODE_MODE(mode));
+}
+
+static int fsl_dcfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+
+ if (var->xoffset + info->var.xres > info->var.xres_virtual)
+ var->xoffset = info->var.xres_virtual - info->var.xres;
+
+ if (var->yoffset + info->var.yres > info->var.yres_virtual)
+ var->yoffset = info->var.yres_virtual - info->var.yres;
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ var->red.length = 5;
+ var->red.offset = 11;
+ var->red.msb_right = 0;
+
+ var->green.length = 6;
+ var->green.offset = 5;
+ var->green.msb_right = 0;
+
+ var->blue.length = 5;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ case 24:
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ case 32:
+ var->red.length = 8;
+ var->red.offset = 16;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 8;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 8;
+ var->transp.offset = 24;
+ var->transp.msb_right = 0;
+ break;
+ default:
+ dev_err(dcfb->dev, "unsupported color depth: %u\n",
+ var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fsl_dcfb_alloc_mem(struct fb_info *info)
+{
+ struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+ u32 smem_len = info->fix.line_length * info->var.yres_virtual;
+
+ info->fix.smem_len = smem_len;
+
+ info->screen_base = dma_alloc_writecombine(info->device,
+ info->fix.smem_len, (dma_addr_t *)&info->fix.smem_start,
+ GFP_KERNEL);
+ if (!info->screen_base) {
+ dev_err(dcfb->dev, "unable to allocate fb memory\n");
+ return -ENOMEM;
+ }
+
+ memset(info->screen_base, 0, info->fix.smem_len);
+
+ return 0;
+}
+
+static void fsl_dcfb_free_mem(struct fb_info *info)
+{
+ if (!info->screen_base)
+ return;
+
+ dma_free_writecombine(info->device, info->fix.smem_len,
+ info->screen_base, info->fix.smem_start);
+
+ info->screen_base = NULL;
+ info->fix.smem_start = 0;
+ info->fix.smem_len = 0;
+}
+
+static int fsl_dcfb_set_par(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+ unsigned int div, len;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->accel = FB_ACCEL_NONE;
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->xpanstep = fix->ypanstep = 1;
+
+ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+ len = info->var.yres_virtual * info->fix.line_length;
+ if (len != info->fix.smem_len) {
+ if (info->fix.smem_start)
+ fsl_dcfb_free_mem(info);
+
+ if (fsl_dcfb_alloc_mem(info)) {
+ dev_err(dcfb->dev, "unable to allocate FB memory\n");
+ return -ENOMEM;
+ }
+ }
+
+ div = KHZ2PICOS(clk_get_rate(dcfb->clk) / 1000);
+ regmap_write(dcfb->regmap, FSL_DCFB_DIV_RATIO,
+ info->var.pixclock / div);
+
+ regmap_write(dcfb->regmap, FSL_DCFB_FIX_SIZE,
+ FSL_DCFB_FIX_SIZE_Y(var->yres) |
+ FSL_DCFB_FIX_SIZE_X(var->xres / 16));
+
+ regmap_write(dcfb->regmap, FSL_DCFB_HSYN,
+ FSL_DCFB_HSYN_BP(var->left_margin) |
+ FSL_DCFB_HSYN_PW(var->hsync_len) |
+ FSL_DCFB_HSYN_FP(var->right_margin));
+
+ regmap_write(dcfb->regmap, FSL_DCFB_VSYN,
+ FSL_DCFB_VSYN_BP(var->upper_margin) |
+ FSL_DCFB_VSYN_PW(var->vsync_len) |
+ FSL_DCFB_VSYN_FP(var->lower_margin));
+
+ regmap_write(dcfb->regmap, FSL_DCFB_SP,
+ FSL_DCFB_SP_VS | FSL_DCFB_SP_HS);
+
+ regmap_write(dcfb->regmap, FSL_DCFB_BGND, FSL_DCFB_BGND_R(0) |
+ FSL_DCFB_BGND_G(0) | FSL_DCFB_BGND_B(0));
+
+ regmap_write(dcfb->regmap, FSL_DCFB_MODE,
+ FSL_DCFB_MODE_BITER(1) | FSL_DCFB_MODE_RASTER_EN);
+
+ regmap_write(dcfb->regmap, FSL_DCFB_TS, FSL_DCFB_TS_LBV(0x03) |
+ FSL_DCFB_TS_OBH(0x78) | FSL_DCFB_TS_OBL(0x0A));
+
+ regmap_write(dcfb->regmap, FSL_DCFB_UPDATE, FSL_DCFB_UPDATE_READREG);
+
+ fsl_dcfb_modeset(dcfb, FSL_DCFB_MOD_NORMAL);
+ fsl_dcfb_set_panel(info);
+
+ return 0;
+}
+
+#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
+static int fsl_dcfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ int ret = 1;
+
+ /*
+ * If greyscale is true, then we convert the RGB value
+ * to greyscale no matter what visual we are using.
+ */
+ if (info->var.grayscale)
+ red = green = blue = (19595 * red + 38470 * green +
+ 7471 * blue) >> 16;
+
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ if (regno < 16) {
+ u32 *pal = info->pseudo_palette;
+ u32 value;
+
+ red = CNVT_TOHW(red, info->var.red.length);
+ green = CNVT_TOHW(green, info->var.green.length);
+ blue = CNVT_TOHW(blue, info->var.blue.length);
+ transp = CNVT_TOHW(transp, info->var.transp.length);
+
+ value = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+
+ pal[regno] = value;
+ ret = 0;
+ }
+ break;
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ break;
+ }
+
+ return ret;
+}
+#undef CNVT_TOHW
+
+static int fsl_dcfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+ unsigned long addr;
+ int offset;
+
+ if ((info->var.xoffset = var->xoffset) &&
+ (info->var.yoffset = var->yoffset))
+ return 0;
+
+ if ((var->xoffset + info->var.xres) > info->var.xres_virtual
+ || (var->yoffset + info->var.yres) > info->var.yres_virtual)
+ return -EINVAL;
+
+ info->var.xoffset = var->xoffset;
+ info->var.yoffset = var->yoffset;
+
+ if (var->vmode & FB_VMODE_YWRAP)
+ info->var.vmode |= FB_VMODE_YWRAP;
+ else
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+
+ offset = (info->var.yoffset * info->var.xres_virtual);
+ offset += info->var.xoffset;
+ addr = info->fix.smem_start +
+ (offset * (info->var.bits_per_pixel >> 3));
+
+ regmap_write(dcfb->regmap, FSL_DCFB_BASE, addr);
+ regmap_write(dcfb->regmap, FSL_DCFB_UPDATE, FSL_DCFB_UPDATE_READREG);
+
+ return 0;
+}
+
+static int fsl_dcfb_blank(int blank_mode, struct fb_info *info)
+{
+ struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+
+ switch (blank_mode) {
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_NORMAL:
+ fsl_dcfb_reset_panel(dcfb);
+ break;
+ case FB_BLANK_POWERDOWN:
+ fsl_dcfb_modeset(dcfb, FSL_DCFB_MOD_OFF);
+ break;
+ case FB_BLANK_UNBLANK:
+ fsl_dcfb_set_panel(info);
+ break;
+ }
+
+ return 0;
+}
+
+static int fsl_dcfb_open(struct fb_info *info, int user)
+{
+ struct fsl_dcfb_fb_info *fsl_info = info->par;
+ int ret = 0;
+
+ fsl_info->count++;
+ if (fsl_info->count = 1) {
+ fsl_dcfb_check_var(&info->var, info);
+ ret = fsl_dcfb_set_par(info);
+ if (ret < 0)
+ fsl_info->count--;
+ }
+
+ return ret;
+}
+
+static int fsl_dcfb_release(struct fb_info *info, int user)
+{
+ struct fsl_dcfb_fb_info *fsl_info = info->par;
+ struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+ int ret = 0;
+
+ fsl_info->count--;
+ if (fsl_info->count = 0)
+ ret = fsl_dcfb_reset_panel(dcfb);
+
+ return ret;
+}
+
+static struct fb_ops fsl_dcfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = fsl_dcfb_check_var,
+ .fb_set_par = fsl_dcfb_set_par,
+ .fb_setcolreg = fsl_dcfb_setcolreg,
+ .fb_blank = fsl_dcfb_blank,
+ .fb_pan_display = fsl_dcfb_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_open = fsl_dcfb_open,
+ .fb_release = fsl_dcfb_release,
+};
+
+static int fsl_dcfb_init_fbinfo(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct fsl_dcfb_fb_private *dcfb = to_fsl_private(info);
+ struct device_node *np = dcfb->dev->of_node;
+ struct device_node *dnp, *tnp;
+ struct display_timings *timings;
+ struct fb_videomode fb_vm;
+ int i, ret;
+
+ INIT_LIST_HEAD(&info->modelist);
+
+ dnp = of_parse_phandle(np, "display", 0);
+ if (!dnp) {
+ dev_err(dcfb->dev, "failed to find \"display\" phandle.\n");
+ return -ENODEV;
+ }
+
+ ret = of_property_read_u32(dnp, "bits-per-pixel",
+ &var->bits_per_pixel);
+ if (ret < 0) {
+ dev_err(dcfb->dev, "failed to get \"bits-per-pixel\" property.\n");
+ goto put_dnp;
+ }
+
+ timings = of_get_display_timings(dnp);
+ if (!timings) {
+ dev_err(dcfb->dev, "failed to get display timings\n");
+ return -ENODEV;
+ goto put_dnp;
+ }
+
+ tnp = of_find_node_by_name(dnp, "display-timings");
+ if (!tnp) {
+ dev_err(dcfb->dev, "failed to find \"display-timings\" node\n");
+ return -ENODEV;
+ goto put_dnp;
+ }
+
+ for (i = 0; i < of_get_child_count(tnp); i++) {
+ struct videomode vm;
+
+ ret = videomode_from_timings(timings, &vm, i);
+ if (ret < 0)
+ goto put_tnp;
+
+ ret = fb_videomode_from_videomode(&vm, &fb_vm);
+ if (ret < 0)
+ goto put_tnp;
+
+ fb_add_videomode(&fb_vm, &info->modelist);
+ }
+
+ ret = of_get_fb_videomode(dnp, &fb_vm, OF_USE_NATIVE_MODE);
+ if (ret)
+ goto put_dnp;
+
+ fb_videomode_to_var(&info->var, &fb_vm);
+ ret = fsl_dcfb_check_var(&info->var, info);
+
+put_tnp:
+ of_node_put(tnp);
+put_dnp:
+ of_node_put(dnp);
+
+ return ret;
+}
+
+static const struct regmap_config fsl_scfg_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+
+ .max_register = FSL_SCFG_CTRL,
+};
+
+static int scfg_config(struct fsl_dcfb_fb_private *dcfb, struct device_node *np)
+{
+ struct device_node *snp;
+ struct platform_device *pdev;
+ struct resource *res;
+ void __iomem *base;
+ struct regmap *regmap;
+ int ret = 0;
+
+ snp = of_parse_phandle(np, "scfg-controller", 0);
+ if (!snp)
+ return -ENODEV;
+
+ pdev = of_find_device_by_node(snp);
+ if (!pdev) {
+ ret = -ENODEV;
+ goto put_snp;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ goto put_snp;
+ }
+
+ base = ioremap(res->start, SZ_4K);
+ if (IS_ERR(base)) {
+ dev_err(&pdev->dev, "could not ioremap scfg resource\n");
+ ret = PTR_ERR(base);
+ goto put_snp;
+ }
+
+ regmap = regmap_init_mmio(&pdev->dev, base,
+ &fsl_scfg_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&pdev->dev, "regmap init failed\n");
+ ret = PTR_ERR(regmap);
+ goto ioremap;
+ }
+
+ regmap_write(regmap, FSL_SCFG_CTRL, FSL_SCFG_PIXEL_EN);
+
+ regmap_exit(regmap);
+ioremap:
+ iounmap(base);
+put_snp:
+ of_node_put(snp);
+
+ return ret;
+}
+
+static int fsl_dcfb_dev_init(struct device_node *np,
+ struct fsl_dcfb_fb_private *dcfb)
+{
+ int ret;
+
+ ret = scfg_config(dcfb, np);
+ if (ret) {
+ dev_err(dcfb->dev, "could not config scfg\n");
+ return -EINVAL;
+ }
+
+ return fsl_dcfb_reset_panel(dcfb);
+}
+
+static const struct regmap_config fsl_dcfb_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+
+ .max_register = FSL_DCFB_MAX,
+};
+
+static int fsl_dcfb_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct fsl_dcfb_fb_private *dcfb;
+ struct fsl_dcfb_fb_info *fsl_info;
+ struct fb_info *info;
+ struct resource *res;
+ void __iomem *base;
+ int ret = 0;
+
+ dcfb = devm_kzalloc(&pdev->dev,
+ sizeof(struct fsl_dcfb_fb_private), GFP_KERNEL);
+ if (!dcfb)
+ return -ENOMEM;
+
+ dcfb->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "could not get memory IO resource\n");
+ return -ENODEV;
+ }
+
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base)) {
+ dev_err(&pdev->dev, "could not ioremap resource\n");
+ return PTR_ERR(base);
+ }
+
+ dcfb->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
+ NULL, base, &fsl_dcfb_regmap_config);
+ if (IS_ERR(dcfb->regmap)) {
+ dev_err(&pdev->dev, "regmap init failed\n");
+ return PTR_ERR(dcfb->regmap);
+ }
+
+ dcfb->clk = devm_clk_get(&pdev->dev, "dcfb");
+ if (IS_ERR(dcfb->clk)) {
+ ret = PTR_ERR(dcfb->clk);
+ dev_err(&pdev->dev, "could not get clock\n");
+ return -EINVAL;
+ }
+ clk_prepare_enable(dcfb->clk);
+
+ fsl_dcfb_dev_init(np, dcfb);
+
+ dcfb->fsl_dcfb_info + framebuffer_alloc(sizeof(struct fsl_dcfb_fb_info), &pdev->dev);
+ if (!dcfb->fsl_dcfb_info) {
+ ret = -ENOMEM;
+ goto err_clk;
+ }
+
+ dcfb->fsl_dcfb_info->fix.smem_start = 0;
+
+ fsl_info = dcfb->fsl_dcfb_info->par;
+ fsl_info->count = 0,
+ fsl_info->parent = dcfb;
+
+ info = dcfb->fsl_dcfb_info;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->fbops = &fsl_dcfb_ops;
+ info->flags = FBINFO_FLAG_DEFAULT;
+ info->pseudo_palette = &fsl_info->pseudo_palette;
+
+ ret = fb_alloc_cmap(&info->cmap, 16, 0);
+ if (ret) {
+ ret = -ENOMEM;
+ goto err_mem;
+ }
+
+ ret = fsl_dcfb_init_fbinfo(info);
+ if (ret)
+ goto err_cmap;
+
+ ret = register_framebuffer(info);
+ if (ret < 0) {
+ dev_err(dcfb->dev, "failed to register framebuffer device\n");
+ goto err_cmap;
+ }
+
+ dev_set_drvdata(&pdev->dev, dcfb);
+
+ goto out;
+
+err_cmap:
+ fb_dealloc_cmap(&info->cmap);
+err_mem:
+ framebuffer_release(dcfb->fsl_dcfb_info);
+err_clk:
+ clk_disable_unprepare(dcfb->clk);
+out:
+ return ret;
+}
+
+static int fsl_dcfb_remove(struct platform_device *pdev)
+{
+ struct fsl_dcfb_fb_private *dcfb = dev_get_drvdata(&pdev->dev);
+ struct fb_info *info = dcfb->fsl_dcfb_info;
+
+ fsl_dcfb_modeset(dcfb, FSL_DCFB_MOD_OFF);
+ fsl_dcfb_free_mem(info);
+
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+ framebuffer_release(dcfb->fsl_dcfb_info);
+ clk_disable_unprepare(dcfb->clk);
+
+ return 0;
+}
+
+static struct of_device_id fsl_dcfb_dt_ids[] = {
+ { .compatible = "fsl,ls1021a-dcfb", },
+ {}
+};
+
+static struct platform_driver fsl_dcfb_driver = {
+ .driver = {
+ .name = "fsl-dcfb",
+ .owner = THIS_MODULE,
+ .of_match_table = fsl_dcfb_dt_ids,
+ },
+ .probe = fsl_dcfb_probe,
+ .remove = fsl_dcfb_remove,
+};
+
+module_platform_driver(fsl_dcfb_driver);
+
+MODULE_DESCRIPTION("Freescale Simple Display Controller FB Driver");
+MODULE_ALIAS("platform:fsl-dcfb");
+MODULE_LICENSE("GPL v2");
--
2.1.0.27.g96db324
^ permalink raw reply related
* [PATCHv2 0/4] LS1021A: Add dcfb framebuffer driver support.
From: Xiubo Li @ 2014-12-03 9:15 UTC (permalink / raw)
To: linux-arm-kernel
Framebuffer driver for the Freescale SoC Display Controller.
Change in V2:
- Use the native-mode timing as default.
- Add to_fsl_private().
Xiubo Li (4):
video: fsl-dcfb: Add dcfb framebuffer driver for LS1021A platform
video: fsl-dcfb: Add devicetree binding support
ARM: ls1021a: dtsi: Add dt node support for dcfb.
ARM: ls1021a: dts: Add and enable dt node for dcfb.
.../devicetree/bindings/video/fsl,dcfb.txt | 52 ++
arch/arm/boot/dts/ls1021a-twr.dts | 26 +
arch/arm/boot/dts/ls1021a.dtsi | 10 +
drivers/video/fbdev/Kconfig | 19 +
drivers/video/fbdev/Makefile | 1 +
drivers/video/fbdev/fsl-dcfb.c | 814 +++++++++++++++++++++
6 files changed, 922 insertions(+)
create mode 100644 Documentation/devicetree/bindings/video/fsl,dcfb.txt
create mode 100644 drivers/video/fbdev/fsl-dcfb.c
--
2.1.0.27.g96db324
^ permalink raw reply
* Re: [PATCH v10 2/6] backlight: Add support Skyworks SKY81452 backlight driver
From: Jingoo Han @ 2014-12-03 7:13 UTC (permalink / raw)
To: gyungoh, sameo, lee.jones, grant.likely, robh+dt, cooloney,
pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
matti.vaittinen, broonie, jason, heiko, shawn.guo,
florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree,
'Jingoo Han'
In-Reply-To: <1417590332-4912-3-git-send-email-jack.yoo@skyworksinc.com>
On Wednesday, December 03, 2014 4:05 PM, Gyungoh Yoo wrote:
>
> From: Gyungoh Yoo <jack.yoo@skyworksinc.com>
>
> Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Acked-by: Jingoo Han <jg1.han@samsung.com>
Best regards,
Jingoo Han
> ---
> Changes v10:
> Removed trivial get_brightness implementations
>
> Changes v9:
> Nothing
>
> Changes v8:
> Renamed property names for backlight with vendor prefix
> Modified gpio-enable property to generic property for GPIO
>
> Changes v7:
> Modified licensing text to GPLv2
>
> Changes v6:
> Added new line character at the end of line of dev_err()
>
> Changes v5:
> Move sky81452-backlight.h to include/linux/platform_data
>
> Changes v4:
> Reordering header files for readability
> Removed calling to backlight_device_unregister()
> Removed MODULE_VERSION()
> Modified license to GPLv2
>
> Changes v3:
> Modified DBG messages
>
> Changes v2:
> Added 'compatible' attribute in the driver
> Added message for exception or errors
>
> drivers/video/backlight/Kconfig | 10 +
> drivers/video/backlight/Makefile | 1 +
> drivers/video/backlight/sky81452-backlight.c | 334 +++++++++++++++++++++++
> include/linux/platform_data/sky81452-backlight.h | 46 ++++
> 4 files changed, 391 insertions(+)
> create mode 100644 drivers/video/backlight/sky81452-backlight.c
> create mode 100644 include/linux/platform_data/sky81452-backlight.h
>
> diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
> index 8d03924..2586fdd 100644
> --- a/drivers/video/backlight/Kconfig
> +++ b/drivers/video/backlight/Kconfig
> @@ -409,6 +409,16 @@ config BACKLIGHT_PANDORA
> If you have a Pandora console, say Y to enable the
> backlight driver.
>
> +config BACKLIGHT_SKY81452
> + tristate "Backlight driver for SKY81452"
> + depends on BACKLIGHT_CLASS_DEVICE && MFD_SKY81452
> + help
> + If you have a Skyworks SKY81452, say Y to enable the
> + backlight driver.
> +
> + To compile this driver as a module, choose M here: the module will
> + be called sky81452-backlight
> +
> config BACKLIGHT_TPS65217
> tristate "TPS65217 Backlight"
> depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
> diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
> index fcd50b73..d67073f 100644
> --- a/drivers/video/backlight/Makefile
> +++ b/drivers/video/backlight/Makefile
> @@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o
> obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
> obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
> obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
> +obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o
> obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
> obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
> obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
> diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-
> backlight.c
> new file mode 100644
> index 0000000..8105597
> --- /dev/null
> +++ b/drivers/video/backlight/sky81452-backlight.c
> @@ -0,0 +1,334 @@
> +/*
> + * sky81452-backlight.c SKY81452 backlight driver
> + *
> + * Copyright 2014 Skyworks Solutions Inc.
> + * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/backlight.h>
> +#include <linux/err.h>
> +#include <linux/gpio.h>
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/platform_data/sky81452-backlight.h>
> +#include <linux/slab.h>
> +
> +/* registers */
> +#define SKY81452_REG0 0x00
> +#define SKY81452_REG1 0x01
> +#define SKY81452_REG2 0x02
> +#define SKY81452_REG4 0x04
> +#define SKY81452_REG5 0x05
> +
> +/* bit mask */
> +#define SKY81452_CS 0xFF
> +#define SKY81452_EN 0x3F
> +#define SKY81452_IGPW 0x20
> +#define SKY81452_PWMMD 0x10
> +#define SKY81452_PHASE 0x08
> +#define SKY81452_ILIM 0x04
> +#define SKY81452_VSHRT 0x03
> +#define SKY81452_OCP 0x80
> +#define SKY81452_OTMP 0x40
> +#define SKY81452_SHRT 0x3F
> +#define SKY81452_OPN 0x3F
> +
> +#define SKY81452_DEFAULT_NAME "lcd-backlight"
> +#define SKY81452_MAX_BRIGHTNESS (SKY81452_CS + 1)
> +
> +#define CTZ(b) __builtin_ctz(b)
> +
> +static int sky81452_bl_update_status(struct backlight_device *bd)
> +{
> + const struct sky81452_bl_platform_data *pdata > + dev_get_platdata(bd->dev.parent);
> + const unsigned int brightness = (unsigned int)bd->props.brightness;
> + struct regmap *regmap = bl_get_data(bd);
> + int ret;
> +
> + if (brightness > 0) {
> + ret = regmap_write(regmap, SKY81452_REG0, brightness - 1);
> + if (IS_ERR_VALUE(ret))
> + return ret;
> +
> + return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
> + pdata->enable << CTZ(SKY81452_EN));
> + }
> +
> + return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN, 0);
> +}
> +
> +static const struct backlight_ops sky81452_bl_ops = {
> + .update_status = sky81452_bl_update_status,
> +};
> +
> +static ssize_t sky81452_bl_store_enable(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t count)
> +{
> + struct regmap *regmap = bl_get_data(to_backlight_device(dev));
> + unsigned long value;
> + int ret;
> +
> + ret = kstrtoul(buf, 16, &value);
> + if (IS_ERR_VALUE(ret))
> + return ret;
> +
> + ret = regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
> + value << CTZ(SKY81452_EN));
> + if (IS_ERR_VALUE(ret))
> + return ret;
> +
> + return count;
> +}
> +
> +static ssize_t sky81452_bl_show_open_short(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct regmap *regmap = bl_get_data(to_backlight_device(dev));
> + unsigned int reg, value = 0;
> + char tmp[3];
> + int i, ret;
> +
> + reg = !strcmp(attr->attr.name, "open") ? SKY81452_REG5 : SKY81452_REG4;
> + ret = regmap_read(regmap, reg, &value);
> + if (IS_ERR_VALUE(ret))
> + return ret;
> +
> + if (value & SKY81452_SHRT) {
> + *buf = 0;
> + for (i = 0; i < 6; i++) {
> + if (value & 0x01) {
> + sprintf(tmp, "%d ", i + 1);
> + strcat(buf, tmp);
> + }
> + value >>= 1;
> + }
> + strcat(buf, "\n");
> + } else {
> + strcpy(buf, "none\n");
> + }
> +
> + return strlen(buf);
> +}
> +
> +static ssize_t sky81452_bl_show_fault(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct regmap *regmap = bl_get_data(to_backlight_device(dev));
> + unsigned int value = 0;
> + int ret;
> +
> + ret = regmap_read(regmap, SKY81452_REG4, &value);
> + if (IS_ERR_VALUE(ret))
> + return ret;
> +
> + *buf = 0;
> +
> + if (value & SKY81452_OCP)
> + strcat(buf, "over-current ");
> +
> + if (value & SKY81452_OTMP)
> + strcat(buf, "over-temperature");
> +
> + strcat(buf, "\n");
> + return strlen(buf);
> +}
> +
> +static DEVICE_ATTR(enable, S_IWGRP | S_IWUSR, NULL, sky81452_bl_store_enable);
> +static DEVICE_ATTR(open, S_IRUGO, sky81452_bl_show_open_short, NULL);
> +static DEVICE_ATTR(short, S_IRUGO, sky81452_bl_show_open_short, NULL);
> +static DEVICE_ATTR(fault, S_IRUGO, sky81452_bl_show_fault, NULL);
> +
> +static struct attribute *sky81452_bl_attribute[] = {
> + &dev_attr_enable.attr,
> + &dev_attr_open.attr,
> + &dev_attr_short.attr,
> + &dev_attr_fault.attr,
> + NULL
> +};
> +
> +static const struct attribute_group sky81452_bl_attr_group = {
> + .attrs = sky81452_bl_attribute,
> +};
> +
> +#ifdef CONFIG_OF
> +static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
> + struct device *dev)
> +{
> + struct device_node *np = of_node_get(dev->of_node);
> + struct sky81452_bl_platform_data *pdata;
> + int ret;
> +
> + if (!np) {
> + dev_err(dev, "backlight node not found.\n");
> + return ERR_PTR(-ENODATA);
> + }
> +
> + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> + if (!pdata) {
> + of_node_put(np);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + of_property_read_string(np, "name", &pdata->name);
> + pdata->ignore_pwm = of_property_read_bool(np, "skyworks,ignore-pwm");
> + pdata->dpwm_mode = of_property_read_bool(np, "skyworks,dpwm-mode");
> + pdata->phase_shift = of_property_read_bool(np, "skyworks,phase-shift");
> + pdata->gpio_enable = of_get_gpio(np, 0);
> +
> + ret = of_property_read_u32(np, "skyworks,en-channels", &pdata->enable);
> + if (IS_ERR_VALUE(ret))
> + pdata->enable = SKY81452_EN >> CTZ(SKY81452_EN);
> +
> + ret = of_property_read_u32(np, "skyworks,short-detection-threshold",
> + &pdata->short_detection_threshold);
> + if (IS_ERR_VALUE(ret))
> + pdata->short_detection_threshold = 7;
> +
> + ret = of_property_read_u32(np, "skyworks,current-limit",
> + &pdata->boost_current_limit);
> + if (IS_ERR_VALUE(ret))
> + pdata->boost_current_limit = 2750;
> +
> + of_node_put(np);
> + return pdata;
> +}
> +#else
> +static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
> + struct device *dev)
> +{
> + return ERR_PTR(-EINVAL);
> +}
> +#endif
> +
> +static int sky81452_bl_init_device(struct regmap *regmap,
> + struct sky81452_bl_platform_data *pdata)
> +{
> + unsigned int value;
> +
> + value = pdata->ignore_pwm ? SKY81452_IGPW : 0;
> + value |= pdata->dpwm_mode ? SKY81452_PWMMD : 0;
> + value |= pdata->phase_shift ? 0 : SKY81452_PHASE;
> +
> + if (pdata->boost_current_limit = 2300)
> + value |= SKY81452_ILIM;
> + else if (pdata->boost_current_limit != 2750)
> + return -EINVAL;
> +
> + if (pdata->short_detection_threshold < 4 ||
> + pdata->short_detection_threshold > 7)
> + return -EINVAL;
> + value |= (7 - pdata->short_detection_threshold) << CTZ(SKY81452_VSHRT);
> +
> + return regmap_write(regmap, SKY81452_REG2, value);
> +}
> +
> +static int sky81452_bl_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct regmap *regmap = dev_get_drvdata(dev->parent);
> + struct sky81452_bl_platform_data *pdata = dev_get_platdata(dev);
> + struct backlight_device *bd;
> + struct backlight_properties props;
> + const char *name;
> + int ret;
> +
> + if (!pdata) {
> + pdata = sky81452_bl_parse_dt(dev);
> + if (IS_ERR(pdata))
> + return PTR_ERR(pdata);
> + }
> +
> + if (gpio_is_valid(pdata->gpio_enable)) {
> + ret = devm_gpio_request_one(dev, pdata->gpio_enable,
> + GPIOF_OUT_INIT_HIGH, "sky81452-en");
> + if (IS_ERR_VALUE(ret)) {
> + dev_err(dev, "failed to request GPIO. err=%d\n", ret);
> + return ret;
> + }
> + }
> +
> + ret = sky81452_bl_init_device(regmap, pdata);
> + if (IS_ERR_VALUE(ret)) {
> + dev_err(dev, "failed to initialize. err=%d\n", ret);
> + return ret;
> + }
> +
> + memset(&props, 0, sizeof(props));
> + props.max_brightness = SKY81452_MAX_BRIGHTNESS,
> + name = pdata->name ? pdata->name : SKY81452_DEFAULT_NAME;
> + bd = devm_backlight_device_register(dev, name, dev, regmap,
> + &sky81452_bl_ops, &props);
> + if (IS_ERR(bd)) {
> + dev_err(dev, "failed to register. err=%ld\n", PTR_ERR(bd));
> + return PTR_ERR(bd);
> + }
> +
> + platform_set_drvdata(pdev, bd);
> +
> + ret = sysfs_create_group(&bd->dev.kobj, &sky81452_bl_attr_group);
> + if (IS_ERR_VALUE(ret)) {
> + dev_err(dev, "failed to create attribute. err=%d\n", ret);
> + return ret;
> + }
> +
> + return ret;
> +}
> +
> +static int sky81452_bl_remove(struct platform_device *pdev)
> +{
> + const struct sky81452_bl_platform_data *pdata > + dev_get_platdata(&pdev->dev);
> + struct backlight_device *bd = platform_get_drvdata(pdev);
> +
> + sysfs_remove_group(&bd->dev.kobj, &sky81452_bl_attr_group);
> +
> + bd->props.power = FB_BLANK_UNBLANK;
> + bd->props.brightness = 0;
> + backlight_update_status(bd);
> +
> + if (gpio_is_valid(pdata->gpio_enable))
> + gpio_set_value_cansleep(pdata->gpio_enable, 0);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id sky81452_bl_of_match[] = {
> + { .compatible = "skyworks,sky81452-backlight", },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, sky81452_bl_of_match);
> +#endif
> +
> +static struct platform_driver sky81452_bl_driver = {
> + .driver = {
> + .name = "sky81452-backlight",
> + .of_match_table = of_match_ptr(sky81452_bl_of_match),
> + },
> + .probe = sky81452_bl_probe,
> + .remove = sky81452_bl_remove,
> +};
> +
> +module_platform_driver(sky81452_bl_driver);
> +
> +MODULE_DESCRIPTION("Skyworks SKY81452 backlight driver");
> +MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/platform_data/sky81452-backlight.h b/include/linux/platform_data/sky81452-
> backlight.h
> new file mode 100644
> index 0000000..1231e9b
> --- /dev/null
> +++ b/include/linux/platform_data/sky81452-backlight.h
> @@ -0,0 +1,46 @@
> +/*
> + * sky81452.h SKY81452 backlight driver
> + *
> + * Copyright 2014 Skyworks Solutions Inc.
> + * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _SKY81452_BACKLIGHT_H
> +#define _SKY81452_BACKLIGHT_H
> +
> +/**
> + * struct sky81452_platform_data
> + * @name: backlight driver name.
> + If it is not defined, default name is lcd-backlight.
> + * @gpio_enable:GPIO number which control EN pin
> + * @enable: Enable mask for current sink channel 1, 2, 3, 4, 5 and 6.
> + * @ignore_pwm: true if DPWMI should be ignored.
> + * @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode.
> + * @phase_shift:true is phase shift mode.
> + * @short_detecion_threshold: It should be one of 4, 5, 6 and 7V.
> + * @boost_current_limit: It should be one of 2300, 2750mA.
> + */
> +struct sky81452_bl_platform_data {
> + const char *name;
> + int gpio_enable;
> + unsigned int enable;
> + bool ignore_pwm;
> + bool dpwm_mode;
> + bool phase_shift;
> + unsigned int short_detection_threshold;
> + unsigned int boost_current_limit;
> +};
> +
> +#endif
> --
> 1.9.1
^ permalink raw reply
* [PATCH v10 6/6] devicetree: i2c: Add SKY81452 to the Trivial Devices list
From: gyungoh @ 2014-12-03 7:05 UTC (permalink / raw)
To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
matti.vaittinen, broonie, jason, heiko, shawn.guo,
florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>
From: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
---
Changes v10:
Nothing
Changes v9:
Nothing
Changes v8:
Nothing
Changes v7:
Nothing
Changes v6:
Nothing
Changes v5:
Nothing
Changes v4:
Nothing
Changes v3:
Nothing
Changes v2:
Add SKY81452 to the Trivial Devices list
Documentation/devicetree/bindings/i2c/trivial-devices.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index fbde415..122fa1e 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -77,6 +77,7 @@ ramtron,24c64 i2c serial eeprom (24cxx)
ricoh,rs5c372a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
samsung,24ad0xd1 S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power)
sii,s35390a 2-wire CMOS real-time clock
+skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
st-micro,24c256 i2c serial eeprom (24cxx)
stm,m41t00 Serial Access TIMEKEEPER
stm,m41t62 Serial real-time clock (RTC) with alarm
--
1.9.1
^ permalink raw reply related
* [PATCH v10 5/6] devicetree: Add vendor prefix for Skyworks Solutions, Inc.
From: gyungoh @ 2014-12-03 7:05 UTC (permalink / raw)
To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
matti.vaittinen, broonie, jason, heiko, shawn.guo,
florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>
From: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
---
Changes v10:
Nothing
Changes v9:
Nothing
Changes v8:
Nothing
Changes v7:
Nothing
Changes v6:
Nothing
Changes v5:
Nothing
Changes v4:
Nothing
Changes v3:
Nothing
Changes v2:
Added vendor prefix for Skyworks Solutions, Inc.
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index a344ec2..68143f0 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -140,6 +140,7 @@ sii Seiko Instruments, Inc.
silergy Silergy Corp.
sirf SiRF Technology, Inc.
sitronix Sitronix Technology Corporation
+skyworks Skyworks Solutions, Inc.
smsc Standard Microsystems Corporation
snps Synopsys, Inc.
solidrun SolidRun
--
1.9.1
^ permalink raw reply related
* [PATCH v10 4/6] devicetree: backlight: Add new SKY81452 backlight binding
From: gyungoh @ 2014-12-03 7:05 UTC (permalink / raw)
To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
matti.vaittinen, broonie, jason, heiko, shawn.guo,
florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>
From: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Acked-by: Bryan Wu <cooloney@gmail.com>
---
Changes v10:
Nothing
Changes v9:
Nothing
Changes v8:
Renamed property names for backlight with vendor prefix
Modified gpio-enable property to generic property for GPIO
Made up the example for backlight DT
Changes v7:
Nothing
Changes v6:
Nothing
Changes v5:
Nothing
Changes v4:
Nothing
Changes v3:
Nothing
Changes v2:
Added reg attribute for I2C slave address
.../video/backlight/sky81452-backlight.txt | 29 ++++++++++++++++++++++
1 file changed, 29 insertions(+)
create mode 100644 Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt
diff --git a/Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt b/Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt
new file mode 100644
index 0000000..8daebf5
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt
@@ -0,0 +1,29 @@
+SKY81452-backlight bindings
+
+Required properties:
+- compatible : Must be "skyworks,sky81452-backlight"
+
+Optional properties:
+- name : Name of backlight device. Default is 'lcd-backlight'.
+- gpios : GPIO to use to EN pin.
+ See Documentation/devicetree/bindings/gpio/gpio.txt
+- skyworks,en-channels : Enable mask for current sink channel 1 to 6.
+- skyworks,ignore-pwm : Ignore both PWM input
+- skyworks,dpwm-mode : Enable DPWM dimming mode, otherwise Analog dimming.
+- skyworks,phase-shift : Enable phase shift mode
+- skyworks,ovp-level : Over-voltage protection level.
+ Should be between 14 or 28V.
+- skyworks,short-detection-threshold : It should be one of 4, 5, 6 and 7V.
+- skyworks,current-limit : It should be 2300mA or 2750mA.
+
+Example:
+
+ backlight {
+ compatible = "skyworks,sky81452-backlight";
+ name = "pwm-backlight";
+ skyworks,en-channels = <0x3f>;
+ skyworks,ignore-pwm;
+ skyworks,phase-shift;
+ skyworks,ovp-level = <20>;
+ skyworks,current-limit = <2300>;
+ };
--
1.9.1
^ permalink raw reply related
* [PATCH v10 3/6] devicetree: mfd: Add new SKY81452 mfd binding
From: gyungoh @ 2014-12-03 7:05 UTC (permalink / raw)
To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
matti.vaittinen, broonie, jason, heiko, shawn.guo,
florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>
From: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
---
Changes v10:
Nothing
Changes v9:
Nothing
Changes v8:
Made up the example for backlight DT
Changes v7:
Nothing
Changes v6:
Nothing
Changes v5:
Changed DT for regulator : 'lout' node should be defined under 'regulator'
Removed compatible string from sky81452-regulator driver
Changes v4:
Nothing
Changes v3:
Nothing
Changes v2:
Added reg attribute for I2C slave address
Documentation/devicetree/bindings/mfd/sky81452.txt | 36 ++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/sky81452.txt
diff --git a/Documentation/devicetree/bindings/mfd/sky81452.txt b/Documentation/devicetree/bindings/mfd/sky81452.txt
new file mode 100644
index 0000000..ab71473
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/sky81452.txt
@@ -0,0 +1,36 @@
+SKY81452 bindings
+
+Required properties:
+- compatible : Must be "skyworks,sky81452"
+- reg : I2C slave address
+
+Required child nodes:
+- backlight : container node for backlight following the binding
+ in video/backlight/sky81452-backlight.txt
+- regulator : container node for regulators following the binding
+ in regulator/sky81452-regulator.txt
+
+Example:
+
+ sky81452@2c {
+ compatible = "skyworks,sky81452";
+ reg = <0x2c>;
+
+ backlight {
+ compatible = "skyworks,sky81452-backlight";
+ name = "pwm-backlight";
+ skyworks,en-channels = <0x3f>;
+ skyworks,ignore-pwm;
+ skyworks,phase-shift;
+ skyworks,ovp-level = <20>;
+ skyworks,current-limit = <2300>;
+ };
+
+ regulator {
+ lout {
+ regulator-name = "sky81452-lout";
+ regulator-min-microvolt = <4500000>;
+ regulator-max-microvolt = <8000000>;
+ };
+ };
+ };
--
1.9.1
^ permalink raw reply related
* [PATCH v10 2/6] backlight: Add support Skyworks SKY81452 backlight driver
From: gyungoh @ 2014-12-03 7:05 UTC (permalink / raw)
To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
matti.vaittinen, broonie, jason, heiko, shawn.guo,
florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>
From: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
---
Changes v10:
Removed trivial get_brightness implementations
Changes v9:
Nothing
Changes v8:
Renamed property names for backlight with vendor prefix
Modified gpio-enable property to generic property for GPIO
Changes v7:
Modified licensing text to GPLv2
Changes v6:
Added new line character at the end of line of dev_err()
Changes v5:
Move sky81452-backlight.h to include/linux/platform_data
Changes v4:
Reordering header files for readability
Removed calling to backlight_device_unregister()
Removed MODULE_VERSION()
Modified license to GPLv2
Changes v3:
Modified DBG messages
Changes v2:
Added 'compatible' attribute in the driver
Added message for exception or errors
drivers/video/backlight/Kconfig | 10 +
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/sky81452-backlight.c | 334 +++++++++++++++++++++++
include/linux/platform_data/sky81452-backlight.h | 46 ++++
4 files changed, 391 insertions(+)
create mode 100644 drivers/video/backlight/sky81452-backlight.c
create mode 100644 include/linux/platform_data/sky81452-backlight.h
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 8d03924..2586fdd 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -409,6 +409,16 @@ config BACKLIGHT_PANDORA
If you have a Pandora console, say Y to enable the
backlight driver.
+config BACKLIGHT_SKY81452
+ tristate "Backlight driver for SKY81452"
+ depends on BACKLIGHT_CLASS_DEVICE && MFD_SKY81452
+ help
+ If you have a Skyworks SKY81452, say Y to enable the
+ backlight driver.
+
+ To compile this driver as a module, choose M here: the module will
+ be called sky81452-backlight
+
config BACKLIGHT_TPS65217
tristate "TPS65217 Backlight"
depends on BACKLIGHT_CLASS_DEVICE && MFD_TPS65217
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index fcd50b73..d67073f 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o
obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
+obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c
new file mode 100644
index 0000000..8105597
--- /dev/null
+++ b/drivers/video/backlight/sky81452-backlight.c
@@ -0,0 +1,334 @@
+/*
+ * sky81452-backlight.c SKY81452 backlight driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/platform_data/sky81452-backlight.h>
+#include <linux/slab.h>
+
+/* registers */
+#define SKY81452_REG0 0x00
+#define SKY81452_REG1 0x01
+#define SKY81452_REG2 0x02
+#define SKY81452_REG4 0x04
+#define SKY81452_REG5 0x05
+
+/* bit mask */
+#define SKY81452_CS 0xFF
+#define SKY81452_EN 0x3F
+#define SKY81452_IGPW 0x20
+#define SKY81452_PWMMD 0x10
+#define SKY81452_PHASE 0x08
+#define SKY81452_ILIM 0x04
+#define SKY81452_VSHRT 0x03
+#define SKY81452_OCP 0x80
+#define SKY81452_OTMP 0x40
+#define SKY81452_SHRT 0x3F
+#define SKY81452_OPN 0x3F
+
+#define SKY81452_DEFAULT_NAME "lcd-backlight"
+#define SKY81452_MAX_BRIGHTNESS (SKY81452_CS + 1)
+
+#define CTZ(b) __builtin_ctz(b)
+
+static int sky81452_bl_update_status(struct backlight_device *bd)
+{
+ const struct sky81452_bl_platform_data *pdata + dev_get_platdata(bd->dev.parent);
+ const unsigned int brightness = (unsigned int)bd->props.brightness;
+ struct regmap *regmap = bl_get_data(bd);
+ int ret;
+
+ if (brightness > 0) {
+ ret = regmap_write(regmap, SKY81452_REG0, brightness - 1);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
+ pdata->enable << CTZ(SKY81452_EN));
+ }
+
+ return regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN, 0);
+}
+
+static const struct backlight_ops sky81452_bl_ops = {
+ .update_status = sky81452_bl_update_status,
+};
+
+static ssize_t sky81452_bl_store_enable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct regmap *regmap = bl_get_data(to_backlight_device(dev));
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul(buf, 16, &value);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ ret = regmap_update_bits(regmap, SKY81452_REG1, SKY81452_EN,
+ value << CTZ(SKY81452_EN));
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ return count;
+}
+
+static ssize_t sky81452_bl_show_open_short(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct regmap *regmap = bl_get_data(to_backlight_device(dev));
+ unsigned int reg, value = 0;
+ char tmp[3];
+ int i, ret;
+
+ reg = !strcmp(attr->attr.name, "open") ? SKY81452_REG5 : SKY81452_REG4;
+ ret = regmap_read(regmap, reg, &value);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ if (value & SKY81452_SHRT) {
+ *buf = 0;
+ for (i = 0; i < 6; i++) {
+ if (value & 0x01) {
+ sprintf(tmp, "%d ", i + 1);
+ strcat(buf, tmp);
+ }
+ value >>= 1;
+ }
+ strcat(buf, "\n");
+ } else {
+ strcpy(buf, "none\n");
+ }
+
+ return strlen(buf);
+}
+
+static ssize_t sky81452_bl_show_fault(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct regmap *regmap = bl_get_data(to_backlight_device(dev));
+ unsigned int value = 0;
+ int ret;
+
+ ret = regmap_read(regmap, SKY81452_REG4, &value);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ *buf = 0;
+
+ if (value & SKY81452_OCP)
+ strcat(buf, "over-current ");
+
+ if (value & SKY81452_OTMP)
+ strcat(buf, "over-temperature");
+
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
+static DEVICE_ATTR(enable, S_IWGRP | S_IWUSR, NULL, sky81452_bl_store_enable);
+static DEVICE_ATTR(open, S_IRUGO, sky81452_bl_show_open_short, NULL);
+static DEVICE_ATTR(short, S_IRUGO, sky81452_bl_show_open_short, NULL);
+static DEVICE_ATTR(fault, S_IRUGO, sky81452_bl_show_fault, NULL);
+
+static struct attribute *sky81452_bl_attribute[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_open.attr,
+ &dev_attr_short.attr,
+ &dev_attr_fault.attr,
+ NULL
+};
+
+static const struct attribute_group sky81452_bl_attr_group = {
+ .attrs = sky81452_bl_attribute,
+};
+
+#ifdef CONFIG_OF
+static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
+ struct device *dev)
+{
+ struct device_node *np = of_node_get(dev->of_node);
+ struct sky81452_bl_platform_data *pdata;
+ int ret;
+
+ if (!np) {
+ dev_err(dev, "backlight node not found.\n");
+ return ERR_PTR(-ENODATA);
+ }
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ of_node_put(np);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ of_property_read_string(np, "name", &pdata->name);
+ pdata->ignore_pwm = of_property_read_bool(np, "skyworks,ignore-pwm");
+ pdata->dpwm_mode = of_property_read_bool(np, "skyworks,dpwm-mode");
+ pdata->phase_shift = of_property_read_bool(np, "skyworks,phase-shift");
+ pdata->gpio_enable = of_get_gpio(np, 0);
+
+ ret = of_property_read_u32(np, "skyworks,en-channels", &pdata->enable);
+ if (IS_ERR_VALUE(ret))
+ pdata->enable = SKY81452_EN >> CTZ(SKY81452_EN);
+
+ ret = of_property_read_u32(np, "skyworks,short-detection-threshold",
+ &pdata->short_detection_threshold);
+ if (IS_ERR_VALUE(ret))
+ pdata->short_detection_threshold = 7;
+
+ ret = of_property_read_u32(np, "skyworks,current-limit",
+ &pdata->boost_current_limit);
+ if (IS_ERR_VALUE(ret))
+ pdata->boost_current_limit = 2750;
+
+ of_node_put(np);
+ return pdata;
+}
+#else
+static struct sky81452_bl_platform_data *sky81452_bl_parse_dt(
+ struct device *dev)
+{
+ return ERR_PTR(-EINVAL);
+}
+#endif
+
+static int sky81452_bl_init_device(struct regmap *regmap,
+ struct sky81452_bl_platform_data *pdata)
+{
+ unsigned int value;
+
+ value = pdata->ignore_pwm ? SKY81452_IGPW : 0;
+ value |= pdata->dpwm_mode ? SKY81452_PWMMD : 0;
+ value |= pdata->phase_shift ? 0 : SKY81452_PHASE;
+
+ if (pdata->boost_current_limit = 2300)
+ value |= SKY81452_ILIM;
+ else if (pdata->boost_current_limit != 2750)
+ return -EINVAL;
+
+ if (pdata->short_detection_threshold < 4 ||
+ pdata->short_detection_threshold > 7)
+ return -EINVAL;
+ value |= (7 - pdata->short_detection_threshold) << CTZ(SKY81452_VSHRT);
+
+ return regmap_write(regmap, SKY81452_REG2, value);
+}
+
+static int sky81452_bl_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap = dev_get_drvdata(dev->parent);
+ struct sky81452_bl_platform_data *pdata = dev_get_platdata(dev);
+ struct backlight_device *bd;
+ struct backlight_properties props;
+ const char *name;
+ int ret;
+
+ if (!pdata) {
+ pdata = sky81452_bl_parse_dt(dev);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ }
+
+ if (gpio_is_valid(pdata->gpio_enable)) {
+ ret = devm_gpio_request_one(dev, pdata->gpio_enable,
+ GPIOF_OUT_INIT_HIGH, "sky81452-en");
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(dev, "failed to request GPIO. err=%d\n", ret);
+ return ret;
+ }
+ }
+
+ ret = sky81452_bl_init_device(regmap, pdata);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(dev, "failed to initialize. err=%d\n", ret);
+ return ret;
+ }
+
+ memset(&props, 0, sizeof(props));
+ props.max_brightness = SKY81452_MAX_BRIGHTNESS,
+ name = pdata->name ? pdata->name : SKY81452_DEFAULT_NAME;
+ bd = devm_backlight_device_register(dev, name, dev, regmap,
+ &sky81452_bl_ops, &props);
+ if (IS_ERR(bd)) {
+ dev_err(dev, "failed to register. err=%ld\n", PTR_ERR(bd));
+ return PTR_ERR(bd);
+ }
+
+ platform_set_drvdata(pdev, bd);
+
+ ret = sysfs_create_group(&bd->dev.kobj, &sky81452_bl_attr_group);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(dev, "failed to create attribute. err=%d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int sky81452_bl_remove(struct platform_device *pdev)
+{
+ const struct sky81452_bl_platform_data *pdata + dev_get_platdata(&pdev->dev);
+ struct backlight_device *bd = platform_get_drvdata(pdev);
+
+ sysfs_remove_group(&bd->dev.kobj, &sky81452_bl_attr_group);
+
+ bd->props.power = FB_BLANK_UNBLANK;
+ bd->props.brightness = 0;
+ backlight_update_status(bd);
+
+ if (gpio_is_valid(pdata->gpio_enable))
+ gpio_set_value_cansleep(pdata->gpio_enable, 0);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id sky81452_bl_of_match[] = {
+ { .compatible = "skyworks,sky81452-backlight", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sky81452_bl_of_match);
+#endif
+
+static struct platform_driver sky81452_bl_driver = {
+ .driver = {
+ .name = "sky81452-backlight",
+ .of_match_table = of_match_ptr(sky81452_bl_of_match),
+ },
+ .probe = sky81452_bl_probe,
+ .remove = sky81452_bl_remove,
+};
+
+module_platform_driver(sky81452_bl_driver);
+
+MODULE_DESCRIPTION("Skyworks SKY81452 backlight driver");
+MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/platform_data/sky81452-backlight.h b/include/linux/platform_data/sky81452-backlight.h
new file mode 100644
index 0000000..1231e9b
--- /dev/null
+++ b/include/linux/platform_data/sky81452-backlight.h
@@ -0,0 +1,46 @@
+/*
+ * sky81452.h SKY81452 backlight driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SKY81452_BACKLIGHT_H
+#define _SKY81452_BACKLIGHT_H
+
+/**
+ * struct sky81452_platform_data
+ * @name: backlight driver name.
+ If it is not defined, default name is lcd-backlight.
+ * @gpio_enable:GPIO number which control EN pin
+ * @enable: Enable mask for current sink channel 1, 2, 3, 4, 5 and 6.
+ * @ignore_pwm: true if DPWMI should be ignored.
+ * @dpwm_mode: true is DPWM dimming mode, otherwise Analog dimming mode.
+ * @phase_shift:true is phase shift mode.
+ * @short_detecion_threshold: It should be one of 4, 5, 6 and 7V.
+ * @boost_current_limit: It should be one of 2300, 2750mA.
+ */
+struct sky81452_bl_platform_data {
+ const char *name;
+ int gpio_enable;
+ unsigned int enable;
+ bool ignore_pwm;
+ bool dpwm_mode;
+ bool phase_shift;
+ unsigned int short_detection_threshold;
+ unsigned int boost_current_limit;
+};
+
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v10 1/6] mfd: Add support for Skyworks SKY81452 driver
From: gyungoh @ 2014-12-03 7:05 UTC (permalink / raw)
To: sameo, lee.jones, grant.likely, robh+dt, jg1.han, cooloney,
pawel.moll, mark.rutland, ijc+devicetree, galak, trivial
Cc: akpm, jic23, thomas.petazzoni, ktsai, hs, stwiss.opensource,
matti.vaittinen, broonie, jason, heiko, shawn.guo,
florian.vaussard, andrew, antonynpavlov, hytszk, plagnioj,
tomi.valkeinen, jack.yoo, linux-fbdev, linux-kernel, devicetree
In-Reply-To: <1417590332-4912-1-git-send-email-jack.yoo@skyworksinc.com>
From: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Signed-off-by: Gyungoh Yoo <jack.yoo@skyworksinc.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
Changes v10:
Nothing
Changes v9:
Nothing
Changes v8:
Nothing
Changes v7:
Modified licensing text to GPLv2
Changes v6:
Added new line character at the end of line of dev_err()
Changes v5:
Move sky81452-backlight.h to include/linux/platform_data
Changes v4:
Removed MODULE_VERSION()
Modified license to GPLv2
Changes v3:
Fixed the backlight name from 'sky81452-bl' to 'sky81452-backlight'
Assigned mfd_cell.of_compatible for binding device node
Modified error messages
Changes v2:
Renamed CONFIG_SKY81452 to CONFIG_MFD_SKY81452
Changed the dependency from I2C=y to I2C, for CONFIG_MFD_SKY81452
Added message for exception or errors
drivers/mfd/Kconfig | 12 +++++
drivers/mfd/Makefile | 1 +
drivers/mfd/sky81452.c | 108 +++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/sky81452.h | 31 +++++++++++++
4 files changed, 152 insertions(+)
create mode 100644 drivers/mfd/sky81452.c
create mode 100644 include/linux/mfd/sky81452.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 1456ea7..a54244c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -693,6 +693,18 @@ config MFD_SM501_GPIO
lines on the SM501. The platform data is used to supply the
base number for the first GPIO line to register.
+config MFD_SKY81452
+ tristate "Skyworks Solutions SKY81452"
+ select MFD_CORE
+ select REGMAP_I2C
+ depends on I2C
+ help
+ This is the core driver for the Skyworks SKY81452 backlight and
+ voltage regulator device.
+
+ This driver can also be built as a module. If so, the module
+ will be called sky81452.
+
config MFD_SMSC
bool "SMSC ECE1099 series chips"
depends on I2C=y
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8bd54b1..d9683ea 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -174,6 +174,7 @@ obj-$(CONFIG_MFD_STW481X) += stw481x.o
obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o
obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o
+obj-$(CONFIG_MFD_SKY81452) += sky81452.o
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
diff --git a/drivers/mfd/sky81452.c b/drivers/mfd/sky81452.c
new file mode 100644
index 0000000..b0c9b04
--- /dev/null
+++ b/drivers/mfd/sky81452.c
@@ -0,0 +1,108 @@
+/*
+ * sky81452.c SKY81452 MFD driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/sky81452.h>
+
+static const struct regmap_config sky81452_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int sky81452_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+ const struct sky81452_platform_data *pdata = dev_get_platdata(dev);
+ struct mfd_cell cells[2];
+ struct regmap *regmap;
+ int ret;
+
+ if (!pdata) {
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ }
+
+ regmap = devm_regmap_init_i2c(client, &sky81452_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "failed to initialize.err=%ld\n", PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ i2c_set_clientdata(client, regmap);
+
+ memset(cells, 0, sizeof(cells));
+ cells[0].name = "sky81452-backlight";
+ cells[0].of_compatible = "skyworks,sky81452-backlight";
+ cells[0].platform_data = pdata->bl_pdata;
+ cells[0].pdata_size = sizeof(*pdata->bl_pdata);
+ cells[1].name = "sky81452-regulator";
+ cells[1].platform_data = pdata->regulator_init_data;
+ cells[1].pdata_size = sizeof(*pdata->regulator_init_data);
+
+ ret = mfd_add_devices(dev, -1, cells, ARRAY_SIZE(cells), NULL, 0, NULL);
+ if (ret)
+ dev_err(dev, "failed to add child devices. err=%d\n", ret);
+
+ return ret;
+}
+
+static int sky81452_remove(struct i2c_client *client)
+{
+ mfd_remove_devices(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id sky81452_ids[] = {
+ { "sky81452" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, sky81452_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id sky81452_of_match[] = {
+ { .compatible = "skyworks,sky81452", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sky81452_of_match);
+#endif
+
+static struct i2c_driver sky81452_driver = {
+ .driver = {
+ .name = "sky81452",
+ .of_match_table = of_match_ptr(sky81452_of_match),
+ },
+ .probe = sky81452_probe,
+ .remove = sky81452_remove,
+ .id_table = sky81452_ids,
+};
+
+module_i2c_driver(sky81452_driver);
+
+MODULE_DESCRIPTION("Skyworks SKY81452 MFD driver");
+MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/sky81452.h b/include/linux/mfd/sky81452.h
new file mode 100644
index 0000000..b0925fa
--- /dev/null
+++ b/include/linux/mfd/sky81452.h
@@ -0,0 +1,31 @@
+/*
+ * sky81452.h SKY81452 MFD driver
+ *
+ * Copyright 2014 Skyworks Solutions Inc.
+ * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SKY81452_H
+#define _SKY81452_H
+
+#include <linux/platform_data/sky81452-backlight.h>
+#include <linux/regulator/machine.h>
+
+struct sky81452_platform_data {
+ struct sky81452_bl_platform_data *bl_pdata;
+ struct regulator_init_data *regulator_init_data;
+};
+
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v10 0/6] Add Skyworks SKY81452 device drivers
From: gyungoh @ 2014-12-03 7:05 UTC (permalink / raw)
To: sameo-VuQAYsv1563Yd54FQh9/CA, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
cooloney-Re5JQEeQqe8AvxtiuMwx3w, pawel.moll-5wv7dgnIgG8,
mark.rutland-5wv7dgnIgG8, ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg,
galak-sgV2jX0FEOL9JmXXK+q4OQ, trivial-DgEjT+Ai2ygdnm+yROfE0A
Cc: akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
jic23-DgEjT+Ai2ygdnm+yROfE0A,
thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
ktsai-GubuWUlQtMwciDkP5Hr2oA, hs-ynQEQJNshbs,
stwiss.opensource-WBD+wuPFNBhBDgjK7y7TUQ,
matti.vaittinen-OYasijW0DpE, broonie-DgEjT+Ai2ygdnm+yROfE0A,
jason-NLaQJdtUoK4Be96aLqz0jA, heiko-4mtYJXux2i+zQB+pC5nmwQ,
shawn.guo-KZfg59tc24xl57MIdRCFDg, florian.vaussard-p8DiymsW2f8,
andrew-g2DYL2Zd6BY, antonynpavlov-Re5JQEeQqe8AvxtiuMwx3w,
hytszk-Re5JQEeQqe8AvxtiuMwx3w, plagnioj-sclMFOaUSTBWk0Htik3J/w,
tomi.valkeinen-l0cyMroinI0, jack.yoo-tjhQNA90jdKqndwCJWfcng,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
From: Gyungoh Yoo <jack.yoo@skyworksinc.com>
This patch set includes regulator and backlight driver for SKY81452.
Also it includes documents for device tree and module.
sky81452-regulator was already applied. So this series doesn't
include it.
v10:
Removed trivial get_brightness implementations for sky81452-backlight
v9:
Removed the change to remove MODULE_VERSION() for sky81452-regulator
v8:
Renamed property names for backlight with vendor prefix
Modified gpio-enable property to generic property for GPIO
Made up the example for backlight DT
Changed the DT parsing of regulator using regulator_node and of_match
v7:
Modified licensing text to GPLv2
Splitted Kconfig renaming from DT patch
v6:
Added new line character at the end of line of dev_err()
v5:
Changed DT for regulator : 'lout' node should be defined under 'regulator'
Removed compatible string from sky81452-regulator driver
Modified sky81452-regulator to return EINVAL when of_node is NULL
Move sky81452-backlight.h to include/linux/platform_data
v4:
Removed MODULE_VERSION()
Modified license to GPLv2
Removed calling to backlight_device_unregister() in sky81452-backlight
v3:
Cleaned-up DBG messages
Cleaned-up DT
Fixed the backlight name from 'sky81452-bl' to 'sky81452-backlight'
Assigned mfd_cell.of_compatible for binding device node
Modified error messages
Modified sky81452-regulator to return ENODATA when of_node is NULL
v2:
Split the patches for each sub-system
Added 'reg' attribute for I2C address in device tree documents
Added 'compatible' attribute in child drivers
Renamed CONFIG_SKY81452 to CONFIG_MFD_SKY81452
Changed the dependency from I2C=y to I2C, for CONFIG_MFD_SKY81452
Added message for exception or errors.
Added vendor prefix for Skyworks Solutions, Inc.
Add SKY81452 to the Trivial Devices list
Gyungoh Yoo (6):
mfd: Add support for Skyworks SKY81452 driver
backlight: Add support Skyworks SKY81452 backlight driver
devicetree: mfd: Add new SKY81452 mfd binding
devicetree: backlight: Add new SKY81452 backlight binding
devicetree: Add vendor prefix for Skyworks Solutions, Inc.
devicetree: i2c: Add SKY81452 to the Trivial Devices list
.../devicetree/bindings/i2c/trivial-devices.txt | 1 +
Documentation/devicetree/bindings/mfd/sky81452.txt | 36 +++
.../devicetree/bindings/vendor-prefixes.txt | 1 +
.../video/backlight/sky81452-backlight.txt | 29 ++
drivers/mfd/Kconfig | 12 +
drivers/mfd/Makefile | 1 +
drivers/mfd/sky81452.c | 108 +++++++
drivers/video/backlight/Kconfig | 10 +
drivers/video/backlight/Makefile | 1 +
drivers/video/backlight/sky81452-backlight.c | 334 +++++++++++++++++++++
include/linux/mfd/sky81452.h | 31 ++
include/linux/platform_data/sky81452-backlight.h | 46 +++
12 files changed, 610 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/sky81452.txt
create mode 100644 Documentation/devicetree/bindings/video/backlight/sky81452-backlight.txt
create mode 100644 drivers/mfd/sky81452.c
create mode 100644 drivers/video/backlight/sky81452-backlight.c
create mode 100644 include/linux/mfd/sky81452.h
create mode 100644 include/linux/platform_data/sky81452-backlight.h
--
1.9.1
^ permalink raw reply
* Re: [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Bryan Wu @ 2014-12-03 2:13 UTC (permalink / raw)
To: Sean Paul
Cc: 김우겸, FBDEV list,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Jingoo Han,
Lee Jones, Stéphane Marchesin, Aaron Durbin
In-Reply-To: <1417570752-23633-2-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
On Tue, Dec 2, 2014 at 5:39 PM, Sean Paul <seanpaul@chromium.org> wrote:
> This patch adds a supply regulator to the lp855x platform data to facilitate
> powering on/off the 3V rail attached to the controller.
>
> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Cc: Aaron Durbin <adurbin@chromium.org>
> Acked-by: Milo Kim <milo.kim@ti.com>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
Acked-by: Bryan Wu <cooloney@gmail.com>
Thanks,
-Bryan
> ---
>
> Changes in v2:
> - Add NULL check in lp855x_remove
>
>
> .../devicetree/bindings/video/backlight/lp855x.txt | 2 ++
> drivers/video/backlight/lp855x_bl.c | 18 ++++++++++++++++++
> include/linux/platform_data/lp855x.h | 2 ++
> 3 files changed, 22 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/video/backlight/lp855x.txt b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> index 96e83a5..0a3ecbc 100644
> --- a/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> +++ b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> @@ -12,6 +12,7 @@ Optional properties:
> - pwm-period: PWM period value. Set only PWM input mode used (u32)
> - rom-addr: Register address of ROM area to be updated (u8)
> - rom-val: Register value to be updated (u8)
> + - power-supply: Regulator which controls the 3V rail
>
> Example:
>
> @@ -56,6 +57,7 @@ Example:
> backlight@2c {
> compatible = "ti,lp8557";
> reg = <0x2c>;
> + power-supply = <&backlight_vdd>;
>
> dev-ctrl = /bits/ 8 <0x41>;
> init-brt = /bits/ 8 <0x0a>;
> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 257b3ba..a26d3bb 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -17,6 +17,7 @@
> #include <linux/of.h>
> #include <linux/platform_data/lp855x.h>
> #include <linux/pwm.h>
> +#include <linux/regulator/consumer.h>
>
> /* LP8550/1/2/3/6 Registers */
> #define LP855X_BRIGHTNESS_CTRL 0x00
> @@ -383,6 +384,13 @@ static int lp855x_parse_dt(struct lp855x *lp)
> pdata->rom_data = &rom[0];
> }
>
> + pdata->supply = devm_regulator_get(dev, "power");
> + if (IS_ERR(pdata->supply)) {
> + if (PTR_ERR(pdata->supply) = -EPROBE_DEFER)
> + return -EPROBE_DEFER;
> + pdata->supply = NULL;
> + }
> +
> lp->pdata = pdata;
>
> return 0;
> @@ -423,6 +431,14 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
> else
> lp->mode = REGISTER_BASED;
>
> + if (lp->pdata->supply) {
> + ret = regulator_enable(lp->pdata->supply);
> + if (ret < 0) {
> + dev_err(&cl->dev, "failed to enable supply: %d\n", ret);
> + return ret;
> + }
> + }
> +
> i2c_set_clientdata(cl, lp);
>
> ret = lp855x_configure(lp);
> @@ -454,6 +470,8 @@ static int lp855x_remove(struct i2c_client *cl)
>
> lp->bl->props.brightness = 0;
> backlight_update_status(lp->bl);
> + if (lp->pdata->supply)
> + regulator_disable(lp->pdata->supply);
> sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
>
> return 0;
> diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h
> index 1b2ba24..9c7fd1e 100644
> --- a/include/linux/platform_data/lp855x.h
> +++ b/include/linux/platform_data/lp855x.h
> @@ -136,6 +136,7 @@ struct lp855x_rom_data {
> Only valid when mode is PWM_BASED.
> * @size_program : total size of lp855x_rom_data
> * @rom_data : list of new eeprom/eprom registers
> + * @supply : regulator that supplies 3V input
> */
> struct lp855x_platform_data {
> const char *name;
> @@ -144,6 +145,7 @@ struct lp855x_platform_data {
> unsigned int period_ns;
> int size_program;
> struct lp855x_rom_data *rom_data;
> + struct regulator *supply;
> };
>
> #endif
> --
> 2.2.0.rc0.207.ga3a616c
>
^ permalink raw reply
* Re: [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
From: Jingoo Han @ 2014-12-03 2:08 UTC (permalink / raw)
To: 'Sean Paul'
Cc: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
lee.jones-QSEj5FYQhm4dnm+yROfE0A,
'Stéphane Marchesin', 'Jingoo Han'
In-Reply-To: <1417570752-23633-1-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
On Wednesday, December 03, 2014 10:39 AM, Sean Paul wrote:
>
> This patch refactors the dt parsing code to avoid setting platform_data,
> instead just setting lp->pdata directly. This facilitates easier
> probe deferral since the current scheme would require us to clear out
> dev->platform_data before deferring.
>
> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
Acked-by: Jingoo Han <jg1.han@samsung.com>
Best regards,
Jingoo Han
> ---
> drivers/video/backlight/lp855x_bl.c | 37 ++++++++++++++++++-------------------
> 1 file changed, 18 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 25fb8e3..257b3ba 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -341,8 +341,10 @@ static const struct attribute_group lp855x_attr_group = {
> };
>
> #ifdef CONFIG_OF
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
> {
> + struct device *dev = lp->dev;
> + struct device_node *node = dev->of_node;
> struct lp855x_platform_data *pdata;
> int rom_length;
>
> @@ -381,12 +383,12 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> pdata->rom_data = &rom[0];
> }
>
> - dev->platform_data = pdata;
> + lp->pdata = pdata;
>
> return 0;
> }
> #else
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
> {
> return -EINVAL;
> }
> @@ -395,18 +397,8 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
> {
> struct lp855x *lp;
> - struct lp855x_platform_data *pdata = dev_get_platdata(&cl->dev);
> - struct device_node *node = cl->dev.of_node;
> int ret;
>
> - if (!pdata) {
> - ret = lp855x_parse_dt(&cl->dev, node);
> - if (ret < 0)
> - return ret;
> -
> - pdata = dev_get_platdata(&cl->dev);
> - }
> -
> if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
> return -EIO;
>
> @@ -414,16 +406,23 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
> if (!lp)
> return -ENOMEM;
>
> - if (pdata->period_ns > 0)
> - lp->mode = PWM_BASED;
> - else
> - lp->mode = REGISTER_BASED;
> -
> lp->client = cl;
> lp->dev = &cl->dev;
> - lp->pdata = pdata;
> lp->chipname = id->name;
> lp->chip_id = id->driver_data;
> + lp->pdata = dev_get_platdata(&cl->dev);
> +
> + if (!lp->pdata) {
> + ret = lp855x_parse_dt(lp);
> + if (ret < 0)
> + return ret;
> + }
> +
> + if (lp->pdata->period_ns > 0)
> + lp->mode = PWM_BASED;
> + else
> + lp->mode = REGISTER_BASED;
> +
> i2c_set_clientdata(cl, lp);
>
> ret = lp855x_configure(lp);
> --
> 2.1.1
^ permalink raw reply
* Re: [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Jingoo Han @ 2014-12-03 2:06 UTC (permalink / raw)
To: 'Sean Paul'
Cc: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
lee.jones-QSEj5FYQhm4dnm+yROfE0A,
'Stéphane Marchesin', 'Aaron Durbin',
'Jingoo Han'
In-Reply-To: <1417570752-23633-2-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
On Wednesday, December 03, 2014 10:39 AM, Sean Paul wrote:
>
> This patch adds a supply regulator to the lp855x platform data to facilitate
> powering on/off the 3V rail attached to the controller.
>
> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Cc: Aaron Durbin <adurbin@chromium.org>
> Acked-by: Milo Kim <milo.kim@ti.com>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
Acked-by: Jingoo Han <jg1.han@samsung.com>
Best regards,
Jingoo Han
> ---
>
> Changes in v2:
> - Add NULL check in lp855x_remove
>
>
> .../devicetree/bindings/video/backlight/lp855x.txt | 2 ++
> drivers/video/backlight/lp855x_bl.c | 18 ++++++++++++++++++
> include/linux/platform_data/lp855x.h | 2 ++
> 3 files changed, 22 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> index 96e83a5..0a3ecbc 100644
> --- a/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> +++ b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
> @@ -12,6 +12,7 @@ Optional properties:
> - pwm-period: PWM period value. Set only PWM input mode used (u32)
> - rom-addr: Register address of ROM area to be updated (u8)
> - rom-val: Register value to be updated (u8)
> + - power-supply: Regulator which controls the 3V rail
>
> Example:
>
> @@ -56,6 +57,7 @@ Example:
> backlight@2c {
> compatible = "ti,lp8557";
> reg = <0x2c>;
> + power-supply = <&backlight_vdd>;
>
> dev-ctrl = /bits/ 8 <0x41>;
> init-brt = /bits/ 8 <0x0a>;
> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 257b3ba..a26d3bb 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -17,6 +17,7 @@
> #include <linux/of.h>
> #include <linux/platform_data/lp855x.h>
> #include <linux/pwm.h>
> +#include <linux/regulator/consumer.h>
>
> /* LP8550/1/2/3/6 Registers */
> #define LP855X_BRIGHTNESS_CTRL 0x00
> @@ -383,6 +384,13 @@ static int lp855x_parse_dt(struct lp855x *lp)
> pdata->rom_data = &rom[0];
> }
>
> + pdata->supply = devm_regulator_get(dev, "power");
> + if (IS_ERR(pdata->supply)) {
> + if (PTR_ERR(pdata->supply) = -EPROBE_DEFER)
> + return -EPROBE_DEFER;
> + pdata->supply = NULL;
> + }
> +
> lp->pdata = pdata;
>
> return 0;
> @@ -423,6 +431,14 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
> else
> lp->mode = REGISTER_BASED;
>
> + if (lp->pdata->supply) {
> + ret = regulator_enable(lp->pdata->supply);
> + if (ret < 0) {
> + dev_err(&cl->dev, "failed to enable supply: %d\n", ret);
> + return ret;
> + }
> + }
> +
> i2c_set_clientdata(cl, lp);
>
> ret = lp855x_configure(lp);
> @@ -454,6 +470,8 @@ static int lp855x_remove(struct i2c_client *cl)
>
> lp->bl->props.brightness = 0;
> backlight_update_status(lp->bl);
> + if (lp->pdata->supply)
> + regulator_disable(lp->pdata->supply);
> sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
>
> return 0;
> diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h
> index 1b2ba24..9c7fd1e 100644
> --- a/include/linux/platform_data/lp855x.h
> +++ b/include/linux/platform_data/lp855x.h
> @@ -136,6 +136,7 @@ struct lp855x_rom_data {
> Only valid when mode is PWM_BASED.
> * @size_program : total size of lp855x_rom_data
> * @rom_data : list of new eeprom/eprom registers
> + * @supply : regulator that supplies 3V input
> */
> struct lp855x_platform_data {
> const char *name;
> @@ -144,6 +145,7 @@ struct lp855x_platform_data {
> unsigned int period_ns;
> int size_program;
> struct lp855x_rom_data *rom_data;
> + struct regulator *supply;
> };
>
> #endif
> --
> 2.2.0.rc0.207.ga3a616c
^ permalink raw reply
* Re: [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Kim, Milo @ 2014-12-03 1:57 UTC (permalink / raw)
To: Sean Paul
Cc: cooloney-Re5JQEeQqe8AvxtiuMwx3w,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
lee.jones-QSEj5FYQhm4dnm+yROfE0A, Stéphane Marchesin,
Aaron Durbin
In-Reply-To: <1417570752-23633-2-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
On 12/3/2014 10:39 AM, Sean Paul wrote:
> This patch adds a supply regulator to the lp855x platform data to facilitate
> powering on/off the 3V rail attached to the controller.
>
> Cc: Stéphane Marchesin<marcheu@chromium.org>
> Cc: Aaron Durbin<adurbin@chromium.org>
> Acked-by: Milo Kim<milo.kim@ti.com>
> Signed-off-by: Sean Paul<seanpaul@chromium.org>
Acked-by: Milo Kim <milo.kim@ti.com>
^ permalink raw reply
* Re: [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
From: Kim, Milo @ 2014-12-03 1:56 UTC (permalink / raw)
To: Sean Paul
Cc: cooloney-Re5JQEeQqe8AvxtiuMwx3w,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
lee.jones-QSEj5FYQhm4dnm+yROfE0A, Stéphane Marchesin
In-Reply-To: <1417570752-23633-1-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
On 12/3/2014 10:39 AM, Sean Paul wrote:
> This patch refactors the dt parsing code to avoid setting platform_data,
> instead just setting lp->pdata directly. This facilitates easier
> probe deferral since the current scheme would require us to clear out
> dev->platform_data before deferring.
>
> Cc: Stéphane Marchesin<marcheu@chromium.org>
> Signed-off-by: Sean Paul<seanpaul@chromium.org>
Acked-by: Milo Kim <milo.kim@ti.com>
^ permalink raw reply
* Re: [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
From: Bryan Wu @ 2014-12-03 1:49 UTC (permalink / raw)
To: Sean Paul
Cc: 김우겸, FBDEV list,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Jingoo Han,
Lee Jones, Stéphane Marchesin
In-Reply-To: <1417570752-23633-1-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
On Tue, Dec 2, 2014 at 5:39 PM, Sean Paul <seanpaul@chromium.org> wrote:
> This patch refactors the dt parsing code to avoid setting platform_data,
> instead just setting lp->pdata directly. This facilitates easier
> probe deferral since the current scheme would require us to clear out
> dev->platform_data before deferring.
>
Looks good to me,
Acked-by: Bryan Wu <cooloney@gmail.com>
Please also wait for Milo to ack. Lee, can you take this patch?
Thanks,
-Bryan
> Cc: Stéphane Marchesin <marcheu@chromium.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
> drivers/video/backlight/lp855x_bl.c | 37 ++++++++++++++++++-------------------
> 1 file changed, 18 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
> index 25fb8e3..257b3ba 100644
> --- a/drivers/video/backlight/lp855x_bl.c
> +++ b/drivers/video/backlight/lp855x_bl.c
> @@ -341,8 +341,10 @@ static const struct attribute_group lp855x_attr_group = {
> };
>
> #ifdef CONFIG_OF
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
> {
> + struct device *dev = lp->dev;
> + struct device_node *node = dev->of_node;
> struct lp855x_platform_data *pdata;
> int rom_length;
>
> @@ -381,12 +383,12 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> pdata->rom_data = &rom[0];
> }
>
> - dev->platform_data = pdata;
> + lp->pdata = pdata;
>
> return 0;
> }
> #else
> -static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> +static int lp855x_parse_dt(struct lp855x *lp)
> {
> return -EINVAL;
> }
> @@ -395,18 +397,8 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
> static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
> {
> struct lp855x *lp;
> - struct lp855x_platform_data *pdata = dev_get_platdata(&cl->dev);
> - struct device_node *node = cl->dev.of_node;
> int ret;
>
> - if (!pdata) {
> - ret = lp855x_parse_dt(&cl->dev, node);
> - if (ret < 0)
> - return ret;
> -
> - pdata = dev_get_platdata(&cl->dev);
> - }
> -
> if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
> return -EIO;
>
> @@ -414,16 +406,23 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
> if (!lp)
> return -ENOMEM;
>
> - if (pdata->period_ns > 0)
> - lp->mode = PWM_BASED;
> - else
> - lp->mode = REGISTER_BASED;
> -
> lp->client = cl;
> lp->dev = &cl->dev;
> - lp->pdata = pdata;
> lp->chipname = id->name;
> lp->chip_id = id->driver_data;
> + lp->pdata = dev_get_platdata(&cl->dev);
> +
> + if (!lp->pdata) {
> + ret = lp855x_parse_dt(lp);
> + if (ret < 0)
> + return ret;
> + }
> +
> + if (lp->pdata->period_ns > 0)
> + lp->mode = PWM_BASED;
> + else
> + lp->mode = REGISTER_BASED;
> +
> i2c_set_clientdata(cl, lp);
>
> ret = lp855x_configure(lp);
> --
> 2.1.1
>
^ permalink raw reply
* [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Sean Paul @ 2014-12-03 1:39 UTC (permalink / raw)
To: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: jg1.han-Sze3O3UU22JBDgjK7y7TUQ, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
Sean Paul, Stéphane Marchesin, Aaron Durbin
In-Reply-To: <1417570752-23633-1-git-send-email-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
This patch adds a supply regulator to the lp855x platform data to facilitate
powering on/off the 3V rail attached to the controller.
Cc: Stéphane Marchesin <marcheu@chromium.org>
Cc: Aaron Durbin <adurbin@chromium.org>
Acked-by: Milo Kim <milo.kim@ti.com>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
Changes in v2:
- Add NULL check in lp855x_remove
.../devicetree/bindings/video/backlight/lp855x.txt | 2 ++
drivers/video/backlight/lp855x_bl.c | 18 ++++++++++++++++++
include/linux/platform_data/lp855x.h | 2 ++
3 files changed, 22 insertions(+)
diff --git a/Documentation/devicetree/bindings/video/backlight/lp855x.txt b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
index 96e83a5..0a3ecbc 100644
--- a/Documentation/devicetree/bindings/video/backlight/lp855x.txt
+++ b/Documentation/devicetree/bindings/video/backlight/lp855x.txt
@@ -12,6 +12,7 @@ Optional properties:
- pwm-period: PWM period value. Set only PWM input mode used (u32)
- rom-addr: Register address of ROM area to be updated (u8)
- rom-val: Register value to be updated (u8)
+ - power-supply: Regulator which controls the 3V rail
Example:
@@ -56,6 +57,7 @@ Example:
backlight@2c {
compatible = "ti,lp8557";
reg = <0x2c>;
+ power-supply = <&backlight_vdd>;
dev-ctrl = /bits/ 8 <0x41>;
init-brt = /bits/ 8 <0x0a>;
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index 257b3ba..a26d3bb 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -17,6 +17,7 @@
#include <linux/of.h>
#include <linux/platform_data/lp855x.h>
#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
/* LP8550/1/2/3/6 Registers */
#define LP855X_BRIGHTNESS_CTRL 0x00
@@ -383,6 +384,13 @@ static int lp855x_parse_dt(struct lp855x *lp)
pdata->rom_data = &rom[0];
}
+ pdata->supply = devm_regulator_get(dev, "power");
+ if (IS_ERR(pdata->supply)) {
+ if (PTR_ERR(pdata->supply) = -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ pdata->supply = NULL;
+ }
+
lp->pdata = pdata;
return 0;
@@ -423,6 +431,14 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
else
lp->mode = REGISTER_BASED;
+ if (lp->pdata->supply) {
+ ret = regulator_enable(lp->pdata->supply);
+ if (ret < 0) {
+ dev_err(&cl->dev, "failed to enable supply: %d\n", ret);
+ return ret;
+ }
+ }
+
i2c_set_clientdata(cl, lp);
ret = lp855x_configure(lp);
@@ -454,6 +470,8 @@ static int lp855x_remove(struct i2c_client *cl)
lp->bl->props.brightness = 0;
backlight_update_status(lp->bl);
+ if (lp->pdata->supply)
+ regulator_disable(lp->pdata->supply);
sysfs_remove_group(&lp->dev->kobj, &lp855x_attr_group);
return 0;
diff --git a/include/linux/platform_data/lp855x.h b/include/linux/platform_data/lp855x.h
index 1b2ba24..9c7fd1e 100644
--- a/include/linux/platform_data/lp855x.h
+++ b/include/linux/platform_data/lp855x.h
@@ -136,6 +136,7 @@ struct lp855x_rom_data {
Only valid when mode is PWM_BASED.
* @size_program : total size of lp855x_rom_data
* @rom_data : list of new eeprom/eprom registers
+ * @supply : regulator that supplies 3V input
*/
struct lp855x_platform_data {
const char *name;
@@ -144,6 +145,7 @@ struct lp855x_platform_data {
unsigned int period_ns;
int size_program;
struct lp855x_rom_data *rom_data;
+ struct regulator *supply;
};
#endif
--
2.2.0.rc0.207.ga3a616c
^ permalink raw reply related
* [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
From: Sean Paul @ 2014-12-03 1:39 UTC (permalink / raw)
To: milo.kim-l0cyMroinI0, cooloney-Re5JQEeQqe8AvxtiuMwx3w,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: jg1.han-Sze3O3UU22JBDgjK7y7TUQ, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
Sean Paul, Stéphane Marchesin
This patch refactors the dt parsing code to avoid setting platform_data,
instead just setting lp->pdata directly. This facilitates easier
probe deferral since the current scheme would require us to clear out
dev->platform_data before deferring.
Cc: Stéphane Marchesin <marcheu@chromium.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
drivers/video/backlight/lp855x_bl.c | 37 ++++++++++++++++++-------------------
1 file changed, 18 insertions(+), 19 deletions(-)
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index 25fb8e3..257b3ba 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -341,8 +341,10 @@ static const struct attribute_group lp855x_attr_group = {
};
#ifdef CONFIG_OF
-static int lp855x_parse_dt(struct device *dev, struct device_node *node)
+static int lp855x_parse_dt(struct lp855x *lp)
{
+ struct device *dev = lp->dev;
+ struct device_node *node = dev->of_node;
struct lp855x_platform_data *pdata;
int rom_length;
@@ -381,12 +383,12 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
pdata->rom_data = &rom[0];
}
- dev->platform_data = pdata;
+ lp->pdata = pdata;
return 0;
}
#else
-static int lp855x_parse_dt(struct device *dev, struct device_node *node)
+static int lp855x_parse_dt(struct lp855x *lp)
{
return -EINVAL;
}
@@ -395,18 +397,8 @@ static int lp855x_parse_dt(struct device *dev, struct device_node *node)
static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
{
struct lp855x *lp;
- struct lp855x_platform_data *pdata = dev_get_platdata(&cl->dev);
- struct device_node *node = cl->dev.of_node;
int ret;
- if (!pdata) {
- ret = lp855x_parse_dt(&cl->dev, node);
- if (ret < 0)
- return ret;
-
- pdata = dev_get_platdata(&cl->dev);
- }
-
if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
return -EIO;
@@ -414,16 +406,23 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
if (!lp)
return -ENOMEM;
- if (pdata->period_ns > 0)
- lp->mode = PWM_BASED;
- else
- lp->mode = REGISTER_BASED;
-
lp->client = cl;
lp->dev = &cl->dev;
- lp->pdata = pdata;
lp->chipname = id->name;
lp->chip_id = id->driver_data;
+ lp->pdata = dev_get_platdata(&cl->dev);
+
+ if (!lp->pdata) {
+ ret = lp855x_parse_dt(lp);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (lp->pdata->period_ns > 0)
+ lp->mode = PWM_BASED;
+ else
+ lp->mode = REGISTER_BASED;
+
i2c_set_clientdata(cl, lp);
ret = lp855x_configure(lp);
--
2.1.1
^ permalink raw reply related
* Re: [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
From: Bryan Wu @ 2014-12-03 1:33 UTC (permalink / raw)
To: Kim, Milo
Cc: Sean Paul, linux-fbdev,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Jingoo Han,
Lee Jones, Stéphane Marchesin, Aaron Durbin
In-Reply-To: <547E643A.7070202-l0cyMroinI0@public.gmane.org>
On Tue, Dec 2, 2014 at 5:15 PM, Kim, Milo <milo.kim@ti.com> wrote:
> Hi Sean,
>
> On 12/3/2014 10:01 AM, Sean Paul wrote:
>>
>> There aren't any changes to PATCH 1/2, is
>> there any value in resending the same patches?
>
>
> No. Title change is only required.
> Please submit two patches in series like below.
>
> [PATCH v2 1/2] backlight/lp855x: Refactor dt parsing code
> [PATCH v2 2/2] backlight/lp855x: Add supply regulator to lp855x
>
It looks good to me too. Please follow Milo's advice and I will give
my Ack then.
Thanks,
-Bryan
^ permalink raw reply
* RE: [PATCH] video: fbmon: Check Standard Timing against DMT and maxclk
From: David Ung @ 2014-12-03 1:16 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1416626512-12919-1-git-send-email-davidu@nvidia.com>
Ping?
> -----Original Message-----
> From: David Ung [mailto:davidu@nvidia.com]
> Sent: Friday, November 21, 2014 7:22 PM
> To: plagnioj@jcrosoft.com; tomi.valkeinen@ti.com
> Cc: linux-fbdev@vger.kernel.org; David Ung
> Subject: [PATCH] video: fbmon: Check Standard Timing against DMT and
> maxclk
>
> fbmon may generate mode timings that are out of spec of the monitor.
> eg DELL U2410 has a max clock 170mhz but advertises a resolutions of
> 1920x1200@60 in its Standard Timings, fbmon creates a mode using the
> GTF timing calculation which gave it a 193mhz clock.
> This patch add the VESA Display Monitor Timing (DMT) table.
> During parsing of Standard Timings, it compare the 2 byte STD code
> with DMT to see what the VESA mode should be. If there is no entry
> in the vesa_modes table or no match found, it fallsback to the GTF
> timings. A final check to see if the mode can be supported by the
> monitor by comparing against monspecs.dclkmax.
>
> Signed-off-by: David Ung <davidu@nvidia.com>
> ---
-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information. Any unauthorized review, use, disclosure or distribution
is prohibited. If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox