cregit-Linux how code gets into the kernel

Release 4.11 drivers/video/fbdev/amba-clcd-versatile.c

#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/platform_data/video-clcd-versatile.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/bitops.h>
#include "amba-clcd-versatile.h"


static struct clcd_panel vga = {
	.mode		= {
		.name		= "VGA",
		.refresh	= 60,
		.xres		= 640,
		.yres		= 480,
		.pixclock	= 39721,
		.left_margin	= 40,
		.right_margin	= 24,
		.upper_margin	= 32,
		.lower_margin	= 11,
		.hsync_len	= 96,
		.vsync_len	= 2,
		.sync		= 0,
		.vmode		= FB_VMODE_NONINTERLACED,
        },
	.width		= -1,
	.height		= -1,
	.tim2		= TIM2_BCD | TIM2_IPC,
	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
	.caps		= CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
	.bpp		= 16,
};


static struct clcd_panel xvga = {
	.mode		= {
		.name		= "XVGA",
		.refresh	= 60,
		.xres		= 1024,
		.yres		= 768,
		.pixclock	= 15748,
		.left_margin	= 152,
		.right_margin	= 48,
		.upper_margin	= 23,
		.lower_margin	= 3,
		.hsync_len	= 104,
		.vsync_len	= 4,
		.sync		= 0,
		.vmode		= FB_VMODE_NONINTERLACED,
        },
	.width		= -1,
	.height		= -1,
	.tim2		= TIM2_BCD | TIM2_IPC,
	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
	.caps		= CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
	.bpp		= 16,
};

/* Sanyo TM38QV67A02A - 3.8 inch QVGA (320x240) Color TFT */

static struct clcd_panel sanyo_tm38qv67a02a = {
	.mode		= {
		.name		= "Sanyo TM38QV67A02A",
		.refresh	= 116,
		.xres		= 320,
		.yres		= 240,
		.pixclock	= 100000,
		.left_margin	= 6,
		.right_margin	= 6,
		.upper_margin	= 5,
		.lower_margin	= 5,
		.hsync_len	= 6,
		.vsync_len	= 6,
		.sync		= 0,
		.vmode		= FB_VMODE_NONINTERLACED,
        },
	.width		= -1,
	.height		= -1,
	.tim2		= TIM2_BCD,
	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
	.caps		= CLCD_CAP_5551,
	.bpp		= 16,
};


static struct clcd_panel sanyo_2_5_in = {
	.mode		= {
		.name		= "Sanyo QVGA Portrait",
		.refresh	= 116,
		.xres		= 240,
		.yres		= 320,
		.pixclock	= 100000,
		.left_margin	= 20,
		.right_margin	= 10,
		.upper_margin	= 2,
		.lower_margin	= 2,
		.hsync_len	= 10,
		.vsync_len	= 2,
		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
		.vmode		= FB_VMODE_NONINTERLACED,
        },
	.width		= -1,
	.height		= -1,
	.tim2		= TIM2_IVS | TIM2_IHS | TIM2_IPC,
	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
	.caps		= CLCD_CAP_5551,
	.bpp		= 16,
};

/* Epson L2F50113T00 - 2.2 inch 176x220 Color TFT */

static struct clcd_panel epson_l2f50113t00 = {
	.mode		= {
		.name		= "Epson L2F50113T00",
		.refresh	= 390,
		.xres		= 176,
		.yres		= 220,
		.pixclock	= 62500,
		.left_margin	= 3,
		.right_margin	= 2,
		.upper_margin	= 1,
		.lower_margin	= 0,
		.hsync_len	= 3,
		.vsync_len	= 2,
		.sync		= 0,
		.vmode		= FB_VMODE_NONINTERLACED,
        },
	.width		= -1,
	.height		= -1,
	.tim2		= TIM2_BCD | TIM2_IPC,
	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
	.caps		= CLCD_CAP_5551,
	.bpp		= 16,
};


static struct clcd_panel *panels[] = {
	&vga,
	&xvga,
	&sanyo_tm38qv67a02a,
	&sanyo_2_5_in,
	&epson_l2f50113t00,
};


struct clcd_panel *versatile_clcd_get_panel(const char *name) { int i; for (i = 0; i < ARRAY_SIZE(panels); i++) if (strcmp(panels[i]->mode.name, name) == 0) break; if (i < ARRAY_SIZE(panels)) return panels[i]; pr_err("CLCD: couldn't get parameters for panel %s\n", name); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Russell King75100.00%1100.00%
Total75100.00%1100.00%


int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize) { dma_addr_t dma; fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, framesize, &dma, GFP_KERNEL); if (!fb->fb.screen_base) { pr_err("CLCD: unable to map framebuffer\n"); return -ENOMEM; } fb->fb.fix.smem_start = dma; fb->fb.fix.smem_len = framesize; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Russell King8298.80%150.00%
Luis R. Rodriguez11.20%150.00%
Total83100.00%2100.00%


int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma) { return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base, fb->fb.fix.smem_start, fb->fb.fix.smem_len); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King4998.00%150.00%
Luis R. Rodriguez12.00%150.00%
Total50100.00%2100.00%


void versatile_clcd_remove_dma(struct clcd_fb *fb) { dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base, fb->fb.fix.smem_start); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King4197.62%150.00%
Luis R. Rodriguez12.38%150.00%
Total42100.00%2100.00%

#ifdef CONFIG_OF static struct regmap *versatile_syscon_map; static struct regmap *versatile_ib2_map; /* * We detect the different syscon types from the compatible strings. */ enum versatile_clcd { INTEGRATOR_CLCD_CM, VERSATILE_CLCD, REALVIEW_CLCD_EB, REALVIEW_CLCD_PB1176, REALVIEW_CLCD_PB11MP, REALVIEW_CLCD_PBA8, REALVIEW_CLCD_PBX, }; static const struct of_device_id versatile_clcd_of_match[] = { { .compatible = "arm,core-module-integrator", .data = (void *)INTEGRATOR_CLCD_CM, }, { .compatible = "arm,versatile-sysreg", .data = (void *)VERSATILE_CLCD, }, { .compatible = "arm,realview-eb-syscon", .data = (void *)REALVIEW_CLCD_EB, }, { .compatible = "arm,realview-pb1176-syscon", .data = (void *)REALVIEW_CLCD_PB1176, }, { .compatible = "arm,realview-pb11mp-syscon", .data = (void *)REALVIEW_CLCD_PB11MP, }, { .compatible = "arm,realview-pba8-syscon", .data = (void *)REALVIEW_CLCD_PBA8, }, { .compatible = "arm,realview-pbx-syscon", .data = (void *)REALVIEW_CLCD_PBX, }, {}, }; /* * Core module CLCD control on the Integrator/CP, bits * 8 thru 19 of the CM_CONTROL register controls a bunch * of CLCD settings. */ #define INTEGRATOR_HDR_CTRL_OFFSET 0x0C #define INTEGRATOR_CLCD_LCDBIASEN BIT(8) #define INTEGRATOR_CLCD_LCDBIASUP BIT(9) #define INTEGRATOR_CLCD_LCDBIASDN BIT(10) /* Bits 11,12,13 controls the LCD type */ #define INTEGRATOR_CLCD_LCDMUX_MASK (BIT(11)|BIT(12)|BIT(13)) #define INTEGRATOR_CLCD_LCDMUX_LCD24 BIT(11) #define INTEGRATOR_CLCD_LCDMUX_VGA565 BIT(12) #define INTEGRATOR_CLCD_LCDMUX_SHARP (BIT(11)|BIT(12)) #define INTEGRATOR_CLCD_LCDMUX_VGA555 BIT(13) #define INTEGRATOR_CLCD_LCDMUX_VGA24 (BIT(11)|BIT(12)|BIT(13)) #define INTEGRATOR_CLCD_LCD0_EN BIT(14) #define INTEGRATOR_CLCD_LCD1_EN BIT(15) /* R/L flip on Sharp */ #define INTEGRATOR_CLCD_LCD_STATIC1 BIT(16) /* U/D flip on Sharp */ #define INTEGRATOR_CLCD_LCD_STATIC2 BIT(17) /* No connection on Sharp */ #define INTEGRATOR_CLCD_LCD_STATIC BIT(18) /* 0 = 24bit VGA, 1 = 18bit VGA */ #define INTEGRATOR_CLCD_LCD_N24BITEN BIT(19) #define INTEGRATOR_CLCD_MASK (INTEGRATOR_CLCD_LCDBIASEN | \ INTEGRATOR_CLCD_LCDBIASUP | \ INTEGRATOR_CLCD_LCDBIASDN | \ INTEGRATOR_CLCD_LCDMUX_MASK | \ INTEGRATOR_CLCD_LCD0_EN | \ INTEGRATOR_CLCD_LCD1_EN | \ INTEGRATOR_CLCD_LCD_STATIC1 | \ INTEGRATOR_CLCD_LCD_STATIC2 | \ INTEGRATOR_CLCD_LCD_STATIC | \ INTEGRATOR_CLCD_LCD_N24BITEN)
static void integrator_clcd_enable(struct clcd_fb *fb) { struct fb_var_screeninfo *var = &fb->fb.var; u32 val; dev_info(&fb->dev->dev, "enable Integrator CLCD connectors\n"); /* FIXME: really needed? */ val = INTEGRATOR_CLCD_LCD_STATIC1 | INTEGRATOR_CLCD_LCD_STATIC2 | INTEGRATOR_CLCD_LCD0_EN | INTEGRATOR_CLCD_LCD1_EN; if (var->bits_per_pixel <= 8 || (var->bits_per_pixel == 16 && var->green.length == 5)) /* Pseudocolor, RGB555, BGR555 */ val |= INTEGRATOR_CLCD_LCDMUX_VGA555; else if (fb->fb.var.bits_per_pixel <= 16) /* truecolor RGB565 */ val |= INTEGRATOR_CLCD_LCDMUX_VGA565; else val = 0; /* no idea for this, don't trust the docs */ regmap_update_bits(versatile_syscon_map, INTEGRATOR_HDR_CTRL_OFFSET, INTEGRATOR_CLCD_MASK, val); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij113100.00%2100.00%
Total113100.00%2100.00%

/* * This configuration register in the Versatile and RealView * family is uniformly present but appears more and more * unutilized starting with the RealView series. */ #define SYS_CLCD 0x50 #define SYS_CLCD_MODE_MASK (BIT(0)|BIT(1)) #define SYS_CLCD_MODE_888 0 #define SYS_CLCD_MODE_5551 BIT(0) #define SYS_CLCD_MODE_565_R_LSB BIT(1) #define SYS_CLCD_MODE_565_B_LSB (BIT(0)|BIT(1)) #define SYS_CLCD_CONNECTOR_MASK (BIT(2)|BIT(3)|BIT(4)|BIT(5)) #define SYS_CLCD_NLCDIOON BIT(2) #define SYS_CLCD_VDDPOSSWITCH BIT(3) #define SYS_CLCD_PWR3V5SWITCH BIT(4) #define SYS_CLCD_VDDNEGSWITCH BIT(5) #define SYS_CLCD_TSNSS BIT(6) /* touchscreen enable */ #define SYS_CLCD_SSPEXP BIT(7) /* SSP expansion enable */ /* The Versatile can detect the connected panel type */ #define SYS_CLCD_CLCDID_MASK (BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)) #define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8) #define SYS_CLCD_ID_SHARP_8_4 (0x01 << 8) #define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8) #define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8) #define SYS_CLCD_ID_VGA (0x1f << 8) #define SYS_CLCD_TSNDAV BIT(13) /* data ready from TS */ /* IB2 control register for the Versatile daughterboard */ #define IB2_CTRL 0x00 #define IB2_CTRL_LCD_SD BIT(1) /* 1 = shut down LCD */ #define IB2_CTRL_LCD_BL_ON BIT(0) #define IB2_CTRL_LCD_MASK (BIT(0)|BIT(1))
static void versatile_clcd_disable(struct clcd_fb *fb) { dev_info(&fb->dev->dev, "disable Versatile CLCD connectors\n"); regmap_update_bits(versatile_syscon_map, SYS_CLCD, SYS_CLCD_CONNECTOR_MASK, 0); /* If we're on an IB2 daughterboard, turn off display */ if (versatile_ib2_map) { dev_info(&fb->dev->dev, "disable IB2 display\n"); regmap_update_bits(versatile_ib2_map, IB2_CTRL, IB2_CTRL_LCD_MASK, IB2_CTRL_LCD_SD); } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij64100.00%1100.00%
Total64100.00%1100.00%


static void versatile_clcd_enable(struct clcd_fb *fb) { struct fb_var_screeninfo *var = &fb->fb.var; u32 val = 0; dev_info(&fb->dev->dev, "enable Versatile CLCD connectors\n"); switch (var->green.length) { case 5: val |= SYS_CLCD_MODE_5551; break; case 6: if (var->red.offset == 0) val |= SYS_CLCD_MODE_565_R_LSB; else val |= SYS_CLCD_MODE_565_B_LSB; break; case 8: val |= SYS_CLCD_MODE_888; break; } /* Set up the MUX */ regmap_update_bits(versatile_syscon_map, SYS_CLCD, SYS_CLCD_MODE_MASK, val); /* Then enable the display */ regmap_update_bits(versatile_syscon_map, SYS_CLCD, SYS_CLCD_CONNECTOR_MASK, SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH); /* If we're on an IB2 daughterboard, turn on display */ if (versatile_ib2_map) { dev_info(&fb->dev->dev, "enable IB2 display\n"); regmap_update_bits(versatile_ib2_map, IB2_CTRL, IB2_CTRL_LCD_MASK, IB2_CTRL_LCD_BL_ON); } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij145100.00%1100.00%
Total145100.00%1100.00%


static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs) { clcdfb_decode(fb, regs); /* Always clear BGR for RGB565: we do the routing externally */ if (fb->fb.var.green.length == 6) regs->cntl &= ~CNTL_BGR; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij45100.00%1100.00%
Total45100.00%1100.00%


static void realview_clcd_disable(struct clcd_fb *fb) { dev_info(&fb->dev->dev, "disable RealView CLCD connectors\n"); regmap_update_bits(versatile_syscon_map, SYS_CLCD, SYS_CLCD_CONNECTOR_MASK, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij34100.00%1100.00%
Total34100.00%1100.00%


static void realview_clcd_enable(struct clcd_fb *fb) { dev_info(&fb->dev->dev, "enable RealView CLCD connectors\n"); regmap_update_bits(versatile_syscon_map, SYS_CLCD, SYS_CLCD_CONNECTOR_MASK, SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij36100.00%1100.00%
Total36100.00%1100.00%

struct versatile_panel { u32 id; char *compatible; bool ib2; }; static const struct versatile_panel versatile_panels[] = { { .id = SYS_CLCD_ID_VGA, .compatible = "VGA", }, { .id = SYS_CLCD_ID_SANYO_3_8, .compatible = "sanyo,tm38qv67a02a", }, { .id = SYS_CLCD_ID_SHARP_8_4, .compatible = "sharp,lq084v1dg21", }, { .id = SYS_CLCD_ID_EPSON_2_2, .compatible = "epson,l2f50113t00", }, { .id = SYS_CLCD_ID_SANYO_2_5, .compatible = "sanyo,alr252rgt", .ib2 = true, }, };
static void versatile_panel_probe(struct device *dev, struct device_node *panel) { struct versatile_panel const *vpanel = NULL; u32 val; int ret; int i; /* * The Versatile CLCD has a panel auto-detection mechanism. * We use this and look for the compatible panel in the * device tree. */ ret = regmap_read(versatile_syscon_map, SYS_CLCD, &val); if (ret) { dev_err(dev, "cannot read CLCD syscon register\n"); return; } val &= SYS_CLCD_CLCDID_MASK; /* First find corresponding panel information */ for (i = 0; i < ARRAY_SIZE(versatile_panels); i++) { vpanel = &versatile_panels[i]; if (val == vpanel->id) { dev_err(dev, "autodetected panel \"%s\"\n", vpanel->compatible); break; } } if (i == ARRAY_SIZE(versatile_panels)) { dev_err(dev, "could not auto-detect panel\n"); return; } if (!of_device_is_compatible(panel, vpanel->compatible)) dev_err(dev, "panel in DT is not compatible with the " "auto-detected panel, continuing anyway\n"); /* * If we have a Sanyo 2.5" port * that we're running on an IB2 and proceed to look for the * IB2 syscon regmap. */ if (!vpanel->ib2) return; versatile_ib2_map = syscon_regmap_lookup_by_compatible( "arm,versatile-ib2-syscon"); if (IS_ERR(versatile_ib2_map)) { dev_err(dev, "could not locate IB2 control register\n"); versatile_ib2_map = NULL; return; } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij18899.47%150.00%
Vladimir Zapolskiy10.53%150.00%
Total189100.00%2100.00%


int versatile_clcd_init_panel(struct clcd_fb *fb, struct device_node *panel) { const struct of_device_id *clcd_id; enum versatile_clcd versatile_clcd_type; struct device_node *np; struct regmap *map; struct device *dev = &fb->dev->dev; np = of_find_matching_node_and_match(NULL, versatile_clcd_of_match, &clcd_id); if (!np) { /* Vexpress does not have this */ return 0; } versatile_clcd_type = (enum versatile_clcd)clcd_id->data; map = syscon_node_to_regmap(np); if (IS_ERR(map)) { dev_err(dev, "no Versatile syscon regmap\n"); return PTR_ERR(map); } switch (versatile_clcd_type) { case INTEGRATOR_CLCD_CM: versatile_syscon_map = map; fb->board->enable = integrator_clcd_enable; /* Override the caps, we have only these */ fb->board->caps = CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888; dev_info(dev, "set up callbacks for Integrator PL110\n"); break; case VERSATILE_CLCD: versatile_syscon_map = map; fb->board->enable = versatile_clcd_enable; fb->board->disable = versatile_clcd_disable; fb->board->decode = versatile_clcd_decode; versatile_panel_probe(dev, panel); dev_info(dev, "set up callbacks for Versatile\n"); break; case REALVIEW_CLCD_EB: case REALVIEW_CLCD_PB1176: case REALVIEW_CLCD_PB11MP: case REALVIEW_CLCD_PBA8: case REALVIEW_CLCD_PBX: versatile_syscon_map = map; fb->board->enable = realview_clcd_enable; fb->board->disable = realview_clcd_disable; dev_info(dev, "set up callbacks for RealView PL111\n"); break; default: dev_info(dev, "unknown Versatile system controller\n"); break; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij24396.43%250.00%
Wei Yongjun72.78%125.00%
Vladimir Zapolskiy20.79%125.00%
Total252100.00%4100.00%

EXPORT_SYMBOL_GPL(versatile_clcd_init_panel); #endif

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Walleij131259.18%444.44%
Russell King88740.01%111.11%
Wei Yongjun70.32%111.11%
Arnd Bergmann50.23%111.11%
Luis R. Rodriguez30.14%111.11%
Vladimir Zapolskiy30.14%111.11%
Total2217100.00%9100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.