Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* RE: [PATCH 5/5] drivers/video/exynos/exynos_dp_core.c: use devm_ functions
From: Julia Lawall @ 2012-08-01  5:13 UTC (permalink / raw)
  To: Jingoo Han
  Cc: 'Sachin Kamat', 'Damien Cassou', kernel-janitors,
	'Florian Tobias Schandinat', linux-fbdev, linux-kernel
In-Reply-To: <003f01cd6fa2$36463bd0$a2d2b370$%han@samsung.com>

On Wed, 1 Aug 2012, Jingoo Han wrote:

> On Wednesday, August 01, 2012 1:38 PM Sachin Kamat wrote:
>>
>> On 1 August 2012 10:00, Jingoo Han <jg1.han@samsung.com> wrote:
>>> On Wednesday, August 01, 2012 1:00 PMSachin Kamat wrote:
>>>>
>>>> On 1 August 2012 04:51, Jingoo Han <jg1.han@samsung.com> wrote:
>>>>> On Wednesday, August 01, 2012 1:39 AM 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>
>>>>>>
>>>>>> ---
>>>>>>  drivers/video/exynos/exynos_dp_core.c |   27 +++++++--------------------
>>>>>>  1 file changed, 7 insertions(+), 20 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
>>>>>> index c6c016a..00fe4f0 100644
>>>>>> --- a/drivers/video/exynos/exynos_dp_core.c
>>>>>> +++ b/drivers/video/exynos/exynos_dp_core.c
>>>>>> @@ -872,7 +872,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
>>>>>>
>>>>>>       dp->dev = &pdev->dev;
>>>>>>
>>>>>> -     dp->clock = clk_get(&pdev->dev, "dp");
>>>>>> +     dp->clock = devm_clk_get(&pdev->dev, "dp");
>>>>>>       if (IS_ERR(dp->clock)) {
>>>>>>               dev_err(&pdev->dev, "failed to get clock\n");
>>>>>>               return PTR_ERR(dp->clock);
>>>>>> @@ -881,31 +881,24 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
>>>>>>       clk_enable(dp->clock);
>>>>>>
>>>>>>       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>> -     if (!res) {
>>>>>> -             dev_err(&pdev->dev, "failed to get registers\n");
>>>>>> -             ret = -EINVAL;
>>>>>> -             goto err_clock;
>>>>>> -     }
>>>>>
>>>>> Why do you remove this return check?
>>>>> If there is no reason, please, do it as follows:
>>>>>
>>>>>         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>         if (!res) {
>>>>>                 dev_err(&pdev->dev, "failed to get registers\n");
>>>>> -               ret = -EINVAL;
>>>>> -               goto err_clock;
>>>>> +               return -EINVAL;
>>>>>         }
>>>>>
>>>>>
>>>>
>>>> devm_request_and_ioremap function checks the validity of res. Hence
>>>> this check above is redundant and can be removed.
>>>
>>>
>>> I don't think so.
>>> Even though function called next checks the NULL value,
>>> for robustness, the return value of platform_get_resource() should be
>>> checked.
>>>
>>> It is possible that devm_request_and_ioremap() can be changed in the future,
>>> as request_mem_region() & ioremap() were changed to devm_request_and_ioremap().
>>
>> They are not changed. They still exist.  devm_request_and_ioremap() is
>> an additional function provided for device managed resources.
>
>
> OK, I see. I accept it.
> Anyway it is simpler.

This thread contains a discussion about the issue 
http://lkml.org/lkml/2012/1/28/10
Look for the comments by Wolfram Sang, who 
implemented devm_request_and_ioremap, and who suggests that the NULL test 
be removed.

I rather agree with the desire to be safe and uniform, but these 
initialization functions are really large, and with error handling code 
(although not in this case) there is always the danger of jumping to the 
wrong place, and thus making more of a mess.  It would be nice if the 
platform_get_resource could be merged with devm_request_and_ioremap, but I 
think that I looked once and there were not enough calls that were similar 
enough to make that compelling.

julia

^ permalink raw reply

* Re: [PATCH 1/4] video: Add support for the Solomon SSD1307 OLED Controller
From: Shawn Guo @ 2012-08-01  5:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1343730576-20494-2-git-send-email-maxime.ripard@free-electrons.com>

On Tue, Jul 31, 2012 at 12:29:33PM +0200, Maxime Ripard wrote:
> +Optional properties:
> +  - oled-reset-active-low: Is the reset gpio is active on physical low?

You may want to take a look at commit c1cb438 (bindings: update imx and
mxs #gpio-cells) which got merged recently.  In case the driver will
only work on mxs, this optional property can just be dropped.

Regards,
Shawn


^ permalink raw reply

* Re: [PATCH 1/4] video: Add support for the Solomon SSD1307 OLED Controller
From: Jingoo Han @ 2012-08-01  5:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1343730576-20494-2-git-send-email-maxime.ripard@free-electrons.com>

On Tuesday, July 31, 2012 7:30 PM Maxime Ripard wrote:
> 
> This patch adds support for the Solomon SSD1307 OLED
> controller found on the Crystalfontz CFA10036 board.
> 
> This controller can drive a display with a resolution up
> to 128x39 and can operate over I2C or SPI.
> 
> The current driver has only been tested on the CFA-10036,
> that is using this controller over I2C to driver a 96x16
> OLED screen.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Cc: Brian Lilly <brian@crystalfontz.com>
> ---
>  .../devicetree/bindings/video/ssd1307fb.txt        |   24 ++
>  drivers/video/Kconfig                              |   14 +
>  drivers/video/Makefile                             |    1 +
>  drivers/video/ssd1307fb.c                          |  418 ++++++++++++++++++++
>  4 files changed, 457 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/video/ssd1307fb.txt
>  create mode 100644 drivers/video/ssd1307fb.c
> 
> diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt
> b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> new file mode 100644
> index 0000000..791e14f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
> @@ -0,0 +1,24 @@
> +* Solomon SSD1307 Framebuffer Driver
> +
> +Required properties:
> +  - compatible: Should be "solomon,ssd1307fb-<bus>". The only supported bus for
> +    now is i2c.
> +  - reg: Should contain address of the controller on the I2C bus. Most likely
> +         0x3c or 0x3d
> +  - pwm: Should contain the pwm to use according to the OF device tree PWM
> +         specification [0]
> +  - oled-reset-gpio: Should contain the GPIO used to reset the OLED display
> +
> +Optional properties:
> +  - oled-reset-active-low: Is the reset gpio is active on physical low?
> +
> +[0]: Documentation/devicetree/bindings/pwm/pwm.txt
> +
> +Examples:
> +ssd1307: oled@3c {
> +        compatible = "solomon,ssd1307fb-i2c";
> +        reg = <0x3c>;
> +        pwms = <&pwm 4 3000>;
> +        oled-reset-gpio = <&gpio2 7 1>;
> +        oled-reset-active-low;
> +};
> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
> index 0217f74..21ae6dd 100644
> --- a/drivers/video/Kconfig
> +++ b/drivers/video/Kconfig
> @@ -2469,4 +2469,18 @@ config FB_SH_MOBILE_MERAM
>  	  Up to 4 memory channels can be configured, allowing 4 RGB or
>  	  2 YCbCr framebuffers to be configured.
> 
> +

Please remove redundant line.

> +config FB_SSD1307
> +	tristate "Solomon SSD1307 framebuffer support"
> +	depends on FB && I2C
> +	select FB_SYS_FOPS
> +	select FB_SYS_FILLRECT
> +	select FB_SYS_COPYAREA
> +	select FB_SYS_IMAGEBLIT
> +	select FB_DEFERRED_IO
> +	select PWM
> +	help
> +	  This driver implements support for the Solomon SSD1307
> +	  OLED controller over I2C.
> +
>  endmenu
> diff --git a/drivers/video/Makefile b/drivers/video/Makefile
> index ee8dafb..6bbb72c 100644
> --- a/drivers/video/Makefile
> +++ b/drivers/video/Makefile
> @@ -164,6 +164,7 @@ obj-$(CONFIG_FB_BFIN_7393)        += bfin_adv7393fb.o
>  obj-$(CONFIG_FB_MX3)		  += mx3fb.o
>  obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
>  obj-$(CONFIG_FB_MXS)		  += mxsfb.o
> +obj-$(CONFIG_FB_SSD1307)	  += ssd1307fb.o
> 
>  # the test framebuffer is last
>  obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
> diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
> new file mode 100644
> index 0000000..c705ab4
> --- /dev/null
> +++ b/drivers/video/ssd1307fb.c
> @@ -0,0 +1,418 @@
> +/*
> + * Driver for the Solomon SSD1307 OLED controler
> + *
> + * Copyright 2012 Free Electrons
> + *
> + * Licensed under the GPLv2 or later.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/i2c.h>
> +#include <linux/fb.h>
> +#include <linux/uaccess.h>
> +#include <linux/of_device.h>
> +#include <linux/of_gpio.h>
> +#include <linux/pwm.h>
> +#include <linux/delay.h>
> +
> +#define SSD1307FB_WIDTH			96
> +#define SSD1307FB_HEIGHT		16
> +
> +#define SSD1307FB_DATA			0x40
> +#define SSD1307FB_COMMAND		0x80
> +
> +#define SSD1307FB_CONTRAST		0x81
> +#define SSD1307FB_SEG_REMAP_ON		0xa1
> +#define SSD1307FB_DISPLAY_OFF		0xae
> +#define SSD1307FB_DISPLAY_ON		0xaf
> +#define SSD1307FB_START_PAGE_ADDRESS	0xb0
> +
> +struct ssd1307fb_par {
> +	struct i2c_client *client;
> +	struct fb_info *info;
> +	struct pwm_device *pwm;
> +	u32 pwm_period;
> +	int reset;
> +};
> +
> +static struct fb_fix_screeninfo ssd1307fb_fix __devinitdata = {
> +	.id		= "Solomon SSD1307",
> +	.type		= FB_TYPE_PACKED_PIXELS,
> +	.visual		= FB_VISUAL_MONO10,
> +	.xpanstep	= 0,
> +	.ypanstep	= 0,
> +	.ywrapstep	= 0,
> +	.line_length	= SSD1307FB_WIDTH / 8,
> +	.accel		= FB_ACCEL_NONE,
> +};
> +
> +static struct fb_var_screeninfo ssd1307fb_var __devinitdata = {
> +	.xres		= SSD1307FB_WIDTH,
> +	.yres		= SSD1307FB_HEIGHT,
> +	.xres_virtual	= SSD1307FB_WIDTH,
> +	.yres_virtual	= SSD1307FB_HEIGHT,
> +	.bits_per_pixel	= 1,
> +};
> +
> +static int ssd1307fb_write_array(struct i2c_client *client, u8 type, u8* cmd, u32 len)
> +{
> +	u8 *buf;
> +	int ret = 0;
> +
> +	buf = kzalloc(len + 1, GFP_KERNEL);
> +	if (!buf) {
> +		dev_err(&client->dev, "Couldn't allocate sending buffer.\n");
> +		ret = -ENOMEM;
> +		goto out;
> +	}

How about using returning - ENOMEM without goto.
It is simpler.

	if (!buf) {
		dev_err(&client->dev, "Couldn't allocate sending buffer.\n");
		return -ENOMEM;
	}


> +
> +	buf[0] = type;
> +	memcpy(buf + 1, cmd, len);
> +
> +	ret = i2c_master_send(client, buf, len + 1);
> +	if (ret != len + 1) {
> +		dev_err(&client->dev, "Couldn't send I2C command.\n");
> +		goto error;
> +	}
> +
> +error:
> +	kfree(buf);
> +out:
> +	return ret;

Please refer to above comment.
If goto out is not used, it would be simpler.

+error:
+	kfree(buf);
+	return ret;


> +}
> +
> +static inline int ssd1307fb_write_cmd_array(struct i2c_client *client, u8* cmd, u32 len)
> +{
> +	return ssd1307fb_write_array(client, SSD1307FB_COMMAND, cmd, len);
> +}
> +
> +static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
> +{
> +	return ssd1307fb_write_cmd_array(client, &cmd, 1);
> +}
> +
> +static inline int ssd1307fb_write_data_array(struct i2c_client *client, u8* cmd, u32 len)
> +{
> +	return ssd1307fb_write_array(client, SSD1307FB_DATA, cmd, len);
> +}
> +
> +static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
> +{
> +	return ssd1307fb_write_data_array(client, &data, 1);
> +}
> +
> +static int ssd1307fb_set(struct i2c_client *client, u8 value)
> +{
> +	int i, j, ret;
> +
> +	for (i = 1; i <= (SSD1307FB_HEIGHT / 8); i++) {
> +		ret = ssd1307fb_write_cmd(client, SSD1307FB_START_PAGE_ADDRESS + i);
> +		if (ret < 0)
> +			goto i2c_error;
> +
> +		ret = ssd1307fb_write_cmd(client, 0x00);
> +		if (ret < 0)
> +			goto i2c_error;
> +
> +		ret = ssd1307fb_write_cmd(client, 0x10);
> +		if (ret < 0)
> +			goto i2c_error;
> +
> +		for (j = 0; j < SSD1307FB_WIDTH; j++)
> +			ssd1307fb_write_data(client, value);
> +	}
> +
> +	return 0;
> +
> +i2c_error:
> +	dev_err(&client->dev, "Couldn't send i2c command: %d\n", ret);
> +	return ret;
> +}
> +
> +static void ssd1307fb_update_display(struct ssd1307fb_par *par)
> +{
> +	u8 *vmem = par->info->screen_base;
> +	int i, j, k;
> +
> +	/*
> +	 * The screen is divided in pages, each having a height of 8
> +	 * pixels, and the width of the screen. When sending a byte of
> +	 * data to the controller, it gives the 8 bits for the current
> +	 * column. I.e, the first byte are the 8 bits of the first
> +	 * column, then the 8 bits for the second column, etc.
> +	 *
> +	 *
> +	 * Representation of the screen, assuming it is 5 bits
> +	 * wide. Each letter-number combination is a bit that controls
> +	 * one pixel.
> +	 *
> +	 * A0 A1 A2 A3 A4
> +	 * B0 B1 B2 B3 B4
> +	 * C0 C1 C2 C3 C4
> +	 * D0 D1 D2 D3 D4
> +	 * E0 E1 E2 E3 E4
> +	 * F0 F1 F2 F3 F4
> +	 * G0 G1 G2 G3 G4
> +	 * H0 H1 H2 H3 H4
> +	 *
> +	 * If you want to update this screen, you need to send 5 bytes:
> +	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
> +	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
> +	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
> +	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
> +	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
> +	 */
> +
> +	for (i = 0; i < (SSD1307FB_HEIGHT / 8); i++) {
> +		ssd1307fb_write_cmd(par->client, SSD1307FB_START_PAGE_ADDRESS + (i + 1));
> +		ssd1307fb_write_cmd(par->client, 0x00);
> +		ssd1307fb_write_cmd(par->client, 0x10);
> +
> +		for (j = 0; j < SSD1307FB_WIDTH; j++) {
> +			u8 buf = 0;
> +			for (k = 0; k < 8; k++) {
> +				u32 page_length = SSD1307FB_WIDTH * i;
> +				u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
> +				u8 byte = *(vmem + index);
> +				u8 bit = byte & (1 << (7 - (j % 8)));
> +				bit = bit >> (7 - (j % 8));
> +				buf |= bit << k;
> +			}
> +			ssd1307fb_write_data(par->client, buf);
> +		}
> +	}
> +
> +	return;
> +}
> +
> +

Please remove unnecessary line.

> +static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
> +		size_t count, loff_t *ppos)
> +{
> +	struct ssd1307fb_par *par = info->par;
> +	unsigned long p = *ppos;
> +	void *dst;
> +	int err = 0;
> +
> +	dst = (void __force *) (info->screen_base + p);
> +
> +	if (copy_from_user(dst, buf, count))
> +		err = -EFAULT;
> +
> +	if  (!err)
> +		*ppos += count;
> +
> +	ssd1307fb_update_display(par);
> +
> +	return (err) ? err : count;
> +}
> +
> +static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
> +{
> +	struct ssd1307fb_par *par = info->par;
> +	sys_fillrect(info, rect);
> +	ssd1307fb_update_display(par);
> +}
> +
> +static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
> +{
> +	struct ssd1307fb_par *par = info->par;
> +	sys_copyarea(info, area);
> +	ssd1307fb_update_display(par);
> +}
> +
> +static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
> +{
> +	struct ssd1307fb_par *par = info->par;
> +	sys_imageblit(info, image);
> +	ssd1307fb_update_display(par);
> +}
> +
> +static struct fb_ops ssd1307fb_ops = {
> +	.owner		= THIS_MODULE,
> +	.fb_read	= fb_sys_read,
> +	.fb_write	= ssd1307fb_write,
> +	.fb_fillrect	= ssd1307fb_fillrect,
> +	.fb_copyarea	= ssd1307fb_copyarea,
> +	.fb_imageblit	= ssd1307fb_imageblit,
> +};
> +
> +static void ssd1307fb_deferred_io(struct fb_info *info,
> +				struct list_head *pagelist)
> +{
> +	ssd1307fb_update_display(info->par);
> +}
> +
> +static struct fb_deferred_io ssd1307fb_defio = {
> +	.delay		= HZ,
> +	.deferred_io	= ssd1307fb_deferred_io,
> +};
> +
> +static int __devinit ssd1307fb_probe(struct i2c_client *client, const struct i2c_device_id *id)
> +{
> +	struct fb_info *info;
> +	u32 vmem_size = SSD1307FB_WIDTH * SSD1307FB_HEIGHT / 8;
> +	struct ssd1307fb_par *par;
> +	u8 *vmem;
> +	int ret;
> +
> +	if (!client->dev.of_node) {
> +		dev_err(&client->dev, "No device tree data found!\n");
> +		ret = -EINVAL;
> +		goto generic_error;
> +	}

How about using returning -EINVAL without goto.
It is simpler.

	if (!client->dev.of_node) {
		dev_err(&client->dev, "No device tree data found!\n");
		return -EINVAL;
	}


> +
> +	info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev);
> +	if (!info) {
> +		ret = -ENOMEM;
> +		goto generic_error;
> +	}


Ditto.


> +
> +	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
> +	if (!vmem) {
> +		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
> +		ret = -ENOMEM;
> +		goto generic_error;
> +	}

Please fix this 'goto generic_error'. goto generic_error cannot call
framebuffer_release(). If framebuffer_alloc() is already called,
framebuffer_release() should be called when error happens.


> +
> +	info->fbops = &ssd1307fb_ops;
> +	info->fix = ssd1307fb_fix;
> +	info->fbdefio = &ssd1307fb_defio;
> +
> +	info->var = ssd1307fb_var;
> +	info->var.red.length = 1;
> +	info->var.red.offset = 0;
> +	info->var.green.length = 1;
> +	info->var.green.offset = 0;
> +	info->var.blue.length = 1;
> +	info->var.blue.offset = 0;
> +
> +	info->screen_base = (u8 __force __iomem *)vmem;
> +	info->fix.smem_start = (unsigned long)vmem;
> +	info->fix.smem_len = vmem_size;
> +
> +	fb_deferred_io_init(info);
> +
> +	par = info->par;
> +	par->info = info;
> +	par->client = client;
> +
> +	par->reset = of_get_named_gpio(client->dev.of_node,
> +					 "oled-reset-gpio", 0);
> +	if (gpio_is_valid(par->reset)) {
> +		int flags = GPIOF_OUT_INIT_HIGH;
> +		if (of_get_property(client->dev.of_node,
> +				    "oled-reset-active-low", NULL))
> +			flags = GPIOF_OUT_INIT_LOW;
> +		ret = devm_gpio_request_one(&client->dev, par->reset,
> +					    flags, "oled-reset");
> +		if (ret) {
> +			dev_err(&client->dev,
> +				"failed to request gpio %d: %d\n",
> +				par->reset, ret);
> +			goto reset_oled_error;
> +		}
> +	}
> +
> +	par->pwm = pwm_get(&client->dev, NULL);
> +	if (IS_ERR(par->pwm)) {
> +		dev_err(&client->dev, "Could not get PWM from device tree!\n");
> +		ret = PTR_ERR(par->pwm);
> +		goto pwm_error;
> +	}
> +
> +	par->pwm_period = pwm_get_period(par->pwm);
> +
> +	dev_dbg(&client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period);
> +
> +	ret = register_framebuffer(info);
> +	if (ret) {
> +		dev_err(&client->dev, "Couldn't register the framebuffer\n");
> +		goto fbreg_error;
> +	}
> +
> +	i2c_set_clientdata(client, info);
> +
> +	/* Reset the screen */
> +	gpio_set_value(par->reset, 1);
> +	udelay(4);
> +	gpio_set_value(par->reset, 0);
> +	udelay(4);
> +
> +	/* Enable the PWM */
> +	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
> +	pwm_enable(par->pwm);
> +
> +	/* Map column 127 of the OLED to segment 0 */
> +	ret = ssd1307fb_write_cmd(client, SSD1307FB_SEG_REMAP_ON);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "Couldn't remap the screen.\n");
> +		goto remap_error;
> +	}
> +
> +	/* Turn on the display */
> +	ret = ssd1307fb_write_cmd(client, SSD1307FB_DISPLAY_ON);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "Couldn't turn the display on.\n");
> +		goto remap_error;
> +	}
> +
> +	dev_info(&client->dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n",
> info->node, info->fix.id, vmem_size);
> +
> +	return 0;
> +
> +remap_error:
> +	unregister_framebuffer(info);
> +	pwm_disable(par->pwm);
> +fbreg_error:
> +	pwm_put(par->pwm);
> +pwm_error:
> +reset_oled_error:
> +	fb_deferred_io_cleanup(info);
> +	framebuffer_release(info);
> +generic_error:
> +	return ret;
> +}
> +
> +static int __devexit ssd1307fb_remove(struct i2c_client *client)
> +{
> +	struct fb_info *info = i2c_get_clientdata(client);
> +	struct ssd1307fb_par *par = info->par;


How about insert new line between variables and functions
to enhance the readability?


> +	unregister_framebuffer(info);
> +	pwm_disable(par->pwm);
> +	pwm_put(par->pwm);
> +	fb_deferred_io_cleanup(info);
> +	framebuffer_release(info);
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id ssd1307fb_i2c_id[] = {
> +	{ "ssd1307fb", 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id);
> +
> +static const struct of_device_id ssd1307fb_of_match[] = {
> +	{ .compatible = "solomon,ssd1307fb-i2c" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
> +
> +static struct i2c_driver ssd1307fb_driver = {
> +	.probe = ssd1307fb_probe,
> +	.remove = __devexit_p(ssd1307fb_remove),
> +	.id_table = ssd1307fb_i2c_id,
> +	.driver = {
> +		.name = "ssd1307fb",
> +		.of_match_table = of_match_ptr(ssd1307fb_of_match),
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +module_i2c_driver(ssd1307fb_driver);
> +
> +MODULE_DESCRIPTION("FB driver for the Solomon SSD1307 OLED controler");
> +MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
> +MODULE_LICENSE("GPL");
> --
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply

* Re: [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Thierry Reding @ 2012-08-01  7:17 UTC (permalink / raw)
  To: Alex Courbot
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Stephen Warren, Greg Kroah-Hartman, Mark Brown,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
In-Reply-To: <5018997B.7010808-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

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

On Wed, Aug 01, 2012 at 11:50:35AM +0900, Alex Courbot wrote:
> On 07/31/2012 07:19 PM, Thierry Reding wrote:
> >* PGP Signed by an unknown key
> >
> >On Tue, Jul 31, 2012 at 06:51:03PM +0900, Alex Courbot wrote:
> >>I would like to do that actually. The issue is that it did not work
> >>go well with the legacy pwm_backlight behavior: a power sequence
> >>needs to be constructed out of a PWM obtained through
> >>pwm_request(int pwm_id, char *label) and this behavior cannot be
> >>emulated using the new platform data interface (which only works
> >>with pwm_get()). But if I remove this old behavior, then I could
> >>make power_seq opaque. I don't think many drivers are using it. What
> >>do you think?
> >
> >I don't see how that is relevant here, since this power-sequencing code
> >is supposed to be generic and not tied to any specific implementation.
> >Can you explain further?
> >
> >In any case you shouldn't be using pwm_request() in new code.
> 
> Power sequences only rely on pwm_get, and never call pwm_request
> since it is, as you stated, deprecated. However there are still
> boards that use the old pwm_id member of the
> pwm_backlight_platform_data. For these, we must call pwm_request
> from the pwm_backlight driver in order to resolve the PWM (see
> pwm_backlight_legacy_probe of the seconds patch). As the PWM is
> being resolved by the backlight driver, and not within the power
> sequences parser, the resolved data structure must be visible to
> pwm_backlight so it can construct it. There are two ways to solve
> this and keep the power sequences structure private:
> 
> 1) Add a way to resolve a PWM by id using pwm_request in the power
> sequences (we probably should not do that)

No. But I think we don't need that either. If you use power sequences,
then you shouldn't be using the pwm_id member. Both methods should be
exclusive.

> 2) Port the old platform pwm_request code to use pwm_add_table and
> pwm_get instead.

In the long term, every PWM user should move to pwm_add_table() and
pwm_get(), but there are quite a lot of boards that need conversion.

> Do I get points if I do 2)? :)

Yes. =) I have a sample patch for PXA EZX, but as I said, many more
boards need conversion.

Thierry

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

^ permalink raw reply

* Re: [RFC][PATCH v3 1/3] runtime interpreted power sequences
From: Thierry Reding @ 2012-08-01  7:41 UTC (permalink / raw)
  To: Mark Brown
  Cc: Alex Courbot, Stephen Warren, Stephen Warren, Simon Glass,
	Grant Likely, Rob Herring, Greg Kroah-Hartman, Arnd Bergmann,
	linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-fbdev@vger.kernel.org, devicetree-discuss@lists.ozlabs.org
In-Reply-To: <20120731153941.GF4468@opensource.wolfsonmicro.com>

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

On Tue, Jul 31, 2012 at 04:39:41PM +0100, Mark Brown wrote:
> On Tue, Jul 31, 2012 at 04:32:35PM +0200, Thierry Reding wrote:
> > On Tue, Jul 31, 2012 at 03:26:07PM +0100, Mark Brown wrote:
> 
> > > This is framework code - it doesn't have much option.  Disabling HOTPLUG
> > > is totally reasonable on space constrained systems, there's no reason
> > > for the code to break things for people.
> 
> > Still if you use this code and disable HOTPLUG, then you shouldn't be
> > using modules either. I mean there is no way you can write a driver that
> 
> Of course.
> 
> > can gracefully handle its platform data being discarded.
> 
> Sure there is - take a copy of the platform data in probe().

Yes, but that will only work for built-in drivers. If you unload the
module and that causes the platform data to be discarded, reloading
won't work.

Thierry

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

^ permalink raw reply

* RE: [PATCH V2 5/5] arm: samsung: delete frame buffer header files from platform
From: Kukjin Kim @ 2012-08-01  9:39 UTC (permalink / raw)
  To: 'Leela Krishna Amudala', 'Sylwester Nawrocki'
  Cc: linux-arm-kernel, linux-samsung-soc, dri-devel, linux-fbdev,
	ben-linux, inki.dae, joshi, jg1.han, m.szyprowski
In-Reply-To: <CAL1wa8cShB7zDj-CPvfEncX+Up7enKM9MJOt-488dThj_tXbMA@mail.gmail.com>

Leela Krishna Amudala wrote:
> 
> Hello Kgene,
> 
> On Wed, Aug 1, 2012 at 7:34 AM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> > Leela Krishna Amudala wrote:
> >>
> >> The FIMD register headers are moved to include/video/
> >> hence, deleting these files from platform side
> >>
> >> Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
> >> ---
> >>  arch/arm/plat-samsung/include/plat/regs-fb-v4.h |  159 ---------
> >>  arch/arm/plat-samsung/include/plat/regs-fb.h    |  403
> > -------------------
> >> ----
> >>  2 files changed, 0 insertions(+), 562 deletions(-)
> >>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> >>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
> >>
> > No. This should be squashed into first patch on this series. See below.
> >
> >  arch/arm/plat-samsung/include/plat/regs-fb-v4.h    |  159
> > --------------------
> >  .../plat/regs-fb.h => include/video/samsung_fimd.h |  145
> > ++++++++++++++++--
> >  2 files changed, 134 insertions(+), 170 deletions(-)
> >  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> >  rename arch/arm/plat-samsung/include/plat/regs-fb.h =>
> > include/video/samsung_fimd.h (74%)
> >
> 
> If I squash it with the first patch and if somebody set that as a head
> commit, it will break the build. Hence, splitted it up from the first
> patch.
> 
NACK. your changes are not adding just moving. So should be squashed. If
required, you could create just one patch for moving them, probably, 1st,
3rd, 4th and 5th patches into one patch.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

> Thank you Sylwester for suggesting this split up change.
> 
> Regards,
> Leela Krishna


^ permalink raw reply

* Re: [PATCH 2/4] ARM: dts: mxs: Add alternative I2C muxing options for imx28
From: Maxime Ripard @ 2012-08-01  9:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAOMZO5AaLB5m7TYPC03wTSFTDUTFrtV4Xr6gHrvKuGnpyUsf8Q@mail.gmail.com>

Hi,

Le 31/07/2012 14:02, Fabio Estevam a écrit :
> On Tue, Jul 31, 2012 at 7:29 AM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> 
>> +                               i2c0_pins_b: i2c0@1 {
>> +                                       reg = <1>;
>> +                                       fsl,pinmux-ids = <0x3001 0x3011>;
> 
> Can you please also list the name of the pin as comment (just like you
> did for pwm4)?
> 
> This would allow us to quickly identify the muxing option without the
> need of looking at the mxs pinctrl doc.

You're right, this will be in the next version.

Thanks!

Maxime

-- 
Maxime Ripard, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* Re: [PATCH] Fix newport con crashes
From: Florian Tobias Schandinat @ 2012-08-01  9:52 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Thomas Bogendoerfer, linux-mips, linux-fbdev
In-Reply-To: <20120730133447.GA29993@linux-mips.org>

On 07/30/2012 01:34 PM, Ralf Baechle wrote:
> On Mon, Jul 30, 2012 at 12:54:16PM +0200, Thomas Bogendoerfer wrote:
> 
>> Because of commit e84de0c61905030a0fe66b7210b6f1bb7c3e1eab
>> [MIPS: GIO bus support for SGI IP22/28] newport con is now taking over
>> console from dummy con, therefore it's necessary to resize the VC to
>> the correct size to avoid crashes and garbage on console
>>
>> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> 
> I've applied your patch to master and the affected -stable branches of the
> lmo git tree.
> 
> Florian, since this is a driver specific to certain MIPS platforms I'd like
> to merge it through the MIPS tree with your ack, if that's ok?

Yes, sounds good to me. The patch looks good.


Best regards,

Florian Tobias Schandinat

^ permalink raw reply

* Re: [PATCH V2 0/5] arm: samsung: Move FIMD headers to include/video/
From: Florian Tobias Schandinat @ 2012-08-01  9:59 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: 'Leela Krishna Amudala', linux-arm-kernel,
	linux-samsung-soc, dri-devel, linux-fbdev, ben-linux, inki.dae,
	joshi, jg1.han, m.szyprowski
In-Reply-To: <02f701cd6f8d$5ca3e850$15ebb8f0$%kim@samsung.com>

On 08/01/2012 02:28 AM, Kukjin Kim wrote:
> Leela Krishna Amudala wrote:
>>
>> This patchset moves the contents of regs-fb-v4.h and regs-fb.h from arch
>> side
>> to include/video/samsung_fimd.h
>>
>> This patchset is created and rebased against master branch of torvalds
>> tree.
>> Tested on smdk5250 board, build tested for other boards.
>>
> (Cc'ed Florian Tobias Schandinat)
> 
> Yeah, since it's merge window, this series could be created against on
> mainline. And IMO, would be helpful to us if this series could be sent to
> upstream via samsung tree after reviewing, because this touches too many
> files in samsung tree and just adds include/video/samsung_fimd.h. But I'm
> not sure the added inclusion will be used in other file of drivers/video. If
> so, I can provide some topic branch can be merged into Florian's tree.
> Florian, how about?

Using a topic branch to merge it in both trees sounds like a good plan
to me.


Best regards,

Florian Tobias Schandinat

> 
> Thanks.
> 
> Best regards,
> Kgene.
> --
> Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
> SW Solution Development Team, Samsung Electronics Co., Ltd.
> 
>> Changes from version 1:
>> 	- Split the patches as per Sylwester comments
>> 	- Changed FIMD_V8_xxx macro to EXYNOS5_xxx
>>
>> Leela Krishna Amudala (5):
>>   include/video: Add samsung FIMD register header
>>   include/video: Add Exynos5 specific FIMD register offsets
>>   arm: samsung: Include the modified FIMD header file
>>   driver: Include the modified FIMD header file
>>   arm: samsung: delete frame buffer header files from platform
>>
>>  arch/arm/mach-exynos/mach-nuri.c                   |    2 +-
>>  arch/arm/mach-exynos/mach-origen.c                 |    2 +-
>>  arch/arm/mach-exynos/mach-smdk4x12.c               |    2 +-
>>  arch/arm/mach-exynos/mach-smdkv310.c               |    2 +-
>>  arch/arm/mach-exynos/mach-universal_c210.c         |    2 +-
>>  arch/arm/mach-exynos/setup-fimd0.c                 |    2 +-
>>  arch/arm/mach-s3c24xx/mach-smdk2416.c              |    2 +-
>>  arch/arm/mach-s3c64xx/mach-anw6410.c               |    2 +-
>>  arch/arm/mach-s3c64xx/mach-crag6410.c              |    2 +-
>>  arch/arm/mach-s3c64xx/mach-hmt.c                   |    2 +-
>>  arch/arm/mach-s3c64xx/mach-mini6410.c              |    2 +-
>>  arch/arm/mach-s3c64xx/mach-ncp.c                   |    2 +-
>>  arch/arm/mach-s3c64xx/mach-real6410.c              |    2 +-
>>  arch/arm/mach-s3c64xx/mach-smartq5.c               |    2 +-
>>  arch/arm/mach-s3c64xx/mach-smartq7.c               |    2 +-
>>  arch/arm/mach-s3c64xx/mach-smdk6410.c              |    2 +-
>>  arch/arm/mach-s5p64x0/mach-smdk6440.c              |    2 +-
>>  arch/arm/mach-s5p64x0/mach-smdk6450.c              |    2 +-
>>  arch/arm/mach-s5pc100/mach-smdkc100.c              |    2 +-
>>  arch/arm/mach-s5pv210/mach-aquila.c                |    2 +-
>>  arch/arm/mach-s5pv210/mach-goni.c                  |    2 +-
>>  arch/arm/mach-s5pv210/mach-smdkv210.c              |    2 +-
>>  arch/arm/plat-samsung/include/plat/regs-fb-v4.h    |  159
> ----------------
>> ----
>>  drivers/gpu/drm/exynos/exynos_drm_fimd.c           |    2 +-
>>  drivers/video/s3c-fb.c                             |    2 +-
>>  .../plat/regs-fb.h => include/video/samsung_fimd.h |  152
>> +++++++++++++++++--
>>  26 files changed, 165 insertions(+), 194 deletions(-)
>>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
>>  rename arch/arm/plat-samsung/include/plat/regs-fb.h =>
>> include/video/samsung_fimd.h (74%)
> 
> 


^ permalink raw reply

* Re: [PATCH V2 5/5] arm: samsung: delete frame buffer header files from platform
From: Sylwester Nawrocki @ 2012-08-01 10:00 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: 'Leela Krishna Amudala', linux-arm-kernel,
	linux-samsung-soc, dri-devel, linux-fbdev, ben-linux, inki.dae,
	joshi, jg1.han, m.szyprowski
In-Reply-To: <037101cd6fc9$85386e30$8fa94a90$%kim@samsung.com>

Hi,

On 08/01/2012 11:39 AM, Kukjin Kim wrote:
> Leela Krishna Amudala wrote:
>> On Wed, Aug 1, 2012 at 7:34 AM, Kukjin Kim <kgene.kim@samsung.com> wrote:
>>> Leela Krishna Amudala wrote:
>>>>
>>>> The FIMD register headers are moved to include/video/
>>>> hence, deleting these files from platform side
>>>>
>>>> Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
>>>> ---
>>>>  arch/arm/plat-samsung/include/plat/regs-fb-v4.h |  159 ---------
>>>>  arch/arm/plat-samsung/include/plat/regs-fb.h    |  403
>>> -------------------
>>>> ----
>>>>  2 files changed, 0 insertions(+), 562 deletions(-)
>>>>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
>>>>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
>>>>
>>> No. This should be squashed into first patch on this series. See below.
>>>
>>>  arch/arm/plat-samsung/include/plat/regs-fb-v4.h    |  159
>>> --------------------
>>>  .../plat/regs-fb.h => include/video/samsung_fimd.h |  145
>>> ++++++++++++++++--
>>>  2 files changed, 134 insertions(+), 170 deletions(-)
>>>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
>>>  rename arch/arm/plat-samsung/include/plat/regs-fb.h =>
>>> include/video/samsung_fimd.h (74%)
>>>
>>
>> If I squash it with the first patch and if somebody set that as a head
>> commit, it will break the build. Hence, splitted it up from the first
>> patch.
>>
> NACK. your changes are not adding just moving. So should be squashed. If
> required, you could create just one patch for moving them, probably, 1st,
> 3rd, 4th and 5th patches into one patch.

Yes, this patch series is mainly moving files around. But to avoid git
bisect breakage, it should be split as it is done now, or the whole
series should be squashed into one patch. The latter might be even easier
to handle, but having a single patch touching arch/arm/ and drivers/
might not be a good idea. If you're fine handling that, then we just
need to squash this series into single patch.
It just need to be ensured, IMO, there is no bisection breakage.

--

Regards,
Sylwester

^ permalink raw reply

* RE: [PATCH V2 0/5] arm: samsung: Move FIMD headers to include/video/
From: Kukjin Kim @ 2012-08-01 10:03 UTC (permalink / raw)
  To: 'Florian Tobias Schandinat'
  Cc: 'Leela Krishna Amudala', linux-arm-kernel,
	linux-samsung-soc, dri-devel, linux-fbdev, ben-linux, inki.dae,
	joshi, jg1.han, m.szyprowski
In-Reply-To: <5018FDF6.4020205@gmx.de>

Florian Tobias Schandinat wrote:
> 
> On 08/01/2012 02:28 AM, Kukjin Kim wrote:
> > Leela Krishna Amudala wrote:
> >>
> >> This patchset moves the contents of regs-fb-v4.h and regs-fb.h from
> arch
> >> side
> >> to include/video/samsung_fimd.h
> >>
> >> This patchset is created and rebased against master branch of torvalds
> >> tree.
> >> Tested on smdk5250 board, build tested for other boards.
> >>
> > (Cc'ed Florian Tobias Schandinat)
> >
> > Yeah, since it's merge window, this series could be created against on
> > mainline. And IMO, would be helpful to us if this series could be sent
> to
> > upstream via samsung tree after reviewing, because this touches too many
> > files in samsung tree and just adds include/video/samsung_fimd.h. But
> I'm
> > not sure the added inclusion will be used in other file of
drivers/video.
> If
> > so, I can provide some topic branch can be merged into Florian's tree.
> > Florian, how about?
> 
> Using a topic branch to merge it in both trees sounds like a good plan
> to me.
> 
Sure, if this change is ready, I will create topic branch then let you know.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.


^ permalink raw reply

* RE: [PATCH V2 5/5] arm: samsung: delete frame buffer header files from platform
From: Kukjin Kim @ 2012-08-01 10:09 UTC (permalink / raw)
  To: 'Sylwester Nawrocki'
  Cc: 'Leela Krishna Amudala', linux-arm-kernel,
	linux-samsung-soc, dri-devel, linux-fbdev, ben-linux, inki.dae,
	joshi, jg1.han, m.szyprowski
In-Reply-To: <5018FE28.8070907@samsung.com>

Sylwester Nawrocki wrote:
> 
> Hi,
> 
> On 08/01/2012 11:39 AM, Kukjin Kim wrote:
> > Leela Krishna Amudala wrote:
> >> On Wed, Aug 1, 2012 at 7:34 AM, Kukjin Kim <kgene.kim@samsung.com>
> wrote:
> >>> Leela Krishna Amudala wrote:
> >>>>
> >>>> The FIMD register headers are moved to include/video/
> >>>> hence, deleting these files from platform side
> >>>>
> >>>> Signed-off-by: Leela Krishna Amudala <l.krishna@samsung.com>
> >>>> ---
> >>>>  arch/arm/plat-samsung/include/plat/regs-fb-v4.h |  159 ---------
> >>>>  arch/arm/plat-samsung/include/plat/regs-fb.h    |  403
> >>> -------------------
> >>>> ----
> >>>>  2 files changed, 0 insertions(+), 562 deletions(-)
> >>>>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> >>>>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb.h
> >>>>
> >>> No. This should be squashed into first patch on this series. See
below.
> >>>
> >>>  arch/arm/plat-samsung/include/plat/regs-fb-v4.h    |  159
> >>> --------------------
> >>>  .../plat/regs-fb.h => include/video/samsung_fimd.h |  145
> >>> ++++++++++++++++--
> >>>  2 files changed, 134 insertions(+), 170 deletions(-)
> >>>  delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
> >>>  rename arch/arm/plat-samsung/include/plat/regs-fb.h =>
> >>> include/video/samsung_fimd.h (74%)
> >>>
> >>
> >> If I squash it with the first patch and if somebody set that as a head
> >> commit, it will break the build. Hence, splitted it up from the first
> >> patch.
> >>
> > NACK. your changes are not adding just moving. So should be squashed. If
> > required, you could create just one patch for moving them, probably,
1st,
> > 3rd, 4th and 5th patches into one patch.
> 
> Yes, this patch series is mainly moving files around. But to avoid git
> bisect breakage, it should be split as it is done now, or the whole
> series should be squashed into one patch. The latter might be even easier
> to handle, but having a single patch touching arch/arm/ and drivers/
> might not be a good idea. If you're fine handling that, then we just
> need to squash this series into single patch.
> It just need to be ensured, IMO, there is no bisection breakage.
> 
I know you meant. But we don't need to keep the changes 'adding and
removing' for just moving on this.

I commented on 0/5 patch in this series before, if this is ready, I will
create topic branch so that it could be merged into both mine and Florian's.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.


^ permalink raw reply

* Re: [PATCH 1/4] video: Add support for the Solomon SSD1307 OLED Controller
From: Maxime Ripard @ 2012-08-01 10:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20120801052424.GD1672@S2100-06.ap.freescale.net>

Hi Shawn,

Le 01/08/2012 07:24, Shawn Guo a écrit :
> On Tue, Jul 31, 2012 at 12:29:33PM +0200, Maxime Ripard wrote:
>> +Optional properties:
>> +  - oled-reset-active-low: Is the reset gpio is active on physical low?
> 
> You may want to take a look at commit c1cb438 (bindings: update imx and
> mxs #gpio-cells) which got merged recently.  In case the driver will
> only work on mxs, this optional property can just be dropped.

Thanks for the tip.
However, I'm not sure this device will be mxs specific, since this
controller is used on some other devices as well (I know for example
that some uses it with the Arduino, even though it's not related to
Linux), so relying on mxs-specific capabilities here might not be that
great.

But since it's only for a mxs board for now, maybe we can rely on this
and add a dt parameter if we need it in the future. I don't know, both
make sense I guess.

Maxime

-- 
Maxime Ripard, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [RFC 00/17] OMAPDSS: Change way of passing timings from panel driver to interface
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja

This series tries to make interface drivers less dependent on omap_dss_device
which represents a panel/device connected to that interface. The current way of
configuring an interface is to populate the panel's omap_dss_device instance
with parameters common to the panel and the interface, they are either populated
in the board file, or in the panel driver. Panel timings, number of lanes
connected to interface, and pixel format are examples of such parameters, these
are then extracted by the interface driver to configure itself.

This approach has some disadvantages:

- The omap_dss_device contains fields which could be handled independently by
  the panel driver. For example, we have an enum field in omap_dss_device to
  tell what mode the panel operates in. This information could be handled by the
  panel driver itself. But it's a part of omap_dss_device since we need to pass
  this down to the interface driver.

- An interface can't exist by itself. That is, it needs a panel to be connected
  to it to configure itself. It's not practical to configure an interface
  without a panel, but it's theoretically possible, and we may need it if we
  expose the interface as an entity to a user of OMAPDSS. It's also useful if we
  represent writeback as an interface, writeback isn't connected to a panel.

- There is a lack of clarity in how the interface configures itself. Since the
  interface driver extracts info from omap_dss_device, it's unclear from a panel
  driver point of view about what information in omap_dss_device the interface
  is using and what it's not using.

- There are issues with checking the correctness of the parameters in
  omap_dss_device. We currently fill up the omap_dss_device completely, and then
  try to enable the interface, this results in catching a wrong parameter at a
  much later point, rather than catching it immediately.

The alternative approach is for the interface drivers to expose functions/api to
the panel drivers to configure such parameters. This way, the panel driver can
pass the parameters to the interface itself, rather than filling up
omap_dss_device. This would need the panel driver to keep a copy of the
parameters so that it can use to configure it later. This resolves all the
issues mentioned above, and also gives us a chance to make a generic set of
function ops for interfaces, this can make a panel driver independent of
the underlying platform.

The current series starts of this work by creating a set_timings function for
all interfaces passing omap_video_timings, this prevents dssdev->panel.timings
references. The first few patches are some minor cleanups which are useful for
the patches which come later.

There are some points on which I need suggestions/clarifications:
- How do we make sure that these functions are called by the panel driver at the
  right time? For example, when setting timings for DSI video mode, we would
  need to call omapdss_dsi_set_timings() before we call
  omapdss_dsi_display_enable(), otherwise the copy of timings contained in DSI
  driver data would be invalid. Also, what should the behaviour of such a
  set_timings operation if the interface is already enabled. It is clear for
  DPI and HDMI, but I'm not clear about what to do about other interfaces. Do we
  add checks for the state of the interface/panel?

- A specific issue about DSI/RFBI getting the resolution via
  device->driver->get_resolution(), does this provide a result based on panel
  rotation? Can this somehow be replaced by timings?

- For SDI, the set_timings operation is simplified, instead of disabling and
  then enabling the panel with a new set of timings, only the new timings are
  configured. This is similar to what is done in DPI. I am not clear if this
  will work for SDI or not.

- There is no set_timings() function for RFBI yet, this needs to be though of
  and fixed. 

The reference tree and branch:

This is based on Tomi's for-florian-merged branch, and has 2 of his patches which
got missed the last merge window.

This hasn't been tested thoroughly with all interfaces yet. I was interested in
getting some comments.

Archit Taneja (17):
  OMAPDSS: APPLY: Constify timings argument in dss_mgr_set_timings
  OMAPDSS: DPI: Remove omap_dss_device arguments in
    dpi_set_dsi_clk/dpi_set_dispc_clk
  OMAPDSS: HDMI: Remove omap_dss_device argument from hdmi_compute_pll
  OMAPDSS: DPI: Add locking for DPI interface
  OMAPDSS: DPI: Maintain our own timings field in driver data
  OMAPDSS: DPI displays: Take care of panel timings in the driver
    itself
  OMAPDSS: Displays: Add locking in generic DPI panel driver
  OMAPDSS: DSI: Maintain own copy of timings in driver data
  OMAPDSS: HDMI: Use our own omap_video_timings field when setting
    interface timings
  OMAPDSS: HDMI: Add a get_timing function for HDMI interface
  OMAPDSS: HDMI: Add locking for hdmi interface get/set timing
    functions
  OMAPDSS: SDI: Create a separate function for timing/clock
    configurations
  OMAPDSS: SDI: Create a function to set timings
  OMAPDSS: SDI: Maintain our own timings field in driver data
  OMAPDSS: VENC: Split VENC into interface and panel driver
  OMAPDSS: VENC: Maintain our own timings field in driver data
  OMAPDSS: VENC: Add a get_timing function for VENC interface

 drivers/video/omap2/displays/panel-acx565akm.c     |   13 +-
 drivers/video/omap2/displays/panel-generic-dpi.c   |   75 ++++++-
 .../omap2/displays/panel-lgphilips-lb035q02.c      |    2 +
 .../omap2/displays/panel-nec-nl8048hl11-01b.c      |    2 +
 drivers/video/omap2/displays/panel-picodlp.c       |    3 +
 .../video/omap2/displays/panel-sharp-ls037v7dw01.c |    2 +
 drivers/video/omap2/displays/panel-taal.c          |    2 +
 drivers/video/omap2/displays/panel-tfp410.c        |    5 +-
 .../video/omap2/displays/panel-tpo-td043mtea1.c    |    6 +-
 drivers/video/omap2/dss/Makefile                   |    2 +-
 drivers/video/omap2/dss/apply.c                    |    4 +-
 drivers/video/omap2/dss/dpi.c                      |   52 +++--
 drivers/video/omap2/dss/dsi.c                      |   27 ++-
 drivers/video/omap2/dss/dss.h                      |   19 +-
 drivers/video/omap2/dss/hdmi.c                     |   60 +++--
 drivers/video/omap2/dss/hdmi_panel.c               |   12 +-
 drivers/video/omap2/dss/sdi.c                      |   87 +++++---
 drivers/video/omap2/dss/venc.c                     |  233 ++++++--------------
 drivers/video/omap2/dss/venc_panel.c               |  231 +++++++++++++++++++
 include/video/omapdss.h                            |    8 +-
 20 files changed, 579 insertions(+), 266 deletions(-)
 create mode 100644 drivers/video/omap2/dss/venc_panel.c

-- 
1.7.9.5


^ permalink raw reply

* [RFC 01/17] OMAPDSS: APPLY: Constify timings argument in dss_mgr_set_timings
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The function dss_mgr_set_timings is supposed to apply timings passed by an
interface driver. It is not supposed to change the timings. Add const qualifier
to the omap_video_timings pointer argument in dss_mgr_set_timings().

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/dss/apply.c |    4 ++--
 drivers/video/omap2/dss/dss.h   |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 0fefc68..52a5940 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -1302,7 +1302,7 @@ err:
 }
 
 static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
-		struct omap_video_timings *timings)
+		const struct omap_video_timings *timings)
 {
 	struct mgr_priv_data *mp = get_mgr_priv(mgr);
 
@@ -1311,7 +1311,7 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
 }
 
 void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
-		struct omap_video_timings *timings)
+		const struct omap_video_timings *timings)
 {
 	unsigned long flags;
 
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 335ee93..8a9630b 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -207,7 +207,7 @@ int dss_mgr_set_device(struct omap_overlay_manager *mgr,
 		struct omap_dss_device *dssdev);
 int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
 void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
-		struct omap_video_timings *timings);
+		const struct omap_video_timings *timings);
 void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
 		const struct dss_lcd_mgr_config *config);
 const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 02/17] OMAPDSS: DPI: Remove omap_dss_device arguments in dpi_set_dsi_clk/dpi_set_dispc_clk
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The clock related info for DSS modules is not tied anymore to a panel's
omap_dss_device struct. It's now passed via platform data. The functions
dpi_set_dsi_clk() and dpi_set_dispc_clk() do not need the omap_dss_device
argument to retieve these clocks. They use the api dss_get_platform_clock_config
to get the clocks. Remove the omap_dss_device arguments from these functions.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/dss/dpi.c |   14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 5fec180..c20fe23 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -80,9 +80,8 @@ static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev)
 		lcd_src = OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
 }
 
-static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
-		unsigned long pck_req, unsigned long *fck, int *lck_div,
-		int *pck_div)
+static int dpi_set_dsi_clk(unsigned long pck_req, unsigned long *fck,
+		int *lck_div, int *pck_div)
 {
 	const struct omapdss_clock_config *clks;
 	struct dsi_clock_info dsi_cinfo;
@@ -111,9 +110,8 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
 	return 0;
 }
 
-static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
-		unsigned long pck_req, unsigned long *fck, int *lck_div,
-		int *pck_div)
+static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
+		int *lck_div, int *pck_div)
 {
 	struct dss_clock_info dss_cinfo;
 	struct dispc_clock_info dispc_cinfo;
@@ -145,10 +143,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
 	int r = 0;
 
 	if (dpi_use_dsi_pll(dssdev))
-		r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck,
+		r = dpi_set_dsi_clk(t->pixel_clock * 1000, &fck,
 				&lck_div, &pck_div);
 	else
-		r = dpi_set_dispc_clk(dssdev, t->pixel_clock * 1000, &fck,
+		r = dpi_set_dispc_clk(t->pixel_clock * 1000, &fck,
 				&lck_div, &pck_div);
 	if (r)
 		return r;
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 03/17] OMAPDSS: HDMI: Remove omap_dss_device argument from hdmi_compute_pll
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The clock related info for DSS modules is not tied anymore to a panel's
omap_dss_device struct. It's now passed via platform data. The function
hdmi_compute_pll() do not need the omap_dss_device argument to retieve these
clocks. They use the api dss_get_platform_clock_config() get the clocks. Remove
the omap_dss_device argument from hdmi_compute_pll()

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 16b2386..6635b09 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -405,8 +405,7 @@ unsigned long hdmi_get_pixel_clock(void)
 	return hdmi.ip_data.cfg.timings.pixel_clock * 1000;
 }
 
-static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
-		struct hdmi_pll_info *pi)
+static void hdmi_compute_pll(int phy, struct hdmi_pll_info *pi)
 {
 	const struct omapdss_clock_config *clks;
 	unsigned long clkin, refclk;
@@ -491,7 +490,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 	}
 	phy = p->pixel_clock;
 
-	hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
+	hdmi_compute_pll(phy, &hdmi.ip_data.pll_data);
 
 	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
 
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 04/17] OMAPDSS: DPI: Add locking for DPI interface
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The DPI interface driver currently relies on the panel driver to ensure calls
like omapdss_dpi_display_enable() and omapdss_dpi_display_disable() are executed
sequentially. Also, currently, there is no way to protect the DPI driver data.

All DPI panel drivers don't ensure this, and in general, a DPI panel driver
should use it's lock to that ensure it's own driver data and omap_dss_device
states are taken care of, and not worry about the DPI interface.

Add mutex locking in the DPI enable/disable/set_timings ops.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/dss/dpi.c |   26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index c20fe23..add47fe 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -39,6 +39,8 @@ static struct {
 	struct regulator *vdds_dsi_reg;
 	struct platform_device *dsidev;
 
+	struct mutex lock;
+
 	struct dss_lcd_mgr_config mgr_config;
 } dpi;
 
@@ -184,14 +186,18 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 {
 	int r;
 
+	mutex_lock(&dpi.lock);
+
 	if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) {
 		DSSERR("no VDSS_DSI regulator\n");
-		return -ENODEV;
+		r = -ENODEV;
+		goto err_no_reg;
 	}
 
 	if (dssdev->manager = NULL) {
 		DSSERR("failed to enable display: no manager\n");
-		return -ENODEV;
+		r = -ENODEV;
+		goto err_no_mgr;
 	}
 
 	if (dpi_use_dsi_pll(dssdev)) {
@@ -238,6 +244,8 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
 	if (r)
 		goto err_mgr_enable;
 
+	mutex_unlock(&dpi.lock);
+
 	return 0;
 
 err_mgr_enable:
@@ -255,12 +263,17 @@ err_get_dispc:
 err_reg_enable:
 	omap_dss_stop_device(dssdev);
 err_start_dev:
+err_no_mgr:
+err_no_reg:
+	mutex_unlock(&dpi.lock);
 	return r;
 }
 EXPORT_SYMBOL(omapdss_dpi_display_enable);
 
 void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 {
+	mutex_lock(&dpi.lock);
+
 	dss_mgr_disable(dssdev->manager);
 
 	if (dpi_use_dsi_pll(dssdev)) {
@@ -275,6 +288,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 		regulator_disable(dpi.vdds_dsi_reg);
 
 	omap_dss_stop_device(dssdev);
+
+	mutex_unlock(&dpi.lock);
 }
 EXPORT_SYMBOL(omapdss_dpi_display_disable);
 
@@ -284,6 +299,9 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
 	int r;
 
 	DSSDBG("dpi_set_timings\n");
+
+	mutex_lock(&dpi.lock);
+
 	dssdev->panel.timings = *timings;
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
 		r = dispc_runtime_get();
@@ -296,6 +314,8 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
 	} else {
 		dss_mgr_set_timings(dssdev->manager, timings);
 	}
+
+	mutex_unlock(&dpi.lock);
 }
 EXPORT_SYMBOL(dpi_set_timings);
 
@@ -392,6 +412,8 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
 
 static int __init omap_dpi_probe(struct platform_device *pdev)
 {
+	mutex_init(&dpi.lock);
+
 	dpi_probe_pdata(pdev);
 
 	return 0;
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 05/17] OMAPDSS: DPI: Maintain our own timings field in driver data
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The DPI driver currently relies on the timings in omap_dss_device struct to
configure the DISPC accordingly. This makes the DPI interface driver dependent
on the omap_dss_device struct.

Make the DPI driver data maintain it's own timings field. The panel driver is
expected to call dpi_set_timings()(renamed to omapdss_dpi_set_timings) to set
these timings before the panel is enabled.

In the set_timings() op, we still ensure that the omap_dss_device timings
(dssdev->panel.timings) are configured. This will later be configured only by
the DPI panel drivers.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/displays/panel-generic-dpi.c   |    4 +++-
 .../omap2/displays/panel-lgphilips-lb035q02.c      |    2 ++
 .../omap2/displays/panel-nec-nl8048hl11-01b.c      |    2 ++
 drivers/video/omap2/displays/panel-picodlp.c       |    3 +++
 .../video/omap2/displays/panel-sharp-ls037v7dw01.c |    2 ++
 drivers/video/omap2/displays/panel-tfp410.c        |    4 +++-
 .../video/omap2/displays/panel-tpo-td043mtea1.c    |    4 +++-
 drivers/video/omap2/dss/dpi.c                      |   11 +++++++----
 include/video/omapdss.h                            |    4 ++--
 9 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index bc5af25..5e70313 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -563,6 +563,8 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
 		return 0;
 
+	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
@@ -695,7 +697,7 @@ static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
 static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
-	dpi_set_timings(dssdev, timings);
+	omapdss_dpi_set_timings(dssdev, timings);
 }
 
 static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index 8028077..7e52aee 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -55,6 +55,8 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
 		return 0;
 
+	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index b122b0f..e501c40 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -175,6 +175,8 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
 		return 0;
 
+	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
index 2d35bd3..0d7a8ff 100644
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -377,6 +377,9 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
 	 * then only i2c commands can be successfully sent to dpp2600
 	 */
 	msleep(1000);
+
+	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r) {
 		dev_err(&dssdev->dev, "failed to enable DPI\n");
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index bd86ba9..1486a81 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -142,6 +142,8 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
 		return 0;
 
+	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index 40cc0cfa..c6f9503 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -65,6 +65,8 @@ static int tfp410_power_on(struct omap_dss_device *dssdev)
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
 		return 0;
 
+	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
@@ -231,7 +233,7 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev,
 	struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
 
 	mutex_lock(&ddata->lock);
-	dpi_set_timings(dssdev, timings);
+	omapdss_dpi_set_timings(dssdev, timings);
 	mutex_unlock(&ddata->lock);
 }
 
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index fa7baa6..ecb163e 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -337,6 +337,8 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
 		return 0;
 
+	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+
 	r = omapdss_dpi_display_enable(dssdev);
 	if (r)
 		goto err0;
@@ -480,7 +482,7 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
 static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
-	dpi_set_timings(dssdev, timings);
+	omapdss_dpi_set_timings(dssdev, timings);
 }
 
 static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index add47fe..96dd1a4 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -41,6 +41,7 @@ static struct {
 
 	struct mutex lock;
 
+	struct omap_video_timings timings;
 	struct dss_lcd_mgr_config mgr_config;
 } dpi;
 
@@ -138,7 +139,7 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
 
 static int dpi_set_mode(struct omap_dss_device *dssdev)
 {
-	struct omap_video_timings *t = &dssdev->panel.timings;
+	struct omap_video_timings *t = &dpi.timings;
 	int lck_div = 0, pck_div = 0;
 	unsigned long fck = 0;
 	unsigned long pck;
@@ -293,8 +294,8 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
 }
 EXPORT_SYMBOL(omapdss_dpi_display_disable);
 
-void dpi_set_timings(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings)
+void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
 {
 	int r;
 
@@ -302,7 +303,9 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
 
 	mutex_lock(&dpi.lock);
 
+	dpi.timings = *timings;
 	dssdev->panel.timings = *timings;
+
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
 		r = dispc_runtime_get();
 		if (r)
@@ -317,7 +320,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
 
 	mutex_unlock(&dpi.lock);
 }
-EXPORT_SYMBOL(dpi_set_timings);
+EXPORT_SYMBOL(omapdss_dpi_set_timings);
 
 int dpi_check_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings)
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 6f7581b..ebf2ebd 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -751,8 +751,8 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
 
 int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
-void dpi_set_timings(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings);
 int dpi_check_timings(struct omap_dss_device *dssdev,
 			struct omap_video_timings *timings);
 
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 06/17] OMAPDSS: DPI displays: Take care of panel timings in the driver itself
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The timings maintained in omap_dss_device(dssdev->panel.timings) should be
maintained by the panel driver itself. It's the panel drivers responsibility
to update it if a new set of timings is to be configured. The DPI interface
driver shouldn't be responsible of updating the panel timings, it's responsible
of maintianing it's own copy of timings.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/displays/panel-generic-dpi.c   |    2 ++
 drivers/video/omap2/displays/panel-tfp410.c        |    1 +
 .../video/omap2/displays/panel-tpo-td043mtea1.c    |    2 ++
 drivers/video/omap2/dss/dpi.c                      |    1 -
 4 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 5e70313..e773594 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -698,6 +698,8 @@ static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
 	omapdss_dpi_set_timings(dssdev, timings);
+
+	dssdev->panel.timings = *timings;
 }
 
 static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index c6f9503..9397236 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -234,6 +234,7 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev,
 
 	mutex_lock(&ddata->lock);
 	omapdss_dpi_set_timings(dssdev, timings);
+	dssdev->panel.timings = *timings;
 	mutex_unlock(&ddata->lock);
 }
 
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index ecb163e..3f47f5f 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -483,6 +483,8 @@ static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
 	omapdss_dpi_set_timings(dssdev, timings);
+
+	dssdev->panel.timings = *timings;
 }
 
 static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 96dd1a4..6c43d80 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -304,7 +304,6 @@ void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
 	mutex_lock(&dpi.lock);
 
 	dpi.timings = *timings;
-	dssdev->panel.timings = *timings;
 
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
 		r = dispc_runtime_get();
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 07/17] OMAPDSS: Displays: Add locking in generic DPI panel driver
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The generic DPI panel driver doesn't currently have locking to ensure that
the display states and the driver data is maintained correctly. Add mutex
locking to take care of this. Add a new get_timings driver op to override the
default get_timings op. The new driver op contains locking to ensure the correct
panel timings are seen when a DSS2 user calls device->driver->get_timings.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/displays/panel-generic-dpi.c |   69 +++++++++++++++++++---
 1 file changed, 62 insertions(+), 7 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index e773594..a07e18c 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -545,6 +545,8 @@ struct panel_drv_data {
 	struct omap_dss_device *dssdev;
 
 	struct panel_config *panel_config;
+
+	struct mutex lock;
 };
 
 static inline struct panel_generic_dpi_data
@@ -636,6 +638,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
 	drv_data->dssdev = dssdev;
 	drv_data->panel_config = panel_config;
 
+	mutex_init(&drv_data->lock);
+
 	dev_set_drvdata(&dssdev->dev, drv_data);
 
 	return 0;
@@ -654,58 +658,108 @@ static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
 
 static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
 {
-	int r = 0;
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+	int r;
+
+	mutex_lock(&drv_data->lock);
 
 	r = generic_dpi_panel_power_on(dssdev);
 	if (r)
-		return r;
+		goto err;
 
 	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+err:
+	mutex_unlock(&drv_data->lock);
 
-	return 0;
+	return r;
 }
 
 static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
 {
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+	mutex_lock(&drv_data->lock);
+
 	generic_dpi_panel_power_off(dssdev);
 
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+
+	mutex_unlock(&drv_data->lock);
 }
 
 static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
 {
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+	mutex_lock(&drv_data->lock);
+
 	generic_dpi_panel_power_off(dssdev);
 
 	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
 
+	mutex_unlock(&drv_data->lock);
+
 	return 0;
 }
 
 static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
 {
-	int r = 0;
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+	int r;
+
+	mutex_lock(&drv_data->lock);
 
 	r = generic_dpi_panel_power_on(dssdev);
 	if (r)
-		return r;
+		goto err;
 
 	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
 
-	return 0;
+err:
+	mutex_unlock(&drv_data->lock);
+
+	return r;
 }
 
 static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+	mutex_lock(&drv_data->lock);
+
 	omapdss_dpi_set_timings(dssdev, timings);
 
 	dssdev->panel.timings = *timings;
+
+	mutex_unlock(&drv_data->lock);
+}
+
+static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+	mutex_lock(&drv_data->lock);
+
+	*timings = dssdev->panel.timings;
+
+	mutex_unlock(&drv_data->lock);
 }
 
 static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
-	return dpi_check_timings(dssdev, timings);
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+	int r;
+
+	mutex_lock(&drv_data->lock);
+
+	r = dpi_check_timings(dssdev, timings);
+
+	mutex_unlock(&drv_data->lock);
+
+	return r;
 }
 
 static struct omap_dss_driver dpi_driver = {
@@ -718,6 +772,7 @@ static struct omap_dss_driver dpi_driver = {
 	.resume		= generic_dpi_panel_resume,
 
 	.set_timings	= generic_dpi_panel_set_timings,
+	.get_timings	= generic_dpi_panel_get_timings,
 	.check_timings	= generic_dpi_panel_check_timings,
 
 	.driver         = {
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 08/17] OMAPDSS: DSI: Maintain own copy of timings in driver data
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The DSI driver currently relies on the timings in omap_dss_device struct to
configure the DISPC and DSI blocks accordingly. This makes the DSI interface
driver dependent on the omap_dss_device struct.

Make the DPI driver data maintain it's own timings field. The panel driver is
expected to call omapdss_dsi_set_timings() to set these timings before the panel
is enabled.

Signed-off-by: Archit Taneja <archit@ti.com>d
---
 drivers/video/omap2/displays/panel-taal.c |    2 ++
 drivers/video/omap2/dss/dsi.c             |   27 ++++++++++++++++++++++-----
 include/video/omapdss.h                   |    2 ++
 3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 3f5acc7..4775580 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1060,6 +1060,8 @@ static int taal_power_on(struct omap_dss_device *dssdev)
 		goto err0;
 	};
 
+	omapdss_dsi_set_timings(dssdev, &td->panel_config->timings);
+
 	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 27c27c4..598d965 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -333,6 +333,7 @@ struct dsi_data {
 	unsigned scp_clk_refcount;
 
 	struct dss_lcd_mgr_config mgr_config;
+	struct omap_video_timings timings;
 };
 
 struct dsi_packet_sent_handler_data {
@@ -3607,9 +3608,10 @@ static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
 	int num_line_buffers;
 
 	if (dssdev->panel.dsi_mode = OMAP_DSS_DSI_VIDEO_MODE) {
+		struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 		int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
 		unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
-		struct omap_video_timings *timings = &dssdev->panel.timings;
+		struct omap_video_timings *timings = &dsi->timings;
 		/*
 		 * Don't use line buffers if width is greater than the video
 		 * port's line buffer size
@@ -3738,7 +3740,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
 	int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
 	int tclk_trail, ths_exit, exiths_clk;
 	bool ddr_alwon;
-	struct omap_video_timings *timings = &dssdev->panel.timings;
+	struct omap_video_timings *timings = &dsi->timings;
 	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
 	int ndl = dsi->num_lanes_used - 1;
 	const struct omapdss_clock_config *clks;
@@ -3996,7 +3998,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
 		int vbp = dssdev->panel.dsi_vm_data.vbp;
 		int window_sync = dssdev->panel.dsi_vm_data.window_sync;
 		bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end;
-		struct omap_video_timings *timings = &dssdev->panel.timings;
+		struct omap_video_timings *timings = &dsi->timings;
 		int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
 		int tl, t_he, width_bytes;
 
@@ -4105,6 +4107,7 @@ EXPORT_SYMBOL(omapdss_dsi_configure_pins);
 int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
 	u8 data_type;
 	u16 word_count;
@@ -4135,7 +4138,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 		/* MODE, 1 = video mode */
 		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
 
-		word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
+		word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
 
 		dsi_vc_write_long_header(dsidev, channel, data_type,
 				word_count, 0);
@@ -4401,7 +4404,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
 		dsi->mgr_config.stallmode = true;
 		dsi->mgr_config.fifohandcheck = true;
 	} else {
-		timings = dssdev->panel.timings;
+		timings = dsi->timings;
 
 		dsi->mgr_config.stallmode = false;
 		dsi->mgr_config.fifohandcheck = false;
@@ -4688,6 +4691,20 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
 }
 EXPORT_SYMBOL(omapdss_dsi_enable_te);
 
+void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
+	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+
+	mutex_lock(&dsi->lock);
+
+	dsi->timings = *timings;
+
+	mutex_unlock(&dsi->lock);
+}
+EXPORT_SYMBOL(omapdss_dsi_set_timings);
+
 static int __init dsi_init_display(struct omap_dss_device *dssdev)
 {
 	struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index ebf2ebd..a2cd133 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -736,6 +736,8 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
 void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
 		bool enable);
 int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
+void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings);
 
 int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
 		void (*callback)(int, void *), void *data);
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 09/17] OMAPDSS: HDMI: Use our own omap_video_timings field when setting interface timings
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The hdmi driver currently updates only the 'code' member of hdmi_config when
the op omapdss_hdmi_display_set_timing() is called by the hdmi panel driver.
The 'timing' field of hdmi_config is updated only when hdmi_power_on is called.
It makes more sense to configure the whole hdmi_config field in the set_timing
op called by the panel driver. This way, we don't need to call both functions
to ensure that our hdmi_config is configured correctly. Also, we don't need to
calculate hdmi_config during hdmi_power_on, or rely on the omap_video_timings
in the panel's omap_dss_device struct.

A default timing is now configured in hdmi's probe if the panel driver doesn't
set any timing, or doesn't set a valid timing before enabling the panel. Also,
when setting manager timings, use the omap_video_timing calculated by
hdmi_get_timings(), this returns the timings as specified in the CEA/VESA
tables, don't use the one provided by the panel driver directly.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/dss/dss.h        |    3 ++-
 drivers/video/omap2/dss/hdmi.c       |   41 +++++++++++++++++-----------------
 drivers/video/omap2/dss/hdmi_panel.c |    2 +-
 3 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 8a9630b..7e38ffd 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -485,7 +485,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
 #endif
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
-void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
+void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 					struct omap_video_timings *timings);
 int omapdss_hdmi_read_edid(u8 *buf, int len);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 6635b09..01665fa 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -462,7 +462,6 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 {
 	const struct omapdss_clock_config *clks;
 	int r;
-	const struct hdmi_config *timing;
 	struct omap_video_timings *p;
 	unsigned long phy;
 
@@ -472,22 +471,10 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 
 	dss_mgr_disable(dssdev->manager);
 
-	p = &dssdev->panel.timings;
+	p = &hdmi.ip_data.cfg.timings;
 
-	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n",
-		dssdev->panel.timings.x_res,
-		dssdev->panel.timings.y_res);
+	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
 
-	timing = hdmi_get_timings();
-	if (timing = NULL) {
-		/* HDMI code 4 corresponds to 640 * 480 VGA */
-		hdmi.ip_data.cfg.cm.code = 4;
-		/* DVI mode 1 corresponds to HDMI 0 to DVI */
-		hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
-		hdmi.ip_data.cfg = vesa_timings[0];
-	} else {
-		hdmi.ip_data.cfg = *timing;
-	}
 	phy = p->pixel_clock;
 
 	hdmi_compute_pll(phy, &hdmi.ip_data.pll_data);
@@ -525,7 +512,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
 	dispc_enable_gamma_table(0);
 
 	/* tv size */
-	dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
+	dss_mgr_set_timings(dssdev->manager, p);
 
 	r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
 	if (r)
@@ -571,13 +558,18 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 
 }
 
-void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
+void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
 {
 	struct hdmi_cm cm;
+	const struct hdmi_config *timing;
+
+	cm = hdmi_get_code(timings);
+	hdmi.ip_data.cfg.cm = cm;
 
-	cm = hdmi_get_code(&dssdev->panel.timings);
-	hdmi.ip_data.cfg.cm.code = cm.code;
-	hdmi.ip_data.cfg.cm.mode = cm.mode;
+	timing = hdmi_get_timings();
+	if (timing != NULL)
+		hdmi.ip_data.cfg = *timing;
 
 	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE) {
 		int r;
@@ -588,7 +580,7 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
 		if (r)
 			DSSERR("failed to power on device\n");
 	} else {
-		dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
+		dss_mgr_set_timings(dssdev->manager, &timing->timings);
 	}
 }
 
@@ -933,6 +925,13 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
 	hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
 	hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
 	hdmi.ip_data.phy_offset = HDMI_PHY;
+
+	/*
+	 * initialize hdmi timings to default value:
+	 * HDMI code 4(VGA) and HDMI mode 1(DVI)
+	 */
+	hdmi.ip_data.cfg = vesa_timings[0];
+
 	mutex_init(&hdmi.ip_data.lock);
 
 	hdmi_panel_init();
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index e10844f..8dce206 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -336,8 +336,8 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
 	 */
 	hdmi_panel_audio_disable(dssdev);
 
+	omapdss_hdmi_display_set_timing(dssdev, timings);
 	dssdev->panel.timings = *timings;
-	omapdss_hdmi_display_set_timing(dssdev);
 
 	mutex_unlock(&hdmi.lock);
 }
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 10/17] OMAPDSS: HDMI: Add a get_timing function for HDMI interface
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

Add function omapdss_hdmi_display_get_timing() which returns the timings
maintained by the HDMI interface driver in it's hdmi_config field. This
prevents the need for the panel driver to configure default timings in it's
probe.

This function is just intended to be used once during the panel driver's probe.
It makes sense for those interfaces which can be configured to a default timing.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/dss/dss.h        |    2 ++
 drivers/video/omap2/dss/hdmi.c       |    6 ++++++
 drivers/video/omap2/dss/hdmi_panel.c |   10 +++++-----
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 7e38ffd..df49c5d 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -485,6 +485,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
 #endif
 int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
+void omapdss_hdmi_display_get_timing(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings);
 void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings);
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 01665fa..2de1f91 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -544,6 +544,12 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 	hdmi_runtime_put();
 }
 
+void omapdss_hdmi_display_get_timing(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	*timings = hdmi.ip_data.cfg.timings;
+}
+
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
 					struct omap_video_timings *timings)
 {
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index 8dce206..8473193 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -41,13 +41,13 @@ static struct {
 
 static int hdmi_panel_probe(struct omap_dss_device *dssdev)
 {
+	struct omap_video_timings timings;
+
 	DSSDBG("ENTER hdmi_panel_probe\n");
 
-	dssdev->panel.timings = (struct omap_video_timings)
-			{ 640, 480, 25175, 96, 16, 48, 2, 11, 31,
-				OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
-				false,
-			};
+	omapdss_hdmi_display_get_timing(dssdev, &timings);
+
+	dssdev->panel.timings = timings;
 
 	DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
 		dssdev->panel.timings.x_res,
-- 
1.7.9.5


^ permalink raw reply related

* [RFC 11/17] OMAPDSS: HDMI: Add locking for hdmi interface get/set timing functions
From: Archit Taneja @ 2012-08-01 10:43 UTC (permalink / raw)
  To: tomi.valkeinen; +Cc: linux-fbdev, linux-omap, sumit.semwal, rob, Archit Taneja
In-Reply-To: <1343817088-29645-1-git-send-email-archit@ti.com>

The hdmi interface driver exposes functions to the hdmi panel driver to
get and configure the interface timings maintained by the hdmi driver.

These timings(stored in hdmi.ip_data.cfg) should be protected by the hdmi lock
to ensure they are called sequentially, this is similar to how hdmi enable and
disable functions need locking.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/video/omap2/dss/hdmi.c |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 2de1f91..dfd582e 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -547,7 +547,11 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
 void omapdss_hdmi_display_get_timing(struct omap_dss_device *dssdev,
 		struct omap_video_timings *timings)
 {
+	mutex_lock(&hdmi.lock);
+
 	*timings = hdmi.ip_data.cfg.timings;
+
+	mutex_unlock(&hdmi.lock);
 }
 
 int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -570,6 +574,8 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
 	struct hdmi_cm cm;
 	const struct hdmi_config *timing;
 
+	mutex_lock(&hdmi.lock);
+
 	cm = hdmi_get_code(timings);
 	hdmi.ip_data.cfg.cm = cm;
 
@@ -588,6 +594,8 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
 	} else {
 		dss_mgr_set_timings(dssdev->manager, &timing->timings);
 	}
+
+	mutex_unlock(&hdmi.lock);
 }
 
 static void hdmi_dump_regs(struct seq_file *s)
-- 
1.7.9.5


^ permalink raw reply related


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