* [PATCH V3 3/3] OMAPDSS: DISPC: Correct DISPC functional clock usage
From: Chandrabhanu Mahapatra @ 2012-04-23 6:58 UTC (permalink / raw)
To: tomi.valkeinen; +Cc: linux-omap, linux-fbdev, Chandrabhanu Mahapatra
In-Reply-To: <1333379598-11544-4-git-send-email-cmahapatra@ti.com>
DISPC_FCLK is incorrectly used as functional clock of DISPC in scaling
calculations. So, DISPC_CORE_CLK replaces as functional clock of DISPC.
DISPC_CORE_CLK is derived from DISPC_FCLK divided by an independent DISPC
divisor LCD.
Signed-off-by: Chandrabhanu Mahapatra <cmahapatra@ti.com>
---
drivers/video/omap2/dss/dispc.c | 67 +++++++++++++++++++++++---------------
drivers/video/omap2/dss/dss.h | 1 +
2 files changed, 41 insertions(+), 27 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 17ffa71..f1be23f 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -1721,11 +1721,11 @@ static int check_horiz_timing_omap3(enum omap_channel channel, u16 pos_x,
return 0;
}
-static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
- u16 height, u16 out_width, u16 out_height,
+static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
+ u16 width, u16 height, u16 out_width, u16 out_height,
enum omap_color_mode color_mode)
{
- u32 fclk = 0;
+ u32 core_clk = 0;
u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
if (height <= out_height && width <= out_width)
@@ -1737,7 +1737,7 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
tmp = pclk * height * out_width;
do_div(tmp, 2 * out_height * ppl);
- fclk = tmp;
+ core_clk = tmp;
if (height > 2 * out_height) {
if (ppl = out_width)
@@ -1745,23 +1745,23 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
tmp = pclk * (height - 2 * out_height) * out_width;
do_div(tmp, 2 * out_height * (ppl - out_width));
- fclk = max(fclk, (u32) tmp);
+ core_clk = max_t(u32, core_clk, tmp);
}
}
if (width > out_width) {
tmp = pclk * width;
do_div(tmp, out_width);
- fclk = max(fclk, (u32) tmp);
+ core_clk = max_t(u32, core_clk, tmp);
if (color_mode = OMAP_DSS_COLOR_RGB24U)
- fclk <<= 1;
+ core_clk <<= 1;
}
- return fclk;
+ return core_clk;
}
-static unsigned long calc_fclk(enum omap_channel channel, u16 width,
+static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
u16 height, u16 out_width, u16 out_height)
{
unsigned int hf, vf;
@@ -1812,7 +1812,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
const int maxsinglelinewidth dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
const int max_decim_limit = 16;
- unsigned long fclk = 0;
+ unsigned long core_clk = 0;
int decim_x, decim_y, error, min_factor;
u16 in_width, in_height, in_width_max = 0;
@@ -1852,10 +1852,10 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
do {
in_height = DIV_ROUND_UP(height, decim_y);
in_width = DIV_ROUND_UP(width, decim_x);
- fclk = calc_fclk(channel, in_width, in_height,
+ core_clk = calc_core_clk(channel, in_width, in_height,
out_width, out_height);
- error = (in_width > maxsinglelinewidth || !fclk ||
- fclk > dispc_fclk_rate());
+ error = (in_width > maxsinglelinewidth || !core_clk ||
+ core_clk > dispc_core_clk_rate());
if (error) {
if (decim_x = decim_y) {
decim_x = min_factor;
@@ -1878,8 +1878,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
do {
in_height = DIV_ROUND_UP(height, decim_y);
in_width = DIV_ROUND_UP(width, decim_x);
- fclk = calc_fclk_five_taps(channel, in_width, in_height,
- out_width, out_height, color_mode);
+ core_clk = calc_core_clk_five_taps(channel, in_width,
+ in_height, out_width, out_height, color_mode);
error = check_horiz_timing_omap3(channel, pos_x,
in_width, in_height, out_width, out_height);
@@ -1889,11 +1889,11 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
in_height < out_height * 2)
*five_taps = false;
if (!*five_taps)
- fclk = calc_fclk(channel, in_width, in_height,
- out_width, out_height);
+ core_clk = calc_core_clk(channel, in_width,
+ in_height, out_width, out_height);
error = (error || in_width > maxsinglelinewidth * 2 ||
(in_width > maxsinglelinewidth && *five_taps) ||
- !fclk || fclk > dispc_fclk_rate());
+ !core_clk || core_clk > dispc_core_clk_rate());
if (error) {
if (decim_x = decim_y) {
decim_x = min_factor;
@@ -1926,7 +1926,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
} else {
int decim_x_min = decim_x;
in_height = DIV_ROUND_UP(height, decim_y);
- in_width_max = dispc_fclk_rate() /
+ in_width_max = dispc_core_clk_rate() /
DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
out_width);
decim_x = DIV_ROUND_UP(width, in_width_max);
@@ -1945,18 +1945,18 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
return -EINVAL;
}
- fclk = calc_fclk(channel, in_width, in_height, out_width,
- out_height);
+ core_clk = calc_core_clk(channel, in_width, in_height,
+ out_width, out_height);
}
- DSSDBG("required fclk rate = %lu Hz\n", fclk);
- DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
+ DSSDBG("required core clk rate = %lu Hz\n", core_clk);
+ DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
- if (!fclk || fclk > dispc_fclk_rate()) {
+ if (!core_clk || core_clk > dispc_core_clk_rate()) {
DSSERR("failed to set up scaling, "
- "required fclk rate = %lu Hz, "
- "current fclk rate = %lu Hz\n",
- fclk, dispc_fclk_rate());
+ "required core clk rate = %lu Hz, "
+ "current core clk rate = %lu Hz\n",
+ core_clk, dispc_core_clk_rate());
return -EINVAL;
}
@@ -2646,6 +2646,19 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
}
}
+unsigned long dispc_core_clk_rate(void)
+{
+ int lcd;
+ unsigned long fclk = dispc_fclk_rate();
+
+ if (dss_has_feature(FEAT_CORE_CLK_DIV))
+ lcd = REG_GET(DISPC_DIVISOR, 23, 16);
+ else
+ lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
+
+ return fclk / lcd;
+}
+
void dispc_dump_clocks(struct seq_file *s)
{
int lcd, pcd;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index d4b3dff..1bde34c 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -451,6 +451,7 @@ void dispc_mgr_set_pol_freq(enum omap_channel channel,
enum omap_panel_config config, u8 acbi, u8 acb);
unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
+unsigned long dispc_core_clk_rate(void);
int dispc_mgr_set_clock_div(enum omap_channel channel,
struct dispc_clock_info *cinfo);
int dispc_mgr_get_clock_div(enum omap_channel channel,
--
1.7.1
^ permalink raw reply related
* Re: [PATCH V3 3/3] OMAPDSS: DISPC: Correct DISPC functional clock usage
From: Tomi Valkeinen @ 2012-04-23 7:50 UTC (permalink / raw)
To: Chandrabhanu Mahapatra; +Cc: linux-omap, linux-fbdev
In-Reply-To: <1335163610-19737-1-git-send-email-cmahapatra@ti.com>
[-- Attachment #1: Type: text/plain, Size: 371 bytes --]
On Mon, 2012-04-23 at 12:16 +0530, Chandrabhanu Mahapatra wrote:
> DISPC_FCLK is incorrectly used as functional clock of DISPC in scaling
> calculations. So, DISPC_CORE_CLK replaces as functional clock of DISPC.
> DISPC_CORE_CLK is derived from DISPC_FCLK divided by an independent DISPC
> divisor LCD.
Thanks, I've applied the series to "dev" branch.
Tomi
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH] OMAPDSS: VENC: allow switching venc type at runtime
From: Tomi Valkeinen @ 2012-04-23 12:23 UTC (permalink / raw)
To: Grazvydas Ignotas; +Cc: linux-fbdev, linux-omap
In-Reply-To: <1332978312-11959-1-git-send-email-notasas@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2966 bytes --]
On Thu, 2012-03-29 at 02:45 +0300, Grazvydas Ignotas wrote:
> VENC type (composite/svideo) doesn't have to be fixed by board wiring,
> it is possible to provide both connectors, which is what pandora does.
> Having to recompile the kernel for users who have TV connector types
> that's don't match default board setting is very inconvenient, especially
> for users of a consumer device, so add support for switching VENC type
> at runtime over a new sysfs file venc_type.
>
> Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
> ---
> Documentation/arm/OMAP/DSS | 1 +
> drivers/video/omap2/dss/venc.c | 55 +++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 55 insertions(+), 1 deletions(-)
>
> diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
> index 888ae7b..18e2214 100644
> --- a/Documentation/arm/OMAP/DSS
> +++ b/Documentation/arm/OMAP/DSS
> @@ -156,6 +156,7 @@ timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
> "pal" and "ntsc"
> panel_name
> tear_elim Tearing elimination 0=off, 1=on
> +venc_type Output type (video encoder only): "composite" or "svideo"
I think we could have a better name here. "venc" name is quite obscure
on the user level. And it's not even quite correct, venc stays the same,
it's just the output that is changed. "output_type"? "connector"?
"connector_type"?
> There are also some debugfs files at <debugfs>/omapdss/ which show information
> about clocks and registers.
> diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
> index 9c3daf7..aa2e74a 100644
> --- a/drivers/video/omap2/dss/venc.c
> +++ b/drivers/video/omap2/dss/venc.c
> @@ -485,16 +485,69 @@ unsigned long venc_get_pixel_clock(void)
> return 13500000;
> }
>
> +static ssize_t display_venc_type_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct omap_dss_device *dssdev = to_dss_device(dev);
> + const char *ret;
> +
> + switch (dssdev->phy.venc.type) {
> + case OMAP_DSS_VENC_TYPE_COMPOSITE:
> + ret = "composite";
> + break;
> + case OMAP_DSS_VENC_TYPE_SVIDEO:
> + ret = "svideo";
> + break;
> + default:
> + ret = "unknown";
> + break;
> + }
Would it be better to return an error here? It would be nice to have
matching input and output for the sysfs file. And generally speaking,
the default branch should never happen.
> +
> + return snprintf(buf, PAGE_SIZE, "%s\n", ret);
> +}
> +
> +static ssize_t display_venc_type_store(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t size)
> +{
> + struct omap_dss_device *dssdev = to_dss_device(dev);
> + enum omap_dss_venc_type new_type;
> +
> + if (strncmp("composite", buf, 9) == 0)
> + new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
> + else if (strncmp("svideo", buf, 6) == 0)
> + new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
Here you could use sysfs_streq().
Tomi
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH] OMAPDSS: VENC: allow switching venc type at runtime
From: Grazvydas Ignotas @ 2012-04-23 15:32 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: linux-fbdev, linux-omap
In-Reply-To: <1335183802.30659.17.camel@deskari>
On Mon, Apr 23, 2012 at 3:23 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> On Thu, 2012-03-29 at 02:45 +0300, Grazvydas Ignotas wrote:
>> VENC type (composite/svideo) doesn't have to be fixed by board wiring,
>> it is possible to provide both connectors, which is what pandora does.
>> Having to recompile the kernel for users who have TV connector types
>> that's don't match default board setting is very inconvenient, especially
>> for users of a consumer device, so add support for switching VENC type
>> at runtime over a new sysfs file venc_type.
>>
>> Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
>> ---
>> Documentation/arm/OMAP/DSS | 1 +
>> drivers/video/omap2/dss/venc.c | 55 +++++++++++++++++++++++++++++++++++++++-
>> 2 files changed, 55 insertions(+), 1 deletions(-)
>>
>> diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
>> index 888ae7b..18e2214 100644
>> --- a/Documentation/arm/OMAP/DSS
>> +++ b/Documentation/arm/OMAP/DSS
>> @@ -156,6 +156,7 @@ timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
>> "pal" and "ntsc"
>> panel_name
>> tear_elim Tearing elimination 0=off, 1=on
>> +venc_type Output type (video encoder only): "composite" or "svideo"
>
> I think we could have a better name here. "venc" name is quite obscure
> on the user level. And it's not even quite correct, venc stays the same,
> it's just the output that is changed. "output_type"? "connector"?
> "connector_type"?
I'll go for output_type then, connector* associates with fixed hardware to me.
I'll take care of other comments too.
--
Gražvydas
^ permalink raw reply
* Re: [PATCH 1/2] video: msm: Fix section mismatches in mddi.c
From: David Brown @ 2012-04-23 16:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4F94F3D7.5030904@gmx.de>
On Mon, Apr 23, 2012 at 06:16:55AM +0000, Florian Tobias Schandinat wrote:
> On 04/12/2012 06:45 PM, David Brown wrote:
> > The change
> > commit 461cbe77d0a4f887c33a3a95ea68a7daf23b4302
> > Author: Gregory Bean <gbean@codeaurora.org>
> > Date: Wed Jul 28 10:22:13 2010 -0700
> >
> > video: msm: Fix section mismatch in mddi.c.
> >
> > fixes a section mismatch between the board file and the driver's probe
> > function, however, it misses the additional mismatches between the
> > probe function and some routines it calls. Fix these up as well.
> >
> > Signed-off-by: David Brown <davidb@codeaurora.org>
>
> Applied.
Hmm. I guess it is somewhat my fault, since I sent the message To
both myself and you. I've already applied this to the MSM tree, and I
believe it has been merged into Linus' tree. I don't think it'll be
an issue, since git merge will handle the duplicate patch fine.
Next time, I'll try to be clearer about which tree I'm thinking for a
patch to go through.
David
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply
* [PATCH v2] OMAPDSS: VENC: allow switching venc output type at runtime
From: Grazvydas Ignotas @ 2012-04-23 21:08 UTC (permalink / raw)
To: linux-fbdev; +Cc: linux-omap, Tomi Valkeinen, Grazvydas Ignotas
VENC output type (composite/svideo) doesn't have to be fixed by board
wiring, it is possible to also provide composite signal through svideo
luminance connector (software enabled), which is what pandora does.
Having to recompile the kernel for users who have TV connector types
that don't match default board setting is very inconvenient, especially
for users of a consumer device, so add support for switching VENC output
type at runtime over a new sysfs file output_type.
Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
---
Documentation/arm/OMAP/DSS | 1 +
drivers/video/omap2/dss/venc.c | 54 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletions(-)
diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS
index 888ae7b..d0aea91 100644
--- a/Documentation/arm/OMAP/DSS
+++ b/Documentation/arm/OMAP/DSS
@@ -156,6 +156,7 @@ timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
"pal" and "ntsc"
panel_name
tear_elim Tearing elimination 0=off, 1=on
+output_type Output type (video encoder only): "composite" or "svideo"
There are also some debugfs files at <debugfs>/omapdss/ which show information
about clocks and registers.
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 9c3daf7..bde0153 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -485,16 +485,68 @@ unsigned long venc_get_pixel_clock(void)
return 13500000;
}
+static ssize_t display_output_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ const char *ret;
+
+ switch (dssdev->phy.venc.type) {
+ case OMAP_DSS_VENC_TYPE_COMPOSITE:
+ ret = "composite";
+ break;
+ case OMAP_DSS_VENC_TYPE_SVIDEO:
+ ret = "svideo";
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", ret);
+}
+
+static ssize_t display_output_type_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct omap_dss_device *dssdev = to_dss_device(dev);
+ enum omap_dss_venc_type new_type;
+
+ if (sysfs_streq("composite", buf))
+ new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
+ else if (sysfs_streq("svideo", buf))
+ new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
+ else
+ return -EINVAL;
+
+ mutex_lock(&venc.venc_lock);
+
+ if (dssdev->phy.venc.type != new_type) {
+ dssdev->phy.venc.type = new_type;
+ if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
+ venc_power_off(dssdev);
+ venc_power_on(dssdev);
+ }
+ }
+
+ mutex_unlock(&venc.venc_lock);
+
+ return size;
+}
+
+static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
+ display_output_type_show, display_output_type_store);
+
/* driver */
static int venc_panel_probe(struct omap_dss_device *dssdev)
{
dssdev->panel.timings = omap_dss_pal_timings;
- return 0;
+ return device_create_file(&dssdev->dev, &dev_attr_output_type);
}
static void venc_panel_remove(struct omap_dss_device *dssdev)
{
+ device_remove_file(&dssdev->dev, &dev_attr_output_type);
}
static int venc_panel_enable(struct omap_dss_device *dssdev)
--
1.7.0.4
^ permalink raw reply related
* [PULL for v3.5] SH Mobile LCDC overlay support
From: Laurent Pinchart @ 2012-04-24 11:31 UTC (permalink / raw)
To: linux-fbdev
Hi Florian,
Could you please pull the following patches that add overlay support for the
SH Mobile LCDC ? They have been posted for review as part of a bigger series
some time ago.
The following changes since commit d313a86d2efb2c5568832389663322e93e291c59:
i.MX28: Shut down the LCD controller to avoid BootROM sampling bug
(2012-04-21 21:53:12 +0000)
are available in the git repository at:
git://linuxtv.org/pinchartl/fbdev.git planes
Laurent Pinchart (3):
fbdev: sh_mobile_lcdc: Constify sh_mobile_lcdc_fix structure
fbdev: sh_mobile_lcdc: Rename fb operation handlers with a common prefix
fbdev: sh_mobile_lcdc: Implement overlays support
drivers/video/sh_mobile_lcdcfb.c | 1004 +++++++++++++++++++++++++++++++++----
include/video/sh_mobile_lcdc.h | 7 +
2 files changed, 915 insertions(+), 96 deletions(-)
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PULL for v3.5] fb: exynos: Fix MIPI/DSI front/back porch settings
From: Laurent Pinchart @ 2012-04-24 12:44 UTC (permalink / raw)
To: linux-fbdev
Hi Florian,
Could you please pull the following fix ?
The following changes since commit d313a86d2efb2c5568832389663322e93e291c59:
i.MX28: Shut down the LCD controller to avoid BootROM sampling bug
(2012-04-21 21:53:12 +0000)
are available in the git repository at:
git://linuxtv.org/pinchartl/fbdev.git fixes
Laurent Pinchart (1):
fb: exynos: Fix MIPI/DSI front/back porch settings
drivers/video/exynos/exynos_mipi_dsi_common.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
--
Regards,
Laurent Pinchart
^ permalink raw reply
* RE: [PATCH] drivers/video/ep93xx-fb.c: clean up error-handling code
From: Joe Perches @ 2012-04-24 12:46 UTC (permalink / raw)
To: Julia Lawall
Cc: Jingoo Han, 'Ryan Mallon',
'Florian Tobias Schandinat', kernel-janitors, linux-fbdev,
linux-kernel
In-Reply-To: <alpine.DEB.2.02.1204190713200.1954@localhost6.localdomain6>
On Thu, 2012-04-19 at 07:14 +0200, Julia Lawall wrote:
> I don't know thw impact of the ./. I use the options
>
> --nokeywords --nogit-fallback --subsystem --norolestats -f
>
> julia
>
> On Thu, 19 Apr 2012, Jingoo Han wrote:
>
> >> -----Original Message-----
> >> From: Ryan Mallon
[]
> >> Oddly, scripts/get_maintainer.pl on this file doesn't return me, even
> >> though, according to git blame, I am the author of 90% of the commits.
> >> Should I have an entry in the MAINTAINERS file, or is
> >> scripts/get_maintainer.pl not working properly?
> >
> > There are optional differences in using scripts/get_maintainer.pl.
> > If you use './' ahead of file path, you will see your name.
> >
> > Without './' ahead of 'drivers/video/ep93xx-fb.c':
> > ./scripts/get_maintainer.pl --file drivers/video/ep93xx-fb.c
> > Florian Tobias Schandinat <FlorianSchandinat@gmx.de> (maintainer:FRAMEBUFFER LAYER)
> > linux-fbdev@vger.kernel.org (open list:FRAMEBUFFER LAYER)
> > linux-kernel@vger.kernel.org (open list)
> >
> > With './' ahead of 'drivers/video/ep93xx-fb.c':
> > ./scripts/get_maintainer.pl --file ./drivers/video/ep93xx-fb.c
> > Ryan Mallon <rmallon@gmail.com> (commit_signer:2/3g%)
> > Paul Gortmaker <paul.gortmaker@windriver.com> (commit_signer:1/33%)
> > H Hartley Sweeten <hsweeten@visionengravers.com> (commit_signer:1/33%)
> > Jesper Juhl <jj@chaosbits.net> (commit_signer:1/33%)
> > Jiri Kosina <jkosina@suse.cz> (commit_signer:1/33%)
> > linux-kernel@vger.kernel.org (open list)
Prefixing "./" to the file path bypasses the normal
get_maintainers pattern check for file maintainership.
Florian Schandinat and linux-fbdev are not returned
in the second lookup above.
One of the patterns for FRAMEBUFFER is
F: drivers/video/
which is a direct match for is ep93xx-fb.c file,
so --git is not used by default.
Adding --git may be appropriate and it also returns
Ryan's name in this case.
$ ./scripts/get_maintainer.pl -f drivers/video/ep93xx-fb.c
Florian Tobias Schandinat <FlorianSchandinat@gmx.de> (maintainer:FRAMEBUFFER LAYER)
linux-fbdev@vger.kernel.org (open list:FRAMEBUFFER LAYER)
linux-kernel@vger.kernel.org (open list)
$ ./scripts/get_maintainer.pl --git -f drivers/video/ep93xx-fb.c
Florian Tobias Schandinat <FlorianSchandinat@gmx.de> (maintainer:FRAMEBUFFER LAYER)
Ryan Mallon <rmallon@gmail.com> (commit_signer:2/3g%)
Paul Gortmaker <paul.gortmaker@windriver.com> (commit_signer:1/33%)
H Hartley Sweeten <hsweeten@visionengravers.com> (commit_signer:1/33%)
Jesper Juhl <jj@chaosbits.net> (commit_signer:1/33%)
Jiri Kosina <jkosina@suse.cz> (commit_signer:1/33%)
linux-fbdev@vger.kernel.org (open list:FRAMEBUFFER LAYER)
linux-kernel@vger.kernel.org (open list)
Nominally, as framebuffer maintainer, Florian
should also have "signed-off" on these commits,
but many subsystems don't actually have a
single path or person for patches and commits.
This file came into the tree via Andrew Morton.
Another way to investigate who actually does
work on an individual file is to use the
get_maintainer.pl option "--interactive".
That can give you an output like:
* # email/list and role:stats auth sign
* 1 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
maintainer:FRAMEBUFFER LAYER
* 2 Ryan Mallon <rmallon@gmail.com> 4 4
commit_signer:2/3g%,authored lines:645/650™%,commits:4/8P%
* 3 Paul Gortmaker <paul.gortmaker@windriver.com> 1 1
commit_signer:1/33%,commits:1/8\x12%
* 4 H Hartley Sweeten <hsweeten@visionengravers.com> 0 2
commit_signer:1/33%,commits:2/8%%
* 5 Jesper Juhl <jj@chaosbits.net> 0 1
commit_signer:1/33%
* 6 Jiri Kosina <jkosina@suse.cz> 0 1
commit_signer:1/33%
* 7 Andrew Morton <akpm@linux-foundation.org> 0 2
commits:2/8%%
* 8 Russell King <rmk+kernel@arm.linux.org.uk> 0 1
commits:1/8\x12%
* 9 linux-fbdev@vger.kernel.org
open list:FRAMEBUFFER LAYER
* 10 linux-kernel@vger.kernel.org
open list
About maintainership for individual files:
If anyone thinks they are the maintainer for
a particular file, generally they should submit
a patch to MAINTAINERS adding a section with
their name, maintainership level and an
appropriate file pattern.
^ permalink raw reply
* Re: [PATCH 0/4] video: add support for the AUO-K190X epd controllers
From: Heiko Stübner @ 2012-04-24 13:44 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201203281932.55438.heiko@sntech.de>
Hi Florian,
Am Mittwoch, 28. März 2012, 19:32:54 schrieb Heiko Stübner:
> This series adds basic support for the AUO-K190X family of epaper
> controllers which consists at the moment of the K1900 and K1901.
>
> These controllers are used mostly in the OEM line of Qisda ebook readers
> sold under different brands worldwide. Among those are the Medion/Thalia
> Oyo 1 + 2, the bq Avant and Avant 3, the Asus eeeReader DR-900, BenQ K60
> and dozens more.
>
> The _dpy_update, _dpy_update_pages and _need_refresh functions are
> intentional duplicated. Currently they do the same, but as the
> controllers emit a greatly different runtime behaviour there is a lot
> of room for future controller-specific performance improvements.
>
> The series also includes the patch which adds a first_io callback to
> defio. This creates a nice way to parallelise the wakup when it is known
> that the controller is needed at the end of the defio cycle.
ping on this series?
Is anything more needed?
Thanks
Heiko
> Heiko Stuebner (4):
> fb_defio: add first_io callback
> video: auo_k190x: add code shared by controller drivers
> video: auo_k190x: add driver for AUO-K1900 variant
> video: auo_k190x: add driver for the AUO-K1901 variant
>
> drivers/video/Kconfig | 28 ++
> drivers/video/Makefile | 3 +
> drivers/video/auo_k1900fb.c | 198 ++++++++
> drivers/video/auo_k1901fb.c | 251 +++++++++++
> drivers/video/auo_k190x.c | 1038
> +++++++++++++++++++++++++++++++++++++++++++ drivers/video/auo_k190x.h |
> 129 ++++++
> drivers/video/fb_defio.c | 4 +
> include/linux/fb.h | 1 +
> include/video/auo_k190xfb.h | 106 +++++
> 9 files changed, 1758 insertions(+), 0 deletions(-)
> create mode 100644 drivers/video/auo_k1900fb.c
> create mode 100644 drivers/video/auo_k1901fb.c
> create mode 100644 drivers/video/auo_k190x.c
> create mode 100644 drivers/video/auo_k190x.h
> create mode 100644 include/video/auo_k190xfb.h
^ permalink raw reply
* Re: [PATCH] drivers/video/ep93xx-fb.c: clean up error-handling code
From: Ryan Mallon @ 2012-04-24 21:12 UTC (permalink / raw)
To: Joe Perches
Cc: Julia Lawall, Jingoo Han, 'Florian Tobias Schandinat',
kernel-janitors, linux-fbdev, linux-kernel
In-Reply-To: <1335271586.25429.19.camel@joe2Laptop>
On 24/04/12 22:46, Joe Perches wrote:
> On Thu, 2012-04-19 at 07:14 +0200, Julia Lawall wrote:
>> I don't know thw impact of the ./. I use the options
>>
>> --nokeywords --nogit-fallback --subsystem --norolestats -f
>>
>> julia
>>
>> On Thu, 19 Apr 2012, Jingoo Han wrote:
>>
>>>> -----Original Message-----
>>>> From: Ryan Mallon
> []
>>>> Oddly, scripts/get_maintainer.pl on this file doesn't return me, even
>>>> though, according to git blame, I am the author of 90% of the commits.
>>>> Should I have an entry in the MAINTAINERS file, or is
>>>> scripts/get_maintainer.pl not working properly?
>>>
>>> There are optional differences in using scripts/get_maintainer.pl.
>>> If you use './' ahead of file path, you will see your name.
>>>
>>> Without './' ahead of 'drivers/video/ep93xx-fb.c':
>>> ./scripts/get_maintainer.pl --file drivers/video/ep93xx-fb.c
>>> Florian Tobias Schandinat <FlorianSchandinat@gmx.de> (maintainer:FRAMEBUFFER LAYER)
>>> linux-fbdev@vger.kernel.org (open list:FRAMEBUFFER LAYER)
>>> linux-kernel@vger.kernel.org (open list)
>>>
>>> With './' ahead of 'drivers/video/ep93xx-fb.c':
>>> ./scripts/get_maintainer.pl --file ./drivers/video/ep93xx-fb.c
>>> Ryan Mallon <rmallon@gmail.com> (commit_signer:2/3g%)
>>> Paul Gortmaker <paul.gortmaker@windriver.com> (commit_signer:1/33%)
>>> H Hartley Sweeten <hsweeten@visionengravers.com> (commit_signer:1/33%)
>>> Jesper Juhl <jj@chaosbits.net> (commit_signer:1/33%)
>>> Jiri Kosina <jkosina@suse.cz> (commit_signer:1/33%)
>>> linux-kernel@vger.kernel.org (open list)
>
> Prefixing "./" to the file path bypasses the normal
> get_maintainers pattern check for file maintainership.
>
> Florian Schandinat and linux-fbdev are not returned
> in the second lookup above.
>
> One of the patterns for FRAMEBUFFER is
> F: drivers/video/
> which is a direct match for is ep93xx-fb.c file,
> so --git is not used by default.
>
> Adding --git may be appropriate and it also returns
> Ryan's name in this case.
Hi Joe,
Thanks for the info.
> Nominally, as framebuffer maintainer, Florian
> should also have "signed-off" on these commits,
> but many subsystems don't actually have a
> single path or person for patches and commits.
>
> This file came into the tree via Andrew Morton.
>
The original driver was written before Florian became the
framebuffer maintainer. The subsystem had no real maintainer
at the time, which is why it went via Andrew.
> About maintainership for individual files:
>
> If anyone thinks they are the maintainer for
> a particular file, generally they should submit
> a patch to MAINTAINERS adding a section with
> their name, maintainership level and an
> appropriate file pattern.
Hmm, perhaps author is a better term than maintainer here. Any
patches should still go via the framebuffer maintainer, Florian,
but it would be useful in many cases for the original and/or
most regular commit author to also get Cc'ed since in many
cases they will have a better understanding of the code, even
if the aren't "maintaining" it.
~Ryan
^ permalink raw reply
* RE: [PATCH] drivers/video/ep93xx-fb.c: clean up error-handling code
From: Jingoo Han @ 2012-04-25 1:19 UTC (permalink / raw)
To: 'Joe Perches'
Cc: 'Ryan Mallon', 'Florian Tobias Schandinat',
kernel-janitors, linux-fbdev, linux-kernel,
'Julia Lawall', 'Jingoo Han'
In-Reply-To: <1335271586.25429.19.camel@joe2Laptop>
On Tue, 24 Apr 2012, Joe Perches wrote:
> -----Original Message-----
> On Thu, 2012-04-19 at 07:14 +0200, Julia Lawall wrote:
> > I don't know thw impact of the ./. I use the options
> >
> > --nokeywords --nogit-fallback --subsystem --norolestats -f
> >
> > julia
> >
> > On Thu, 19 Apr 2012, Jingoo Han wrote:
> >
> > >> -----Original Message-----
> > >> From: Ryan Mallon
> []
> > >> Oddly, scripts/get_maintainer.pl on this file doesn't return me, even
> > >> though, according to git blame, I am the author of 90% of the commits.
> > >> Should I have an entry in the MAINTAINERS file, or is
> > >> scripts/get_maintainer.pl not working properly?
> > >
> > > There are optional differences in using scripts/get_maintainer.pl.
> > > If you use './' ahead of file path, you will see your name.
> > >
> > > Without './' ahead of 'drivers/video/ep93xx-fb.c':
> > > ./scripts/get_maintainer.pl --file drivers/video/ep93xx-fb.c
> > > Florian Tobias Schandinat <FlorianSchandinat@gmx.de> (maintainer:FRAMEBUFFER LAYER)
> > > linux-fbdev@vger.kernel.org (open list:FRAMEBUFFER LAYER)
> > > linux-kernel@vger.kernel.org (open list)
> > >
> > > With './' ahead of 'drivers/video/ep93xx-fb.c':
> > > ./scripts/get_maintainer.pl --file ./drivers/video/ep93xx-fb.c
> > > Ryan Mallon <rmallon@gmail.com> (commit_signer:2/3g%)
> > > Paul Gortmaker <paul.gortmaker@windriver.com> (commit_signer:1/33%)
> > > H Hartley Sweeten <hsweeten@visionengravers.com> (commit_signer:1/33%)
> > > Jesper Juhl <jj@chaosbits.net> (commit_signer:1/33%)
> > > Jiri Kosina <jkosina@suse.cz> (commit_signer:1/33%)
> > > linux-kernel@vger.kernel.org (open list)
>
> Prefixing "./" to the file path bypasses the normal
> get_maintainers pattern check for file maintainership.
>
> Florian Schandinat and linux-fbdev are not returned
> in the second lookup above.
>
> One of the patterns for FRAMEBUFFER is
> F: drivers/video/
> which is a direct match for is ep93xx-fb.c file,
> so --git is not used by default.
>
> Adding --git may be appropriate and it also returns
> Ryan's name in this case.
>
> $ ./scripts/get_maintainer.pl -f drivers/video/ep93xx-fb.c
> Florian Tobias Schandinat <FlorianSchandinat@gmx.de> (maintainer:FRAMEBUFFER LAYER)
> linux-fbdev@vger.kernel.org (open list:FRAMEBUFFER LAYER)
> linux-kernel@vger.kernel.org (open list)
>
> $ ./scripts/get_maintainer.pl --git -f drivers/video/ep93xx-fb.c
> Florian Tobias Schandinat <FlorianSchandinat@gmx.de> (maintainer:FRAMEBUFFER LAYER)
> Ryan Mallon <rmallon@gmail.com> (commit_signer:2/3g%)
> Paul Gortmaker <paul.gortmaker@windriver.com> (commit_signer:1/33%)
> H Hartley Sweeten <hsweeten@visionengravers.com> (commit_signer:1/33%)
> Jesper Juhl <jj@chaosbits.net> (commit_signer:1/33%)
> Jiri Kosina <jkosina@suse.cz> (commit_signer:1/33%)
> linux-fbdev@vger.kernel.org (open list:FRAMEBUFFER LAYER)
> linux-kernel@vger.kernel.org (open list)
>
> Nominally, as framebuffer maintainer, Florian
> should also have "signed-off" on these commits,
> but many subsystems don't actually have a
> single path or person for patches and commits.
>
> This file came into the tree via Andrew Morton.
>
> Another way to investigate who actually does
> work on an individual file is to use the
> get_maintainer.pl option "--interactive".
Thank you for your reply.
It is very helpful.
Best regards,
Jingoo Han
>
> That can give you an output like:
>
> * # email/list and role:stats auth sign
> * 1 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
> maintainer:FRAMEBUFFER LAYER
> * 2 Ryan Mallon <rmallon@gmail.com> 4 4
> commit_signer:2/3g%,authored lines:645/650™%,commits:4/8P%
> * 3 Paul Gortmaker <paul.gortmaker@windriver.com> 1 1
> commit_signer:1/33%,commits:1/8\x12%
> * 4 H Hartley Sweeten <hsweeten@visionengravers.com> 0 2
> commit_signer:1/33%,commits:2/8%%
> * 5 Jesper Juhl <jj@chaosbits.net> 0 1
> commit_signer:1/33%
> * 6 Jiri Kosina <jkosina@suse.cz> 0 1
> commit_signer:1/33%
> * 7 Andrew Morton <akpm@linux-foundation.org> 0 2
> commits:2/8%%
> * 8 Russell King <rmk+kernel@arm.linux.org.uk> 0 1
> commits:1/8\x12%
> * 9 linux-fbdev@vger.kernel.org
> open list:FRAMEBUFFER LAYER
> * 10 linux-kernel@vger.kernel.org
> open list
>
> About maintainership for individual files:
>
> If anyone thinks they are the maintainer for
> a particular file, generally they should submit
> a patch to MAINTAINERS adding a section with
> their name, maintainership level and an
> appropriate file pattern.
^ permalink raw reply
* Re: [PATCH v2] OMAPDSS: VENC: allow switching venc output type at runtime
From: Tomi Valkeinen @ 2012-04-25 12:37 UTC (permalink / raw)
To: Grazvydas Ignotas; +Cc: linux-fbdev, linux-omap
In-Reply-To: <1335215334-32608-1-git-send-email-notasas@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 858 bytes --]
On Tue, 2012-04-24 at 00:08 +0300, Grazvydas Ignotas wrote:
> VENC output type (composite/svideo) doesn't have to be fixed by board
> wiring, it is possible to also provide composite signal through svideo
> luminance connector (software enabled), which is what pandora does.
>
> Having to recompile the kernel for users who have TV connector types
> that don't match default board setting is very inconvenient, especially
> for users of a consumer device, so add support for switching VENC output
> type at runtime over a new sysfs file output_type.
>
> Signed-off-by: Grazvydas Ignotas <notasas@gmail.com>
> ---
> Documentation/arm/OMAP/DSS | 1 +
> drivers/video/omap2/dss/venc.c | 54 +++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 54 insertions(+), 1 deletions(-)
Looks fine to me. Thanks! Applying.
Tomi
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH 0/4] video: add support for the AUO-K190X epd controllers
From: Florian Tobias Schandinat @ 2012-04-26 6:44 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201203281932.55438.heiko@sntech.de>
Hi Heiko,
On 04/24/2012 01:44 PM, Heiko Stübner wrote:
> Hi Florian,
>
> Am Mittwoch, 28. März 2012, 19:32:54 schrieb Heiko Stübner:
>> This series adds basic support for the AUO-K190X family of epaper
>> controllers which consists at the moment of the K1900 and K1901.
>>
>> These controllers are used mostly in the OEM line of Qisda ebook readers
>> sold under different brands worldwide. Among those are the Medion/Thalia
>> Oyo 1 + 2, the bq Avant and Avant 3, the Asus eeeReader DR-900, BenQ K60
>> and dozens more.
>>
>> The _dpy_update, _dpy_update_pages and _need_refresh functions are
>> intentional duplicated. Currently they do the same, but as the
>> controllers emit a greatly different runtime behaviour there is a lot
>> of room for future controller-specific performance improvements.
>>
>> The series also includes the patch which adds a first_io callback to
>> defio. This creates a nice way to parallelise the wakup when it is known
>> that the controller is needed at the end of the defio cycle.
>
> ping on this series?
>
> Is anything more needed?
I wanted to do do a patch to show you what I want but didn't find the
time to do so, so I'll try to explain it:
If I remember correctly the problem with the patches is the Kconfig menu
structure as "make menuconfig" shows it: Your driver ends up in the
graphics system and not in the framebuffer subsystem. The problem is the
invisible entry you add, it has no dependency on the FB subsystem and
therefore terminates the framebuffer menuconfig. The easy fix would be
to make it depend on fb but I'd consider it nicer to change the hidden
entry into a menunconfig one and let the individual drivers depend on it
rather than select it.
Best regards,
Florian Tobias Schandinat
>
>
> Thanks
> Heiko
>
>> Heiko Stuebner (4):
>> fb_defio: add first_io callback
>> video: auo_k190x: add code shared by controller drivers
>> video: auo_k190x: add driver for AUO-K1900 variant
>> video: auo_k190x: add driver for the AUO-K1901 variant
>>
>> drivers/video/Kconfig | 28 ++
>> drivers/video/Makefile | 3 +
>> drivers/video/auo_k1900fb.c | 198 ++++++++
>> drivers/video/auo_k1901fb.c | 251 +++++++++++
>> drivers/video/auo_k190x.c | 1038
>> +++++++++++++++++++++++++++++++++++++++++++ drivers/video/auo_k190x.h |
>> 129 ++++++
>> drivers/video/fb_defio.c | 4 +
>> include/linux/fb.h | 1 +
>> include/video/auo_k190xfb.h | 106 +++++
>> 9 files changed, 1758 insertions(+), 0 deletions(-)
>> create mode 100644 drivers/video/auo_k1900fb.c
>> create mode 100644 drivers/video/auo_k1901fb.c
>> create mode 100644 drivers/video/auo_k190x.c
>> create mode 100644 drivers/video/auo_k190x.h
>> create mode 100644 include/video/auo_k190xfb.h
>
>
^ permalink raw reply
* Re: [PATCH 0/4] video: add support for the AUO-K190X epd controllers
From: Heiko Stübner @ 2012-04-26 7:29 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201203281932.55438.heiko@sntech.de>
Hi Florian,
Am Donnerstag, 26. April 2012, 08:44:11 schrieb Florian Tobias Schandinat:
> Hi Heiko,
>
> On 04/24/2012 01:44 PM, Heiko Stübner wrote:
> > Hi Florian,
> >
> > Am Mittwoch, 28. März 2012, 19:32:54 schrieb Heiko Stübner:
> >> This series adds basic support for the AUO-K190X family of epaper
> >> controllers which consists at the moment of the K1900 and K1901.
> >>
> >> These controllers are used mostly in the OEM line of Qisda ebook readers
> >> sold under different brands worldwide. Among those are the Medion/Thalia
> >> Oyo 1 + 2, the bq Avant and Avant 3, the Asus eeeReader DR-900, BenQ K60
> >> and dozens more.
> >>
> >> The _dpy_update, _dpy_update_pages and _need_refresh functions are
> >> intentional duplicated. Currently they do the same, but as the
> >> controllers emit a greatly different runtime behaviour there is a lot
> >> of room for future controller-specific performance improvements.
> >>
> >> The series also includes the patch which adds a first_io callback to
> >> defio. This creates a nice way to parallelise the wakup when it is known
> >> that the controller is needed at the end of the defio cycle.
> >
> > ping on this series?
> >
> > Is anything more needed?
>
> I wanted to do do a patch to show you what I want but didn't find the
> time to do so, so I'll try to explain it:
>
> If I remember correctly the problem with the patches is the Kconfig menu
> structure as "make menuconfig" shows it: Your driver ends up in the
> graphics system and not in the framebuffer subsystem. The problem is the
> invisible entry you add, it has no dependency on the FB subsystem and
> therefore terminates the framebuffer menuconfig. The easy fix would be
> to make it depend on fb but I'd consider it nicer to change the hidden
> entry into a menunconfig one and let the individual drivers depend on it
> rather than select it.
ok, will change it to work like this.
I was unsure on what was the correct way to do it. At first I had it
implemented like you described but as the base driver does not provide any
usable functionality in itself changed it to the invisible config node.
Personally I have no hard preference, and will resubmit the series with the
change.
Thanks
Heiko
> >
> >> Heiko Stuebner (4):
> >> fb_defio: add first_io callback
> >> video: auo_k190x: add code shared by controller drivers
> >> video: auo_k190x: add driver for AUO-K1900 variant
> >> video: auo_k190x: add driver for the AUO-K1901 variant
> >>
> >> drivers/video/Kconfig | 28 ++
> >> drivers/video/Makefile | 3 +
> >> drivers/video/auo_k1900fb.c | 198 ++++++++
> >> drivers/video/auo_k1901fb.c | 251 +++++++++++
> >> drivers/video/auo_k190x.c | 1038
> >>
> >> +++++++++++++++++++++++++++++++++++++++++++ drivers/video/auo_k190x.h
> >> | 129 ++++++
> >>
> >> drivers/video/fb_defio.c | 4 +
> >> include/linux/fb.h | 1 +
> >> include/video/auo_k190xfb.h | 106 +++++
> >> 9 files changed, 1758 insertions(+), 0 deletions(-)
> >> create mode 100644 drivers/video/auo_k1900fb.c
> >> create mode 100644 drivers/video/auo_k1901fb.c
> >> create mode 100644 drivers/video/auo_k190x.c
> >> create mode 100644 drivers/video/auo_k190x.h
> >> create mode 100644 include/video/auo_k190xfb.h
^ permalink raw reply
* Re: [PATCH 2/4] misc: add LM3533 ambient light sensor driver
From: Johan Hovold @ 2012-04-26 11:52 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Richard Purdie, Samuel Ortiz, Arnd Bergmann,
Florian Tobias Schandinat, Andrew Morton, linux-kernel,
linux-fbdev
In-Reply-To: <20120420173754.GA22222@kroah.com>
On Fri, Apr 20, 2012 at 10:37:54AM -0700, Greg Kroah-Hartman wrote:
> On Fri, Apr 20, 2012 at 07:28:49PM +0200, Johan Hovold wrote:
> > On Fri, Apr 20, 2012 at 08:57:34AM -0700, Greg Kroah-Hartman wrote:
> > > On Fri, Apr 20, 2012 at 05:30:24PM +0200, Johan Hovold wrote:
> > > > Add sub-driver for the ambient light sensor in National Semiconductor /
> > > > TI LM3533 lighting power chips.
> > > >
> > > > Raw ADC values as well as current ALS zone can be retrieved through
> > > > sysfs. The ALS zone can also be read using a character device
> > > > (/dev/lm3533-als) which is updated on zone changes (interrupt driven or
> > > > polled).
> > > >
> > > > The driver provides a configuration interface through sysfs.
> > >
> > > Which seems to not be documented at all :(
> >
> > There are the following sysfs entries for configuring ALS control:
>
> <snip>
>
> That's fine, but you need a Documentation/ABI entry for any new sysfs
> file you create.
> > > What about using the iio interface for this instead? Doesn't that
> > > already provide this standard interface you are looking for?
> >
> > I had a look at iio last fall and decided not to use it at the time. I
> > can't remember exactly what the reasons were right now, so I'll have
> > to get back to you on this.
>
> Please look into this, the iio framework is about to move out of the
> staging tree for 3.5, so there should not be any reason for you to
> create yet-another user api for this type of thing.
We had an initial requirement to support fairly old kernels, but this
have since been relaxed (and has of course never in itself been a valid
reason to not use iio for upstream). As iio is moving out of staging, I
see no problems using it, and the required changes appear quite small.
I'll submit a v2 against iio and make sure to document the sysfs-entries.
Thanks,
Johan
^ permalink raw reply
* [PATCH] i2c: Split I2C_M_NOSTART support out of I2C_FUNC_PROTOCOL_MANGLING
From: Mark Brown @ 2012-04-26 12:37 UTC (permalink / raw)
To: Jean Delvare, Wolfram Sang
Cc: Florian Tobias Schandinat, Dmitry Torokhov,
linux-i2c-u79uwXL29TY76Z2rM5mHXA,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA, Mark Brown
Since there are uses for I2C_M_NOSTART which are much more sensible and
standard than most of the protocol mangling functionality (the main one
being gather writes to devices where something like a register address
needs to be inserted before a block of data) create a new I2C_FUNC_NOSTART
for this feature and update all the users to use it.
In the case of regmap-i2c we remove the requirement for mangling as
I2C_M_NOSTART is the only mangling feature which is being used.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
Documentation/i2c/functionality | 1 +
drivers/base/regmap/regmap-i2c.c | 2 +-
drivers/i2c/algos/i2c-algo-bit.c | 2 +-
drivers/i2c/algos/i2c-algo-pcf.c | 2 +-
drivers/i2c/busses/i2c-nuc900.c | 3 ++-
drivers/i2c/busses/i2c-s3c2410.c | 3 ++-
drivers/input/joystick/as5011.c | 1 +
drivers/video/matrox/matroxfb_maven.c | 1 +
include/linux/i2c.h | 3 ++-
9 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality
index 42c17c1..fb2e77e 100644
--- a/Documentation/i2c/functionality
+++ b/Documentation/i2c/functionality
@@ -33,6 +33,7 @@ For the most up-to-date list of functionality constants, please check
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA Handles the SMBus write_block_data command
I2C_FUNC_SMBUS_READ_I2C_BLOCK Handles the SMBus read_i2c_block_data command
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK Handles the SMBus write_i2c_block_data command
+ I2C_FUNC_NOSTART Transfers can be sent without a start
A few combinations of the above flags are also defined for your convenience:
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index 5f6b247..fa6bf52 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -42,7 +42,7 @@ static int regmap_i2c_gather_write(void *context,
/* If the I2C controller can't do a gather tell the core, it
* will substitute in a linear write for us.
*/
- if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_PROTOCOL_MANGLING))
+ if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_NOSTART))
return -ENOTSUPP;
xfer[0].addr = i2c->addr;
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 7f0b832..fad22b0 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -608,7 +608,7 @@ bailout:
static u32 bit_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL |
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 5c23795..8b38986 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -401,7 +401,7 @@ out:
static u32 pcf_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL |
I2C_FUNC_PROTOCOL_MANGLING;
}
diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c
index 03b6157..a26dfb8 100644
--- a/drivers/i2c/busses/i2c-nuc900.c
+++ b/drivers/i2c/busses/i2c-nuc900.c
@@ -502,7 +502,8 @@ static int nuc900_i2c_xfer(struct i2c_adapter *adap,
/* declare our i2c functionality */
static u32 nuc900_i2c_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART |
+ I2C_FUNC_PROTOCOL_MANGLING;
}
/* i2c bus registration info */
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 8764d6a..faa1f23 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -591,7 +591,8 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
/* declare our i2c functionality */
static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART |
+ I2C_FUNC_PROTOCOL_MANGLING;
}
/* i2c bus registration info */
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
index 3063464..57d19d4 100644
--- a/drivers/input/joystick/as5011.c
+++ b/drivers/input/joystick/as5011.c
@@ -231,6 +231,7 @@ static int __devinit as5011_probe(struct i2c_client *client,
}
if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_NOSTART |
I2C_FUNC_PROTOCOL_MANGLING)) {
dev_err(&client->dev,
"need i2c bus that supports protocol mangling\n");
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 31b8f67..217678e 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -1243,6 +1243,7 @@ static int maven_probe(struct i2c_client *client,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA |
I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_NOSTART |
I2C_FUNC_PROTOCOL_MANGLING))
goto ERROR0;
if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 195d8b3..c18b5b1 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -540,7 +540,7 @@ struct i2c_msg {
__u16 flags;
#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
#define I2C_M_RD 0x0001 /* read data, from slave to master */
-#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */
#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
@@ -568,6 +568,7 @@ struct i2c_msg {
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
+#define I2C_FUNC_NOSTART 0x10000000 /* I2C_M_NOSTART */
#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
I2C_FUNC_SMBUS_WRITE_BYTE)
--
1.7.10
^ permalink raw reply related
* Re: [PATCH 1/4] mfd: add LM3533 lighting-power core driver
From: Mark Brown @ 2012-04-26 12:41 UTC (permalink / raw)
To: Johan Hovold
Cc: Richard Purdie, Samuel Ortiz, Arnd Bergmann, Greg Kroah-Hartman,
Florian Tobias Schandinat, Andrew Morton, linux-kernel,
linux-fbdev
In-Reply-To: <1334935826-12527-2-git-send-email-jhovold@gmail.com>
On Fri, Apr 20, 2012 at 05:30:23PM +0200, Johan Hovold wrote:
> +static int __lm3533_read(struct lm3533 *lm3533, u8 reg, u8 *val)
> +{
> + int ret;
> +
> + ret = lm3533->read(lm3533, reg, val);
> + if (ret < 0) {
Looks like you could save a bunch of code by using regmap for the
register I/O. This would also give you access to the cache and
diagnostic infrastructure it has.
^ permalink raw reply
* Re: [Xen-devel] [PATCH] drivers/video/xen-fbfront.c: add missing cleanup code
From: Konrad Rzeszutek Wilk @ 2012-04-26 21:42 UTC (permalink / raw)
To: Julia Lawall, FlorianSchandinat
Cc: Jeremy Fitzhardinge, xen-devel, linux-kernel, kernel-janitors,
linux-fbdev, virtualization
In-Reply-To: <1335088660-13219-1-git-send-email-Julia.Lawall@lip6.fr>
On Sun, Apr 22, 2012 at 11:57:40AM +0200, Julia Lawall wrote:
> From: Julia Lawall <Julia.Lawall@lip6.fr>
>
> The operations in the subsequent error-handling code appear to be also
> useful here.
How about doing it this way?
Florian, are you OK me carrying this patch in my tree for Linus or would
you prefer to do it?
commit a833fb9973b47cb30d1086e73f20b62a425bcd85
Author: Julia Lawall <Julia.Lawall@lip6.fr>
Date: Sun Apr 22 11:57:40 2012 +0200
drivers/video/xen-fbfront.c: add missing cleanup code
The operations in the subsequent error-handling code appear to be also
useful here.
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
[v1: Collapse some of the error handling functions]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index cb4529c..aa42160 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -458,26 +458,31 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
xenfb_init_shared_page(info, fb_info);
ret = xenfb_connect_backend(dev, info);
- if (ret < 0)
- goto error;
+ if (ret < 0) {
+ xenbus_dev_fatal(dev, ret, "xenfb_connect_backend");
+ goto error_fb;
+ }
ret = register_framebuffer(fb_info);
if (ret) {
- fb_deferred_io_cleanup(fb_info);
- fb_dealloc_cmap(&fb_info->cmap);
- framebuffer_release(fb_info);
xenbus_dev_fatal(dev, ret, "register_framebuffer");
- goto error;
+ goto error_fb;
}
info->fb_info = fb_info;
xenfb_make_preferred_console();
return 0;
- error_nomem:
- ret = -ENOMEM;
- xenbus_dev_fatal(dev, ret, "allocating device memory");
- error:
+error_fb:
+ fb_deferred_io_cleanup(fb_info);
+ fb_dealloc_cmap(&fb_info->cmap);
+ framebuffer_release(fb_info);
+error_nomem:
+ if (!ret) {
+ ret = -ENOMEM;
+ xenbus_dev_fatal(dev, ret, "allocating device memory");
+ }
+error:
xenfb_remove(dev);
return ret;
}
>
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
>
> ---
> Not tested.
>
> drivers/video/xen-fbfront.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
> index cb4529c..b0bd59c 100644
> --- a/drivers/video/xen-fbfront.c
> +++ b/drivers/video/xen-fbfront.c
> @@ -458,8 +458,13 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
> xenfb_init_shared_page(info, fb_info);
>
> ret = xenfb_connect_backend(dev, info);
> - if (ret < 0)
> + if (ret < 0) {
> + fb_deferred_io_cleanup(fb_info);
> + fb_dealloc_cmap(&fb_info->cmap);
> + framebuffer_release(fb_info);
> + xenbus_dev_fatal(dev, ret, "xenfb_connect_backend");
> goto error;
> + }
>
> ret = register_framebuffer(fb_info);
> if (ret) {
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
^ permalink raw reply related
* [PATCH] efifb: Skip DMI checks if the bootloader knows what it's doing
From: Matthew Garrett @ 2012-04-27 14:54 UTC (permalink / raw)
To: linux-fbdev; +Cc: pjones, linux-kernel, Matthew Garrett
The majority of the DMI checks in efifb are for cases where the bootloader
has provided invalid information. However, on some machines the overrides
may do more harm than good due to configuration differences between machines
with the same machine identifier. It turns out that it's possible for the
bootloader to get the correct information on GOP-based systems, but we
can't guarantee that the kernel's being booted with one that's been updated
to do so. Add support for a capabilities flag that can be set by the
bootloader, and skip the DMI checks in that case.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
drivers/video/efifb.c | 4 +++-
include/linux/screen_info.h | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index b4a632a..932abaa 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -553,7 +553,9 @@ static int __init efifb_init(void)
int ret;
char *option = NULL;
- dmi_check_system(dmi_system_table);
+ if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
+ !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
+ dmi_check_system(dmi_system_table);
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
return -ENODEV;
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index 899fbb4..fb3c5a8 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -68,6 +68,8 @@ struct screen_info {
#define VIDEO_FLAGS_NOCURSOR (1 << 0) /* The video mode has no cursor set */
+#define VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0)
+
#ifdef __KERNEL__
extern struct screen_info screen_info;
--
1.7.10
^ permalink raw reply related
* Re: [PATCH] efifb: Skip DMI checks if the bootloader knows what it's doing
From: Peter Jones @ 2012-04-27 17:37 UTC (permalink / raw)
To: Matthew Garrett; +Cc: linux-fbdev, linux-kernel
In-Reply-To: <1335538451-4395-1-git-send-email-mjg@redhat.com>
On 04/27/2012 10:54 AM, Matthew Garrett wrote:
> The majority of the DMI checks in efifb are for cases where the bootloader
> has provided invalid information. However, on some machines the overrides
> may do more harm than good due to configuration differences between machines
> with the same machine identifier. It turns out that it's possible for the
> bootloader to get the correct information on GOP-based systems, but we
> can't guarantee that the kernel's being booted with one that's been updated
> to do so. Add support for a capabilities flag that can be set by the
> bootloader, and skip the DMI checks in that case.
>
> Signed-off-by: Matthew Garrett<mjg@redhat.com>
Looks right to me.
Acked-by: Peter Jones <pjones@redhat.com>
> ---
> drivers/video/efifb.c | 4 +++-
> include/linux/screen_info.h | 2 ++
> 2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
> index b4a632a..932abaa 100644
> --- a/drivers/video/efifb.c
> +++ b/drivers/video/efifb.c
> @@ -553,7 +553,9 @@ static int __init efifb_init(void)
> int ret;
> char *option = NULL;
>
> - dmi_check_system(dmi_system_table);
> + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
> + !(screen_info.capabilities& VIDEO_CAPABILITY_SKIP_QUIRKS))
> + dmi_check_system(dmi_system_table);
>
> if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
> return -ENODEV;
> diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
> index 899fbb4..fb3c5a8 100644
> --- a/include/linux/screen_info.h
> +++ b/include/linux/screen_info.h
> @@ -68,6 +68,8 @@ struct screen_info {
>
> #define VIDEO_FLAGS_NOCURSOR (1<< 0) /* The video mode has no cursor set */
>
> +#define VIDEO_CAPABILITY_SKIP_QUIRKS (1<< 0)
> +
> #ifdef __KERNEL__
> extern struct screen_info screen_info;
>
--
Peter
Any connection between your reality and mine is purely coincidental.
01234567890123456789012345678901234567890123456789012345678901234567890123456789
^ permalink raw reply
* Re: [PATCH v2] backlight: Add LMS501KF03 LCD panel driver
From: Sachin Kamat @ 2012-04-28 2:14 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <1334835208-32055-1-git-send-email-sachin.kamat@linaro.org>
Any comments on the revised patch?
On 19 April 2012 17:03, Sachin Kamat <sachin.kamat@linaro.org> wrote:
> LMS501KF03 is a 480x800 LCD module with brightness control.
> The driver uses 3-wired SPI inteface.
>
> Signed-off-by: Ilho Lee <Ilho215.lee@samsung.com>
> Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
> ---
> Changes since v1:
> Incorporated review comments from Florian Tobias Schandinat
> <FlorianSchandinat@gmx.de> - Simplied lms501kf03_ldi_enable and
> lms501kf03_ldi_disable function implementations.
> ---
> drivers/video/backlight/Kconfig | 8 +
> drivers/video/backlight/Makefile | 1 +
> drivers/video/backlight/lms501kf03.c | 525 ++++++++++++++++++++++++++++++++++
> 3 files changed, 534 insertions(+), 0 deletions(-)
> create mode 100644 drivers/video/backlight/lms501kf03.c
>
> diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
> index af16884..e216f77 100644
> --- a/drivers/video/backlight/Kconfig
> +++ b/drivers/video/backlight/Kconfig
> @@ -125,6 +125,14 @@ config LCD_AMS369FG06
> If you have an AMS369FG06 AMOLED Panel, say Y to enable its
> LCD control driver.
>
> +config LCD_LMS501KF03
> + tristate "LMS501KF03 AMOLED LCD Driver"
> + depends on SPI_GPIO && BACKLIGHT_CLASS_DEVICE
> + default n
> + help
> + If you have an 5.01" LMS501KF03 AMOLED Panel, say Y to enable its
> + LCD control driver.
> +
> endif # LCD_CLASS_DEVICE
>
> #
> diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
> index 36855ae..1b1e62a 100644
> --- a/drivers/video/backlight/Makefile
> +++ b/drivers/video/backlight/Makefile
> @@ -14,6 +14,7 @@ obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o
> obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o
> obj-$(CONFIG_LCD_LD9040) += ld9040.o
> obj-$(CONFIG_LCD_AMS369FG06) += ams369fg06.o
> +obj-$(CONFIG_LCD_LMS501KF03) += lms501kf03.o
>
> obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
> obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
> diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c
> new file mode 100644
> index 0000000..af25532
> --- /dev/null
> +++ b/drivers/video/backlight/lms501kf03.c
> @@ -0,0 +1,525 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * LMS501KF03 5.01" LCD module driver
> + *
> + * 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.
> +*/
> +
> +#include <linux/backlight.h>
> +#include <linux/delay.h>
> +#include <linux/fb.h>
> +#include <linux/gpio.h>
> +#include <linux/lcd.h>
> +#include <linux/module.h>
> +#include <linux/spi/spi.h>
> +#include <linux/wait.h>
> +
> +#define ENDDEF 0xFF00
> +#define COMMAND_ONLY 0x00
> +#define DATA_ONLY 0x01
> +
> +#define MIN_BRIGHTNESS 0
> +#define MAX_BRIGHTNESS 255
> +#define DEFAULT_BRIGHTNESS 150
> +
> +#define POWER_IS_ON(power) ((power) <= FB_BLANK_NORMAL)
> +
> +struct lms501kf03 {
> + struct device *dev;
> + struct spi_device *spi;
> + unsigned int power;
> + struct lcd_device *ld;
> + struct backlight_device *bd;
> + struct lcd_platform_data *lcd_pd;
> +};
> +
> +const unsigned short SEQ_PASSWORD[] = {
> + 0xb9, 0xff, 0x83, 0x69,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_POWER[] = {
> + 0xb1, 0x01, 0x00, 0x34, 0x06, 0x00, 0x14, 0x14, 0x20, 0x28,
> + 0x12, 0x12, 0x17, 0x0a, 0x01, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_DISPLAY[] = {
> + 0xb2, 0x00, 0x2b, 0x03, 0x03, 0x70, 0x00, 0xff, 0x00, 0x00,
> + 0x00, 0x00, 0x03, 0x03, 0x00, 0x01,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_RGB_IF[] = {
> + 0xb3, 0x09,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_DISPLAY_INV[] = {
> + 0xb4, 0x01, 0x08, 0x77, 0x0e, 0x06,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_VCOM[] = {
> + 0xb6, 0x4c, 0x2e,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_GATE[] = {
> + 0xd5, 0x00, 0x05, 0x03, 0x29, 0x01, 0x07, 0x17, 0x68, 0x13,
> + 0x37, 0x20, 0x31, 0x8a, 0x46, 0x9b, 0x57, 0x13, 0x02, 0x75,
> + 0xb9, 0x64, 0xa8, 0x07, 0x0f, 0x04, 0x07,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_PANEL[] = {
> + 0xcc, 0x02,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_COL_MOD[] = {
> + 0x3a, 0x77,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_W_GAMMA[] = {
> + 0xe0, 0x00, 0x04, 0x09, 0x0f, 0x1f, 0x3f, 0x1f, 0x2f, 0x0a,
> + 0x0f, 0x10, 0x16, 0x18, 0x16, 0x17, 0x0d, 0x15, 0x00, 0x04,
> + 0x09, 0x0f, 0x38, 0x3f, 0x20, 0x39, 0x0a, 0x0f, 0x10, 0x16,
> + 0x18, 0x16, 0x17, 0x0d, 0x15,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_RGB_GAMMA[] = {
> + 0xc1, 0x01, 0x03, 0x07, 0x0f, 0x1a, 0x22, 0x2c, 0x33, 0x3c,
> + 0x46, 0x4f, 0x58, 0x60, 0x69, 0x71, 0x79, 0x82, 0x89, 0x92,
> + 0x9a, 0xa1, 0xa9, 0xb1, 0xb9, 0xc1, 0xc9, 0xcf, 0xd6, 0xde,
> + 0xe5, 0xec, 0xf3, 0xf9, 0xff, 0xdd, 0x39, 0x07, 0x1c, 0xcb,
> + 0xab, 0x5f, 0x49, 0x80, 0x03, 0x07, 0x0f, 0x19, 0x20, 0x2a,
> + 0x31, 0x39, 0x42, 0x4b, 0x53, 0x5b, 0x63, 0x6b, 0x73, 0x7b,
> + 0x83, 0x8a, 0x92, 0x9b, 0xa2, 0xaa, 0xb2, 0xba, 0xc2, 0xca,
> + 0xd0, 0xd8, 0xe1, 0xe8, 0xf0, 0xf8, 0xff, 0xf7, 0xd8, 0xbe,
> + 0xa7, 0x39, 0x40, 0x85, 0x8c, 0xc0, 0x04, 0x07, 0x0c, 0x17,
> + 0x1c, 0x23, 0x2b, 0x34, 0x3b, 0x43, 0x4c, 0x54, 0x5b, 0x63,
> + 0x6a, 0x73, 0x7a, 0x82, 0x8a, 0x91, 0x98, 0xa1, 0xa8, 0xb0,
> + 0xb7, 0xc1, 0xc9, 0xcf, 0xd9, 0xe3, 0xea, 0xf4, 0xff, 0x00,
> + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_UP_DN[] = {
> + 0x36, 0x10,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_SLEEP_IN[] = {
> + 0x10,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_SLEEP_OUT[] = {
> + 0x11,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_DISPLAY_ON[] = {
> + 0x29,
> + ENDDEF
> +};
> +
> +const unsigned short SEQ_DISPLAY_OFF[] = {
> + 0x10,
> + ENDDEF
> +};
> +
> +static int lms501kf03_spi_write_byte(struct lms501kf03 *lcd, int addr, int data)
> +{
> + u16 buf[1];
> + struct spi_message msg;
> +
> + struct spi_transfer xfer = {
> + .len = 2,
> + .tx_buf = buf,
> + };
> +
> + buf[0] = (addr << 8) | data;
> +
> + spi_message_init(&msg);
> + spi_message_add_tail(&xfer, &msg);
> +
> + return spi_sync(lcd->spi, &msg);
> +}
> +
> +static int lms501kf03_spi_write(struct lms501kf03 *lcd, unsigned char address,
> + unsigned char command)
> +{
> + int ret = 0;
> +
> + ret = lms501kf03_spi_write_byte(lcd, address, command);
> +
> + return ret;
> +}
> +
> +static int lms501kf03_panel_send_sequence(struct lms501kf03 *lcd,
> + const unsigned short *wbuf)
> +{
> + int ret = 0, i = 0;
> +
> + while (wbuf[i] != ENDDEF) {
> + if (i = 0)
> + ret = lms501kf03_spi_write(lcd, COMMAND_ONLY, wbuf[i]);
> + else
> + ret = lms501kf03_spi_write(lcd, DATA_ONLY, wbuf[i]);
> + if (ret)
> + break;
> +
> + udelay(100);
> + i += 1;
> + }
> + return ret;
> +}
> +
> +static int lms501kf03_ldi_init(struct lms501kf03 *lcd)
> +{
> + int ret, i;
> + const unsigned short *init_seq[] = {
> + SEQ_PASSWORD,
> + SEQ_POWER,
> + SEQ_DISPLAY,
> + SEQ_RGB_IF,
> + SEQ_DISPLAY_INV,
> + SEQ_VCOM,
> + SEQ_GATE,
> + SEQ_PANEL,
> + SEQ_COL_MOD,
> + SEQ_W_GAMMA,
> + SEQ_RGB_GAMMA,
> + SEQ_SLEEP_OUT,
> + };
> +
> + for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
> + ret = lms501kf03_panel_send_sequence(lcd, init_seq[i]);
> + if (ret)
> + break;
> + }
> + mdelay(120);
> +
> + return ret;
> +}
> +
> +static int lms501kf03_ldi_enable(struct lms501kf03 *lcd)
> +{
> + return lms501kf03_panel_send_sequence(lcd, SEQ_DISPLAY_ON);
> +}
> +
> +static int lms501kf03_ldi_disable(struct lms501kf03 *lcd)
> +{
> + return lms501kf03_panel_send_sequence(lcd, SEQ_DISPLAY_OFF);
> +}
> +
> +static int lms501kf03_power_on(struct lms501kf03 *lcd)
> +{
> + int ret = 0;
> + struct lcd_platform_data *pd = NULL;
> + struct backlight_device *bd = NULL;
> +
> + pd = lcd->lcd_pd;
> + if (!pd) {
> + dev_err(lcd->dev, "platform data is NULL.\n");
> + return -EFAULT;
> + }
> +
> + bd = lcd->bd;
> + if (!bd) {
> + dev_err(lcd->dev, "backlight device is NULL.\n");
> + return -EFAULT;
> + }
> +
> + if (!pd->power_on) {
> + dev_err(lcd->dev, "power_on is NULL.\n");
> + return -EFAULT;
> + } else {
> + pd->power_on(lcd->ld, 1);
> + mdelay(pd->power_on_delay);
> + }
> +
> + if (!pd->reset) {
> + dev_err(lcd->dev, "reset is NULL.\n");
> + return -EFAULT;
> + } else {
> + pd->reset(lcd->ld);
> + mdelay(pd->reset_delay);
> + }
> +
> + ret = lms501kf03_ldi_init(lcd);
> + if (ret) {
> + dev_err(lcd->dev, "failed to initialize ldi.\n");
> + return ret;
> + }
> +
> + ret = lms501kf03_ldi_enable(lcd);
> + if (ret) {
> + dev_err(lcd->dev, "failed to enable ldi.\n");
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int lms501kf03_power_off(struct lms501kf03 *lcd)
> +{
> + int ret = 0;
> + struct lcd_platform_data *pd = NULL;
> +
> + pd = lcd->lcd_pd;
> + if (!pd) {
> + dev_err(lcd->dev, "platform data is NULL\n");
> + return -EFAULT;
> + }
> +
> + ret = lms501kf03_ldi_disable(lcd);
> + if (ret) {
> + dev_err(lcd->dev, "lcd setting failed.\n");
> + return -EIO;
> + }
> +
> + mdelay(pd->power_off_delay);
> +
> + if (!pd->power_on) {
> + dev_err(lcd->dev, "power_on is NULL.\n");
> + return -EFAULT;
> + } else
> + pd->power_on(lcd->ld, 0);
> +
> + return 0;
> +}
> +
> +static int lms501kf03_power(struct lms501kf03 *lcd, int power)
> +{
> + int ret = 0;
> +
> + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
> + ret = lms501kf03_power_on(lcd);
> + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
> + ret = lms501kf03_power_off(lcd);
> +
> + if (!ret)
> + lcd->power = power;
> +
> + return ret;
> +}
> +
> +static int lms501kf03_get_power(struct lcd_device *ld)
> +{
> + struct lms501kf03 *lcd = lcd_get_data(ld);
> +
> + return lcd->power;
> +}
> +
> +static int lms501kf03_set_power(struct lcd_device *ld, int power)
> +{
> + struct lms501kf03 *lcd = lcd_get_data(ld);
> +
> + if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
> + power != FB_BLANK_NORMAL) {
> + dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
> + return -EINVAL;
> + }
> +
> + return lms501kf03_power(lcd, power);
> +}
> +
> +static int lms501kf03_get_brightness(struct backlight_device *bd)
> +{
> + return bd->props.brightness;
> +}
> +
> +static int lms501kf03_set_brightness(struct backlight_device *bd)
> +{
> + int ret = 0;
> + int brightness = bd->props.brightness;
> +
> + if (brightness < MIN_BRIGHTNESS ||
> + brightness > bd->props.max_brightness) {
> + dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
> + MIN_BRIGHTNESS, MAX_BRIGHTNESS);
> + return -EINVAL;
> + }
> +
> + return ret;
> +}
> +
> +static struct lcd_ops lms501kf03_lcd_ops = {
> + .get_power = lms501kf03_get_power,
> + .set_power = lms501kf03_set_power,
> +};
> +
> +static const struct backlight_ops lms501kf03_backlight_ops = {
> + .get_brightness = lms501kf03_get_brightness,
> + .update_status = lms501kf03_set_brightness,
> +};
> +
> +static int __devinit lms501kf03_probe(struct spi_device *spi)
> +{
> + struct lms501kf03 *lcd = NULL;
> + struct lcd_device *ld = NULL;
> + struct backlight_device *bd = NULL;
> + struct backlight_properties props;
> + int ret = 0;
> +
> + lcd = kzalloc(sizeof(struct lms501kf03), GFP_KERNEL);
> + if (!lcd)
> + return -ENOMEM;
> +
> + /* lms501kf03 lcd panel uses 3-wire 9-bit SPI Mode. */
> + spi->bits_per_word = 9;
> +
> + ret = spi_setup(spi);
> + if (ret < 0) {
> + dev_err(&spi->dev, "spi setup failed.\n");
> + goto out_free_lcd;
> + }
> +
> + lcd->spi = spi;
> + lcd->dev = &spi->dev;
> +
> + lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data;
> + if (!lcd->lcd_pd) {
> + dev_err(&spi->dev, "platform data is NULL\n");
> + goto out_free_lcd;
> + }
> +
> + ld = lcd_device_register("lms501kf03", &spi->dev, lcd,
> + &lms501kf03_lcd_ops);
> + if (IS_ERR(ld)) {
> + ret = PTR_ERR(ld);
> + goto out_free_lcd;
> + }
> +
> + lcd->ld = ld;
> +
> + memset(&props, 0, sizeof(struct backlight_properties));
> + props.type = BACKLIGHT_RAW;
> + props.max_brightness = MAX_BRIGHTNESS;
> +
> + bd = backlight_device_register("lms501kf03-bl", &spi->dev, lcd,
> + &lms501kf03_backlight_ops, &props);
> + if (IS_ERR(bd)) {
> + ret = PTR_ERR(bd);
> + goto out_lcd_unregister;
> + }
> +
> + bd->props.brightness = DEFAULT_BRIGHTNESS;
> + lcd->bd = bd;
> +
> + if (!lcd->lcd_pd->lcd_enabled) {
> + /*
> + * if lcd panel was off from bootloader then
> + * current lcd status is powerdown and then
> + * it enables lcd panel.
> + */
> + lcd->power = FB_BLANK_POWERDOWN;
> +
> + lms501kf03_power(lcd, FB_BLANK_UNBLANK);
> + } else
> + lcd->power = FB_BLANK_UNBLANK;
> +
> + dev_set_drvdata(&spi->dev, lcd);
> +
> + dev_info(&spi->dev, "lms501kf03 panel driver has been probed.\n");
> +
> + return 0;
> +
> +out_lcd_unregister:
> + lcd_device_unregister(ld);
> +out_free_lcd:
> + kfree(lcd);
> + return ret;
> +}
> +
> +static int __devexit lms501kf03_remove(struct spi_device *spi)
> +{
> + struct lms501kf03 *lcd = dev_get_drvdata(&spi->dev);
> +
> + lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
> + lcd_device_unregister(lcd->ld);
> + kfree(lcd);
> +
> + return 0;
> +}
> +
> +#if defined(CONFIG_PM)
> +unsigned int before_power;
> +
> +static int lms501kf03_suspend(struct spi_device *spi, pm_message_t mesg)
> +{
> + int ret = 0;
> + struct lms501kf03 *lcd = dev_get_drvdata(&spi->dev);
> +
> + dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
> +
> + before_power = lcd->power;
> +
> + /*
> + * when lcd panel is suspend, lcd panel becomes off
> + * regardless of status.
> + */
> + ret = lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
> +
> + return ret;
> +}
> +
> +static int lms501kf03_resume(struct spi_device *spi)
> +{
> + int ret = 0;
> + struct lms501kf03 *lcd = dev_get_drvdata(&spi->dev);
> +
> + /*
> + * after suspended, if lcd panel status is FB_BLANK_UNBLANK
> + * (at that time, before_power is FB_BLANK_UNBLANK) then
> + * it changes that status to FB_BLANK_POWERDOWN to get lcd on.
> + */
> + if (before_power = FB_BLANK_UNBLANK)
> + lcd->power = FB_BLANK_POWERDOWN;
> +
> + dev_dbg(&spi->dev, "before_power = %d\n", before_power);
> +
> + ret = lms501kf03_power(lcd, before_power);
> +
> + return ret;
> +}
> +#else
> +#define lms501kf03_suspend NULL
> +#define lms501kf03_resume NULL
> +#endif
> +
> +void lms501kf03_shutdown(struct spi_device *spi)
> +{
> + struct lms501kf03 *lcd = dev_get_drvdata(&spi->dev);
> +
> + lms501kf03_power(lcd, FB_BLANK_POWERDOWN);
> +}
> +
> +static struct spi_driver lms501kf03_driver = {
> + .driver = {
> + .name = "lms501kf03",
> + .bus = &spi_bus_type,
> + .owner = THIS_MODULE,
> + },
> + .probe = lms501kf03_probe,
> + .remove = __devexit_p(lms501kf03_remove),
> + .shutdown = lms501kf03_shutdown,
> + .suspend = lms501kf03_suspend,
> + .resume = lms501kf03_resume,
> +};
> +
> +module_spi_driver(lms501kf03_driver);
> +
> +MODULE_AUTHOR("Ilho Lee <Ilho215.lee@samsung.com>");
> +MODULE_AUTHOR("Sachin Kamat <sachin.kamat@samsung.com>");
> +MODULE_DESCRIPTION("LMS501KF03 LCD Driver");
> +MODULE_LICENSE("GPL");
> --
> 1.7.4.1
>
--
With warm regards,
Sachin
^ permalink raw reply
* [PATCH v2 0/4] video: add support for the AUO-K190X epd controllers
From: Heiko Stübner @ 2012-04-28 10:18 UTC (permalink / raw)
To: linux-fbdev
Second version of support for the Sipix epd controllers made by AUO.
Changes were made to the common code in patch 2, including fixing
the Kconfig options as suggested by Florian Tobias Schandinat and
fixing a possible runtime-pm mismatch if the deferred_io
callback was called without a prior call to first_io.
Heiko Stübner (4):
fb_defio: add first_io callback
video: auo_k190x: add code shared by controller drivers
video: auo_k190x: add driver for AUO-K1900 variant
video: auo_k190x: add driver for AUO-K1901 variant
drivers/video/Kconfig | 33 ++
drivers/video/Makefile | 3 +
drivers/video/auo_k1900fb.c | 198 ++++++++
drivers/video/auo_k1901fb.c | 251 +++++++++++
drivers/video/auo_k190x.c | 1046 +++++++++++++++++++++++++++++++++++++++++++
drivers/video/auo_k190x.h | 129 ++++++
drivers/video/fb_defio.c | 4 +
drivers/video/smscufx.c | 2 +-
drivers/video/udlfb.c | 2 +-
include/linux/fb.h | 1 +
include/video/auo_k190xfb.h | 106 +++++
11 files changed, 1773 insertions(+), 2 deletions(-)
create mode 100644 drivers/video/auo_k1900fb.c
create mode 100644 drivers/video/auo_k1901fb.c
create mode 100644 drivers/video/auo_k190x.c
create mode 100644 drivers/video/auo_k190x.h
create mode 100644 include/video/auo_k190xfb.h
--
1.7.5.4
^ permalink raw reply
* [PATCH v2 1/4] fb_defio: add first_io callback
From: Heiko Stübner @ 2012-04-28 10:19 UTC (permalink / raw)
To: linux-fbdev
With this optional callback the driver is notified when the first page
is entered into the pagelist and a new deferred_io call is scheduled.
A possible use-case for this is runtime-pm. In the first_io call
pm_runtime_get()
could be called, which starts an asynchronous runtime_resume of the
device. In the deferred_io callback a call to
pm_runtime_barrier()
makes the sure, the device is resumed by then and a
pm_runtime_put()
may put the device back to sleep.
Also, some SoCs may use the runtime-pm system to determine if they
are able to enter deeper idle states. Therefore it is necessary to
keep the use-count from the first written page until the conclusion
of the screen update, to prevent the system from going to sleep before
completing the pending update.
Two users of defio were using kmalloc to allocate the structure.
These allocations are changed to kzalloc, to prevent uninitialised
.first_io members in those drivers.
Signed-off-by: Heiko Stübner <heiko@sntech.de>
---
changes since v1: convert fb_deferred_io kmalloc calls to kzalloc
drivers/video/fb_defio.c | 4 ++++
drivers/video/smscufx.c | 2 +-
drivers/video/udlfb.c | 2 +-
include/linux/fb.h | 1 +
4 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index c27e153..070f26f 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -107,6 +107,10 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
/* protect against the workqueue changing the page list */
mutex_lock(&fbdefio->lock);
+ /* first write in this cycle, notify the driver */
+ if (fbdefio->first_io && list_empty(&fbdefio->pagelist))
+ fbdefio->first_io(info);
+
/*
* We want the page to remain locked from ->page_mkwrite until
* the PTE is marked dirty to avoid page_mkclean() being called
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c
index ccbfef5..9985785 100644
--- a/drivers/video/smscufx.c
+++ b/drivers/video/smscufx.c
@@ -1083,7 +1083,7 @@ static int ufx_ops_open(struct fb_info *info, int user)
struct fb_deferred_io *fbdefio;
- fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
+ fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
if (fbdefio) {
fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index a159b63..e9d43b4 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -893,7 +893,7 @@ static int dlfb_ops_open(struct fb_info *info, int user)
struct fb_deferred_io *fbdefio;
- fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
+ fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
if (fbdefio) {
fbdefio->delay = DL_DEFIO_WRITE_DELAY;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index a3229d7..ac3f1c6 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -611,6 +611,7 @@ struct fb_deferred_io {
struct mutex lock; /* mutex that protects the page list */
struct list_head pagelist; /* list of touched pages */
/* callback */
+ void (*first_io)(struct fb_info *info);
void (*deferred_io)(struct fb_info *info, struct list_head *pagelist);
};
#endif
--
1.7.5.4
^ permalink raw reply related
* [PATCH v2 2/4] video: auo_k190x: add code shared by controller drivers
From: Heiko Stübner @ 2012-04-28 10:20 UTC (permalink / raw)
To: linux-fbdev
The AUO-K190X controllers share a very similar set of commands and
can therefore also share most of the driver code.
Signed-off-by: Heiko Stübner <heiko@sntech.de>
---
changes since v1: fix Kconfig (depends instead of select)
and catch possible runtime-pm mismatch.
drivers/video/Kconfig | 17 +
drivers/video/Makefile | 1 +
drivers/video/auo_k190x.c | 1046 +++++++++++++++++++++++++++++++++++++++++++
drivers/video/auo_k190x.h | 129 ++++++
include/video/auo_k190xfb.h | 106 +++++
5 files changed, 1299 insertions(+), 0 deletions(-)
create mode 100644 drivers/video/auo_k190x.c
create mode 100644 drivers/video/auo_k190x.h
create mode 100644 include/video/auo_k190xfb.h
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index a290be5..31c029b 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2382,6 +2382,23 @@ config FB_BROADSHEET
and could also have been called by other names when coupled with
a bridge adapter.
+config FB_AUO_K190X
+ tristate "AUO-K190X EPD controller support"
+ depends on FB
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
+ help
+ Provides support for epaper controllers from the K190X series
+ of AUO. These controllers can be used to drive epaper displays
+ from Sipix.
+
+ This option enables the common support, shared by the individual
+ controller drivers. You will also have to enable the driver
+ for the controller type used in your device.
+
config FB_JZ4740
tristate "JZ4740 LCD framebuffer support"
depends on FB && MACH_JZ4740
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9356add..d5406f2 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -118,6 +118,7 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_METRONOME) += metronomefb.o
obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
+obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
obj-$(CONFIG_FB_SH7760) += sh7760fb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c
new file mode 100644
index 0000000..94ba7e7
--- /dev/null
+++ b/drivers/video/auo_k190x.c
@@ -0,0 +1,1046 @@
+/*
+ * Common code for AUO-K190X framebuffer drivers
+ *
+ * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/pm_runtime.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/auo_k190xfb.h>
+
+#include "auo_k190x.h"
+
+struct panel_info {
+ int w;
+ int h;
+};
+
+/* table of panel specific parameters to be indexed into by the board drivers */
+static struct panel_info panel_table[] = {
+ /* standard 6" */
+ [AUOK190X_RESOLUTION_800_600] = {
+ .w = 800,
+ .h = 600,
+ },
+ /* standard 9" */
+ [AUOK190X_RESOLUTION_1024_768] = {
+ .w = 1024,
+ .h = 768,
+ },
+};
+
+/*
+ * private I80 interface to the board driver
+ */
+
+static void auok190x_issue_data(struct auok190xfb_par *par, u16 data)
+{
+ par->board->set_ctl(par, AUOK190X_I80_WR, 0);
+ par->board->set_hdb(par, data);
+ par->board->set_ctl(par, AUOK190X_I80_WR, 1);
+}
+
+static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data)
+{
+ par->board->set_ctl(par, AUOK190X_I80_DC, 0);
+ auok190x_issue_data(par, data);
+ par->board->set_ctl(par, AUOK190X_I80_DC, 1);
+}
+
+static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
+ u16 *data)
+{
+ struct device *dev = par->info->device;
+ int i;
+ u16 tmp;
+
+ if (size & 3) {
+ dev_err(dev, "issue_pixels: size %d must be a multiple of 4\n",
+ size);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < (size >> 1); i++) {
+ par->board->set_ctl(par, AUOK190X_I80_WR, 0);
+
+ /* simple reduction of 8bit staticgray to 4bit gray
+ * combines 4 * 4bit pixel values into a 16bit value
+ */
+ tmp = (data[2*i] & 0xF0) >> 4;
+ tmp |= (data[2*i] & 0xF000) >> 8;
+ tmp |= (data[2*i+1] & 0xF0) << 4;
+ tmp |= (data[2*i+1] & 0xF000);
+
+ par->board->set_hdb(par, tmp);
+ par->board->set_ctl(par, AUOK190X_I80_WR, 1);
+ }
+
+ return 0;
+}
+
+static u16 auok190x_read_data(struct auok190xfb_par *par)
+{
+ u16 data;
+
+ par->board->set_ctl(par, AUOK190X_I80_OE, 0);
+ data = par->board->get_hdb(par);
+ par->board->set_ctl(par, AUOK190X_I80_OE, 1);
+
+ return data;
+}
+
+/*
+ * Command interface for the controller drivers
+ */
+
+void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data)
+{
+ par->board->set_ctl(par, AUOK190X_I80_CS, 0);
+ auok190x_issue_cmd(par, data);
+ par->board->set_ctl(par, AUOK190X_I80_CS, 1);
+}
+EXPORT_SYMBOL_GPL(auok190x_send_command_nowait);
+
+void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
+ int argc, u16 *argv)
+{
+ int i;
+
+ par->board->set_ctl(par, AUOK190X_I80_CS, 0);
+ auok190x_issue_cmd(par, cmd);
+
+ for (i = 0; i < argc; i++)
+ auok190x_issue_data(par, argv[i]);
+ par->board->set_ctl(par, AUOK190X_I80_CS, 1);
+}
+EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_nowait);
+
+int auok190x_send_command(struct auok190xfb_par *par, u16 data)
+{
+ int ret;
+
+ ret = par->board->wait_for_rdy(par);
+ if (ret)
+ return ret;
+
+ auok190x_send_command_nowait(par, data);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_send_command);
+
+int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd,
+ int argc, u16 *argv)
+{
+ int ret;
+
+ ret = par->board->wait_for_rdy(par);
+ if (ret)
+ return ret;
+
+ auok190x_send_cmdargs_nowait(par, cmd, argc, argv);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_send_cmdargs);
+
+int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd,
+ int argc, u16 *argv)
+{
+ int i, ret;
+
+ ret = par->board->wait_for_rdy(par);
+ if (ret)
+ return ret;
+
+ par->board->set_ctl(par, AUOK190X_I80_CS, 0);
+ auok190x_issue_cmd(par, cmd);
+
+ for (i = 0; i < argc; i++)
+ argv[i] = auok190x_read_data(par);
+ par->board->set_ctl(par, AUOK190X_I80_CS, 1);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_read_cmdargs);
+
+void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par, u16 cmd,
+ int argc, u16 *argv, int size, u16 *data)
+{
+ int i;
+
+ par->board->set_ctl(par, AUOK190X_I80_CS, 0);
+
+ auok190x_issue_cmd(par, cmd);
+
+ for (i = 0; i < argc; i++)
+ auok190x_issue_data(par, argv[i]);
+
+ auok190x_issue_pixels(par, size, data);
+
+ par->board->set_ctl(par, AUOK190X_I80_CS, 1);
+}
+EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels_nowait);
+
+int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd,
+ int argc, u16 *argv, int size, u16 *data)
+{
+ int ret;
+
+ ret = par->board->wait_for_rdy(par);
+ if (ret)
+ return ret;
+
+ auok190x_send_cmdargs_pixels_nowait(par, cmd, argc, argv, size, data);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels);
+
+/*
+ * fbdefio callbacks - common on both controllers.
+ */
+
+static void auok190xfb_dpy_first_io(struct fb_info *info)
+{
+ /* tell runtime-pm that we wish to use the device in a short time */
+ pm_runtime_get(info->device);
+}
+
+/* this is called back from the deferred io workqueue */
+static void auok190xfb_dpy_deferred_io(struct fb_info *info,
+ struct list_head *pagelist)
+{
+ struct fb_deferred_io *fbdefio = info->fbdefio;
+ struct auok190xfb_par *par = info->par;
+ u16 yres = info->var.yres;
+ u16 xres = info->var.xres;
+ u16 y1 = 0, h = 0;
+ int prev_index = -1;
+ struct page *cur;
+ int h_inc;
+ int threshold;
+
+ if (!list_empty(pagelist))
+ /* the device resume should've been requested through first_io,
+ * if the resume did not finish until now, wait for it.
+ */
+ pm_runtime_barrier(info->device);
+ else
+ /* We reached this via the fsync or some other way.
+ * In either case the first_io function did not run,
+ * so we runtime_resume the device here synchronously.
+ */
+ pm_runtime_get_sync(info->device);
+
+ /* Do a full screen update every n updates to prevent
+ * excessive darkening of the Sipix display.
+ * If we do this, there is no need to walk the pages.
+ */
+ if (par->need_refresh(par)) {
+ par->update_all(par);
+ goto out;
+ }
+
+ /* height increment is fixed per page */
+ h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
+
+ /* calculate number of pages from pixel height */
+ threshold = par->consecutive_threshold / h_inc;
+ if (threshold < 1)
+ threshold = 1;
+
+ /* walk the written page list and swizzle the data */
+ list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+ if (prev_index < 0) {
+ /* just starting so assign first page */
+ y1 = (cur->index << PAGE_SHIFT) / xres;
+ h = h_inc;
+ } else if ((cur->index - prev_index) <= threshold) {
+ /* page is within our threshold for single updates */
+ h += h_inc * (cur->index - prev_index);
+ } else {
+ /* page not consecutive, issue previous update first */
+ par->update_partial(par, y1, y1 + h);
+
+ /* start over with our non consecutive page */
+ y1 = (cur->index << PAGE_SHIFT) / xres;
+ h = h_inc;
+ }
+ prev_index = cur->index;
+ }
+
+ /* if we still have any pages to update we do so now */
+ if (h >= yres)
+ /* its a full screen update, just do it */
+ par->update_all(par);
+ else
+ par->update_partial(par, y1, min((u16) (y1 + h), yres));
+
+out:
+ pm_runtime_mark_last_busy(info->device);
+ pm_runtime_put_autosuspend(info->device);
+}
+
+/*
+ * framebuffer operations
+ */
+
+/*
+ * this is the slow path from userspace. they can seek and write to
+ * the fb. it's inefficient to do anything less than a full screen draw
+ */
+static ssize_t auok190xfb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct auok190xfb_par *par = info->par;
+ unsigned long p = *ppos;
+ void *dst;
+ int err = 0;
+ unsigned long total_size;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return -EPERM;
+
+ total_size = info->fix.smem_len;
+
+ if (p > total_size)
+ return -EFBIG;
+
+ if (count > total_size) {
+ err = -EFBIG;
+ count = total_size;
+ }
+
+ if (count + p > total_size) {
+ if (!err)
+ err = -ENOSPC;
+
+ count = total_size - p;
+ }
+
+ dst = (void *)(info->screen_base + p);
+
+ if (copy_from_user(dst, buf, count))
+ err = -EFAULT;
+
+ if (!err)
+ *ppos += count;
+
+ par->update_all(par);
+
+ return (err) ? err : count;
+}
+
+static void auok190xfb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+{
+ struct auok190xfb_par *par = info->par;
+
+ sys_fillrect(info, rect);
+
+ par->update_all(par);
+}
+
+static void auok190xfb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
+ struct auok190xfb_par *par = info->par;
+
+ sys_copyarea(info, area);
+
+ par->update_all(par);
+}
+
+static void auok190xfb_imageblit(struct fb_info *info,
+ const struct fb_image *image)
+{
+ struct auok190xfb_par *par = info->par;
+
+ sys_imageblit(info, image);
+
+ par->update_all(par);
+}
+
+static int auok190xfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ if (info->var.xres != var->xres || info->var.yres != var->yres ||
+ info->var.xres_virtual != var->xres_virtual ||
+ info->var.yres_virtual != var->yres_virtual) {
+ pr_info("%s: Resolution not supported: X%u x Y%u\n",
+ __func__, var->xres, var->yres);
+ return -EINVAL;
+ }
+
+ /*
+ * Memory limit
+ */
+
+ if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+ pr_info("%s: Memory Limit requested yres_virtual = %u\n",
+ __func__, var->yres_virtual);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static struct fb_ops auok190xfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_read = fb_sys_read,
+ .fb_write = auok190xfb_write,
+ .fb_fillrect = auok190xfb_fillrect,
+ .fb_copyarea = auok190xfb_copyarea,
+ .fb_imageblit = auok190xfb_imageblit,
+ .fb_check_var = auok190xfb_check_var,
+};
+
+/*
+ * Controller-functions common to both K1900 and K1901
+ */
+
+static int auok190x_read_temperature(struct auok190xfb_par *par)
+{
+ struct device *dev = par->info->device;
+ u16 data[4];
+ int temp;
+
+ pm_runtime_get_sync(dev);
+
+ mutex_lock(&(par->io_lock));
+
+ auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data);
+
+ mutex_unlock(&(par->io_lock));
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ /* sanitize and split of half-degrees for now */
+ temp = ((data[0] & AUOK190X_VERSION_TEMP_MASK) >> 1);
+
+ /* handle positive and negative temperatures */
+ if (temp >= 201)
+ return (255 - temp + 1) * (-1);
+ else
+ return temp;
+}
+
+static void auok190x_identify(struct auok190xfb_par *par)
+{
+ struct device *dev = par->info->device;
+ u16 data[4];
+
+ pm_runtime_get_sync(dev);
+
+ mutex_lock(&(par->io_lock));
+
+ auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data);
+
+ mutex_unlock(&(par->io_lock));
+
+ par->epd_type = data[1] & AUOK190X_VERSION_TEMP_MASK;
+
+ par->panel_size_int = AUOK190X_VERSION_SIZE_INT(data[2]);
+ par->panel_size_float = AUOK190X_VERSION_SIZE_FLOAT(data[2]);
+ par->panel_model = AUOK190X_VERSION_MODEL(data[2]);
+
+ par->tcon_version = AUOK190X_VERSION_TCON(data[3]);
+ par->lut_version = AUOK190X_VERSION_LUT(data[3]);
+
+ dev_dbg(dev, "panel %d.%din, model 0x%x, EPD 0x%x TCON-rev 0x%x, LUT-rev 0x%x",
+ par->panel_size_int, par->panel_size_float, par->panel_model,
+ par->epd_type, par->tcon_version, par->lut_version);
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+}
+
+/*
+ * Sysfs functions
+ */
+
+static ssize_t update_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct auok190xfb_par *par = info->par;
+
+ return sprintf(buf, "%d\n", par->update_mode);
+}
+
+static ssize_t update_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct auok190xfb_par *par = info->par;
+ int mode, ret;
+
+ ret = kstrtoint(buf, 10, &mode);
+ if (ret)
+ return ret;
+
+ par->update_mode = mode;
+
+ /* if we enter a better mode, do a full update */
+ if (par->last_mode > 1 && mode < par->last_mode)
+ par->update_all(par);
+
+ return count;
+}
+
+static ssize_t flash_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct auok190xfb_par *par = info->par;
+
+ return sprintf(buf, "%d\n", par->flash);
+}
+
+static ssize_t flash_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct auok190xfb_par *par = info->par;
+ int flash, ret;
+
+ ret = kstrtoint(buf, 10, &flash);
+ if (ret)
+ return ret;
+
+ if (flash > 0)
+ par->flash = 1;
+ else
+ par->flash = 0;
+
+ return count;
+}
+
+static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct auok190xfb_par *par = info->par;
+ int temp;
+
+ temp = auok190x_read_temperature(par);
+ return sprintf(buf, "%d\n", temp);
+}
+
+static DEVICE_ATTR(update_mode, 0644, update_mode_show, update_mode_store);
+static DEVICE_ATTR(flash, 0644, flash_show, flash_store);
+static DEVICE_ATTR(temp, 0644, temp_show, NULL);
+
+static struct attribute *auok190x_attributes[] = {
+ &dev_attr_update_mode.attr,
+ &dev_attr_flash.attr,
+ &dev_attr_temp.attr,
+ NULL
+};
+
+static const struct attribute_group auok190x_attr_group = {
+ .attrs = auok190x_attributes,
+};
+
+static int auok190x_power(struct auok190xfb_par *par, bool on)
+{
+ struct auok190x_board *board = par->board;
+ int ret;
+
+ if (on) {
+ /* We should maintain POWER up for at least 80ms before set
+ * RST_N and SLP_N to high (TCON spec 20100803_v35 p59)
+ */
+ ret = regulator_enable(par->regulator);
+ if (ret)
+ return ret;
+
+ msleep(200);
+ gpio_set_value(board->gpio_nrst, 1);
+ gpio_set_value(board->gpio_nsleep, 1);
+ msleep(200);
+ } else {
+ regulator_disable(par->regulator);
+ gpio_set_value(board->gpio_nrst, 0);
+ gpio_set_value(board->gpio_nsleep, 0);
+ }
+
+ return 0;
+}
+
+/*
+ * Recovery - powercycle the controller
+ */
+
+static void auok190x_recover(struct auok190xfb_par *par)
+{
+ auok190x_power(par, 0);
+ msleep(100);
+ auok190x_power(par, 1);
+
+ par->init(par);
+
+ /* wait for init to complete */
+ par->board->wait_for_rdy(par);
+}
+
+/*
+ * Power-management
+ */
+
+#ifdef CONFIG_PM
+static int auok190x_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fb_info *info = platform_get_drvdata(pdev);
+ struct auok190xfb_par *par = info->par;
+ struct auok190x_board *board = par->board;
+ u16 standby_param;
+
+ /* take and keep the lock until we are resumed, as the controller
+ * will never reach the non-busy state when in standby mode
+ */
+ mutex_lock(&(par->io_lock));
+
+ if (par->standby) {
+ dev_warn(dev, "already in standby, runtime-pm pairing mismatch\n");
+ mutex_unlock(&(par->io_lock));
+ return 0;
+ }
+
+ /* according to runtime_pm.txt runtime_suspend only means, that the
+ * device will not process data and will not communicate with the CPU
+ * As we hold the lock, this stays true even without standby
+ */
+ if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
+ dev_dbg(dev, "runtime suspend without standby\n");
+ goto finish;
+ } else if (board->quirks & AUOK190X_QUIRK_STANDBYPARAM) {
+ /* for some TCON versions STANDBY expects a parameter (0) but
+ * it seems the real tcon version has to be determined yet.
+ */
+ dev_dbg(dev, "runtime suspend with additional empty param\n");
+ standby_param = 0;
+ auok190x_send_cmdargs(par, AUOK190X_CMD_STANDBY, 1,
+ &standby_param);
+ } else {
+ dev_dbg(dev, "runtime suspend without param\n");
+ auok190x_send_command(par, AUOK190X_CMD_STANDBY);
+ }
+
+ msleep(64);
+
+finish:
+ par->standby = 1;
+
+ return 0;
+}
+
+static int auok190x_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fb_info *info = platform_get_drvdata(pdev);
+ struct auok190xfb_par *par = info->par;
+ struct auok190x_board *board = par->board;
+
+ if (!par->standby) {
+ dev_warn(dev, "not in standby, runtime-pm pairing mismatch\n");
+ return 0;
+ }
+
+ if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
+ dev_dbg(dev, "runtime resume without standby\n");
+ } else {
+ /* when in standby, controller is always busy
+ * and only accepts the wakeup command
+ */
+ dev_dbg(dev, "runtime resume from standby\n");
+ auok190x_send_command_nowait(par, AUOK190X_CMD_WAKEUP);
+
+ msleep(160);
+
+ /* wait for the controller to be ready and release the lock */
+ board->wait_for_rdy(par);
+ }
+
+ par->standby = 0;
+
+ mutex_unlock(&(par->io_lock));
+
+ return 0;
+}
+
+static int auok190x_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fb_info *info = platform_get_drvdata(pdev);
+ struct auok190xfb_par *par = info->par;
+ struct auok190x_board *board = par->board;
+ int ret;
+
+ dev_dbg(dev, "suspend\n");
+ if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
+ /* suspend via powering off the ic */
+ dev_dbg(dev, "suspend with broken standby\n");
+
+ auok190x_power(par, 0);
+ } else {
+ dev_dbg(dev, "suspend using sleep\n");
+
+ /* the sleep state can only be entered from the standby state.
+ * pm_runtime_get_noresume gets called before the suspend call.
+ * So the devices usage count is >0 but it is not necessarily
+ * active.
+ */
+ if (!pm_runtime_status_suspended(dev)) {
+ ret = auok190x_runtime_suspend(dev);
+ if (ret < 0) {
+ dev_err(dev, "auok190x_runtime_suspend failed with %d\n",
+ ret);
+ return ret;
+ }
+ par->manual_standby = 1;
+ }
+
+ gpio_direction_output(board->gpio_nsleep, 0);
+ }
+
+ msleep(100);
+
+ return 0;
+}
+
+static int auok190x_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fb_info *info = platform_get_drvdata(pdev);
+ struct auok190xfb_par *par = info->par;
+ struct auok190x_board *board = par->board;
+
+ dev_dbg(dev, "resume\n");
+ if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
+ dev_dbg(dev, "resume with broken standby\n");
+
+ auok190x_power(par, 1);
+
+ par->init(par);
+ } else {
+ dev_dbg(dev, "resume from sleep\n");
+
+ /* device should be in runtime suspend when we were suspended
+ * and pm_runtime_put_sync gets called after this function.
+ * So there is no need to touch the standby mode here at all.
+ */
+ gpio_direction_output(board->gpio_nsleep, 1);
+ msleep(100);
+
+ /* an additional init call seems to be necessary after sleep */
+ auok190x_runtime_resume(dev);
+ par->init(par);
+
+ /* if we were runtime-suspended before, suspend again*/
+ if (!par->manual_standby)
+ auok190x_runtime_suspend(dev);
+ else
+ par->manual_standby = 0;
+ }
+
+ return 0;
+}
+#endif
+
+const struct dev_pm_ops auok190x_pm = {
+ SET_RUNTIME_PM_OPS(auok190x_runtime_suspend, auok190x_runtime_resume,
+ NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(auok190x_suspend, auok190x_resume)
+};
+EXPORT_SYMBOL_GPL(auok190x_pm);
+
+/*
+ * Common probe and remove code
+ */
+
+int __devinit auok190x_common_probe(struct platform_device *pdev,
+ struct auok190x_init_data *init)
+{
+ struct auok190x_board *board = init->board;
+ struct auok190xfb_par *par;
+ struct fb_info *info;
+ struct panel_info *panel;
+ int videomemorysize, ret;
+ unsigned char *videomemory;
+
+ /* check board contents */
+ if (!board->init || !board->cleanup || !board->wait_for_rdy
+ || !board->set_ctl || !board->set_hdb || !board->get_hdb
+ || !board->setup_irq)
+ return -EINVAL;
+
+ info = framebuffer_alloc(sizeof(struct auok190xfb_par), &pdev->dev);
+ if (!info)
+ return -ENOMEM;
+
+ par = info->par;
+ par->info = info;
+ par->board = board;
+ par->recover = auok190x_recover;
+ par->update_partial = init->update_partial;
+ par->update_all = init->update_all;
+ par->need_refresh = init->need_refresh;
+ par->init = init->init;
+
+ /* init update modes */
+ par->update_cnt = 0;
+ par->update_mode = -1;
+ par->last_mode = -1;
+ par->flash = 0;
+
+ par->regulator = regulator_get(info->device, "vdd");
+ if (IS_ERR(par->regulator)) {
+ ret = PTR_ERR(par->regulator);
+ dev_err(info->device, "Failed to get regulator: %d\n", ret);
+ goto err_reg;
+ }
+
+ ret = board->init(par);
+ if (ret) {
+ dev_err(info->device, "board init failed, %d\n", ret);
+ goto err_board;
+ }
+
+ ret = gpio_request(board->gpio_nsleep, "AUOK190x sleep");
+ if (ret) {
+ dev_err(info->device, "could not request sleep gpio, %d\n",
+ ret);
+ goto err_gpio1;
+ }
+
+ ret = gpio_direction_output(board->gpio_nsleep, 0);
+ if (ret) {
+ dev_err(info->device, "could not set sleep gpio, %d\n", ret);
+ goto err_gpio2;
+ }
+
+ ret = gpio_request(board->gpio_nrst, "AUOK190x reset");
+ if (ret) {
+ dev_err(info->device, "could not request reset gpio, %d\n",
+ ret);
+ goto err_gpio2;
+ }
+
+ ret = gpio_direction_output(board->gpio_nrst, 0);
+ if (ret) {
+ dev_err(info->device, "could not set reset gpio, %d\n", ret);
+ goto err_gpio3;
+ }
+
+ ret = auok190x_power(par, 1);
+ if (ret) {
+ dev_err(info->device, "could not power on the device, %d\n",
+ ret);
+ goto err_gpio3;
+ }
+
+ mutex_init(&par->io_lock);
+
+ init_waitqueue_head(&par->waitq);
+
+ ret = par->board->setup_irq(par->info);
+ if (ret) {
+ dev_err(info->device, "could not setup ready-irq, %d\n", ret);
+ goto err_irq;
+ }
+
+ /* wait for init to complete */
+ par->board->wait_for_rdy(par);
+
+ /*
+ * From here on the controller can talk to us
+ */
+
+ /* initialise fix, var, resolution and rotation */
+
+ strlcpy(info->fix.id, init->id, 16);
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+ info->fix.xpanstep = 0;
+ info->fix.ypanstep = 0;
+ info->fix.ywrapstep = 0;
+ info->fix.accel = FB_ACCEL_NONE;
+
+ info->var.bits_per_pixel = 8;
+ info->var.grayscale = 1;
+ info->var.red.length = 8;
+ info->var.green.length = 8;
+ info->var.blue.length = 8;
+
+ panel = &panel_table[board->resolution];
+
+ /* if 90 degree rotation, switch width and height */
+ if (board->rotation & 1) {
+ info->var.xres = panel->h;
+ info->var.yres = panel->w;
+ info->var.xres_virtual = panel->h;
+ info->var.yres_virtual = panel->w;
+ info->fix.line_length = panel->h;
+ } else {
+ info->var.xres = panel->w;
+ info->var.yres = panel->h;
+ info->var.xres_virtual = panel->w;
+ info->var.yres_virtual = panel->h;
+ info->fix.line_length = panel->w;
+ }
+
+ par->resolution = board->resolution;
+ par->rotation = board->rotation;
+
+ /* videomemory handling */
+
+ videomemorysize = roundup((panel->w * panel->h), PAGE_SIZE);
+ videomemory = vmalloc(videomemorysize);
+ if (!videomemory) {
+ ret = -ENOMEM;
+ goto err_irq;
+ }
+
+ memset(videomemory, 0, videomemorysize);
+ info->screen_base = (char *)videomemory;
+ info->fix.smem_len = videomemorysize;
+
+ info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
+ info->fbops = &auok190xfb_ops;
+
+ /* deferred io init */
+
+ info->fbdefio = devm_kzalloc(info->device,
+ sizeof(struct fb_deferred_io),
+ GFP_KERNEL);
+ if (!info->fbdefio) {
+ dev_err(info->device, "Failed to allocate memory\n");
+ ret = -ENOMEM;
+ goto err_defio;
+ }
+
+ dev_dbg(info->device, "targetting %d frames per second\n", board->fps);
+ info->fbdefio->delay = HZ / board->fps;
+ info->fbdefio->first_io = auok190xfb_dpy_first_io,
+ info->fbdefio->deferred_io = auok190xfb_dpy_deferred_io,
+ fb_deferred_io_init(info);
+
+ /* color map */
+
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret < 0) {
+ dev_err(info->device, "Failed to allocate colormap\n");
+ goto err_cmap;
+ }
+
+ /* controller init */
+
+ par->consecutive_threshold = 100;
+ par->init(par);
+ auok190x_identify(par);
+
+ platform_set_drvdata(pdev, info);
+
+ ret = register_framebuffer(info);
+ if (ret < 0)
+ goto err_regfb;
+
+ ret = sysfs_create_group(&info->device->kobj, &auok190x_attr_group);
+ if (ret)
+ goto err_sysfs;
+
+ dev_info(info->device, "fb%d: %dx%d using %dK of video memory\n",
+ info->node, info->var.xres, info->var.yres,
+ videomemorysize >> 10);
+
+ /* increase autosuspend_delay when we use alternative methods
+ * for runtime_pm
+ */
+ par->autosuspend_delay = (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN)
+ ? 1000 : 200;
+
+ pm_runtime_set_active(info->device);
+ pm_runtime_enable(info->device);
+ pm_runtime_set_autosuspend_delay(info->device, par->autosuspend_delay);
+ pm_runtime_use_autosuspend(info->device);
+
+ return 0;
+
+err_sysfs:
+ unregister_framebuffer(info);
+err_regfb:
+ fb_dealloc_cmap(&info->cmap);
+err_cmap:
+ fb_deferred_io_cleanup(info);
+ kfree(info->fbdefio);
+err_defio:
+ vfree((void *)info->screen_base);
+err_irq:
+ auok190x_power(par, 0);
+err_gpio3:
+ gpio_free(board->gpio_nrst);
+err_gpio2:
+ gpio_free(board->gpio_nsleep);
+err_gpio1:
+ board->cleanup(par);
+err_board:
+ regulator_put(par->regulator);
+err_reg:
+ framebuffer_release(info);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(auok190x_common_probe);
+
+int __devexit auok190x_common_remove(struct platform_device *pdev)
+{
+ struct fb_info *info = platform_get_drvdata(pdev);
+ struct auok190xfb_par *par = info->par;
+ struct auok190x_board *board = par->board;
+
+ pm_runtime_disable(info->device);
+
+ sysfs_remove_group(&info->device->kobj, &auok190x_attr_group);
+
+ unregister_framebuffer(info);
+
+ fb_dealloc_cmap(&info->cmap);
+
+ fb_deferred_io_cleanup(info);
+ kfree(info->fbdefio);
+
+ vfree((void *)info->screen_base);
+
+ auok190x_power(par, 0);
+
+ gpio_free(board->gpio_nrst);
+ gpio_free(board->gpio_nsleep);
+
+ board->cleanup(par);
+
+ regulator_put(par->regulator);
+
+ framebuffer_release(info);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(auok190x_common_remove);
+
+MODULE_DESCRIPTION("Common code for AUO-K190X controllers");
+MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/auo_k190x.h b/drivers/video/auo_k190x.h
new file mode 100644
index 0000000..e35af1f
--- /dev/null
+++ b/drivers/video/auo_k190x.h
@@ -0,0 +1,129 @@
+/*
+ * Private common definitions for AUO-K190X framebuffer drivers
+ *
+ * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * 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.
+ */
+
+/*
+ * I80 interface specific defines
+ */
+
+#define AUOK190X_I80_CS 0x01
+#define AUOK190X_I80_DC 0x02
+#define AUOK190X_I80_WR 0x03
+#define AUOK190X_I80_OE 0x04
+
+/*
+ * AUOK190x commands, common to both controllers
+ */
+
+#define AUOK190X_CMD_INIT 0x0000
+#define AUOK190X_CMD_STANDBY 0x0001
+#define AUOK190X_CMD_WAKEUP 0x0002
+#define AUOK190X_CMD_TCON_RESET 0x0003
+#define AUOK190X_CMD_DATA_STOP 0x1002
+#define AUOK190X_CMD_LUT_START 0x1003
+#define AUOK190X_CMD_DISP_REFRESH 0x1004
+#define AUOK190X_CMD_DISP_RESET 0x1005
+#define AUOK190X_CMD_PRE_DISPLAY_START 0x100D
+#define AUOK190X_CMD_PRE_DISPLAY_STOP 0x100F
+#define AUOK190X_CMD_FLASH_W 0x2000
+#define AUOK190X_CMD_FLASH_E 0x2001
+#define AUOK190X_CMD_FLASH_STS 0x2002
+#define AUOK190X_CMD_FRAMERATE 0x3000
+#define AUOK190X_CMD_READ_VERSION 0x4000
+#define AUOK190X_CMD_READ_STATUS 0x4001
+#define AUOK190X_CMD_READ_LUT 0x4003
+#define AUOK190X_CMD_DRIVERTIMING 0x5000
+#define AUOK190X_CMD_LBALANCE 0x5001
+#define AUOK190X_CMD_AGINGMODE 0x6000
+#define AUOK190X_CMD_AGINGEXIT 0x6001
+
+/*
+ * Common settings for AUOK190X_CMD_INIT
+ */
+
+#define AUOK190X_INIT_DATA_FILTER (0 << 12)
+#define AUOK190X_INIT_DATA_BYPASS (1 << 12)
+#define AUOK190X_INIT_INVERSE_WHITE (0 << 9)
+#define AUOK190X_INIT_INVERSE_BLACK (1 << 9)
+#define AUOK190X_INIT_SCAN_DOWN (0 << 1)
+#define AUOK190X_INIT_SCAN_UP (1 << 1)
+#define AUOK190X_INIT_SHIFT_LEFT (0 << 0)
+#define AUOK190X_INIT_SHIFT_RIGHT (1 << 0)
+
+/* Common bits to pixels
+ * Mode 15-12 11-8 7-4 3-0
+ * format0 4 3 2 1
+ * format1 3 4 1 2
+ */
+
+#define AUOK190X_INIT_FORMAT0 0
+#define AUOK190X_INIT_FORMAT1 (1 << 6)
+
+/*
+ * settings for AUOK190X_CMD_RESET
+ */
+
+#define AUOK190X_RESET_TCON (0 << 0)
+#define AUOK190X_RESET_NORMAL (1 << 0)
+#define AUOK190X_RESET_PON (1 << 1)
+
+/*
+ * AUOK190X_CMD_VERSION
+ */
+
+#define AUOK190X_VERSION_TEMP_MASK (0x1ff)
+#define AUOK190X_VERSION_EPD_MASK (0xff)
+#define AUOK190X_VERSION_SIZE_INT(_val) ((_val & 0xfc00) >> 10)
+#define AUOK190X_VERSION_SIZE_FLOAT(_val) ((_val & 0x3c0) >> 6)
+#define AUOK190X_VERSION_MODEL(_val) (_val & 0x3f)
+#define AUOK190X_VERSION_LUT(_val) (_val & 0xff)
+#define AUOK190X_VERSION_TCON(_val) ((_val & 0xff00) >> 8)
+
+/*
+ * update modes for CMD_PARTIALDISP on K1900 and CMD_DDMA on K1901
+ */
+
+#define AUOK190X_UPDATE_MODE(_res) ((_res & 0x7) << 12)
+#define AUOK190X_UPDATE_NONFLASH (1 << 15)
+
+/*
+ * track panel specific parameters for common init
+ */
+
+struct auok190x_init_data {
+ char *id;
+ struct auok190x_board *board;
+
+ void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2);
+ void (*update_all)(struct auok190xfb_par *par);
+ bool (*need_refresh)(struct auok190xfb_par *par);
+ void (*init)(struct auok190xfb_par *par);
+};
+
+
+extern void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data);
+extern int auok190x_send_command(struct auok190xfb_par *par, u16 data);
+extern void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
+ int argc, u16 *argv);
+extern int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd,
+ int argc, u16 *argv);
+extern void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par,
+ u16 cmd, int argc, u16 *argv,
+ int size, u16 *data);
+extern int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd,
+ int argc, u16 *argv, int size,
+ u16 *data);
+extern int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd,
+ int argc, u16 *argv);
+
+extern int auok190x_common_probe(struct platform_device *pdev,
+ struct auok190x_init_data *init);
+extern int auok190x_common_remove(struct platform_device *pdev);
+
+extern const struct dev_pm_ops auok190x_pm;
diff --git a/include/video/auo_k190xfb.h b/include/video/auo_k190xfb.h
new file mode 100644
index 0000000..609efe8
--- /dev/null
+++ b/include/video/auo_k190xfb.h
@@ -0,0 +1,106 @@
+/*
+ * Definitions for AUO-K190X framebuffer drivers
+ *
+ * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_VIDEO_AUO_K190XFB_H_
+#define _LINUX_VIDEO_AUO_K190XFB_H_
+
+/* Controller standby command needs a param */
+#define AUOK190X_QUIRK_STANDBYPARAM (1 << 0)
+
+/* Controller standby is completely broken */
+#define AUOK190X_QUIRK_STANDBYBROKEN (1 << 1)
+
+/*
+ * Resolutions for the displays
+ */
+#define AUOK190X_RESOLUTION_800_600 0
+#define AUOK190X_RESOLUTION_1024_768 1
+
+/*
+ * struct used by auok190x. board specific stuff comes from *board
+ */
+struct auok190xfb_par {
+ struct fb_info *info;
+ struct auok190x_board *board;
+
+ struct regulator *regulator;
+
+ struct mutex io_lock;
+ struct delayed_work work;
+ wait_queue_head_t waitq;
+ int resolution;
+ int rotation;
+ int consecutive_threshold;
+ int update_cnt;
+
+ /* panel and controller informations */
+ int epd_type;
+ int panel_size_int;
+ int panel_size_float;
+ int panel_model;
+ int tcon_version;
+ int lut_version;
+
+ /* individual controller callbacks */
+ void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2);
+ void (*update_all)(struct auok190xfb_par *par);
+ bool (*need_refresh)(struct auok190xfb_par *par);
+ void (*init)(struct auok190xfb_par *par);
+ void (*recover)(struct auok190xfb_par *par);
+
+ int update_mode; /* mode to use for updates */
+ int last_mode; /* update mode last used */
+ int flash;
+
+ /* power management */
+ int autosuspend_delay;
+ bool standby;
+ bool manual_standby;
+};
+
+/**
+ * Board specific platform-data
+ * @init: initialize the controller interface
+ * @cleanup: cleanup the controller interface
+ * @wait_for_rdy: wait until the controller is not busy anymore
+ * @set_ctl: change an interface control
+ * @set_hdb: write a value to the data register
+ * @get_hdb: read a value from the data register
+ * @setup_irq: method to setup the irq handling on the busy gpio
+ * @gpio_nsleep: sleep gpio
+ * @gpio_nrst: reset gpio
+ * @gpio_nbusy: busy gpio
+ * @resolution: one of the AUOK190X_RESOLUTION constants
+ * @rotation: rotation of the framebuffer
+ * @quirks: controller quirks to honor
+ * @fps: frames per second for defio
+ */
+struct auok190x_board {
+ int (*init)(struct auok190xfb_par *);
+ void (*cleanup)(struct auok190xfb_par *);
+ int (*wait_for_rdy)(struct auok190xfb_par *);
+
+ void (*set_ctl)(struct auok190xfb_par *, unsigned char, u8);
+ void (*set_hdb)(struct auok190xfb_par *, u16);
+ u16 (*get_hdb)(struct auok190xfb_par *);
+
+ int (*setup_irq)(struct fb_info *);
+
+ int gpio_nsleep;
+ int gpio_nrst;
+ int gpio_nbusy;
+
+ int resolution;
+ int rotation;
+ int quirks;
+ int fps;
+};
+
+#endif
--
1.7.5.4
^ permalink raw reply related
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