Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH 3/8] OMAP4: TWL: add vdda_hdmi_dac regulator supply
From: Tomi Valkeinen @ 2012-08-23 13:45 UTC (permalink / raw)
  To: archit; +Cc: linux-omap, linux-fbdev, Tomi Valkeinen, Tony Lindgren
In-Reply-To: <1345729514-2441-1-git-send-email-tomi.valkeinen@ti.com>

HDMI requires vdda_hdmi_dac (vdac) power for operation. The regulator,
or the regulator supplying the vdac, has been enabled by default and
things have worked without the HDMI driver enabling the vdac.

I encountered the problem when implementing HDMI device tree support,
where the regulator was not enabled by default.

This patch adds the vdda_hdmi_dac to twl-common.c so that the HDMI
driver can use it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/twl-common.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index 119d5a9..bf90356 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -257,6 +257,10 @@ static struct twl4030_usb_data omap4_usb_pdata = {
 	.phy_suspend	= omap4430_phy_suspend,
 };
 
+static struct regulator_consumer_supply omap4_vdda_hdmi_dac_supplies[] = {
+	REGULATOR_SUPPLY("vdda_hdmi_dac", "omapdss_hdmi"),
+};
+
 static struct regulator_init_data omap4_vdac_idata = {
 	.constraints = {
 		.min_uV			= 1800000,
@@ -266,6 +270,8 @@ static struct regulator_init_data omap4_vdac_idata = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(omap4_vdda_hdmi_dac_supplies),
+	.consumer_supplies	= omap4_vdda_hdmi_dac_supplies,
 	.supply_regulator	= "V2V1",
 };
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 4/8] OMAPDSS: HDMI: use vdda_hdmi_dac
From: Tomi Valkeinen @ 2012-08-23 13:45 UTC (permalink / raw)
  To: archit; +Cc: linux-omap, linux-fbdev, Tomi Valkeinen
In-Reply-To: <1345729514-2441-1-git-send-email-tomi.valkeinen@ti.com>

The HDMI driver requires vdda_hdmi_dac power for operation, but does not
enable it. This has worked because the regulator has been always
enabled.

But this may not always be the case, as I encountered when implementing
HDMI device tree support.

This patch changes the HDMI driver to use the vdda_hdmi_dac.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 96a6e29..ccfc677 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -33,6 +33,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
 #include <video/omapdss.h>
 
 #include "ti_hdmi.h"
@@ -62,6 +63,7 @@ static struct {
 	struct hdmi_ip_data ip_data;
 
 	struct clk *sys_clk;
+	struct regulator *vdda_hdmi_dac_reg;
 
 	int ct_cp_hpd_gpio;
 	int ls_oe_gpio;
@@ -331,6 +333,19 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
 
 	dss_init_hdmi_ip_ops(&hdmi.ip_data);
 
+	if (hdmi.vdda_hdmi_dac_reg = NULL) {
+		struct regulator *reg;
+
+		reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
+
+		if (IS_ERR(reg)) {
+			DSSERR("can't get VDDA_HDMI_DAC regulator\n");
+			return PTR_ERR(reg);
+		}
+
+		hdmi.vdda_hdmi_dac_reg = reg;
+	}
+
 	r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
 	if (r)
 		return r;
@@ -495,6 +510,10 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 	/* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
 	udelay(300);
 
+	r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
+	if (r)
+		goto err_vdac_enable;
+
 	r = hdmi_runtime_get();
 	if (r)
 		goto err_runtime_get;
@@ -562,6 +581,8 @@ err_phy_enable:
 err_pll_enable:
 	hdmi_runtime_put();
 err_runtime_get:
+	regulator_disable(hdmi.vdda_hdmi_dac_reg);
+err_vdac_enable:
 	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
 	gpio_set_value(hdmi.ls_oe_gpio, 0);
 	return -EIO;
@@ -576,6 +597,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
 	hdmi_runtime_put();
 
+	regulator_disable(hdmi.vdda_hdmi_dac_reg);
+
 	gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
 	gpio_set_value(hdmi.ls_oe_gpio, 0);
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 5/8] OMAPDSS: Add DSI fclk maximum to dss_features
From: Tomi Valkeinen @ 2012-08-23 13:45 UTC (permalink / raw)
  To: archit; +Cc: linux-omap, linux-fbdev, Tomi Valkeinen
In-Reply-To: <1345729514-2441-1-git-send-email-tomi.valkeinen@ti.com>

Add max value of DSI functional clock to dss_features, so that DSI
driver can use it.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/dss/dss_features.c |    2 ++
 drivers/video/omap2/dss/dss_features.h |    1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 2fe39d6..c26fc1f 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -326,6 +326,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
 	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 4) - 1 },
 	[FEAT_PARAM_DSIPLL_FINT]		= { 750000, 2100000 },
 	[FEAT_PARAM_DSIPLL_LPDIV]		= { 1, (1 << 13) - 1},
+	[FEAT_PARAM_DSI_FCK]			= { 0, 173000000 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 1024 },
 	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
@@ -341,6 +342,7 @@ static const struct dss_param_range omap4_dss_param_range[] = {
 	[FEAT_PARAM_DSIPLL_REGM_DSI]		= { 0, (1 << 5) - 1 },
 	[FEAT_PARAM_DSIPLL_FINT]		= { 500000, 2500000 },
 	[FEAT_PARAM_DSIPLL_LPDIV]		= { 0, (1 << 13) - 1 },
+	[FEAT_PARAM_DSI_FCK]			= { 0, 170000000 },
 	[FEAT_PARAM_DOWNSCALE]			= { 1, 4 },
 	[FEAT_PARAM_LINEWIDTH]			= { 1, 2048 },
 	[FEAT_PARAM_MGR_WIDTH]			= { 1, 2048 },
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 26d43a4..b81d603 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -92,6 +92,7 @@ enum dss_range_param {
 	FEAT_PARAM_DSIPLL_REGM_DSI,
 	FEAT_PARAM_DSIPLL_FINT,
 	FEAT_PARAM_DSIPLL_LPDIV,
+	FEAT_PARAM_DSI_FCK,
 	FEAT_PARAM_DOWNSCALE,
 	FEAT_PARAM_LINEWIDTH,
 	FEAT_PARAM_MGR_WIDTH,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 6/8] OMAPDSS: DSI: calculate dsi clock
From: Tomi Valkeinen @ 2012-08-23 13:45 UTC (permalink / raw)
  To: archit; +Cc: linux-omap, linux-fbdev, Tomi Valkeinen
In-Reply-To: <1345729514-2441-1-git-send-email-tomi.valkeinen@ti.com>

Currently the way to configure clocks related to DSI (both DSI and DISPC
clocks) happens via omapdss platform data. The reason for this is that
configuring the DSS clocks is a very complex problem, and it's
impossible for the SW to know requirements about things like
interference.

However, for general cases it should be fine to calculate the dividers
for clocks in the SW. The calculated clocks are probably not perfect,
but should work.

This patch adds support to calculate the dividers when using DSI command
mode panels. The panel gives the required DDR clock rate and LP clock
rate, and the DSI driver configures itself and DISPC accordingly.

This patch is somewhat ugly, though. The code does its job by modifying
the platform data where the clock dividers would be if the board file
gave them. This is not how it's going to be in the future, but allows us
to have quite simple patch and keep the backward compatibility.

It also allows the developer to still give the exact dividers from the
board file when there's need for that, as long as the panel driver does
not override them.

There are also other areas for improvement. For example, it would be
better if the panel driver could ask for a DSI clock in a certain range,
as, at least command mode panels, the panel can work fine with many
different clock speeds.

While the patch is not perfect, it allows us to remove the hardcoded
clock dividers from the board file, making it easier to bring up a new
panel and to use device tree from omapdss.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-taal.c |    6 ++
 drivers/video/omap2/dss/dsi.c             |  126 +++++++++++++++++++++++++++++
 include/video/omapdss.h                   |    2 +
 3 files changed, 134 insertions(+)

diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 77aed0e..ddda96a 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1065,6 +1065,12 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 	omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
 	omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
 
+	r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
+	if (r) {
+		dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
+		goto err0;
+	}
+
 	r = omapdss_dsi_display_enable(dssdev);
 	if (r) {
 		dev_err(&dssdev->dev, "failed to enable DSI\n");
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 96d0024..340c832 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -1454,6 +1454,68 @@ found:
 	return 0;
 }
 
+static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
+		unsigned long req_clk, struct dsi_clock_info *cinfo)
+{
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clock_info cur, best;
+	unsigned long dss_sys_clk, max_dss_fck, max_dsi_fck;
+	unsigned long req_clkin4ddr;
+
+	DSSDBG("dsi_pll_calc_ddrfreq\n");
+
+	dss_sys_clk = clk_get_rate(dsi->sys_clk);
+
+	max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
+	max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
+
+	memset(&best, 0, sizeof(best));
+	memset(&cur, 0, sizeof(cur));
+
+	cur.clkin = dss_sys_clk;
+
+	req_clkin4ddr = req_clk * 4;
+
+	for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
+		cur.fint = cur.clkin / cur.regn;
+
+		if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
+			continue;
+
+		/* DSIPHY(MHz) = (2 * regm / regn) * clkin */
+		for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
+			unsigned long a, b;
+
+			a = 2 * cur.regm * (cur.clkin/1000);
+			b = cur.regn;
+			cur.clkin4ddr = a / b * 1000;
+
+			if (cur.clkin4ddr > 1800 * 1000 * 1000)
+				break;
+
+			if (abs(cur.clkin4ddr - req_clkin4ddr) <
+					abs(best.clkin4ddr - req_clkin4ddr)) {
+				best = cur;
+				DSSDBG("best %ld\n", best.clkin4ddr);
+			}
+
+			if (cur.clkin4ddr = req_clkin4ddr)
+				goto found;
+		}
+	}
+found:
+	best.regm_dispc = DIV_ROUND_UP(best.clkin4ddr, max_dss_fck);
+	best.dsi_pll_hsdiv_dispc_clk = best.clkin4ddr / best.regm_dispc;
+
+	best.regm_dsi = DIV_ROUND_UP(best.clkin4ddr, max_dsi_fck);
+	best.dsi_pll_hsdiv_dsi_clk = best.clkin4ddr / best.regm_dsi;
+
+	if (cinfo)
+		*cinfo = best;
+
+	return 0;
+}
+
 int dsi_pll_set_clock_div(struct platform_device *dsidev,
 		struct dsi_clock_info *cinfo)
 {
@@ -4110,6 +4172,70 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 }
 EXPORT_SYMBOL(omapdss_dsi_configure_pins);
 
+int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
+		unsigned long ddr_clk, unsigned long lp_clk)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+	struct dsi_clock_info cinfo;
+	struct dispc_clock_info dispc_cinfo;
+	unsigned lp_clk_div;
+	unsigned long dsi_fclk;
+	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
+	unsigned long pck;
+	int r;
+
+	DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
+
+	mutex_lock(&dsi->lock);
+
+	r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk, &cinfo);
+	if (r)
+		goto err;
+
+	dssdev->clocks.dsi.regn = cinfo.regn;
+	dssdev->clocks.dsi.regm = cinfo.regm;
+	dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
+	dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
+
+
+	dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
+	lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
+
+	dssdev->clocks.dsi.lp_clk_div = lp_clk_div;
+
+	/* pck = TxByteClkHS * datalanes * 8 / bitsperpixel */
+
+	pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
+
+	DSSDBG("finding dispc dividers for pck %lu\n", pck);
+
+	dispc_find_clk_divs(pck, cinfo.dsi_pll_hsdiv_dispc_clk, &dispc_cinfo);
+
+	dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
+	dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
+
+
+	dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
+
+	dssdev->clocks.dispc.channel.lcd_clk_src +		dsi->module_id = 0 ?
+		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
+		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
+
+	dssdev->clocks.dsi.dsi_fclk_src +		dsi->module_id = 0 ?
+		OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
+		OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
+
+	mutex_unlock(&dsi->lock);
+	return 0;
+err:
+	mutex_unlock(&dsi->lock);
+	return r;
+}
+EXPORT_SYMBOL(omapdss_dsi_set_clocks);
+
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index c6ffe88..8a926f8 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -738,6 +738,8 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
 void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
 int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
 		const struct omap_dsi_pin_config *pin_cfg);
+int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
+		unsigned long ddr_clk, unsigned long lp_clk);
 
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 7/8] OMAP: 4430SDP: remove DSI clock config from board file
From: Tomi Valkeinen @ 2012-08-23 13:45 UTC (permalink / raw)
  To: archit; +Cc: linux-omap, linux-fbdev, Tomi Valkeinen, Tony Lindgren
In-Reply-To: <1345729514-2441-1-git-send-email-tomi.valkeinen@ti.com>

DSI clocks are now configured dynamically by the DSI driver, so we can
remove the hardcoded clock configuration from the board file.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
---
 arch/arm/mach-omap2/board-4430sdp.c |   46 -----------------------------------
 1 file changed, 46 deletions(-)

diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 852e05c..4352d91 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -621,29 +621,6 @@ static struct omap_dss_device sdp4430_lcd_device = {
 	.phy.dsi		= {
 		.module		= 0,
 	},
-
-	.clocks = {
-		.dispc = {
-			.channel = {
-				/* Logic Clock = 172.8 MHz */
-				.lck_div	= 1,
-				/* Pixel Clock = 34.56 MHz */
-				.pck_div	= 5,
-				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
-			},
-			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,
-		},
-
-		.dsi = {
-			.regn		= 16,	/* Fint = 2.4 MHz */
-			.regm		= 180,	/* DDR Clock = 216 MHz */
-			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */
-			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */
-
-			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */
-			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
-		},
-	},
 	.channel		= OMAP_DSS_CHANNEL_LCD,
 };
 
@@ -668,29 +645,6 @@ static struct omap_dss_device sdp4430_lcd2_device = {
 
 		.module		= 1,
 	},
-
-	.clocks = {
-		.dispc = {
-			.channel = {
-				/* Logic Clock = 172.8 MHz */
-				.lck_div	= 1,
-				/* Pixel Clock = 34.56 MHz */
-				.pck_div	= 5,
-				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC,
-			},
-			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,
-		},
-
-		.dsi = {
-			.regn		= 16,	/* Fint = 2.4 MHz */
-			.regm		= 180,	/* DDR Clock = 216 MHz */
-			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */
-			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */
-
-			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */
-			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI,
-		},
-	},
 	.channel		= OMAP_DSS_CHANNEL_LCD2,
 };
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 8/8] OMAPDSS: fix use of dssdev->caps
From: Tomi Valkeinen @ 2012-08-23 13:45 UTC (permalink / raw)
  To: archit; +Cc: linux-omap, linux-fbdev, Tomi Valkeinen
In-Reply-To: <1345729514-2441-1-git-send-email-tomi.valkeinen@ti.com>

Recent commit dca2b1522ccab28d03fb79f6e70e70ea78033d52 (OMAPDSS: DSI:
Maintain copy of operation mode in driver data) broke DSI for video mode
displays. The commit changed the way dssdev->caps are initialized, and
the result was that every DSI display is initialized with manual-update
and tear-elim caps.

The code that sets dssdev->caps is not very good, even when fixed.
omapdss driver shouldn't be writing dssdev->caps at all.

This patch fixes the problem with video mode displays by moving the
initialization of dssdev->caps to the panel driver. The same change is
done for RFBI.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/omap2/displays/panel-n8x0.c |    1 +
 drivers/video/omap2/displays/panel-taal.c |    2 ++
 drivers/video/omap2/dss/dsi.c             |    5 -----
 drivers/video/omap2/dss/rfbi.c            |    1 -
 4 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index 17ae85e..3fc5ad0 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -489,6 +489,7 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
 	dssdev->panel.timings.y_res = 480;
 	dssdev->ctrl.pixel_size = 16;
 	dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
+	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
 
 	memset(&props, 0, sizeof(props));
 	props.max_brightness = 127;
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index ddda96a..7b2d7bb 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -884,6 +884,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
 
 	dssdev->panel.timings = panel_config->timings;
 	dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
+	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
+		OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
 
 	td = kzalloc(sizeof(*td), GFP_KERNEL);
 	if (!td) {
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 340c832..254666f 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -4866,11 +4866,6 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
 
 	DSSDBG("DSI init\n");
 
-	if (dsi->mode = OMAP_DSS_DSI_CMD_MODE) {
-		dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
-			OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
-	}
-
 	if (dsi->vdds_dsi_reg = NULL) {
 		struct regulator *vdds_dsi;
 
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 5a9c0e9..2e520d3 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -939,7 +939,6 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable);
 static int __init rfbi_init_display(struct omap_dss_device *dssdev)
 {
 	rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
-	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
 	return 0;
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH] pwm: Call pwm_enable() before pwm_config()
From: Benoît Thébaudeau @ 2012-08-23 14:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <320569847.2756382.1345729013971.JavaMail.root@advansee.com>

Some PWM drivers enable the clock of the PWM peripheral in pwm_enable(). Hence,
for these drivers, a call to pwm_config() does not have any effect before
pwm_enable() has been called.

This patch fixes the PWM users to make sure that they call pwm_enable() before
pwm_config().

This fixes the first setting of brightness through sysfs that had no effect with
leds-pwm and the i.MX PWM driver.

Cc: Thierry Reding <thierry.reding@avionic-design.de>
Cc: <linux-kernel@vger.kernel.org>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: <linux-arm-kernel@lists.infradead.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: <linux-input@vger.kernel.org>
Cc: Bryan Wu <bryan.wu@canonical.com>
Cc: Richard Purdie <rpurdie@rpsys.net>
Cc: <linux-leds@vger.kernel.org>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: <linux-fbdev@vger.kernel.org>
Cc: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
---
 .../drivers/input/misc/pwm-beeper.c                |    6 +++---
 .../drivers/leds/leds-pwm.c                        |    2 +-
 .../drivers/video/backlight/pwm_bl.c               |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git linux-next-c94456b.orig/drivers/input/misc/pwm-beeper.c linux-next-c94456b/drivers/input/misc/pwm-beeper.c
index fc84c8a..97d322b 100644
--- linux-next-c94456b.orig/drivers/input/misc/pwm-beeper.c
+++ linux-next-c94456b/drivers/input/misc/pwm-beeper.c
@@ -53,10 +53,10 @@ static int pwm_beeper_event(struct input_dev *input,
 		pwm_disable(beeper->pwm);
 	} else {
 		period = HZ_TO_NANOSECONDS(value);
-		ret = pwm_config(beeper->pwm, period / 2, period);
+		ret = pwm_enable(beeper->pwm);
 		if (ret)
 			return ret;
-		ret = pwm_enable(beeper->pwm);
+		ret = pwm_config(beeper->pwm, period / 2, period);
 		if (ret)
 			return ret;
 		beeper->period = period;
@@ -156,8 +156,8 @@ static int pwm_beeper_resume(struct device *dev)
 	struct pwm_beeper *beeper = dev_get_drvdata(dev);
 
 	if (beeper->period) {
-		pwm_config(beeper->pwm, beeper->period / 2, beeper->period);
 		pwm_enable(beeper->pwm);
+		pwm_config(beeper->pwm, beeper->period / 2, beeper->period);
 	}
 
 	return 0;
diff --git linux-next-c94456b.orig/drivers/leds/leds-pwm.c linux-next-c94456b/drivers/leds/leds-pwm.c
index f2e44c7..c2e0c22 100644
--- linux-next-c94456b.orig/drivers/leds/leds-pwm.c
+++ linux-next-c94456b/drivers/leds/leds-pwm.c
@@ -42,8 +42,8 @@ static void led_pwm_set(struct led_classdev *led_cdev,
 		pwm_config(led_dat->pwm, 0, period);
 		pwm_disable(led_dat->pwm);
 	} else {
-		pwm_config(led_dat->pwm, brightness * period / max, period);
 		pwm_enable(led_dat->pwm);
+		pwm_config(led_dat->pwm, brightness * period / max, period);
 	}
 }
 
diff --git linux-next-c94456b.orig/drivers/video/backlight/pwm_bl.c linux-next-c94456b/drivers/video/backlight/pwm_bl.c
index 995f016..a4bb95c 100644
--- linux-next-c94456b.orig/drivers/video/backlight/pwm_bl.c
+++ linux-next-c94456b/drivers/video/backlight/pwm_bl.c
@@ -65,8 +65,8 @@ static int pwm_backlight_update_status(struct backlight_device *bl)
 
 		duty_cycle = pb->lth_brightness +
 		     (duty_cycle * (pb->period - pb->lth_brightness) / max);
-		pwm_config(pb->pwm, duty_cycle, pb->period);
 		pwm_enable(pb->pwm);
+		pwm_config(pb->pwm, duty_cycle, pb->period);
 	}
 
 	if (pb->notify_after)

^ permalink raw reply related

* Re: [PATCH 2/4] ARM: dts: mxs: Add alternative I2C muxing options for imx28
From: Shawn Guo @ 2012-08-23 14:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1345711351-16367-3-git-send-email-maxime.ripard@free-electrons.com>

On Thu, Aug 23, 2012 at 10:42:29AM +0200, Maxime Ripard wrote:
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Cc: Brian Lilly <brian@crystalfontz.com>
> ---
>  arch/arm/boot/dts/imx28.dtsi |   11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index 787efac..f6ffcd9 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -410,6 +410,17 @@
>  					fsl,pull-up = <1>;
>  				};
>  
> +				i2c0_pins_b: i2c0@1 {
> +					reg = <1>;
> +					fsl,pinmux-ids = <
> +						0x3001 /* MX28_PAD_AUART0_RX__DUART_CTS */
> +						0x3011 /* MX28_PAD_AUART0_TX__DUART_RTS */

The comments are wrong.  I fixed them as below and applied the patch.

						0x3001 /* MX28_PAD_AUART0_RX__I2C0_SCL */
						0x3011 /* MX28_PAD_AUART0_TX__I2C0_SDA */

Regards,
Shawn


> +					>;
> +					fsl,drive-strength = <1>;
> +					fsl,voltage = <1>;
> +					fsl,pull-up = <1>;
> +				};
> +
>  				saif0_pins_a: saif0@0 {
>  					reg = <0>;
>  					fsl,pinmux-ids = <
> -- 
> 1.7.9.5
> 

^ permalink raw reply

* Re: [PATCH 3/4] ARM: dts: mxs: Add pwm4 muxing options for imx28
From: Shawn Guo @ 2012-08-23 14:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1345711351-16367-4-git-send-email-maxime.ripard@free-electrons.com>

On Thu, Aug 23, 2012 at 10:42:30AM +0200, Maxime Ripard wrote:
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Cc: Brian Lilly <brian@crystalfontz.com>

Applied, thanks.

> ---
>  arch/arm/boot/dts/imx28.dtsi |   10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
> index f6ffcd9..60d10d7 100644
> --- a/arch/arm/boot/dts/imx28.dtsi
> +++ b/arch/arm/boot/dts/imx28.dtsi
> @@ -464,6 +464,16 @@
>  					fsl,pull-up = <0>;
>  				};
>  
> +				pwm4_pins_a: pwm4@0 {
> +					reg = <0>;
> +					fsl,pinmux-ids = <
> +						0x31d0 /* MX28_PAD_PWM4__PWM_4 */
> +					>;
> +					fsl,drive-strength = <0>;
> +					fsl,voltage = <1>;
> +					fsl,pull-up = <0>;
> +				};
> +
>  				lcdif_24bit_pins_a: lcdif-24bit@0 {
>  					reg = <0>;
>  					fsl,pinmux-ids = <
> -- 
> 1.7.9.5
> 

^ permalink raw reply

* Re: [PATCH 4/4] ARM: dts: mxs: add oled support for the cfa-10036
From: Shawn Guo @ 2012-08-23 14:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1345711351-16367-5-git-send-email-maxime.ripard@free-electrons.com>

On Thu, Aug 23, 2012 at 10:42:31AM +0200, Maxime Ripard wrote:
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Cc: Brian Lilly <brian@crystalfontz.com>
> ---
>  arch/arm/boot/dts/imx28-cfa10036.dts |   20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 
Looks mostly good, but I have to postpone it until driver part gets
accepted.

Some minor comments below.

> diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
> index c03a577..92784a9 100644
> --- a/arch/arm/boot/dts/imx28-cfa10036.dts
> +++ b/arch/arm/boot/dts/imx28-cfa10036.dts
> @@ -33,11 +33,31 @@
>  		};
>  
>  		apbx@80040000 {
> +			pwm: pwm@80064000 {
> +				pinctrl-names = "default";
> +				pinctrl-0 = <&pwm4_pins_a>;
> +				status = "okay";
> +			};
> +
>  			duart: serial@80074000 {
>  				pinctrl-names = "default";
>  				pinctrl-0 = <&duart_pins_b>;
>  				status = "okay";
>  			};
> +
> +			i2c0: i2c@80058000 {
> +				pinctrl-names = "default";
> +				pinctrl-0 = <&i2c0_pins_b>;
> +				status = "okay";
> +
> +				ssd1307: oled@3c {
> +					compatible = "solomon,ssd1307fb-i2c";
> +					reg = <0x3c>;
> +					pwms = <&pwm 4 3000>;
> +					oled-reset-gpio = <&gpio2 7 1>;

The idiom of naming gpio in DT is *-gpios, even though most of times
there is only one pin.

> +					oled-reset-active-low;

I would drop oled- prefix for above two properties.

Regards,
Shawn

> +				};
> +			};
>  		};
>  	};
>  
> -- 
> 1.7.9.5
> 

^ permalink raw reply

* Re: [PATCH] pwm: Call pwm_enable() before pwm_config()
From: Lars-Peter Clausen @ 2012-08-23 15:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <217877237.2758643.1345731587941.JavaMail.root@advansee.com>

On 08/23/2012 04:19 PM, Benoît Thébaudeau wrote:
> Some PWM drivers enable the clock of the PWM peripheral in pwm_enable(). Hence,
> for these drivers, a call to pwm_config() does not have any effect before
> pwm_enable() has been called.
> 
> This patch fixes the PWM users to make sure that they call pwm_enable() before
> pwm_config().
> 
> This fixes the first setting of brightness through sysfs that had no effect with
> leds-pwm and the i.MX PWM driver.

But isn't this a bug in the PWM peripheral driver? With this change the PWM
will start with the old settings first. While this is not so much of a problem
for a backlight (although it might cause a short flickering) it might cause
problems for other applications, like using the PWM pin as a timing generator.
In my opinion it's better to fix the PWM peripheral drivers which have this
problem instead of trying to work around it in every user of the PWM API.

- Lars

^ permalink raw reply

* Re: [PATCH] pwm: Call pwm_enable() before pwm_config()
From: Benoît Thébaudeau @ 2012-08-23 16:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <217877237.2758643.1345731587941.JavaMail.root@advansee.com>

On Thursday, August 23, 2012 5:43:32 PM, Lars-Peter Clausen wrote:
> On 08/23/2012 04:19 PM, Benoît Thébaudeau wrote:
> > Some PWM drivers enable the clock of the PWM peripheral in
> > pwm_enable(). Hence,
> > for these drivers, a call to pwm_config() does not have any effect
> > before
> > pwm_enable() has been called.
> > 
> > This patch fixes the PWM users to make sure that they call
> > pwm_enable() before
> > pwm_config().
> > 
> > This fixes the first setting of brightness through sysfs that had
> > no effect with
> > leds-pwm and the i.MX PWM driver.
> 
> But isn't this a bug in the PWM peripheral driver? With this change
> the PWM
> will start with the old settings first. While this is not so much of
> a problem
> for a backlight (although it might cause a short flickering) it might
> cause
> problems for other applications, like using the PWM pin as a timing
> generator.
> In my opinion it's better to fix the PWM peripheral drivers which
> have this
> problem instead of trying to work around it in every user of the PWM
> API.

I don't know. See my detailed description of this issue here:
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-August/115667.html

Where the bug is depends on the detailed definition of the PWM API, which I
don't find documented anywhere.

If pwm_enable() means "start PWM timer with the configured settings", then the
bug is in the drivers. If it means "enable the PWM peripheral so that we can
work with it", then the bug is in the PWM users.

I don't really have time to work on this, so I suggested this patch as a simple
solution. Otherwise, it means reworking several PWM drivers for different
hardware that is not available to everyone for testing.

If we decide to only change the i.MX PWM driver, the fix would be:
pwm_config()
{
        save passed config in private data;
        if (pwm enabled)
                apply passed config;
}

pwm_enable()
{
        if (!(pwm enabled)) {
                enable pwm ip clk;
                apply config from private data;
        }
}

If we fix only this driver, we must not forget that the same issue probably
exists with several other PWM drivers.

As I said in my bug description, the PWM users set the duty cycle to 0 before
calling pwm_disable(), so fixing the PWM users should not be an issue, even in
the timing generator use case you're talking about.

I don't have a strong opinion about what should be fixed here.

Best regards,
Benoît

^ permalink raw reply

* Re: [PATCH] pwm: Call pwm_enable() before pwm_config()
From: Lars-Peter Clausen @ 2012-08-23 17:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <36966374.2768747.1345741025741.JavaMail.root@advansee.com>

On 08/23/2012 06:57 PM, Benoît Thébaudeau wrote:
> On Thursday, August 23, 2012 5:43:32 PM, Lars-Peter Clausen wrote:
>> On 08/23/2012 04:19 PM, Benoît Thébaudeau wrote:
>>> Some PWM drivers enable the clock of the PWM peripheral in
>>> pwm_enable(). Hence,
>>> for these drivers, a call to pwm_config() does not have any effect
>>> before
>>> pwm_enable() has been called.
>>>
>>> This patch fixes the PWM users to make sure that they call
>>> pwm_enable() before
>>> pwm_config().
>>>
>>> This fixes the first setting of brightness through sysfs that had
>>> no effect with
>>> leds-pwm and the i.MX PWM driver.
>>
>> But isn't this a bug in the PWM peripheral driver? With this change
>> the PWM
>> will start with the old settings first. While this is not so much of
>> a problem
>> for a backlight (although it might cause a short flickering) it might
>> cause
>> problems for other applications, like using the PWM pin as a timing
>> generator.
>> In my opinion it's better to fix the PWM peripheral drivers which
>> have this
>> problem instead of trying to work around it in every user of the PWM
>> API.
> 
> I don't know. See my detailed description of this issue here:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2012-August/115667.html
> 
> Where the bug is depends on the detailed definition of the PWM API, which I
> don't find documented anywhere.
> 
> If pwm_enable() means "start PWM timer with the configured settings", then the
> bug is in the drivers. If it means "enable the PWM peripheral so that we can
> work with it", then the bug is in the PWM users.

It really is the former. See the description of pwm_enable() in drivers/pwm/core.c

> 
> I don't really have time to work on this, so I suggested this patch as a simple
> solution. Otherwise, it means reworking several PWM drivers for different
> hardware that is not available to everyone for testing.
> 
> If we decide to only change the i.MX PWM driver, the fix would be:
> pwm_config()
> {
>         save passed config in private data;
>         if (pwm enabled)
>                 apply passed config;
> }
> 
> pwm_enable()
> {
>         if (!(pwm enabled)) {
>                 enable pwm ip clk;
>                 apply config from private data;
>         }
> }

Another option is to enable the clock if it is disabled when the device is
configured. E.g. that's what tegra does.

> 
> If we fix only this driver, we must not forget that the same issue probably
> exists with several other PWM drivers.
> 

Since this seems to be a common pattern in a number of PWM drivers it might
make sense to simply add support for enabling/disabling a clk to the pwm core.
Or maybe just use the runtime pm API for this. This probably makes even more
sense and grab a reference to the pm context when the enable() is called,
release it when disable() is called and also grab it before calling the
device's config callback and release it afterward.

- Lars

^ permalink raw reply

* Re: [PATCH] pwm: Call pwm_enable() before pwm_config()
From: Lars-Peter Clausen @ 2012-08-23 17:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50366464.4070801@metafoo.de>

On 08/23/2012 07:12 PM, Lars-Peter Clausen wrote:
>[...]
> Or maybe just use the runtime pm API for this. This probably makes even more
> sense and grab a reference to the pm context when the enable() is called,
> release it when disable() is called and also grab it before calling the
> device's config callback and release it afterward.

Btw. this seems to be exactly what the pwm-tiecap and pwm-tiehrpwm drivers
already do today. I'd just make that a core PWM framework feature.

^ permalink raw reply

* Re: [PATCH] pwm: Call pwm_enable() before pwm_config()
From: Thierry Reding @ 2012-08-23 19:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50366628.5020007@metafoo.de>

[-- Attachment #1: Type: text/plain, Size: 1237 bytes --]

On Thu, Aug 23, 2012 at 07:19:36PM +0200, Lars-Peter Clausen wrote:
> On 08/23/2012 07:12 PM, Lars-Peter Clausen wrote:
> >[...]
> > Or maybe just use the runtime pm API for this. This probably makes even more
> > sense and grab a reference to the pm context when the enable() is called,
> > release it when disable() is called and also grab it before calling the
> > device's config callback and release it afterward.
> 
> Btw. this seems to be exactly what the pwm-tiecap and pwm-tiehrpwm drivers
> already do today. I'd just make that a core PWM framework feature.

Using runtime PM for this sounds indeed like the most generic approach.
I'm not very familiar with the API, but I thought it required explicit
architecture or bus support (or the driver itself can provide hooks via
pm_ops), so it might be difficult to implement for platforms that don't
have working runtime PM support. I'll have to look into this some more.

Anyway, if we add this kind of support to the PWM core we should take it
through next first. For drivers that are currently broken, they should
be, as you said, fixed by enabling the clock before reconfiguring and
disable it after (unless the PWM is enabled) like Tegra does.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH] pwm: Call pwm_enable() before pwm_config()
From: Thierry Reding @ 2012-08-23 19:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50366464.4070801@metafoo.de>

[-- Attachment #1: Type: text/plain, Size: 3954 bytes --]

On Thu, Aug 23, 2012 at 07:12:04PM +0200, Lars-Peter Clausen wrote:
> On 08/23/2012 06:57 PM, Benoît Thébaudeau wrote:
> > On Thursday, August 23, 2012 5:43:32 PM, Lars-Peter Clausen wrote:
> >> On 08/23/2012 04:19 PM, Benoît Thébaudeau wrote:
> >>> Some PWM drivers enable the clock of the PWM peripheral in
> >>> pwm_enable(). Hence,
> >>> for these drivers, a call to pwm_config() does not have any effect
> >>> before
> >>> pwm_enable() has been called.
> >>>
> >>> This patch fixes the PWM users to make sure that they call
> >>> pwm_enable() before
> >>> pwm_config().
> >>>
> >>> This fixes the first setting of brightness through sysfs that had
> >>> no effect with
> >>> leds-pwm and the i.MX PWM driver.
> >>
> >> But isn't this a bug in the PWM peripheral driver? With this change
> >> the PWM
> >> will start with the old settings first. While this is not so much of
> >> a problem
> >> for a backlight (although it might cause a short flickering) it might
> >> cause
> >> problems for other applications, like using the PWM pin as a timing
> >> generator.
> >> In my opinion it's better to fix the PWM peripheral drivers which
> >> have this
> >> problem instead of trying to work around it in every user of the PWM
> >> API.
> > 
> > I don't know. See my detailed description of this issue here:
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2012-August/115667.html
> > 
> > Where the bug is depends on the detailed definition of the PWM API, which I
> > don't find documented anywhere.
> > 
> > If pwm_enable() means "start PWM timer with the configured settings", then the
> > bug is in the drivers. If it means "enable the PWM peripheral so that we can
> > work with it", then the bug is in the PWM users.
> 
> It really is the former. See the description of pwm_enable() in drivers/pwm/core.c

Yes. pwm_enable() is only for starting the PWM and *not* the peripheral.
I should update the documentation to make this clearer.

> > I don't really have time to work on this, so I suggested this patch as a simple
> > solution. Otherwise, it means reworking several PWM drivers for different
> > hardware that is not available to everyone for testing.
> > 
> > If we decide to only change the i.MX PWM driver, the fix would be:
> > pwm_config()
> > {
> >         save passed config in private data;
> >         if (pwm enabled)
> >                 apply passed config;
> > }
> > 
> > pwm_enable()
> > {
> >         if (!(pwm enabled)) {
> >                 enable pwm ip clk;
> >                 apply config from private data;
> >         }
> > }
> 
> Another option is to enable the clock if it is disabled when the device is
> configured. E.g. that's what tegra does.

Yes, that would have been my proposal as well.

> > If we fix only this driver, we must not forget that the same issue probably
> > exists with several other PWM drivers.
> 
> Since this seems to be a common pattern in a number of PWM drivers it might
> make sense to simply add support for enabling/disabling a clk to the pwm core.
> Or maybe just use the runtime pm API for this. This probably makes even more
> sense and grab a reference to the pm context when the enable() is called,
> release it when disable() is called and also grab it before calling the
> device's config callback and release it afterward.

The problem with adding this kind of support in the core is that the
device or platform doesn't necessarily support runtime PM. Perhaps
adding a flag to mark compatible drivers would be an option. If the
runtime PM API gracefully handles cases where no callbacks are
implemented (and therefore assumed unneeded) things should also work.

On the other hand this really is very driver-specific stuff. A lot of
hardware doesn't require an explicit clock being enabled to write
registers so those wouldn't need the implicit PM calls either.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH 2/4] fbcon: prevent possible buffer overflow.
From: Florian Tobias Schandinat @ 2012-08-23 20:28 UTC (permalink / raw)
  To: Paul Cercueil; +Cc: linux-kernel, linux-fbdev
In-Reply-To: <1343091626-11435-2-git-send-email-paul@crapouillou.net>

On 07/24/2012 01:00 AM, Paul Cercueil wrote:
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>

Applied.


Thanks,

Florian Tobias Schandinat

> ---
>  drivers/video/console/fbcon.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
> index a0b1818..3ffab97 100644
> --- a/drivers/video/console/fbcon.c
> +++ b/drivers/video/console/fbcon.c
> @@ -442,7 +442,7 @@ static int __init fb_console_setup(char *this_opt)
>  
>  	while ((options = strsep(&this_opt, ",")) != NULL) {
>  		if (!strncmp(options, "font:", 5))
> -			strcpy(fontname, options + 5);
> +			strlcpy(fontname, options + 5, sizeof(fontname));
>  		
>  		if (!strncmp(options, "scrollback:", 11)) {
>  			char *k;


^ permalink raw reply

* Re: [PATCH] fbcon: Fix bit_putcs() call to kmalloc(s, GFP_KERNEL)
From: Florian Tobias Schandinat @ 2012-08-23 20:29 UTC (permalink / raw)
  To: Bruno Prémont; +Cc: linux-fbdev, linux-kernel
In-Reply-To: <20120730210949.5ccc5164@neptune.home>

On 07/30/2012 07:09 PM, Bruno Prémont wrote:
> Switch to kmalloc(,GFP_ATOMIC) in bit_putcs to fix below trace:
> 
> [    9.771812] BUG: sleeping function called from invalid context at /usr/src/linux-git/mm/slub.c:943
> [    9.771814] in_atomic(): 1, irqs_disabled(): 1, pid: 1063, name: mount
> [    9.771818] Pid: 1063, comm: mount Not tainted 3.5.0-jupiter-00003-g8d858b1-dirty #2
> [    9.771819] Call Trace:
> [    9.771838]  [<c104f79b>] __might_sleep+0xcb/0xe0
> [    9.771844]  [<c10c00d4>] __kmalloc+0xb4/0x1c0
> [    9.771851]  [<c1041d4a>] ? queue_work+0x1a/0x30
> [    9.771854]  [<c1041dcf>] ? queue_delayed_work+0xf/0x30
> [    9.771862]  [<c1205832>] ? bit_putcs+0xf2/0x3e0
> [    9.771865]  [<c1041e01>] ? schedule_delayed_work+0x11/0x20
> [    9.771868]  [<c1205832>] bit_putcs+0xf2/0x3e0
> [    9.771875]  [<c12002b8>] ? get_color.clone.14+0x28/0x100
> [    9.771878]  [<c1200d2f>] fbcon_putcs+0x11f/0x130
> [    9.771882]  [<c1205740>] ? bit_clear+0xe0/0xe0
> [    9.771885]  [<c1200f6d>] fbcon_redraw.clone.21+0x11d/0x160
> [    9.771889]  [<c120383d>] fbcon_scroll+0x79d/0xe10
> [    9.771892]  [<c12002b8>] ? get_color.clone.14+0x28/0x100
> [    9.771897]  [<c124c0b4>] scrup+0x64/0xd0
> [    9.771900]  [<c124c22b>] lf+0x2b/0x60
> [    9.771903]  [<c124cc95>] vt_console_print+0x1d5/0x2f0
> [    9.771907]  [<c124cac0>] ? register_vt_notifier+0x20/0x20
> [    9.771913]  [<c102b335>] call_console_drivers.clone.5+0xa5/0xc0
> [    9.771916]  [<c102c58e>] console_unlock+0x2fe/0x3c0
> [    9.771920]  [<c102ca16>] vprintk_emit+0x2e6/0x300
> [    9.771924]  [<c13f01ae>] printk+0x38/0x3a
> [    9.771931]  [<c112e8fe>] reiserfs_remount+0x2ae/0x3e0
> [    9.771934]  [<c112e650>] ? reiserfs_fill_super+0xb00/0xb00
> [    9.771939]  [<c10ca0ab>] do_remount_sb+0xab/0x150
> [    9.771943]  [<c1034476>] ? ns_capable+0x46/0x70
> [    9.771948]  [<c10e059c>] do_mount+0x20c/0x6b0
> [    9.771955]  [<c10a7044>] ? strndup_user+0x34/0x50
> [    9.771958]  [<c10e0acc>] sys_mount+0x6c/0xa0
> [    9.771964]  [<c13f2557>] sysenter_do_call+0x12/0x26
> 
> According to comment in bit_putcs() that kammloc() call only happens
> when fbcon is drawing to a monochrome framebuffer (which is my case with
> hid-picolcd).
> 
> Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>

Applied.


Thanks,

Florian Tobias Schandinat

> ---
>  drivers/video/console/bitblit.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
> index 28b1a83..61b182b 100644
> --- a/drivers/video/console/bitblit.c
> +++ b/drivers/video/console/bitblit.c
> @@ -162,7 +162,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
>  	image.depth = 1;
>  
>  	if (attribute) {
> -		buf = kmalloc(cellsize, GFP_KERNEL);
> +		buf = kmalloc(cellsize, GFP_ATOMIC);
>  		if (!buf)
>  			return;
>  	}


^ permalink raw reply

* Re: [PATCH 1/3] drivers/video/auo_k190x.c: drop kfree of devm_kzalloc's data
From: Florian Tobias Schandinat @ 2012-08-23 20:30 UTC (permalink / raw)
  To: Julia Lawall; +Cc: kernel-janitors, linux-fbdev, linux-kernel
In-Reply-To: <1344081632-4729-1-git-send-email-Julia.Lawall@lip6.fr>

On 08/04/2012 12:00 PM, Julia Lawall wrote:
> From: Julia Lawall <Julia.Lawall@lip6.fr>
> 
> Using kfree to free data allocated with devm_kzalloc causes double frees.
> 
> The semantic patch that fixes this problem is as follows:
> (http://coccinelle.lip6.fr/)
> 
> // <smpl>
> @@
> expression x;
> @@
> 
> x = devm_kzalloc(...)
> ...
> ?-kfree(x);
> // </smpl>
> 
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>

Applied.


Thanks,

Florian Tobias Schandinat

> 
> ---
>  drivers/video/auo_k190x.c |    2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c
> index 77da6a2..c03ecdd 100644
> --- a/drivers/video/auo_k190x.c
> +++ b/drivers/video/auo_k190x.c
> @@ -987,7 +987,6 @@ 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:
> @@ -1022,7 +1021,6 @@ int  __devexit auok190x_common_remove(struct platform_device *pdev)
>  	fb_dealloc_cmap(&info->cmap);
>  
>  	fb_deferred_io_cleanup(info);
> -	kfree(info->fbdefio);
>  
>  	vfree((void *)info->screen_base);
>  
> 
> 


^ permalink raw reply

* Re: [patch] video: mb862xxfb: prevent divide by zero bug
From: Florian Tobias Schandinat @ 2012-08-23 20:30 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20120818155541.GB22424@elgon.mountain>

On 08/18/2012 03:55 PM, Dan Carpenter wrote:
> Do a sanity check on these before using them as divisors.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Applied.


Thanks,

Florian Tobias Schandinat

> 
> diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
> index 00ce1f3..57d940b 100644
> --- a/drivers/video/mb862xx/mb862xxfbdrv.c
> +++ b/drivers/video/mb862xx/mb862xxfbdrv.c
> @@ -328,6 +328,8 @@ static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd,
>  	case MB862XX_L1_SET_CFG:
>  		if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg)))
>  			return -EFAULT;
> +		if (l1_cfg->dh = 0 || l1_cfg->dw = 0)
> +			return -EINVAL;
>  		if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) {
>  			/* downscaling */
>  			outreg(cap, GC_CAP_CSC,
> 


^ permalink raw reply

* Re: [PATCH 0/2] OMAPDSS: fixes for -rc
From: Florian Tobias Schandinat @ 2012-08-23 20:34 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-fbdev, linux-omap
In-Reply-To: <1345529388-3509-1-git-send-email-tomi.valkeinen@ti.com>

Hi Tomi,

On 08/21/2012 06:09 AM, Tomi Valkeinen wrote:
> Hi Florian,
> 
> Here are two small fixes for omapfb and omapdss. The first one fixes an old bug
> that causes colors to be wrong on fb console. The other fixes SDI output that
> got broken in the previous merge window.

Applied both patches. ("The first" is actually 2/2)


Thanks,

Florian Tobias Schandinat

> 
>  Tomi
> 
> Grazvydas Ignotas (1):
>   OMAPFB: fix framebuffer console colors
> 
> Tomi Valkeinen (1):
>   OMAPDSS: Fix SDI PLL locking
> 
>  drivers/video/omap2/dss/sdi.c            |   14 ++++++++++++++
>  drivers/video/omap2/omapfb/omapfb-main.c |    2 +-
>  2 files changed, 15 insertions(+), 1 deletion(-)
> 


^ permalink raw reply

* Re: [PATCH] video: exynos_dp: adjust voltage swing and pre-emphasis during Link Training
From: Florian Tobias Schandinat @ 2012-08-23 20:34 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <001101cd656a$5ea25c90$1be715b0$%han@samsung.com>

On 07/19/2012 04:52 AM, Jingoo Han wrote:
> This patch adds adjustement for voltage swing and pre-emphasis during
> Link Training procedure. According to the DP specification, unless all
> the LANEx_CR_DONE bits are set, the transmitter must read
> the ADJUST_REQUEST_LANEx_x, increase the voltage swing according to
> the request, and update the TRAINING_LANEx_SET bytes to match the new
> voltage swing setting.
> 
> Refer to the DP specification v1.1a, Section 3.5.1.3 Link Training.
> 
> Signed-off-by: Jingoo Han <jg1.han@samsung.com>

Applied.


Thanks,

Florian Tobias Schandinat

> ---
>  drivers/video/exynos/exynos_dp_core.c |  282 +++++++++++++++++----------------
>  drivers/video/exynos/exynos_dp_core.h |    2 +-
>  2 files changed, 144 insertions(+), 140 deletions(-)
> 
> diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
> index c6c016a..9c0140f 100644
> --- a/drivers/video/exynos/exynos_dp_core.c
> +++ b/drivers/video/exynos/exynos_dp_core.c
> @@ -260,7 +260,7 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
>  
>  static void exynos_dp_link_start(struct exynos_dp_device *dp)
>  {
> -	u8 buf[5];
> +	u8 buf[4];
>  	int lane;
>  	int lane_count;
>  
> @@ -295,10 +295,10 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
>  	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
>  
>  	/* Set RX training pattern */
> -	buf[0] = DPCD_SCRAMBLING_DISABLED |
> -		 DPCD_TRAINING_PATTERN_1;
>  	exynos_dp_write_byte_to_dpcd(dp,
> -		DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]);
> +		DPCD_ADDR_TRAINING_PATTERN_SET,
> +		DPCD_SCRAMBLING_DISABLED |
> +		DPCD_TRAINING_PATTERN_1);
>  
>  	for (lane = 0; lane < lane_count; lane++)
>  		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
> @@ -308,7 +308,7 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
>  		lane_count, buf);
>  }
>  
> -static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
> +static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
>  {
>  	int shift = (lane & 1) * 4;
>  	u8 link_value = link_status[lane>>1];
> @@ -316,7 +316,7 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
>  	return (link_value >> shift) & 0xf;
>  }
>  
> -static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
> +static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
>  {
>  	int lane;
>  	u8 lane_status;
> @@ -329,22 +329,23 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
>  	return 0;
>  }
>  
> -static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count)
> +static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
>  {
>  	int lane;
>  	u8 lane_align;
>  	u8 lane_status;
>  
> -	lane_align = link_status[2];
> +	lane_align = link_align[2];
>  	if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) = 0)
>  		return -EINVAL;
>  
>  	for (lane = 0; lane < lane_count; lane++) {
> -		lane_status = exynos_dp_get_lane_status(link_status, lane);
> +		lane_status = exynos_dp_get_lane_status(link_align, lane);
>  		lane_status &= DPCD_CHANNEL_EQ_BITS;
>  		if (lane_status != DPCD_CHANNEL_EQ_BITS)
>  			return -EINVAL;
>  	}
> +
>  	return 0;
>  }
>  
> @@ -417,69 +418,17 @@ static unsigned int exynos_dp_get_lane_link_training(
>  
>  static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
>  {
> -	if (dp->link_train.link_rate = LINK_RATE_2_70GBPS) {
> -		/* set to reduced bit rate */
> -		dp->link_train.link_rate = LINK_RATE_1_62GBPS;
> -		dev_err(dp->dev, "set to bandwidth %.2x\n",
> -			dp->link_train.link_rate);
> -		dp->link_train.lt_state = START;
> -	} else {
> -		exynos_dp_training_pattern_dis(dp);
> -		/* set enhanced mode if available */
> -		exynos_dp_set_enhanced_mode(dp);
> -		dp->link_train.lt_state = FAILED;
> -	}
> -}
> -
> -static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp,
> -				u8 adjust_request[2])
> -{
> -	int lane;
> -	int lane_count;
> -	u8 voltage_swing;
> -	u8 pre_emphasis;
> -	u8 training_lane;
> +	exynos_dp_training_pattern_dis(dp);
> +	exynos_dp_set_enhanced_mode(dp);
>  
> -	lane_count = dp->link_train.lane_count;
> -	for (lane = 0; lane < lane_count; lane++) {
> -		voltage_swing = exynos_dp_get_adjust_request_voltage(
> -						adjust_request, lane);
> -		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> -						adjust_request, lane);
> -		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> -				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
> -
> -		if (voltage_swing = VOLTAGE_LEVEL_3 ||
> -		   pre_emphasis = PRE_EMPHASIS_LEVEL_3) {
> -			training_lane |= DPCD_MAX_SWING_REACHED;
> -			training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
> -		}
> -		dp->link_train.training_lane[lane] = training_lane;
> -	}
> -}
> -
> -static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp,
> -					u8 voltage_swing)
> -{
> -	int lane;
> -	int lane_count;
> -
> -	lane_count = dp->link_train.lane_count;
> -	for (lane = 0; lane < lane_count; lane++) {
> -		if (voltage_swing = VOLTAGE_LEVEL_3 ||
> -			dp->link_train.cr_loop[lane] = MAX_CR_LOOP)
> -			return -EINVAL;
> -	}
> -	return 0;
> +	dp->link_train.lt_state = FAILED;
>  }
>  
>  static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
>  {
> -	u8 data;
> -	u8 link_status[6];
> +	u8 link_status[2];
>  	int lane;
>  	int lane_count;
> -	u8 buf[5];
>  
>  	u8 adjust_request[2];
>  	u8 voltage_swing;
> @@ -488,98 +437,152 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
>  
>  	usleep_range(100, 101);
>  
> -	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
> -				6, link_status);
>  	lane_count = dp->link_train.lane_count;
>  
> +	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
> +				2, link_status);
> +
>  	if (exynos_dp_clock_recovery_ok(link_status, lane_count) = 0) {
>  		/* set training pattern 2 for EQ */
>  		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
>  
> -		adjust_request[0] = link_status[4];
> -		adjust_request[1] = link_status[5];
> +		for (lane = 0; lane < lane_count; lane++) {
> +			exynos_dp_read_bytes_from_dpcd(dp,
> +					DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
> +					2, adjust_request);
> +			voltage_swing = exynos_dp_get_adjust_request_voltage(
> +							adjust_request, lane);
> +			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> +							adjust_request, lane);
> +			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> +					DPCD_PRE_EMPHASIS_SET(pre_emphasis);
>  
> -		exynos_dp_get_adjust_train(dp, adjust_request);
> +			if (voltage_swing = VOLTAGE_LEVEL_3)
> +				training_lane |= DPCD_MAX_SWING_REACHED;
> +			if (pre_emphasis = PRE_EMPHASIS_LEVEL_3)
> +				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
>  
> -		buf[0] = DPCD_SCRAMBLING_DISABLED |
> -			 DPCD_TRAINING_PATTERN_2;
> -		exynos_dp_write_byte_to_dpcd(dp,
> -			DPCD_ADDR_TRAINING_PATTERN_SET,
> -			buf[0]);
> +			dp->link_train.training_lane[lane] = training_lane;
>  
> -		for (lane = 0; lane < lane_count; lane++) {
>  			exynos_dp_set_lane_link_training(dp,
>  				dp->link_train.training_lane[lane],
>  				lane);
> -			buf[lane] = dp->link_train.training_lane[lane];
> -			exynos_dp_write_byte_to_dpcd(dp,
> -				DPCD_ADDR_TRAINING_LANE0_SET + lane,
> -				buf[lane]);
>  		}
> -		dp->link_train.lt_state = EQUALIZER_TRAINING;
> -	} else {
> -		exynos_dp_read_byte_from_dpcd(dp,
> -			DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
> -			&data);
> -		adjust_request[0] = data;
>  
> -		exynos_dp_read_byte_from_dpcd(dp,
> -			DPCD_ADDR_ADJUST_REQUEST_LANE2_3,
> -			&data);
> -		adjust_request[1] = data;
> +		exynos_dp_write_byte_to_dpcd(dp,
> +			DPCD_ADDR_TRAINING_PATTERN_SET,
> +			DPCD_SCRAMBLING_DISABLED |
> +			DPCD_TRAINING_PATTERN_2);
> +
> +		exynos_dp_write_bytes_to_dpcd(dp,
> +			DPCD_ADDR_TRAINING_LANE0_SET,
> +			lane_count,
> +			dp->link_train.training_lane);
>  
> +		dev_info(dp->dev, "Link Training Clock Recovery success\n");
> +		dp->link_train.lt_state = EQUALIZER_TRAINING;
> +	} else {
>  		for (lane = 0; lane < lane_count; lane++) {
>  			training_lane = exynos_dp_get_lane_link_training(
>  							dp, lane);
> +			exynos_dp_read_bytes_from_dpcd(dp,
> +					DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
> +					2, adjust_request);
>  			voltage_swing = exynos_dp_get_adjust_request_voltage(
>  							adjust_request, lane);
>  			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
>  							adjust_request, lane);
> -			if ((DPCD_VOLTAGE_SWING_GET(training_lane) = voltage_swing) &&
> -			    (DPCD_PRE_EMPHASIS_GET(training_lane) = pre_emphasis))
> -				dp->link_train.cr_loop[lane]++;
> -			dp->link_train.training_lane[lane] = training_lane;
> -		}
>  
> -		if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) {
> -			exynos_dp_reduce_link_rate(dp);
> -		} else {
> -			exynos_dp_get_adjust_train(dp, adjust_request);
> +			if (voltage_swing = VOLTAGE_LEVEL_3 ||
> +			    pre_emphasis = PRE_EMPHASIS_LEVEL_3) {
> +				dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
> +				goto reduce_link_rate;
> +			}
>  
> -			for (lane = 0; lane < lane_count; lane++) {
> -				exynos_dp_set_lane_link_training(dp,
> -					dp->link_train.training_lane[lane],
> -					lane);
> -				buf[lane] = dp->link_train.training_lane[lane];
> -				exynos_dp_write_byte_to_dpcd(dp,
> -					DPCD_ADDR_TRAINING_LANE0_SET + lane,
> -					buf[lane]);
> +			if ((DPCD_VOLTAGE_SWING_GET(training_lane) =
> +					voltage_swing) &&
> +			   (DPCD_PRE_EMPHASIS_GET(training_lane) =
> +					pre_emphasis)) {
> +				dp->link_train.cr_loop[lane]++;
> +				if (dp->link_train.cr_loop[lane] = MAX_CR_LOOP) {
> +					dev_err(dp->dev, "CR Max loop\n");
> +					goto reduce_link_rate;
> +				}
>  			}
> +
> +			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> +					DPCD_PRE_EMPHASIS_SET(pre_emphasis);
> +
> +			if (voltage_swing = VOLTAGE_LEVEL_3)
> +				training_lane |= DPCD_MAX_SWING_REACHED;
> +			if (pre_emphasis = PRE_EMPHASIS_LEVEL_3)
> +				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
> +
> +			dp->link_train.training_lane[lane] = training_lane;
> +
> +			exynos_dp_set_lane_link_training(dp,
> +				dp->link_train.training_lane[lane], lane);
>  		}
> +
> +		exynos_dp_write_bytes_to_dpcd(dp,
> +			DPCD_ADDR_TRAINING_LANE0_SET,
> +			lane_count,
> +			dp->link_train.training_lane);
>  	}
>  
>  	return 0;
> +
> +reduce_link_rate:
> +	exynos_dp_reduce_link_rate(dp);
> +	return -EIO;
>  }
>  
>  static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
>  {
> -	u8 link_status[6];
> +	u8 link_status[2];
> +	u8 link_align[3];
>  	int lane;
>  	int lane_count;
> -	u8 buf[5];
>  	u32 reg;
>  
>  	u8 adjust_request[2];
> +	u8 voltage_swing;
> +	u8 pre_emphasis;
> +	u8 training_lane;
>  
>  	usleep_range(400, 401);
>  
> -	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
> -				6, link_status);
>  	lane_count = dp->link_train.lane_count;
>  
> +	exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
> +				2, link_status);
> +
>  	if (exynos_dp_clock_recovery_ok(link_status, lane_count) = 0) {
> -		adjust_request[0] = link_status[4];
> -		adjust_request[1] = link_status[5];
> +		link_align[0] = link_status[0];
> +		link_align[1] = link_status[1];
> +
> +		exynos_dp_read_byte_from_dpcd(dp,
> +			DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
> +			&link_align[2]);
> +
> +		for (lane = 0; lane < lane_count; lane++) {
> +			exynos_dp_read_bytes_from_dpcd(dp,
> +					DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
> +					2, adjust_request);
> +			voltage_swing = exynos_dp_get_adjust_request_voltage(
> +							adjust_request, lane);
> +			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> +							adjust_request, lane);
> +			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> +					DPCD_PRE_EMPHASIS_SET(pre_emphasis);
> +
> +			if (voltage_swing = VOLTAGE_LEVEL_3)
> +				training_lane |= DPCD_MAX_SWING_REACHED;
> +			if (pre_emphasis = PRE_EMPHASIS_LEVEL_3)
> +				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
> +
> +			dp->link_train.training_lane[lane] = training_lane;
> +		}
>  
>  		if (exynos_dp_channel_eq_ok(link_status, lane_count) = 0) {
>  			/* traing pattern Set to Normal */
> @@ -596,39 +599,42 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
>  			dp->link_train.lane_count = reg;
>  			dev_dbg(dp->dev, "final lane count = %.2x\n",
>  				dp->link_train.lane_count);
> +
>  			/* set enhanced mode if available */
>  			exynos_dp_set_enhanced_mode(dp);
> -
>  			dp->link_train.lt_state = FINISHED;
>  		} else {
>  			/* not all locked */
>  			dp->link_train.eq_loop++;
>  
>  			if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
> -				exynos_dp_reduce_link_rate(dp);
> -			} else {
> -				exynos_dp_get_adjust_train(dp, adjust_request);
> -
> -				for (lane = 0; lane < lane_count; lane++) {
> -					exynos_dp_set_lane_link_training(dp,
> -						dp->link_train.training_lane[lane],
> -						lane);
> -					buf[lane] = dp->link_train.training_lane[lane];
> -					exynos_dp_write_byte_to_dpcd(dp,
> -						DPCD_ADDR_TRAINING_LANE0_SET + lane,
> -						buf[lane]);
> -				}
> +				dev_err(dp->dev, "EQ Max loop\n");
> +				goto reduce_link_rate;
>  			}
> +
> +			for (lane = 0; lane < lane_count; lane++)
> +				exynos_dp_set_lane_link_training(dp,
> +					dp->link_train.training_lane[lane],
> +					lane);
> +
> +			exynos_dp_write_bytes_to_dpcd(dp,
> +				DPCD_ADDR_TRAINING_LANE0_SET,
> +				lane_count,
> +				dp->link_train.training_lane);
>  		}
>  	} else {
> -		exynos_dp_reduce_link_rate(dp);
> +		goto reduce_link_rate;
>  	}
>  
>  	return 0;
> +
> +reduce_link_rate:
> +	exynos_dp_reduce_link_rate(dp);
> +	return -EIO;
>  }
>  
>  static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
> -			u8 *bandwidth)
> +					u8 *bandwidth)
>  {
>  	u8 data;
>  
> @@ -641,7 +647,7 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
>  }
>  
>  static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
> -			u8 *lane_count)
> +					u8 *lane_count)
>  {
>  	u8 data;
>  
> @@ -693,13 +699,7 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,
>  static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
>  {
>  	int retval = 0;
> -	int training_finished;
> -
> -	/* Turn off unnecessary lane */
> -	if (dp->link_train.lane_count = 1)
> -		exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1);
> -
> -	training_finished = 0;
> +	int training_finished = 0;
>  
>  	dp->link_train.lt_state = START;
>  
> @@ -710,10 +710,14 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
>  			exynos_dp_link_start(dp);
>  			break;
>  		case CLOCK_RECOVERY:
> -			exynos_dp_process_clock_recovery(dp);
> +			retval = exynos_dp_process_clock_recovery(dp);
> +			if (retval)
> +				dev_err(dp->dev, "LT CR failed!\n");
>  			break;
>  		case EQUALIZER_TRAINING:
> -			exynos_dp_process_equalizer_training(dp);
> +			retval = exynos_dp_process_equalizer_training(dp);
> +			if (retval)
> +				dev_err(dp->dev, "LT EQ failed!\n");
>  			break;
>  		case FINISHED:
>  			training_finished = 1;
> diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
> index 8526e54..44c11e1 100644
> --- a/drivers/video/exynos/exynos_dp_core.h
> +++ b/drivers/video/exynos/exynos_dp_core.h
> @@ -144,7 +144,7 @@ void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
>  #define DPCD_ADDR_TRAINING_PATTERN_SET		0x0102
>  #define DPCD_ADDR_TRAINING_LANE0_SET		0x0103
>  #define DPCD_ADDR_LANE0_1_STATUS		0x0202
> -#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED	0x0204
> +#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED	0x0204
>  #define DPCD_ADDR_ADJUST_REQUEST_LANE0_1	0x0206
>  #define DPCD_ADDR_ADJUST_REQUEST_LANE2_3	0x0207
>  #define DPCD_ADDR_TEST_REQUEST			0x0218


^ permalink raw reply

* Re: [PATCH 5/5] drivers/video/ep93xx-fb.c: use devm_ functions
From: Florian Tobias Schandinat @ 2012-08-23 20:35 UTC (permalink / raw)
  To: Damien Cassou; +Cc: kernel-janitors, linux-fbdev, linux-kernel
In-Reply-To: <1343742860-16213-2-git-send-email-damien.cassou@lifl.fr>

On 07/31/2012 01:54 PM, Damien Cassou wrote:
> From: Damien Cassou <damien.cassou@lifl.fr>
> 
> The various devm_ functions allocate memory that is released when a driver
> detaches.  This patch uses these functions for data that is allocated in
> the probe function of a platform device and is only freed in the remove
> function.
> 
> Signed-off-by: Damien Cassou <damien.cassou@lifl.fr>

Applied.


Thanks,

Florian Tobias Schandinat

> 
> ---
>  drivers/video/ep93xx-fb.c |   17 ++++++-----------
>  1 file changed, 6 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
> index 345d962..69c89f2 100644
> --- a/drivers/video/ep93xx-fb.c
> +++ b/drivers/video/ep93xx-fb.c
> @@ -529,7 +529,8 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
>  	 * any of the framebuffer registers.
>  	 */
>  	fbi->res = res;
> -	fbi->mmio_base = ioremap(res->start, resource_size(res));
> +	fbi->mmio_base = devm_ioremap(&pdev->dev, res->start,
> +				      resource_size(res));
>  	if (!fbi->mmio_base) {
>  		err = -ENXIO;
>  		goto failed_resource;
> @@ -553,20 +554,20 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
>  	if (err = 0) {
>  		dev_err(info->dev, "No suitable video mode found\n");
>  		err = -EINVAL;
> -		goto failed_mode;
> +		goto failed_resource;
>  	}
>  
>  	if (mach_info->setup) {
>  		err = mach_info->setup(pdev);
>  		if (err)
> -			goto failed_mode;
> +			goto failed_resource;
>  	}
>  
>  	err = ep93xxfb_check_var(&info->var, info);
>  	if (err)
>  		goto failed_check;
>  
> -	fbi->clk = clk_get(info->dev, NULL);
> +	fbi->clk = devm_clk_get(&pdev->dev, NULL);
>  	if (IS_ERR(fbi->clk)) {
>  		err = PTR_ERR(fbi->clk);
>  		fbi->clk = NULL;
> @@ -578,19 +579,15 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
>  
>  	err = register_framebuffer(info);
>  	if (err)
> -		goto failed;
> +		goto failed_check;
>  
>  	dev_info(info->dev, "registered. Mode = %dx%d-%d\n",
>  		 info->var.xres, info->var.yres, info->var.bits_per_pixel);
>  	return 0;
>  
> -failed:
> -	clk_put(fbi->clk);
>  failed_check:
>  	if (fbi->mach_info->teardown)
>  		fbi->mach_info->teardown(pdev);
> -failed_mode:
> -	iounmap(fbi->mmio_base);
>  failed_resource:
>  	ep93xxfb_dealloc_videomem(info);
>  failed_videomem:
> @@ -609,8 +606,6 @@ static int __devexit ep93xxfb_remove(struct platform_device *pdev)
>  
>  	unregister_framebuffer(info);
>  	clk_disable(fbi->clk);
> -	clk_put(fbi->clk);
> -	iounmap(fbi->mmio_base);
>  	ep93xxfb_dealloc_videomem(info);
>  	fb_dealloc_cmap(&info->cmap);
>  
> 
> 


^ permalink raw reply

* Re: [PATCH 3/5] drivers/video/cobalt_lcdfb.c: use devm_ functions
From: Florian Tobias Schandinat @ 2012-08-23 20:36 UTC (permalink / raw)
  To: Damien Cassou; +Cc: kernel-janitors, linux-fbdev, linux-kernel
In-Reply-To: <1343742860-16213-4-git-send-email-damien.cassou@lifl.fr>

On 07/31/2012 01:54 PM, Damien Cassou wrote:
> From: Damien Cassou <damien.cassou@lifl.fr>
> 
> The various devm_ functions allocate memory that is released when a driver
> detaches.  This patch uses these functions for data that is allocated in
> the probe function of a platform device and is only freed in the remove
> function.
> 
> Signed-off-by: Damien Cassou <damien.cassou@lifl.fr>

Applied.


Thanks,

Florian Tobias Schandinat

> 
> ---
>  drivers/video/cobalt_lcdfb.c |    5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
> index eae46f6..01a4ee7 100644
> --- a/drivers/video/cobalt_lcdfb.c
> +++ b/drivers/video/cobalt_lcdfb.c
> @@ -348,7 +348,8 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
>  	}
>  
>  	info->screen_size = resource_size(res);
> -	info->screen_base = ioremap(res->start, info->screen_size);
> +	info->screen_base = devm_ioremap(&dev->dev, res->start,
> +					 info->screen_size);
>  	info->fbops = &cobalt_lcd_fbops;
>  	info->fix = cobalt_lcdfb_fix;
>  	info->fix.smem_start = res->start;
> @@ -359,7 +360,6 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
>  
>  	retval = register_framebuffer(info);
>  	if (retval < 0) {
> -		iounmap(info->screen_base);
>  		framebuffer_release(info);
>  		return retval;
>  	}
> @@ -380,7 +380,6 @@ static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
>  
>  	info = platform_get_drvdata(dev);
>  	if (info) {
> -		iounmap(info->screen_base);
>  		unregister_framebuffer(info);
>  		framebuffer_release(info);
>  	}
> 
> 


^ permalink raw reply

* Re: [PATCH 1/5] drivers/video/bf537-lq035.c: use devm_ functions
From: Florian Tobias Schandinat @ 2012-08-23 20:36 UTC (permalink / raw)
  To: Damien Cassou; +Cc: kernel-janitors, linux-fbdev, linux-kernel
In-Reply-To: <1343742860-16213-6-git-send-email-damien.cassou@lifl.fr>

On 07/31/2012 01:54 PM, Damien Cassou wrote:
> From: Damien Cassou <damien.cassou@lifl.fr>
> 
> The various devm_ functions allocate memory that is released when a driver
> detaches.  This patch uses these functions for data that is allocated in
> the probe function of a platform device and is only freed in the remove
> function.
> 
> Signed-off-by: Damien Cassou <damien.cassou@lifl.fr>

Applied.


Thanks,

Florian Tobias Schandinat

> 
> ---
>  drivers/video/bf537-lq035.c |   12 +++++-------
>  1 file changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
> index befbc80..7347aa1 100644
> --- a/drivers/video/bf537-lq035.c
> +++ b/drivers/video/bf537-lq035.c
> @@ -760,18 +760,20 @@ static int __devinit bfin_lq035_probe(struct platform_device *pdev)
>  	bfin_lq035_fb.flags = FBINFO_DEFAULT;
>  
>  
> -	bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL);
> +	bfin_lq035_fb.pseudo_palette = devm_kzalloc(&pdev->dev,
> +						    sizeof(u32) * 16,
> +						    GFP_KERNEL);
>  	if (bfin_lq035_fb.pseudo_palette = NULL) {
>  		pr_err("failed to allocate pseudo_palette\n");
>  		ret = -ENOMEM;
> -		goto out_palette;
> +		goto out_table;
>  	}
>  
>  	if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
>  		pr_err("failed to allocate colormap (%d entries)\n",
>  			NBR_PALETTE);
>  		ret = -EFAULT;
> -		goto out_cmap;
> +		goto out_table;
>  	}
>  
>  	if (register_framebuffer(&bfin_lq035_fb) < 0) {
> @@ -804,9 +806,6 @@ out_lcd:
>  	unregister_framebuffer(&bfin_lq035_fb);
>  out_reg:
>  	fb_dealloc_cmap(&bfin_lq035_fb.cmap);
> -out_cmap:
> -	kfree(bfin_lq035_fb.pseudo_palette);
> -out_palette:
>  out_table:
>  	dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
>  	fb_buffer = NULL;
> @@ -834,7 +833,6 @@ static int __devexit bfin_lq035_remove(struct platform_device *pdev)
>  	free_dma(CH_PPI);
>  
>  
> -	kfree(bfin_lq035_fb.pseudo_palette);
>  	fb_dealloc_cmap(&bfin_lq035_fb.cmap);
>  
>  
> 
> 


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox