aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Chen <jason.chen@linaro.org>2011-12-05 18:18:59 +0800
committerEric Miao <eric.miao@linaro.org>2012-01-11 21:39:11 +0800
commitddf51fe00663c6ddeacbf0c2b77bf5aa23425ae3 (patch)
tree89e3f06a697ce026d49d921e7b82d86c2e3c7666
parent95756b30fb488275e2a2b9925c1e52f8a06aeca1 (diff)
imx6q-sabrelite: add ipuv3 fb dt support
Signed-off-by: Jason Chen <jason.chen@linaro.org>
-rw-r--r--arch/arm/boot/dts/imx6q-sabrelite.dts35
-rw-r--r--arch/arm/plat-mxc/include/mach/ipu-v3.h2
-rw-r--r--drivers/video/mxc/mxc_ipuv3_fb.c161
3 files changed, 148 insertions, 50 deletions
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts
index a8bd4dcdd4d..b199cd9a7e6 100644
--- a/arch/arm/boot/dts/imx6q-sabrelite.dts
+++ b/arch/arm/boot/dts/imx6q-sabrelite.dts
@@ -61,4 +61,39 @@
di = <0>;
};
};
+
+ leds {
+ compatible = "gpio-leds";
+
+ debug-led {
+ label = "Heartbeat";
+ gpios = <&gpio2 25 0>; /* GPIO3_25 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ displays {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+
+ disp1: fb@0 {
+ compatible = "fsl,mxcfb-ipuv3";
+ disp_dev = "hdmi";
+ interface_pix_fmt = "RGB24";
+ mode_str = "1280x720M@60";
+ internal_clk = "false";
+ reg = <0x00000000 0x0>; /* reserve fb mem */
+ };
+
+ disp2: fb@1 {
+ compatible = "fsl,mxcfb-ipuv3";
+ disp_dev = "ldb";
+ interface_pix_fmt = "RGB666";
+ mode_str = "LDB-XGA";
+ internal_clk = "false";
+ reg = <0x00000001 0x0>; /* reserve fb mem */
+ };
+ };
};
diff --git a/arch/arm/plat-mxc/include/mach/ipu-v3.h b/arch/arm/plat-mxc/include/mach/ipu-v3.h
index 480b4ea338e..bccb8811673 100644
--- a/arch/arm/plat-mxc/include/mach/ipu-v3.h
+++ b/arch/arm/plat-mxc/include/mach/ipu-v3.h
@@ -691,7 +691,7 @@ uint32_t bytes_per_pixel(uint32_t fmt);
struct ipuv3_fb_platform_data {
char disp_dev[32];
u32 interface_pix_fmt;
- char *mode_str;
+ char mode_str[32];
int default_bpp;
bool int_clk;
diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c
index 63807917350..1447c455202 100644
--- a/drivers/video/mxc/mxc_ipuv3_fb.c
+++ b/drivers/video/mxc/mxc_ipuv3_fb.c
@@ -91,6 +91,8 @@ struct mxcfb_info {
void *ipu;
struct fb_info *ovfbi;
+
+ struct ipuv3_fb_platform_data of_data;
};
struct mxcfb_alloc_list {
@@ -109,6 +111,7 @@ enum {
static bool g_dp_in_use[2];
LIST_HEAD(fb_alloc_list);
+static int of_dev_id;
static uint32_t bpp_to_pixfmt(struct fb_info *fbi)
{
@@ -131,6 +134,38 @@ static uint32_t bpp_to_pixfmt(struct fb_info *fbi)
return pixfmt;
}
+static int if_fmt_parse(const char *fmt)
+{
+ int if_fmt;
+
+ if (!strncmp(fmt, "RGB24", 5))
+ if_fmt = IPU_PIX_FMT_RGB24;
+ else if (!strncmp(fmt, "BGR24", 5))
+ if_fmt = IPU_PIX_FMT_BGR24;
+ else if (!strncmp(fmt, "GBR24", 5))
+ if_fmt = IPU_PIX_FMT_GBR24;
+ else if (!strncmp(fmt, "RGB565", 6))
+ if_fmt = IPU_PIX_FMT_RGB565;
+ else if (!strncmp(fmt, "RGB666", 6))
+ if_fmt = IPU_PIX_FMT_RGB666;
+ else if (!strncmp(fmt, "YUV444", 6))
+ if_fmt = IPU_PIX_FMT_YUV444;
+ else if (!strncmp(fmt, "LVDS666", 7))
+ if_fmt = IPU_PIX_FMT_LVDS666;
+ else if (!strncmp(fmt, "YUYV16", 6))
+ if_fmt = IPU_PIX_FMT_YUYV;
+ else if (!strncmp(fmt, "UYVY16", 6))
+ if_fmt = IPU_PIX_FMT_UYVY;
+ else if (!strncmp(fmt, "YVYU16", 6))
+ if_fmt = IPU_PIX_FMT_YVYU;
+ else if (!strncmp(fmt, "VYUY16", 6))
+ if_fmt = IPU_PIX_FMT_VYUY;
+ else
+ if_fmt = IPU_PIX_FMT_RGB24;
+
+ return if_fmt;
+}
+
static struct fb_info *found_registered_fb(ipu_channel_t ipu_ch, int ipu_id)
{
int i;
@@ -1233,7 +1268,8 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
down(&mxc_fbi->flip_sem);
- mxc_fbi->cur_ipu_buf = (++mxc_fbi->cur_ipu_buf) % 3;
+ mxc_fbi->cur_ipu_buf++;
+ mxc_fbi->cur_ipu_buf %= 3;
mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
dev_dbg(info->device, "Updating SDC %s buf %d address=0x%08lX\n",
@@ -1280,8 +1316,10 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
IPU_INPUT_BUFFER, 1),
ipu_check_buffer_ready(mxc_fbi->ipu, mxc_fbi->ipu_ch,
IPU_INPUT_BUFFER, 2));
- mxc_fbi->cur_ipu_buf = (++mxc_fbi->cur_ipu_buf) % 3;
- mxc_fbi->cur_ipu_buf = (++mxc_fbi->cur_ipu_buf) % 3;
+ mxc_fbi->cur_ipu_buf++;
+ mxc_fbi->cur_ipu_buf %= 3;
+ mxc_fbi->cur_ipu_buf++;
+ mxc_fbi->cur_ipu_buf %= 3;
mxc_fbi->cur_ipu_alpha_buf = !mxc_fbi->cur_ipu_alpha_buf;
ipu_clear_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
ipu_enable_irq(mxc_fbi->ipu, mxc_fbi->ipu_ch_irq);
@@ -1672,49 +1710,8 @@ static int mxcfb_option_setup(struct platform_device *pdev)
continue;
}
if (!strncmp(opt, "if=", 3)) {
- if (!strncmp(opt+3, "RGB24", 5)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_RGB24;
- continue;
- } else if (!strncmp(opt+6, "BGR24", 5)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_BGR24;
- continue;
- }
- if (!strncmp(opt+3, "GBR24", 5)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_GBR24;
- continue;
- }
- if (!strncmp(opt+3, "RGB565", 6)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_RGB565;
- continue;
- }
- if (!strncmp(opt+3, "RGB666", 6)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_RGB666;
- continue;
- }
- if (!strncmp(opt+3, "YUV444", 6)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_YUV444;
- continue;
- }
- if (!strncmp(opt+3, "LVDS666", 7)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_LVDS666;
- continue;
- }
- if (!strncmp(opt+3, "YUYV16", 6)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_YUYV;
- continue;
- }
- if (!strncmp(opt+3, "UYVY16", 6)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_UYVY;
- continue;
- }
- if (!strncmp(opt+3, "YVYU16", 6)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_YVYU;
- continue;
- }
- if (!strncmp(opt+3, "VYUY16", 6)) {
- pdata->interface_pix_fmt = IPU_PIX_FMT_VYUY;
- continue;
- }
+ pdata->interface_pix_fmt = if_fmt_parse(opt+3);
+ continue;
}
if (!strncmp(opt, "int_clk", 7)) {
pdata->int_clk = true;
@@ -1727,8 +1724,10 @@ static int mxcfb_option_setup(struct platform_device *pdev)
fb_mode_str = opt;
}
- if (fb_mode_str)
- pdata->mode_str = fb_mode_str;
+ if (fb_mode_str) {
+ memcpy(pdata->mode_str, fb_mode_str, strlen(fb_mode_str));
+ pdata->mode_str[strlen(fb_mode_str)] = '\0';
+ }
return 0;
}
@@ -1896,6 +1895,54 @@ static void ipu_clear_usage(int ipu, int di)
ipu_usage[ipu][di] = false;
}
+static int of_get_fb_data(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct ipuv3_fb_platform_data *plat_data = pdev->dev.platform_data;
+ const char *disp_dev, *if_fmt, *mode_str, *int_clk;
+ const char *default_dev = "lcd";
+ const char *default_mode_str = "800x480M@55";
+ int ret;
+
+ if (!np)
+ return -EINVAL;
+
+ pdev->id = of_dev_id;
+ of_dev_id++;
+
+ plat_data->default_bpp = 16;
+
+ ret = of_property_read_string(np, "disp_dev", &disp_dev);
+ if (ret < 0)
+ memcpy(plat_data->disp_dev, default_dev, strlen(default_dev));
+ else
+ memcpy(plat_data->disp_dev, disp_dev, strlen(disp_dev));
+
+ ret = of_property_read_string(np, "interface_pix_fmt", &if_fmt);
+ if (ret < 0)
+ plat_data->interface_pix_fmt = IPU_PIX_FMT_RGB24;
+ else
+ plat_data->interface_pix_fmt = if_fmt_parse(if_fmt);
+
+ ret = of_property_read_string(np, "mode_str", &mode_str);
+ if (ret < 0)
+ memcpy(plat_data->mode_str, default_mode_str, strlen(default_mode_str));
+ else
+ memcpy(plat_data->mode_str, mode_str, strlen(mode_str));
+
+ ret = of_property_read_string(np, "internal_clk", &int_clk);
+ if (ret < 0)
+ plat_data->int_clk = false;
+ else {
+ if (!strcmp(int_clk, "true"))
+ plat_data->int_clk = true;
+ else
+ plat_data->int_clk = false;
+ }
+
+ return 0;
+}
+
/*!
* Probe routine for the framebuffer driver. It is called during the
* driver binding process. The following functions are performed in
@@ -1921,9 +1968,18 @@ static int mxcfb_probe(struct platform_device *pdev)
goto init_fbinfo_failed;
}
+ mxcfbi = (struct mxcfb_info *)fbi->par;
+
+ if (!plat_data) {
+ plat_data = pdev->dev.platform_data = &mxcfbi->of_data;
+ if (of_get_fb_data(pdev) < 0) {
+ dev_err(&pdev->dev, "no platform data\n");
+ goto platform_data_err;
+ }
+ }
+
mxcfb_option_setup(pdev);
- mxcfbi = (struct mxcfb_info *)fbi->par;
mxcfbi->ipu_int_clk = plat_data->int_clk;
ret = mxcfb_dispdrv_init(pdev, fbi);
if (ret < 0)
@@ -2000,6 +2056,7 @@ get_ipu_failed:
ipu_clear_usage(mxcfbi->ipu_id, mxcfbi->ipu_di);
ipu_in_busy:
init_dispdrv_failed:
+platform_data_err:
fb_dealloc_cmap(&fbi->cmap);
framebuffer_release(fbi);
init_fbinfo_failed:
@@ -2031,12 +2088,18 @@ static int mxcfb_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id mxcfb_ipuv3_dt_ids[] = {
+ { .compatible = "fsl,mxcfb-ipuv3", },
+ { /* sentinel */ }
+};
+
/*!
* This structure contains pointers to the power management callback functions.
*/
static struct platform_driver mxcfb_driver = {
.driver = {
.name = MXCFB_NAME,
+ .of_match_table = mxcfb_ipuv3_dt_ids,
},
.probe = mxcfb_probe,
.remove = mxcfb_remove,