tiny4412 linux-4.2 移植(十一)LCD驱动移植
简介
tiny4412 lcd屏使用的液晶屏型号是S702,它通过RGB888跟4412进行数据通信。LCD驱动的实现方式有两种,一种是单独写驱动模块,另一种是基于源码s3c-fb.c去修改。
第一种方式可以参考
【TINY4412】LINUX移植笔记:(27)设备树LCD驱动
Exynos4412——LCD驱动
另外一种方式是参考fire brother的github去修改的。
第二种方式的思路是基于友善之臂的linux3.5源码移植过来,然后改成设备树的形式。我这里仅仅是做了移植操作,没有去仔细分析代码,所以我这里仅提供diff。
diff
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 6085e92..7cf499e 100755
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -722,8 +722,8 @@reg = <0x11c00000 0x20000>;interrupt-names = "fifo", "vsync", "lcd_sys";interrupts = <11 0>, <11 1>, <11 2>;
- clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;
- clock-names = "sclk_fimd", "fimd";
+ clocks = <&clock CLK_FIMD0>, <&clock CLK_SCLK_FIMD0>;
+ clock-names = "fimd", "sclk_fimd";power-domains = <&pd_lcd0>;iommus = <&sysmmu_fimd0>;samsung,sysreg = <&sys_reg>;
diff --git a/arch/arm/boot/dts/exynos4412-pinctrl.dtsi b/arch/arm/boot/dts/exynos4412-pinctrl.dtsi
old mode 100644
new mode 100755
index d7d5fdc..8bbb3a8
--- a/arch/arm/boot/dts/exynos4412-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4412-pinctrl.dtsi
@@ -363,7 +363,7 @@samsung,pins = "gpf0-0", "gpf0-1", "gpf0-2", "gpf0-3";samsung,pin-function = <EXYNOS_PIN_FUNC_2>;samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
- samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+ samsung,pin-drv = <EXYNOS4_PIN_DRV_LV2>;};lcd_data16: lcd-data-width16 {@@ -396,7 +396,7 @@"gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3";samsung,pin-function = <EXYNOS_PIN_FUNC_2>;samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
- samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+ samsung,pin-drv = <EXYNOS4_PIN_DRV_LV3>;};lcd_ldi: lcd-ldi {diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts
index f6b00a7..92aa0f0 100755
--- a/arch/arm/boot/dts/exynos4412-tiny4412.dts
+++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts
@@ -11,6 +11,8 @@
/dts-v1/;
#include "exynos4412.dtsi"
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/video/samsung_fimd.h>
+
/ {model = "FriendlyARM TINY4412 board based on Exynos4412";
@@ -92,6 +94,147 @@clock-frequency = <24000000>;};};
+ tiny4412_lcd {+ status = "okay";
+
+ s702{+ width = <800>;
+ height = <480>;
+ p_width = <155>;
+ p_height = <93>;
+ bpp = <24>;
+ freq = <63>;
+
+ timing {+ h_fp = <80>;
+ h_bp = <36>;
+ h_sw = <10>;
+ v_fp = <22>;
+ v_fpe = <1>;
+ v_bp = <15>;
+ v_bpe = <1>;
+ v_sw = <8>;
+ };
+
+ polarity {+ rise_vclk;
+ inv_hsync;
+ inv_vsync;
+ };
+ };
+ };
+
+&fimd {+ compatible = "samsung,exynos4-fb";
+ sclk-fimd-rate = <800000000>;
+ pinctrl-0 = <&lcd_clk &lcd_data24>;
+ pinctrl-names = "lcd0_pin_cfg";
+ sysreg_lcd_blk_cfg_offset = /bits/ 32 <0x0210>;
+ status = "okay";
+ lcd_name = "s702";
+
+ lcd_default_config {+ vidcon0 = <VIDCON0_VIDOUT_RGB VIDCON0_PNRMODE_RGB>;
+ vidcon1 = <VIDCON1_INV_HSYNC VIDCON1_INV_VSYNC>;
+ setup_gpio = "exynos4_fimd0_gpio_setup_24bpp";
+
+ vtiming {+ left_margin = <9>;
+ right_margin = <9>;
+ upper_margin = <5>;
+ lower_margin = <5>;
+ hsync_len = <2>;
+ vsync_len = <2>;
+ xres = <480>;
+ yres = <800>;
+ };
+ wins_array {+ win0 {+ xres = /bits/ 16 <480>;
+ yres = /bits/ 16 <800>;
+ virtual_x = /bits/ 16 <480>;
+ virtual_y = /bits/ 16 <800>;
+ max_bpp = /bits/ 16 <32>;
+ default_bpp = /bits/ 16 <24>;
+ width = /bits/ 16 <66>;
+ height = /bits/ 16 <109>;
+ };
+
+ win1 {+ xres = /bits/ 16 <480>;
+ yres = /bits/ 16 <800>;
+ virtual_x = /bits/ 16 <480>;
+ virtual_y = /bits/ 16 <800>;
+ max_bpp = /bits/ 16 <32>;
+ default_bpp = /bits/ 16 <24>;
+ width = /bits/ 16 <66>;
+ height = /bits/ 16 <109>;
+ };
+
+ win2 {+ xres = /bits/ 16 <480>;
+ yres = /bits/ 16 <800>;
+ virtual_x = /bits/ 16 <480>;
+ virtual_y = /bits/ 16 <800>;
+ max_bpp = /bits/ 16 <32>;
+ default_bpp = /bits/ 16 <24>;
+ width = /bits/ 16 <66>;
+ height = /bits/ 16 <109>;
+ };
+
+ win3 {+ xres = /bits/ 16 <480>;
+ yres = /bits/ 16 <800>;
+ virtual_x = /bits/ 16 <480>;
+ virtual_y = /bits/ 16 <800>;
+ max_bpp = /bits/ 16 <32>;
+ default_bpp = /bits/ 16 <24>;
+ width = /bits/ 16 <66>;
+ height = /bits/ 16 <109>;
+ };
+
+ win4 {+ xres = /bits/ 16 <480>;
+ yres = /bits/ 16 <800>;
+ virtual_x = /bits/ 16 <480>;
+ virtual_y = /bits/ 16 <800>;
+ max_bpp = /bits/ 16 <32>;
+ default_bpp = /bits/ 16 <24>;
+ width = /bits/ 16 <66>;
+ height = /bits/ 16 <109>;
+ };
+ };
+
+ };
+
+
};
&i2c_0 {diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index 846b0c9..bf66a1d 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -102,7 +102,7 @@ obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
obj-$(CONFIG_FB_SH7760) += sh7760fb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
-obj-$(CONFIG_FB_S3C) += s3c-fb.o
+obj-y += s3c-fb.o
obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
diff --git a/drivers/video/fbdev/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c
old mode 100644
new mode 100755
index 9ec85cc..a343636
--- a/drivers/video/fbdev/s3c-fb.c
+++ b/drivers/video/fbdev/s3c-fb.c
@@ -24,10 +24,17 @@
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
+#include <linux/dma-buf.h>
+
#include <linux/platform_data/video_s3c.h>
#include <video/samsung_fimd.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/gpio.h>
+#include <linux/byteorder/generic.h>
+
/* This driver will export a number of framebuffer interfaces depending* on the configuration passed in via the platform data. Each fb instance* maps to a hardware window. Currently there is no support for runtime
@@ -54,7 +61,7 @@
/* irq_flags bits */
#define S3C_FB_VSYNC_IRQ_EN 0
-#define VSYNC_TIMEOUT_MSEC 50
+#define VSYNC_TIMEOUT_MSEC 60
struct s3c_fb;
@@ -153,6 +160,13 @@ struct s3c_fb_palette {struct fb_bitfield a;
};
+struct s3c_dma_buf_data {+ struct dma_buf *dma_buf;
+ struct dma_buf_attachment *attachment;
+ struct sg_table *sg_table;
+ dma_addr_t dma_addr;
+};
+
/*** struct s3c_fb_win - per window private data for each framebuffer.* @windata: The platform data supplied for the window configuration.
@@ -174,6 +188,13 @@ struct s3c_fb_win {u32 *palette_buffer;u32 pseudo_palette[16];unsigned int index;
+
+ struct s3c_dma_buf_data dma_buf_data;
+ struct fb_var_screeninfo prev_var;
+ struct fb_fix_screeninfo prev_fix;
+
+ int fps;
+
};
/**
@@ -221,6 +242,90 @@ struct s3c_fb {struct s3c_fb_vsync vsync_info;
};
+#ifdef CONFIG_OF
+
+typedef struct lcd_io_reg_cfg{
+ struct pinctrl *pctrl;
+ struct pinctrl_state *pin_lcd_cfg;
+ void __iomem *lcd_blk_cfg_reg;
+} lcd_io_reg_cfg;
+
+static struct lcd_io_reg_cfg lcd_io_cfg = {
+ .lcd_blk_cfg_reg = NULL,
+ .pctrl = NULL,
+ .pin_lcd_cfg = NULL,
+};
+
+static const struct of_device_id s3c_fb_of_match[];
+static struct s3c_fb_platdata * of_get_s3_fb_lcd(const struct device_node *node,
+ const char *name);
+static int of_parse_lcd_io_reg_cfg(struct platform_device *pdev,
+ struct lcd_io_reg_cfg *pcfg);
+
+#endif
+
+
+/*
+ * struct s3cfb_lcd_polarity
+ * @rise_vclk: if 1, video data is fetched at rising edge
+ * @inv_hsync: if HSYNC polarity is inversed
+ * @inv_vsync: if VSYNC polarity is inversed
+ * @inv_vden: if VDEN polarity is inversed
+ */
+struct s3cfb_lcd_polarity {+ int rise_vclk;
+ int inv_hsync;
+ int inv_vsync;
+ int inv_vden;
+};
+
+/*
+ * struct s3cfb_lcd_timing
+ * @h_fp: horizontal front porch
+ * @h_bp: horizontal back porch
+ * @h_sw: horizontal sync width
+ * @v_fp: vertical front porch
+ * @v_fpe: vertical front porch for even field
+ * @v_bp: vertical back porch
+ * @v_bpe: vertical back porch for even field
+ */
+struct s3cfb_lcd_timing {+ int h_fp;
+ int h_bp;
+ int h_sw;
+ int v_fp;
+ int v_fpe;
+ int v_bp;
+ int v_bpe;
+ int v_sw;
+};
+
+
+/*
+ * struct s3cfb_lcd
+ * @width: horizontal resolution
+ * @height: vertical resolution
+ * @p_width: width of lcd in mm
+ * @p_height: height of lcd in mm
+ * @bpp: bits per pixel
+ * @freq: vframe frequency
+ * @timing: timing values
+ * @polarity: polarity settings
+ * @init_ldi: pointer to LDI init function
+ *
+ */
+struct s3cfb_lcd {+ int width;
+ int height;
+ int p_width;
+ int p_height;
+ int bpp;
+ int freq;
+ struct s3cfb_lcd_timing timing;
+ struct s3cfb_lcd_polarity polarity;
+};
+
+
/*** s3c_fb_validate_win_bpp - validate the bits-per-pixel for this mode.* @win: The device window.
@@ -962,7 +1067,7 @@ static irqreturn_t s3c_fb_irq(int irq, void *dev_id)struct s3c_fb *sfb = dev_id;void __iomem *regs = sfb->regs;u32 irq_sts_reg;
-
+ printk(KERN_WARNING"s3c_fb_irq do irq!\n");spin_lock(&sfb->slock);irq_sts_reg = readl(regs + VIDINTCON1);
@@ -1098,21 +1203,25 @@ static int s3c_fb_alloc_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)size = (real_size > virt_size) ? real_size : virt_size;size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp;
- size /= 8;
+ size >>= 3;fbi->fix.smem_len = size;size = PAGE_ALIGN(size);dev_dbg(sfb->dev, "want %u bytes for window\n", size);
- fbi->screen_base = dma_alloc_wc(sfb->dev, size, &map_dma, GFP_KERNEL);
- if (!fbi->screen_base)
+ fbi->screen_base = dma_alloc_writecombine(sfb->dev, size, &map_dma, GFP_KERNEL);
+ printk(KERN_WARNING"s3c_fb_alloc_memory dma addr 0x%08X\n", map_dma);
+ if (!fbi->screen_base){
+ dev_err(sfb->dev, "dma_alloc_writecombine err\n");return -ENOMEM;
+ }
+dev_dbg(sfb->dev, "mapped %x to %p\n",(unsigned int)map_dma, fbi->screen_base);
- memset(fbi->screen_base, 0x0, size);
+ memset(fbi->screen_base, 0x00, size);fbi->fix.smem_start = map_dma;return 0;
@@ -1130,7 +1239,7 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)struct fb_info *fbi = win->fbinfo;if (fbi->screen_base)
- dma_free_wc(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
+ dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),fbi->screen_base, fbi->fix.smem_start);
}
@@ -1242,6 +1351,8 @@ static int s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,initmode.yres = windata->yres;fb_videomode_to_var(&fbinfo->var, &initmode);
+ fbinfo->var.width = windata->width;
+ fbinfo->var.height = windata->height;fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;fbinfo->fix.accel = FB_ACCEL_NONE;fbinfo->var.activate = FB_ACTIVATE_NOW;
@@ -1314,6 +1425,13 @@ static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb)data |= (1 << 5);writel(data, regs + VIDCON0);
+ if (sfb->variant.has_blendcon) {
+ data = readl(sfb->regs + BLENDCON);
+ data &= ~BLENDCON_NEW_MASK;
+ data |= BLENDCON_NEW_8BIT_ALPHA_VALUE;
+ writel(data, sfb->regs + BLENDCON);
+ }
+data = VIDTCON0_VBPD(vmode->upper_margin - 1) |VIDTCON0_VFPD(vmode->lower_margin - 1) |VIDTCON0_VSPW(vmode->vsync_len - 1);
@@ -1356,29 +1474,182 @@ static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)writel(reg, sfb->regs + SHADOWCON);}
}
+static int of_parse_tiny4412_lcd(const char *lcd_name, struct s3cfb_lcd *lcd)
+{
+ struct device_node *lcd_np = NULL;
+ struct device_node *spec_lcd_np = NULL;
+ struct device_node *timing_np = NULL;
+ struct device_node *polar_np = NULL;
+
+ if((NULL == lcd_name) || (NULL == lcd))
+ return -1;
+
+ lcd_np = of_find_node_by_name(NULL, "tiny4412_lcd");
+
+ if(NULL == lcd_np)
+ return -1;
+
+ spec_lcd_np = of_get_child_by_name(lcd_np, lcd_name);
+
+ if(NULL == spec_lcd_np)
+ return -1;
+
+ of_property_read_u32(spec_lcd_np, "width", &lcd->width);
+ of_property_read_u32(spec_lcd_np, "height", &lcd->height);
+ of_property_read_u32(spec_lcd_np, "p_width", &lcd->p_width);
+ of_property_read_u32(spec_lcd_np, "p_height", &lcd->p_height);
+ of_property_read_u32(spec_lcd_np, "bpp", &lcd->bpp);
+ of_property_read_u32(spec_lcd_np, "freq", &lcd->freq);
+
+ timing_np = of_get_child_by_name(spec_lcd_np, "timing");
+ of_property_read_u32(timing_np, "h_fp", &lcd->timing.h_fp);
+ of_property_read_u32(timing_np, "h_bp", &lcd->timing.h_bp);
+ of_property_read_u32(timing_np, "h_sw", &lcd->timing.h_sw);
+ of_property_read_u32(timing_np, "v_fp", &lcd->timing.v_fp);
+ of_property_read_u32(timing_np, "v_fpe", &lcd->timing.v_fpe);
+ of_property_read_u32(timing_np, "v_bp", &lcd->timing.v_bp);
+ of_property_read_u32(timing_np, "v_bpe", &lcd->timing.v_bpe);
+ of_property_read_u32(timing_np, "v_sw", &lcd->timing.v_sw);
+
+ polar_np = of_get_child_by_name(spec_lcd_np, "polarity");
+ memset(&lcd->polarity, 0x00, sizeof(lcd->polarity));
+ if(of_property_read_bool(polar_np, "rise_vclk"))
+ lcd->polarity.rise_vclk = 1;
+
+ if(of_property_read_bool(polar_np, "inv_hsync"))
+ lcd->polarity.inv_hsync = 1;
+
+ if(of_property_read_bool(polar_np, "inv_vsync"))
+ lcd->polarity.inv_vsync = 1;
+
+ if(of_property_read_bool(polar_np, "inv_vden"))
+ lcd->polarity.inv_vden = 1;
+
+
+ return 0;
+
+}
+
+static void tiny4412_fb_init_pdata(const char *lcd_name, struct s3c_fb_platdata *pd) {
+ struct s3cfb_lcd *lcd = NULL;
+ struct s3c_fb_pd_win *win;
+ struct fb_videomode *mode = pd->vtiming;
+ unsigned long val = 0;
+ u64 pixclk = 1000000000000ULL;
+ u32 div;
+ int i, err;
+
+ if(NULL == lcd_name)
+ return;
+ printk(KERN_WARNING"lcd_name %s\n", lcd_name);
+
+ lcd = kzalloc(sizeof(struct s3cfb_lcd), GFP_KERNEL);
+ err = of_parse_tiny4412_lcd(lcd_name, lcd);
+ if(err < 0){
+ printk(KERN_WARNING"%s of_parse_tiny4412_lcd fail!!\n", lcd_name);
+ goto out;
+ }
+
+ for (i = 0; i < S3C_FB_MAX_WIN; i++) {
+ if (pd->win[i] == NULL)
+ continue;
+
+ win = pd->win[i];
+ win->xres = lcd->width;
+ win->yres = lcd->height;
+ win->default_bpp= lcd->bpp ? : 24;
+ win->virtual_x = win->xres;
+ win->virtual_y = win->yres * 3;
+ win->width = lcd->p_width;
+ win->height = lcd->p_height;
+ }
+
+ mode->left_margin = lcd->timing.h_bp;
+ mode->right_margin = lcd->timing.h_fp;
+ mode->upper_margin = lcd->timing.v_bp;
+ mode->lower_margin = lcd->timing.v_fp;
+ mode->hsync_len = lcd->timing.h_sw;
+ mode->vsync_len = lcd->timing.v_sw;
+ mode->xres = lcd->width;
+ mode->yres = lcd->height;
+
+ /* calculates pixel clock */
+ div = mode->left_margin + mode->hsync_len + mode->right_margin +
+ mode->xres;
+ div *= mode->upper_margin + mode->vsync_len + mode->lower_margin +
+ mode->yres;
+ div *= lcd->freq ? : 60;
+
+ do_div(pixclk, div);
+
+ mode->pixclock = pixclk + 386;
+
+ /* initialize signal polarity of RGB interface */
+ if (lcd->polarity.rise_vclk)
+ val |= VIDCON1_INV_VCLK;
+ if (lcd->polarity.inv_hsync)
+ val |= VIDCON1_INV_HSYNC;
+ if (lcd->polarity.inv_vsync)
+ val |= VIDCON1_INV_VSYNC;
+ if (lcd->polarity.inv_vden)
+ val |= VIDCON1_INV_VDEN;
+
+ pd->vidcon1 = val;
+
+out:
+ if(NULL != lcd){+ kfree(lcd);
+ lcd = NULL;
+ }
+
+}
+
static int s3c_fb_probe(struct platform_device *pdev)
{const struct platform_device_id *platid;
+ struct of_device_id *of_id = NULL;
+ struct device_node *fimd_root_dn = NULL;
+struct s3c_fb_driverdata *fbdrv;struct device *dev = &pdev->dev;struct s3c_fb_platdata *pd;struct s3c_fb *sfb;
+ struct s3c_fb_win *fbwin;struct resource *res;
+ const char *lcd_name = NULL;int win;int ret = 0;
- u32 reg;
+ u32 reg, clk_rate = 0;
+ printk("s3c_fb_probe\n");
+
+ of_id = of_match_device(s3c_fb_of_match, &pdev->dev);
+ if(NULL != of_id){+ printk(KERN_WARNING"s3c_fb_probe: of_match_device OK \n");
+ fbdrv = (struct s3c_fb_driverdata *)of_id->data;
+ fimd_root_dn = dev->of_node;
+ }
+ else{+ platid = platform_get_device_id(pdev);
+ fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
+ }
- platid = platform_get_device_id(pdev);
- fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {dev_err(dev, "too many windows, cannot attach\n");return -EINVAL;}
- pd = dev_get_platdata(&pdev->dev);
- if (!pd) {+ if(NULL != fimd_root_dn)
+ {+ of_parse_lcd_io_reg_cfg(pdev, &lcd_io_cfg);
+ pd = of_get_s3_fb_lcd(fimd_root_dn, "lcd_default_config");
+ }
+ else
+ pd = dev_get_platdata(&pdev->dev);
+
+ if(!pd){+dev_err(dev, "no platform data specified\n");return -EINVAL;}
@@ -1388,6 +1659,8 @@ static int s3c_fb_probe(struct platform_device *pdev)return -ENOMEM;dev_dbg(dev, "allocate new framebuffer %p\n", sfb);
+ of_property_read_string(fimd_root_dn, "lcd_name", &lcd_name);
+ tiny4412_fb_init_pdata(lcd_name, pd);sfb->dev = dev;sfb->pdata = pd;
@@ -1395,7 +1668,7 @@ static int s3c_fb_probe(struct platform_device *pdev)spin_lock_init(&sfb->slock);
- sfb->bus_clk = devm_clk_get(dev, "lcd");
+ sfb->bus_clk = devm_clk_get(dev, "fimd");if (IS_ERR(sfb->bus_clk)) {dev_err(dev, "failed to get bus clock\n");return PTR_ERR(sfb->bus_clk);
@@ -1410,6 +1683,8 @@ static int s3c_fb_probe(struct platform_device *pdev)ret = PTR_ERR(sfb->lcd_clk);goto err_bus_clk;}
+ of_property_read_u32(fimd_root_dn, "sclk-fimd-rate", &clk_rate);
+ clk_set_rate(sfb->lcd_clk, clk_rate);clk_prepare_enable(sfb->lcd_clk);}
@@ -1423,13 +1698,12 @@ static int s3c_fb_probe(struct platform_device *pdev)goto err_lcd_clk;}
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {+ sfb->irq_no = platform_get_irq_byname(pdev, "vsync");
+ if (sfb->irq_no < 0) {dev_err(dev, "failed to acquire irq resource\n");ret = -ENOENT;goto err_lcd_clk;}
- sfb->irq_no = res->start;ret = devm_request_irq(dev, sfb->irq_no, s3c_fb_irq,0, "s3c_fb", sfb);if (ret) {@@ -1478,8 +1752,8 @@ static int s3c_fb_probe(struct platform_device *pdev)if (!pd->win[win])continue;
- ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
- &sfb->windows[win]);
+ ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
+ &sfb->windows[win]);if (ret < 0) {dev_err(dev, "failed to create window %d\n", win);for (; win >= 0; win--)
@@ -1487,9 +1761,17 @@ static int s3c_fb_probe(struct platform_device *pdev)goto err_pm_runtime;}}
+ fbwin = sfb->windows[0];
+
+ if (fb_prepare_logo(fbwin->fbinfo, FB_ROTATE_UR)) {+ printk("Start display and show logo\n");
+ fb_set_cmap(&fbwin->fbinfo->cmap, fbwin->fbinfo);
+ fb_show_logo(fbwin->fbinfo, FB_ROTATE_UR);
+
+ }platform_set_drvdata(pdev, sfb);
- pm_runtime_put_sync(sfb->dev);
+return 0;
@@ -1658,6 +1940,152 @@ static int s3c_fb_runtime_resume(struct device *dev)
}
#endif
+#ifdef CONFIG_OF
+
+
+static int of_parse_lcd_io_reg_cfg(struct platform_device *pdev,
+ struct lcd_io_reg_cfg *pcfg)
+{+ struct device *dev = NULL;
+ struct device_node *sysreg_node = NULL;
+ u32 sysreg, offset, addr_cells_nr, size_cells_nr;
+ phandle sysreg_ph;
+
+ if((NULL == pdev) || (NULL == pcfg))
+ return -EINVAL;
+
+ dev = &pdev->dev;
+ of_property_read_u32_index(dev->of_node, "samsung,sysreg", 0, &sysreg_ph);
+ of_property_read_u32(dev->of_node, "sysreg_lcd_blk_cfg_offset", &offset);
+ sysreg_node = of_find_node_by_phandle(sysreg_ph);
+ addr_cells_nr = of_n_addr_cells(sysreg_node);
+ of_property_read_u32_index(sysreg_node, "reg", 0, &sysreg);
+ size_cells_nr = of_n_size_cells(sysreg_node);
+ pcfg->lcd_blk_cfg_reg = ioremap(sysreg + offset, 4);
+
+ pcfg->pctrl = devm_pinctrl_get(dev);
+ pcfg->pin_lcd_cfg = pinctrl_lookup_state(pcfg->pctrl, "lcd0_pin_cfg");
+ if((NULL != pcfg->pctrl) && (NULL != pcfg->pin_lcd_cfg))
+ printk(KERN_WARNING"of_parse_lcd_io_reg_cfg pctrl setup OK!\n");
+
+ return 0;
+}
+static void setup_lcd_pin_cfg(void)
+{+ u32 reg;
+
+ pinctrl_select_state(lcd_io_cfg.pctrl, lcd_io_cfg.pin_lcd_cfg);
+ /*
+ * Set DISPLAY_CONTROL register for Display path selection.
+ *
+ * DISPLAY_CONTROL[1:0]
+ * ---------------------
+ * 00 | MIE
+ * 01 | MDINE
+ * 10 | FIMD : selected
+ * 11 | FIMD
+ */
+ reg = readl(lcd_io_cfg.lcd_blk_cfg_reg);
+ reg |= (1 << 1);
+ writel(reg, lcd_io_cfg.lcd_blk_cfg_reg);
+
+}
+
+
+static int of_parse_fimd_def_lcd(const struct device_node * np, struct s3c_fb_platdata *pdata)
+{+ struct device_node *vt_node;
+ struct device_node *wins_arr_node;
+
+ int i ,cnt;
+ u32 val;
+
+ if((NULL == np) || (NULL == pdata))
+ return -EINVAL;
+
+ cnt = of_property_count_elems_of_size(np, "vidcon0", sizeof(u32));
+ for(i = 0; i < cnt; i++)
+ {+ of_property_read_u32_index(np, "vidcon0", i, &val);
+ pdata->vidcon0 |= val;
+ }
+
+ cnt = of_property_count_elems_of_size(np, "vidcon1", sizeof(u32));
+ for(i = 0; i < cnt; i++)
+ {+ of_property_read_u32_index(np, "vidcon1", i, &val);
+ pdata->vidcon1 |= val;
+ }
+ vt_node = of_get_child_by_name(np, "vtiming");
+ if(NULL != vt_node)
+ {+ pdata->vtiming = kzalloc(sizeof(struct fb_videomode), GFP_KERNEL);
+ of_property_read_u32(vt_node, "left_margin", &pdata->vtiming->left_margin);
+ of_property_read_u32(vt_node, "right_margin", &pdata->vtiming->right_margin);
+ of_property_read_u32(vt_node, "upper_margin", &pdata->vtiming->upper_margin);
+ of_property_read_u32(vt_node, "lower_margin", &pdata->vtiming->lower_margin);
+ of_property_read_u32(vt_node, "hsync_len", &pdata->vtiming->hsync_len);
+ of_property_read_u32(vt_node, "vsync_len", &pdata->vtiming->vsync_len);
+ of_property_read_u32(vt_node, "xres", &pdata->vtiming->xres);
+ of_property_read_u32(vt_node, "yres", &pdata->vtiming->yres);
+ }
+ wins_arr_node = of_get_child_by_name(np, "wins_array");
+ if(NULL != wins_arr_node)
+ {+ struct device_node *child;
+ int j = 0;
+ for_each_child_of_node(wins_arr_node, child)
+ {+ pdata->win[j] = kzalloc(sizeof(struct s3c_fb_pd_win), GFP_KERNEL);
+ of_property_read_u16(child, "xres", &pdata->win[j]->xres);
+ of_property_read_u16(child, "yres", &pdata->win[j]->yres);
+ of_property_read_u16(child, "virtual_x", &pdata->win[j]->virtual_x);
+ of_property_read_u16(child, "virtual_y", &pdata->win[j]->virtual_y);
+ of_property_read_u16(child, "max_bpp", &pdata->win[j]->max_bpp);
+ of_property_read_u16(child, "default_bpp", &pdata->win[j]->default_bpp);
+ j++;
+ }
+ }
+
+ pdata->setup_gpio = setup_lcd_pin_cfg;
+
+ return 0;
+}
+
+static struct s3c_fb_platdata * of_get_s3_fb_lcd(const struct device_node *node,
+ const char *name)
+{+ struct device_node *def_lcd_node = NULL;
+ struct s3c_fb_platdata *pdata = NULL;
+ int err = 0;
+
+ def_lcd_node = of_get_child_by_name(node, name);
+ if(NULL != def_lcd_node)
+ {+ pdata = kzalloc(sizeof(struct s3c_fb_platdata), GFP_KERNEL);
+ if(!pdata)
+ goto err_out;
+
+ err = of_parse_fimd_def_lcd(def_lcd_node, pdata);
+ if(err)
+ {+ goto err_out;
+ }
+
+ return pdata;
+ }
+
+err_out:
+ if(pdata)
+ {+ kfree(pdata);
+ pdata = NULL;
+ }
+ return NULL;
+}
+
+
+
#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
@@ -1714,6 +2142,64 @@ static int s3c_fb_runtime_resume(struct device *dev)},
};
+static struct s3c_fb_win_variant s3c_fb_data_s5p_wins[] = {+ [0] = {+ .has_osd_c = 1,
+ .osd_size_off = 0x8,
+ .palette_sz = 256,
+ .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
+ VALID_BPP(15) | VALID_BPP(16) |
+ VALID_BPP(18) | VALID_BPP(19) |
+ VALID_BPP(24) | VALID_BPP(25) |
+ VALID_BPP(32)),
+ },
+ [1] = {+ .has_osd_c = 1,
+ .has_osd_d = 1,
+ .osd_size_off = 0xc,
+ .has_osd_alpha = 1,
+ .palette_sz = 256,
+ .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
+ VALID_BPP(15) | VALID_BPP(16) |
+ VALID_BPP(18) | VALID_BPP(19) |
+ VALID_BPP(24) | VALID_BPP(25) |
+ VALID_BPP(32)),
+ },
+ [2] = {+ .has_osd_c = 1,
+ .has_osd_d = 1,
+ .osd_size_off = 0xc,
+ .has_osd_alpha = 1,
+ .palette_sz = 256,
+ .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
+ VALID_BPP(15) | VALID_BPP(16) |
+ VALID_BPP(18) | VALID_BPP(19) |
+ VALID_BPP(24) | VALID_BPP(25) |
+ VALID_BPP(32)),
+ },
+ [3] = {+ .has_osd_c = 1,
+ .has_osd_alpha = 1,
+ .palette_sz = 256,
+ .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
+ VALID_BPP(15) | VALID_BPP(16) |
+ VALID_BPP(18) | VALID_BPP(19) |
+ VALID_BPP(24) | VALID_BPP(25) |
+ VALID_BPP(32)),
+ },
+ [4] = {+ .has_osd_c = 1,
+ .has_osd_alpha = 1,
+ .palette_sz = 256,
+ .valid_bpp = (VALID_BPP1248 | VALID_BPP(13) |
+ VALID_BPP(15) | VALID_BPP(16) |
+ VALID_BPP(18) | VALID_BPP(19) |
+ VALID_BPP(24) | VALID_BPP(25) |
+ VALID_BPP(32)),
+ },
+};
+
+
static struct s3c_fb_driverdata s3c_fb_data_64xx = {.variant = {.nr_windows = 5,
@@ -1781,6 +2267,46 @@ static int s3c_fb_runtime_resume(struct device *dev)VALID_BPP(28)),},
};
+static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {+ .variant = {+ .nr_windows = 5,
+ .vidtcon = VIDTCON0,
+ .wincon = WINCON(0),
+ .winmap = WINxMAP(0),
+ .keycon = WKEYCON,
+ .osd = VIDOSD_BASE,
+ .osd_stride = 16,
+ .buf_start = VIDW_BUF_START(0),
+ .buf_size = VIDW_BUF_SIZE(0),
+ .buf_end = VIDW_BUF_END(0),
+
+ .palette = {+ [0] = 0x2400,
+ [1] = 0x2800,
+ [2] = 0x2c00,
+ [3] = 0x3000,
+ [4] = 0x3400,
+ },
+
+ .has_shadowcon = 1,
+ .has_blendcon = 1,
+ .has_fixvclk = 1,
+ },
+ .win[0] = &s3c_fb_data_s5p_wins[0],
+ .win[1] = &s3c_fb_data_s5p_wins[1],
+ .win[2] = &s3c_fb_data_s5p_wins[2],
+ .win[3] = &s3c_fb_data_s5p_wins[3],
+ .win[4] = &s3c_fb_data_s5p_wins[4],
+};
+
+
+static const struct of_device_id s3c_fb_of_match[] = {+ { .compatible = "samsung,exynos4-fb",
+ .data = &s3c_fb_data_exynos4 },
+ {},
+};
+MODULE_DEVICE_TABLE(of, s3c_fb_of_match);
+#endif
static const struct platform_device_id s3c_fb_driver_ids[] = {{@@ -1789,6 +2315,9 @@ static int s3c_fb_runtime_resume(struct device *dev)}, {.name = "s3c2443-fb",.driver_data = (unsigned long)&s3c_fb_data_s3c2443,
+ },{+ .name = "exynos4-fb",
+ .driver_data = (unsigned long)&s3c_fb_data_exynos4,},{},
};
@@ -1807,6 +2336,7 @@ static int s3c_fb_runtime_resume(struct device *dev).driver = {.name = "s3c-fb",.pm = &s3cfb_pm_ops,
+ .of_match_table = s3c_fb_of_match,},
};
diff --git a/include/dt-bindings/video/samsung_fimd.h b/include/dt-bindings/video/samsung_fimd.h
new file mode 100644
index 0000000..d8fc96e
--- /dev/null
+++ b/include/dt-bindings/video/samsung_fimd.h
@@ -0,0 +1,477 @@
+/* include/video/samsung_fimd.h
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ * http://armlinux.simtec.co.uk/
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C Platform - new-style fimd and framebuffer register definitions
+ *
+ * This is the register set for the fimd and new style framebuffer interface
+ * found from the S3C2443 onwards into the S3C2416, S3C2450, the
+ * S3C64XX series such as the S3C6400 and S3C6410, and EXYNOS series.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* VIDCON0 */
+
+#define VIDCON0 0x00
+#define VIDCON0_DSI_EN (1 << 30)
+#define VIDCON0_INTERLACE (1 << 29)
+#define VIDCON0_VIDOUT_MASK (0x7 << 26)
+#define VIDCON0_VIDOUT_SHIFT 26
+#define VIDCON0_VIDOUT_RGB (0x0 << 26)
+#define VIDCON0_VIDOUT_TV (0x1 << 26)
+#define VIDCON0_VIDOUT_I80_LDI0 (0x2 << 26)
+#define VIDCON0_VIDOUT_I80_LDI1 (0x3 << 26)
+#define VIDCON0_VIDOUT_WB_RGB (0x4 << 26)
+#define VIDCON0_VIDOUT_WB_I80_LDI0 (0x6 << 26)
+#define VIDCON0_VIDOUT_WB_I80_LDI1 (0x7 << 26)
+
+#define VIDCON0_L1_DATA_MASK (0x7 << 23)
+#define VIDCON0_L1_DATA_SHIFT 23
+#define VIDCON0_L1_DATA_16BPP (0x0 << 23)
+#define VIDCON0_L1_DATA_18BPP16 (0x1 << 23)
+#define VIDCON0_L1_DATA_18BPP9 (0x2 << 23)
+#define VIDCON0_L1_DATA_24BPP (0x3 << 23)
+#define VIDCON0_L1_DATA_18BPP (0x4 << 23)
+#define VIDCON0_L1_DATA_16BPP8 (0x5 << 23)
+
+#define VIDCON0_L0_DATA_MASK (0x7 << 20)
+#define VIDCON0_L0_DATA_SHIFT 20
+#define VIDCON0_L0_DATA_16BPP (0x0 << 20)
+#define VIDCON0_L0_DATA_18BPP16 (0x1 << 20)
+#define VIDCON0_L0_DATA_18BPP9 (0x2 << 20)
+#define VIDCON0_L0_DATA_24BPP (0x3 << 20)
+#define VIDCON0_L0_DATA_18BPP (0x4 << 20)
+#define VIDCON0_L0_DATA_16BPP8 (0x5 << 20)
+
+#define VIDCON0_PNRMODE_MASK (0x3 << 17)
+#define VIDCON0_PNRMODE_SHIFT 17
+#define VIDCON0_PNRMODE_RGB (0x0 << 17)
+#define VIDCON0_PNRMODE_BGR (0x1 << 17)
+#define VIDCON0_PNRMODE_SERIAL_RGB (0x2 << 17)
+#define VIDCON0_PNRMODE_SERIAL_BGR (0x3 << 17)
+
+#define VIDCON0_CLKVALUP (1 << 16)
+#define VIDCON0_CLKVAL_F_MASK (0xff << 6)
+#define VIDCON0_CLKVAL_F_SHIFT 6
+#define VIDCON0_CLKVAL_F_LIMIT 0xff
+#define VIDCON0_CLKVAL_F(_x) ((_x) << 6)
+#define VIDCON0_VLCKFREE (1 << 5)
+#define VIDCON0_CLKDIR (1 << 4)
+
+#define VIDCON0_CLKSEL_MASK (0x3 << 2)
+#define VIDCON0_CLKSEL_SHIFT 2
+#define VIDCON0_CLKSEL_HCLK (0x0 << 2)
+#define VIDCON0_CLKSEL_LCD (0x1 << 2)
+#define VIDCON0_CLKSEL_27M (0x3 << 2)
+
+#define VIDCON0_ENVID (1 << 1)
+#define VIDCON0_ENVID_F (1 << 0)
+
+#define VIDCON1 0x04
+#define VIDCON1_LINECNT_MASK (0x7ff << 16)
+#define VIDCON1_LINECNT_SHIFT 16
+#define VIDCON1_LINECNT_GET(_v) (((_v) >> 16) & 0x7ff)
+#define VIDCON1_FSTATUS_EVEN (1 << 15)
+#define VIDCON1_VSTATUS_MASK (0x3 << 13)
+#define VIDCON1_VSTATUS_SHIFT 13
+#define VIDCON1_VSTATUS_VSYNC (0x0 << 13)
+#define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13)
+#define VIDCON1_VSTATUS_ACTIVE (0x2 << 13)
+#define VIDCON1_VSTATUS_FRONTPORCH (0x3 << 13)
+#define VIDCON1_VCLK_MASK (0x3 << 9)
+#define VIDCON1_VCLK_HOLD (0x0 << 9)
+#define VIDCON1_VCLK_RUN (0x1 << 9)
+
+#define VIDCON1_INV_VCLK (1 << 7)
+#define VIDCON1_INV_HSYNC (1 << 6)
+#define VIDCON1_INV_VSYNC (1 << 5)
+#define VIDCON1_INV_VDEN (1 << 4)
+
+/* VIDCON2 */
+
+#define VIDCON2 0x08
+#define VIDCON2_EN601 (1 << 23)
+#define VIDCON2_TVFMTSEL_SW (1 << 14)
+
+#define VIDCON2_TVFMTSEL1_MASK (0x3 << 12)
+#define VIDCON2_TVFMTSEL1_SHIFT 12
+#define VIDCON2_TVFMTSEL1_RGB (0x0 << 12)
+#define VIDCON2_TVFMTSEL1_YUV422 (0x1 << 12)
+#define VIDCON2_TVFMTSEL1_YUV444 (0x2 << 12)
+
+#define VIDCON2_ORGYCbCr (1 << 8)
+#define VIDCON2_YUVORDCrCb (1 << 7)
+
+/* PRTCON (S3C6410)
+ * Might not be present in the S3C6410 documentation,
+ * but tests prove it's there almost for sure; shouldn't hurt in any case.
+ */
+#define PRTCON 0x0c
+#define PRTCON_PROTECT (1 << 11)
+
+/* VIDTCON0 */
+
+#define VIDTCON0 0x10
+#define VIDTCON0_VBPDE_MASK (0xff << 24)
+#define VIDTCON0_VBPDE_SHIFT 24
+#define VIDTCON0_VBPDE_LIMIT 0xff
+#define VIDTCON0_VBPDE(_x) ((_x) << 24)
+
+#define VIDTCON0_VBPD_MASK (0xff << 16)
+#define VIDTCON0_VBPD_SHIFT 16
+#define VIDTCON0_VBPD_LIMIT 0xff
+#define VIDTCON0_VBPD(_x) ((_x) << 16)
+
+#define VIDTCON0_VFPD_MASK (0xff << 8)
+#define VIDTCON0_VFPD_SHIFT 8
+#define VIDTCON0_VFPD_LIMIT 0xff
+#define VIDTCON0_VFPD(_x) ((_x) << 8)
+
+#define VIDTCON0_VSPW_MASK (0xff << 0)
+#define VIDTCON0_VSPW_SHIFT 0
+#define VIDTCON0_VSPW_LIMIT 0xff
+#define VIDTCON0_VSPW(_x) ((_x) << 0)
+
+/* VIDTCON1 */
+
+#define VIDTCON1 0x14
+#define VIDTCON1_VFPDE_MASK (0xff << 24)
+#define VIDTCON1_VFPDE_SHIFT 24
+#define VIDTCON1_VFPDE_LIMIT 0xff
+#define VIDTCON1_VFPDE(_x) ((_x) << 24)
+
+#define VIDTCON1_HBPD_MASK (0xff << 16)
+#define VIDTCON1_HBPD_SHIFT 16
+#define VIDTCON1_HBPD_LIMIT 0xff
+#define VIDTCON1_HBPD(_x) ((_x) << 16)
+
+#define VIDTCON1_HFPD_MASK (0xff << 8)
+#define VIDTCON1_HFPD_SHIFT 8
+#define VIDTCON1_HFPD_LIMIT 0xff
+#define VIDTCON1_HFPD(_x) ((_x) << 8)
+
+#define VIDTCON1_HSPW_MASK (0xff << 0)
+#define VIDTCON1_HSPW_SHIFT 0
+#define VIDTCON1_HSPW_LIMIT 0xff
+#define VIDTCON1_HSPW(_x) ((_x) << 0)
+
+#define VIDTCON2 0x18
+#define VIDTCON2_LINEVAL_E(_x) ((((_x) & 0x800) >> 11) << 23)
+#define VIDTCON2_LINEVAL_MASK (0x7ff << 11)
+#define VIDTCON2_LINEVAL_SHIFT 11
+#define VIDTCON2_LINEVAL_LIMIT 0x7ff
+#define VIDTCON2_LINEVAL(_x) (((_x) & 0x7ff) << 11)
+
+#define VIDTCON2_HOZVAL_E(_x) ((((_x) & 0x800) >> 11) << 22)
+#define VIDTCON2_HOZVAL_MASK (0x7ff << 0)
+#define VIDTCON2_HOZVAL_SHIFT 0
+#define VIDTCON2_HOZVAL_LIMIT 0x7ff
+#define VIDTCON2_HOZVAL(_x) (((_x) & 0x7ff) << 0)
+
+/* WINCONx */
+
+#define WINCON(_win) (0x20 + ((_win) * 4))
+#define WINCONx_CSCCON_EQ601 (0x0 << 28)
+#define WINCONx_CSCCON_EQ709 (0x1 << 28)
+#define WINCONx_CSCWIDTH_MASK (0x3 << 26)
+#define WINCONx_CSCWIDTH_SHIFT 26
+#define WINCONx_CSCWIDTH_WIDE (0x0 << 26)
+#define WINCONx_CSCWIDTH_NARROW (0x3 << 26)
+#define WINCONx_ENLOCAL (1 << 22)
+#define WINCONx_BUFSTATUS (1 << 21)
+#define WINCONx_BUFSEL (1 << 20)
+#define WINCONx_BUFAUTOEN (1 << 19)
+#define WINCONx_BITSWP (1 << 18)
+#define WINCONx_BYTSWP (1 << 17)
+#define WINCONx_HAWSWP (1 << 16)
+#define WINCONx_WSWP (1 << 15)
+#define WINCONx_YCbCr (1 << 13)
+#define WINCONx_BURSTLEN_MASK (0x3 << 9)
+#define WINCONx_BURSTLEN_SHIFT 9
+#define WINCONx_BURSTLEN_16WORD (0x0 << 9)
+#define WINCONx_BURSTLEN_8WORD (0x1 << 9)
+#define WINCONx_BURSTLEN_4WORD (0x2 << 9)
+#define WINCONx_ENWIN (1 << 0)
+
+#define WINCON0_BPPMODE_MASK (0xf << 2)
+#define WINCON0_BPPMODE_SHIFT 2
+#define WINCON0_BPPMODE_1BPP (0x0 << 2)
+#define WINCON0_BPPMODE_2BPP (0x1 << 2)
+#define WINCON0_BPPMODE_4BPP (0x2 << 2)
+#define WINCON0_BPPMODE_8BPP_PALETTE (0x3 << 2)
+#define WINCON0_BPPMODE_16BPP_565 (0x5 << 2)
+#define WINCON0_BPPMODE_16BPP_1555 (0x7 << 2)
+#define WINCON0_BPPMODE_18BPP_666 (0x8 << 2)
+#define WINCON0_BPPMODE_24BPP_888 (0xb << 2)
+
+#define WINCON1_LOCALSEL_CAMIF (1 << 23)
+#define WINCON1_BLD_PIX (1 << 6)
+#define WINCON1_BPPMODE_MASK (0xf << 2)
+#define WINCON1_BPPMODE_SHIFT 2
+#define WINCON1_BPPMODE_1BPP (0x0 << 2)
+#define WINCON1_BPPMODE_2BPP (0x1 << 2)
+#define WINCON1_BPPMODE_4BPP (0x2 << 2)
+#define WINCON1_BPPMODE_8BPP_PALETTE (0x3 << 2)
+#define WINCON1_BPPMODE_8BPP_1232 (0x4 << 2)
+#define WINCON1_BPPMODE_16BPP_565 (0x5 << 2)
+#define WINCON1_BPPMODE_16BPP_A1555 (0x6 << 2)
+#define WINCON1_BPPMODE_16BPP_I1555 (0x7 << 2)
+#define WINCON1_BPPMODE_18BPP_666 (0x8 << 2)
+#define WINCON1_BPPMODE_18BPP_A1665 (0x9 << 2)
+#define WINCON1_BPPMODE_19BPP_A1666 (0xa << 2)
+#define WINCON1_BPPMODE_24BPP_888 (0xb << 2)
+#define WINCON1_BPPMODE_24BPP_A1887 (0xc << 2)
+#define WINCON1_BPPMODE_25BPP_A1888 (0xd << 2)
+#define WINCON1_BPPMODE_28BPP_A4888 (0xd << 2)
+#define WINCON1_ALPHA_SEL (1 << 1)
+
+/* S5PV210 */
+#define SHADOWCON 0x34
+#define SHADOWCON_WINx_PROTECT(_win) (1 << (10 + (_win)))
+/* DMA channels (all windows) */
+#define SHADOWCON_CHx_ENABLE(_win) (1 << (_win))
+/* Local input channels (windows 0-2) */
+#define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win)))
+
+/* VIDOSDx */
+
+#define VIDOSD_BASE 0x40
+#define VIDOSDxA_TOPLEFT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
+#define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11)
+#define VIDOSDxA_TOPLEFT_X_SHIFT 11
+#define VIDOSDxA_TOPLEFT_X_LIMIT 0x7ff
+#define VIDOSDxA_TOPLEFT_X(_x) (((_x) & 0x7ff) << 11)
+
+#define VIDOSDxA_TOPLEFT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
+#define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0)
+#define VIDOSDxA_TOPLEFT_Y_SHIFT 0
+#define VIDOSDxA_TOPLEFT_Y_LIMIT 0x7ff
+#define VIDOSDxA_TOPLEFT_Y(_x) (((_x) & 0x7ff) << 0)
+
+#define VIDOSDxB_BOTRIGHT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
+#define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11)
+#define VIDOSDxB_BOTRIGHT_X_SHIFT 11
+#define VIDOSDxB_BOTRIGHT_X_LIMIT 0x7ff
+#define VIDOSDxB_BOTRIGHT_X(_x) (((_x) & 0x7ff) << 11)
+
+#define VIDOSDxB_BOTRIGHT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
+#define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0)
+#define VIDOSDxB_BOTRIGHT_Y_SHIFT 0
+#define VIDOSDxB_BOTRIGHT_Y_LIMIT 0x7ff
+#define VIDOSDxB_BOTRIGHT_Y(_x) (((_x) & 0x7ff) << 0)
+
+/* For VIDOSD[1..4]C */
+#define VIDISD14C_ALPHA0_R(_x) ((_x) << 20)
+#define VIDISD14C_ALPHA0_G_MASK (0xf << 16)
+#define VIDISD14C_ALPHA0_G_SHIFT 16
+#define VIDISD14C_ALPHA0_G_LIMIT 0xf
+#define VIDISD14C_ALPHA0_G(_x) ((_x) << 16)
+#define VIDISD14C_ALPHA0_B_MASK (0xf << 12)
+#define VIDISD14C_ALPHA0_B_SHIFT 12
+#define VIDISD14C_ALPHA0_B_LIMIT 0xf
+#define VIDISD14C_ALPHA0_B(_x) ((_x) << 12)
+#define VIDISD14C_ALPHA1_R_MASK (0xf << 8)
+#define VIDISD14C_ALPHA1_R_SHIFT 8
+#define VIDISD14C_ALPHA1_R_LIMIT 0xf
+#define VIDISD14C_ALPHA1_R(_x) ((_x) << 8)
+#define VIDISD14C_ALPHA1_G_MASK (0xf << 4)
+#define VIDISD14C_ALPHA1_G_SHIFT 4
+#define VIDISD14C_ALPHA1_G_LIMIT 0xf
+#define VIDISD14C_ALPHA1_G(_x) ((_x) << 4)
+#define VIDISD14C_ALPHA1_B_MASK (0xf << 0)
+#define VIDISD14C_ALPHA1_B_SHIFT 0
+#define VIDISD14C_ALPHA1_B_LIMIT 0xf
+#define VIDISD14C_ALPHA1_B(_x) ((_x) << 0)
+
+#define VIDW_ALPHA 0x021c
+#define VIDW_ALPHA_R(_x) ((_x) << 16)
+#define VIDW_ALPHA_G(_x) ((_x) << 8)
+#define VIDW_ALPHA_B(_x) ((_x) << 0)
+
+/* Video buffer addresses */
+#define VIDW_BUF_START(_buff) (0xA0 + ((_buff) * 8))
+#define VIDW_BUF_START_S(_buff) (0x40A0 + ((_buff) * 8))
+#define VIDW_BUF_START1(_buff) (0xA4 + ((_buff) * 8))
+#define VIDW_BUF_END(_buff) (0xD0 + ((_buff) * 8))
+#define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8))
+#define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4))
+
+#define VIDW_BUF_SIZE_OFFSET_E(_x) ((((_x) & 0x2000) >> 13) << 27)
+#define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13)
+#define VIDW_BUF_SIZE_OFFSET_SHIFT 13
+#define VIDW_BUF_SIZE_OFFSET_LIMIT 0x1fff
+#define VIDW_BUF_SIZE_OFFSET(_x) (((_x) & 0x1fff) << 13)
+
+#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x) ((((_x) & 0x2000) >> 13) << 26)
+#define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0)
+#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT 0
+#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT 0x1fff
+#define VIDW_BUF_SIZE_PAGEWIDTH(_x) (((_x) & 0x1fff) << 0)
+
+/* Interrupt controls and status */
+
+#define VIDINTCON0 0x130
+#define VIDINTCON0_FIFOINTERVAL_MASK (0x3f << 20)
+#define VIDINTCON0_FIFOINTERVAL_SHIFT 20
+#define VIDINTCON0_FIFOINTERVAL_LIMIT 0x3f
+#define VIDINTCON0_FIFOINTERVAL(_x) ((_x) << 20)
+
+#define VIDINTCON0_INT_SYSMAINCON (1 << 19)
+#define VIDINTCON0_INT_SYSSUBCON (1 << 18)
+#define VIDINTCON0_INT_I80IFDONE (1 << 17)
+
+#define VIDINTCON0_FRAMESEL0_MASK (0x3 << 15)
+#define VIDINTCON0_FRAMESEL0_SHIFT 15
+#define VIDINTCON0_FRAMESEL0_BACKPORCH (0x0 << 15)
+#define VIDINTCON0_FRAMESEL0_VSYNC (0x1 << 15)
+#define VIDINTCON0_FRAMESEL0_ACTIVE (0x2 << 15)
+#define VIDINTCON0_FRAMESEL0_FRONTPORCH (0x3 << 15)
+
+#define VIDINTCON0_FRAMESEL1 (1 << 13)
+#define VIDINTCON0_FRAMESEL1_MASK (0x3 << 13)
+#define VIDINTCON0_FRAMESEL1_NONE (0x0 << 13)
+#define VIDINTCON0_FRAMESEL1_BACKPORCH (0x1 << 13)
+#define VIDINTCON0_FRAMESEL1_VSYNC (0x2 << 13)
+#define VIDINTCON0_FRAMESEL1_FRONTPORCH (0x3 << 13)
+
+#define VIDINTCON0_INT_FRAME (1 << 12)
+#define VIDINTCON0_FIFIOSEL_MASK (0x7f << 5)
+#define VIDINTCON0_FIFIOSEL_SHIFT 5
+#define VIDINTCON0_FIFIOSEL_WINDOW0 (0x1 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW1 (0x2 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW2 (0x10 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW3 (0x20 << 5)
+#define VIDINTCON0_FIFIOSEL_WINDOW4 (0x40 << 5)
+
+#define VIDINTCON0_FIFOLEVEL_MASK (0x7 << 2)
+#define VIDINTCON0_FIFOLEVEL_SHIFT 2
+#define VIDINTCON0_FIFOLEVEL_TO25PC (0x0 << 2)
+#define VIDINTCON0_FIFOLEVEL_TO50PC (0x1 << 2)
+#define VIDINTCON0_FIFOLEVEL_TO75PC (0x2 << 2)
+#define VIDINTCON0_FIFOLEVEL_EMPTY (0x3 << 2)
+#define VIDINTCON0_FIFOLEVEL_FULL (0x4 << 2)
+
+#define VIDINTCON0_INT_FIFO_MASK (0x3 << 0)
+#define VIDINTCON0_INT_FIFO_SHIFT 0
+#define VIDINTCON0_INT_ENABLE (1 << 0)
+
+#define VIDINTCON1 0x134
+#define VIDINTCON1_INT_I80 (1 << 2)
+#define VIDINTCON1_INT_FRAME (1 << 1)
+#define VIDINTCON1_INT_FIFO (1 << 0)
+
+/* Window colour-key control registers */
+#define WKEYCON 0x140
+
+#define WKEYCON0 0x00
+#define WKEYCON1 0x04
+
+#define WxKEYCON0_KEYBL_EN (1 << 26)
+#define WxKEYCON0_KEYEN_F (1 << 25)
+#define WxKEYCON0_DIRCON (1 << 24)
+#define WxKEYCON0_COMPKEY_MASK (0xffffff << 0)
+#define WxKEYCON0_COMPKEY_SHIFT 0
+#define WxKEYCON0_COMPKEY_LIMIT 0xffffff
+#define WxKEYCON0_COMPKEY(_x) ((_x) << 0)
+#define WxKEYCON1_COLVAL_MASK (0xffffff << 0)
+#define WxKEYCON1_COLVAL_SHIFT 0
+#define WxKEYCON1_COLVAL_LIMIT 0xffffff
+#define WxKEYCON1_COLVAL(_x) ((_x) << 0)
+
+/* Dithering control */
+#define DITHMODE 0x170
+#define DITHMODE_R_POS_MASK (0x3 << 5)
+#define DITHMODE_R_POS_SHIFT 5
+#define DITHMODE_R_POS_8BIT (0x0 << 5)
+#define DITHMODE_R_POS_6BIT (0x1 << 5)
+#define DITHMODE_R_POS_5BIT (0x2 << 5)
+#define DITHMODE_G_POS_MASK (0x3 << 3)
+#define DITHMODE_G_POS_SHIFT 3
+#define DITHMODE_G_POS_8BIT (0x0 << 3)
+#define DITHMODE_G_POS_6BIT (0x1 << 3)
+#define DITHMODE_G_POS_5BIT (0x2 << 3)
+#define DITHMODE_B_POS_MASK (0x3 << 1)
+#define DITHMODE_B_POS_SHIFT 1
+#define DITHMODE_B_POS_8BIT (0x0 << 1)
+#define DITHMODE_B_POS_6BIT (0x1 << 1)
+#define DITHMODE_B_POS_5BIT (0x2 << 1)
+#define DITHMODE_DITH_EN (1 << 0)
+
+/* Window blanking (MAP) */
+#define WINxMAP(_win) (0x180 + ((_win) * 4))
+#define WINxMAP_MAP (1 << 24)
+#define WINxMAP_MAP_COLOUR_MASK (0xffffff << 0)
+#define WINxMAP_MAP_COLOUR_SHIFT 0
+#define WINxMAP_MAP_COLOUR_LIMIT 0xffffff
+#define WINxMAP_MAP_COLOUR(_x) ((_x) << 0)
+
+/* Winodw palette control */
+#define WPALCON 0x1A0
+#define WPALCON_PAL_UPDATE (1 << 9)
+#define WPALCON_W4PAL_16BPP_A555 (1 << 8)
+#define WPALCON_W3PAL_16BPP_A555 (1 << 7)
+#define WPALCON_W2PAL_16BPP_A555 (1 << 6)
+#define WPALCON_W1PAL_MASK (0x7 << 3)
+#define WPALCON_W1PAL_SHIFT 3
+#define WPALCON_W1PAL_25BPP_A888 (0x0 << 3)
+#define WPALCON_W1PAL_24BPP (0x1 << 3)
+#define WPALCON_W1PAL_19BPP_A666 (0x2 << 3)
+#define WPALCON_W1PAL_18BPP_A665 (0x3 << 3)
+#define WPALCON_W1PAL_18BPP (0x4 << 3)
+#define WPALCON_W1PAL_16BPP_A555 (0x5 << 3)
+#define WPALCON_W1PAL_16BPP_565 (0x6 << 3)
+#define WPALCON_W0PAL_MASK (0x7 << 0)
+#define WPALCON_W0PAL_SHIFT 0
+#define WPALCON_W0PAL_25BPP_A888 (0x0 << 0)
+#define WPALCON_W0PAL_24BPP (0x1 << 0)
+#define WPALCON_W0PAL_19BPP_A666 (0x2 << 0)
+#define WPALCON_W0PAL_18BPP_A665 (0x3 << 0)
+#define WPALCON_W0PAL_18BPP (0x4 << 0)
+#define WPALCON_W0PAL_16BPP_A555 (0x5 << 0)
+#define WPALCON_W0PAL_16BPP_565 (0x6 << 0)
+
+/* Blending equation control */
+#define BLENDCON 0x260
+#define BLENDCON_NEW_MASK (1 << 0)
+#define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0)
+#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0)
+
+/* Display port clock control */
+#define DP_MIE_CLKCON 0x27c
+#define DP_MIE_CLK_DISABLE 0x0
+#define DP_MIE_CLK_DP_ENABLE 0x2
+#define DP_MIE_CLK_MIE_ENABLE 0x3
+
+/* Notes on per-window bpp settings
+ *
+ * Value Win0 Win1 Win2 Win3 Win 4
+ * 0000 1(P) 1(P) 1(P) 1(P) 1(P)
+ * 0001 2(P) 2(P) 2(P) 2(P) 2(P)
+ * 0010 4(P) 4(P) 4(P) 4(P) -none-
+ * 0011 8(P) 8(P) -none- -none- -none-
+ * 0100 -none- 8(A232) 8(A232) -none- -none-
+ * 0101 16(565) 16(565) 16(565) 16(565) 16(565)
+ * 0110 -none- 16(A555) 16(A555) 16(A555) 16(A555)
+ * 0111 16(I555) 16(I565) 16(I555) 16(I555) 16(I555)
+ * 1000 18(666) 18(666) 18(666) 18(666) 18(666)
+ * 1001 -none- 18(A665) 18(A665) 18(A665) 16(A665)
+ * 1010 -none- 19(A666) 19(A666) 19(A666) 19(A666)
+ * 1011 24(888) 24(888) 24(888) 24(888) 24(888)
+ * 1100 -none- 24(A887) 24(A887) 24(A887) 24(A887)
+ * 1101 -none- 25(A888) 25(A888) 25(A888) 25(A888)
+ * 1110 -none- -none- -none- -none- -none-
+ * 1111 -none- -none- -none- -none- -none-
+*/
+
+/* FIMD Version 8 register offset definitions */
+#define FIMD_V8_VIDTCON0 0x20010
+#define FIMD_V8_VIDTCON1 0x20014
+#define FIMD_V8_VIDTCON2 0x20018
+#define FIMD_V8_VIDTCON3 0x2001C
+#define FIMD_V8_VIDCON1 0x20004
diff --git a/include/linux/platform_data/video_s3c.h b/include/linux/platform_data/video_s3c.h
old mode 100644
new mode 100755
index dd7747b..48f8687
--- a/include/linux/platform_data/video_s3c.h
+++ b/include/linux/platform_data/video_s3c.h
@@ -23,6 +23,9 @@ struct s3c_fb_pd_win {unsigned short yres;unsigned short virtual_x;unsigned short virtual_y;
+ unsigned short width;
+ unsigned short height;
+
};
tiny4412 linux-4.2 移植(十一)LCD驱动移植相关推荐
- STM32MP157 Linux系统移植开发篇14:Linux内核RGB LCD驱动移植
本文章为<STM32MP157 Linux系统移植开发篇>系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板).stm32mp157是ARM双核,2 ...
- [lcm] Qualcomm平台的显示屏lcd驱动移植步骤
1lk部分 1-1 target_displayc 1-2 oem_panelc 1-3 panel_innont51021b_1200p_videoh 2Kernel 2-1 dsi-panel-b ...
- linux在开发板LCD上显,W35型LCD驱动移植 - linux-2.6.32在mini2440开发板上移植_Linux编程_Linux公社-Linux系统门户网站...
编者注:本移植主要步骤还是按照手册来,里面讲解了一些有用的基础知识.但书册上提供了集中屏幕的方案,我们这里主要就用一种,也就是开发板自带的W35型号.液晶驱动的源程序在src/drivers/vide ...
- Barebox for Tiny6410(LCD驱动移植)
一.目的 熟悉Barebox的Frame buffer框架.LCD驱动的移植和测试命令的编写. 二.主要内容 1.1 为Barebox移植基于Tiny6410的LCD驱动. 1.2 编写lcd命令测试 ...
- linux-2.6.32在mini2440开发板上移植 ---W35型LCD驱动移植
转载:http://blog.csdn.net/viewsky11/article/details/11846359 编者注:本移植主要步骤还是按照手册来,里面讲解了一些有用的基础知识.但书册上提供了 ...
- LCD驱动移植之开机logo
移植环境 BootLoader:u-boot-1.1.6 kernel:linux-2.6.30.4 CPU:s3c2440 开发板:TQ2440 LCD:TFT480*272 参考资料:<天嵌 ...
- rtthread工业使用_RT-Thread三探--LCD驱动移植(使用GUI Engine)
既网络之后又一个比较重要的功能--GUI 对于RT-Thread使用的GUI我还没有什么概念,本文只是针对LCD驱动部分的移植,并使用GUI运行本身提供的demo样例. 当然还是和ETH一样,在STM ...
- 基于正点原子F103精英板和CubeIDE的Hal库LCD驱动移植(从零开始)
最近在学习王维波老师的<STM32Cube高效开发教程>,王老师移植的是普中科技的驱动,而我手动移植了一下正点原子的lcd驱动,看了网上的诸多教程,有的博客存在一些bug,于是乎手动整理了 ...
- LCD驱动移植(二)
LCD驱动的话会在MINI2440里是向Plaform注册的一个驱动 Plaform的话可以在网上查查这方面的资料,主要要注意这两个函数,如下: (1)platform_device_register ...
- mtk平台lcd驱动移植
mtk平台lcd驱动分为两个部分:lk和kernel.两部分基本流程相同,除了GPIO操作及头文件. 1. lk:需要修改的目录 vendor/mediatek/proprietary/bootabl ...
最新文章
- 【linux】Valgrind工具集详解(二):入门
- 三星15TB固态硬盘开卖 售价高达10000美元
- 大一java实训报告1500字_从800字小作文,到3000字小论文你用了多久? | 校媒FM
- JAVA String 相加编译器发生了什么?
- 【云计算 Hadoop】Hadoop 版本 生态圈 MapReduce模型
- 《快乐编程大本营》java语言训练班-第4课:java流程控制
- MTK:oemlock介绍
- nodejs实现的高性能服务器编程,使用NodeJS搭建自己的接口服务器,提交APP的开发效率...
- linux lib64被改名,问题解决:Centos误将/lib64更改为lib64.bak
- centos5.5中安装mysql5.5.3
- 第五十五期:MongoDB数据库误删后的恢复
- chrome扩展之3:一步步跟我学开发一个表单填写扩展
- 克拉克拉(KilaKila):大规模实时计算平台架构实战 1
- 发布了!2020 年 AI 人才发展报告,最高补助 1000 万!
- LeetCode 135. 分发糖果(贪心算法)
- 数据库面试题之PL/SQL面试题
- Apache+tomcat配置集群(1)
- 怎么在Linux上抓包分析
- 高校校园网络设计与实现
- Android 百度地图--定位、周边搜索