Skip to content

Commit

Permalink
video: mxsfb: get display timings from device tree
Browse files Browse the repository at this point in the history
Use videomode helpers to get display timings and configurations from
device tree when platform_data is absent.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
  • Loading branch information
Shawn Guo committed Apr 4, 2013
1 parent 36f3e99 commit 6694065
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 12 deletions.
34 changes: 34 additions & 0 deletions Documentation/devicetree/bindings/fb/mxsfb.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,49 @@ Required properties:
imx23 and imx28.
- reg: Address and length of the register set for lcdif
- interrupts: Should contain lcdif interrupts
- display : phandle to display node (see below for details)

Optional properties:
- panel-enable-gpios : Should specify the gpio for panel enable

* display node

Required properties:
- bits-per-pixel : <16> for RGB565, <32> for RGB888/666.
- bus-width : number of data lines. Could be <8>, <16>, <18> or <24>.

Required sub-node:
- display-timings : Refer to binding doc display-timing.txt for details.

Examples:

lcdif@80030000 {
compatible = "fsl,imx28-lcdif";
reg = <0x80030000 2000>;
interrupts = <38 86>;
panel-enable-gpios = <&gpio3 30 0>;

display: display {
bits-per-pixel = <32>;
bus-width = <24>;

display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <33500000>;
hactive = <800>;
vactive = <480>;
hfront-porch = <164>;
hback-porch = <89>;
hsync-len = <10>;
vback-porch = <23>;
vfront-porch = <10>;
vsync-len = <10>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;
};
};
};
};
2 changes: 2 additions & 0 deletions drivers/video/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2437,6 +2437,8 @@ config FB_MXS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_MODE_HELPERS
select OF_VIDEOMODE
help
Framebuffer support for the MXS SoC.

Expand Down
122 changes: 110 additions & 12 deletions drivers/video/mxsfb.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@
#include <linux/kernel.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <video/of_display_timing.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/pinctrl/consumer.h>
#include <linux/mxsfb.h>
#include <video/videomode.h>

#define REG_SET 4
#define REG_CLR 8
Expand Down Expand Up @@ -678,6 +680,97 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
return 0;
}

static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host)
{
struct fb_info *fb_info = &host->fb_info;
struct fb_var_screeninfo *var = &fb_info->var;
struct device *dev = &host->pdev->dev;
struct device_node *np = host->pdev->dev.of_node;
struct device_node *display_np;
struct device_node *timings_np;
struct display_timings *timings;
u32 width;
int i;
int ret = 0;

display_np = of_parse_phandle(np, "display", 0);
if (!display_np) {
dev_err(dev, "failed to find display phandle\n");
return -ENOENT;
}

ret = of_property_read_u32(display_np, "bus-width", &width);
if (ret < 0) {
dev_err(dev, "failed to get property bus-width\n");
goto put_display_node;
}

switch (width) {
case 8:
host->ld_intf_width = STMLCDIF_8BIT;
break;
case 16:
host->ld_intf_width = STMLCDIF_16BIT;
break;
case 18:
host->ld_intf_width = STMLCDIF_18BIT;
break;
case 24:
host->ld_intf_width = STMLCDIF_24BIT;
break;
default:
dev_err(dev, "invalid bus-width value\n");
ret = -EINVAL;
goto put_display_node;
}

ret = of_property_read_u32(display_np, "bits-per-pixel",
&var->bits_per_pixel);
if (ret < 0) {
dev_err(dev, "failed to get property bits-per-pixel\n");
goto put_display_node;
}

timings = of_get_display_timings(display_np);
if (!timings) {
dev_err(dev, "failed to get display timings\n");
ret = -ENOENT;
goto put_display_node;
}

timings_np = of_find_node_by_name(display_np,
"display-timings");
if (!timings_np) {
dev_err(dev, "failed to find display-timings node\n");
ret = -ENOENT;
goto put_display_node;
}

for (i = 0; i < of_get_child_count(timings_np); i++) {
struct videomode vm;
struct fb_videomode fb_vm;

ret = videomode_from_timing(timings, &vm, i);
if (ret < 0)
goto put_timings_node;
ret = fb_videomode_from_videomode(&vm, &fb_vm);
if (ret < 0)
goto put_timings_node;

if (vm.data_flags & DISPLAY_FLAGS_DE_HIGH)
host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
if (vm.data_flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
host->sync |= MXSFB_SYNC_DOTCLK_FAILING_ACT;
fb_add_videomode(&fb_vm, &fb_info->modelist);
}

put_timings_node:
of_node_put(timings_np);
put_display_node:
of_node_put(display_np);
return ret;
}

static int mxsfb_init_fbinfo(struct mxsfb_info *host)
{
struct fb_info *fb_info = &host->fb_info;
Expand All @@ -686,6 +779,7 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host)
dma_addr_t fb_phys;
void *fb_virt;
unsigned fb_size;
int ret;

fb_info->fbops = &mxsfb_ops;
fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
Expand All @@ -695,14 +789,21 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host)
fb_info->fix.visual = FB_VISUAL_TRUECOLOR,
fb_info->fix.accel = FB_ACCEL_NONE;

var->bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16;
if (pdata) {
host->ld_intf_width = pdata->ld_intf_width;
var->bits_per_pixel =
pdata->default_bpp ? pdata->default_bpp : 16;
} else {
ret = mxsfb_init_fbinfo_dt(host);
if (ret)
return ret;
}

var->nonstd = 0;
var->activate = FB_ACTIVATE_NOW;
var->accel_flags = 0;
var->vmode = FB_VMODE_NONINTERLACED;

host->ld_intf_width = pdata->ld_intf_width;

/* Memory allocation for framebuffer */
fb_size = SZ_2M;
fb_virt = alloc_pages_exact(fb_size, GFP_DMA);
Expand Down Expand Up @@ -765,11 +866,6 @@ static int mxsfb_probe(struct platform_device *pdev)
if (of_id)
pdev->id_entry = of_id->data;

if (!pdata) {
dev_err(&pdev->dev, "No platformdata. Giving up\n");
return -ENODEV;
}

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Cannot get memory IO resource\n");
Expand Down Expand Up @@ -833,14 +929,16 @@ static int mxsfb_probe(struct platform_device *pdev)

INIT_LIST_HEAD(&fb_info->modelist);

host->sync = pdata->sync;

ret = mxsfb_init_fbinfo(host);
if (ret != 0)
goto fb_release;

for (i = 0; i < pdata->mode_count; i++)
fb_add_videomode(&pdata->mode_list[i], &fb_info->modelist);
if (pdata) {
host->sync = pdata->sync;
for (i = 0; i < pdata->mode_count; i++)
fb_add_videomode(&pdata->mode_list[i],
&fb_info->modelist);
}

modelist = list_first_entry(&fb_info->modelist,
struct fb_modelist, list);
Expand Down

0 comments on commit 6694065

Please sign in to comment.