cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clcd.h (6971B)


      1/*
      2 * linux/include/asm-arm/hardware/amba_clcd.h -- Integrator LCD panel.
      3 *
      4 * David A Rusling
      5 *
      6 * Copyright (C) 2001 ARM Limited
      7 *
      8 * This file is subject to the terms and conditions of the GNU General Public
      9 * License.  See the file COPYING in the main directory of this archive
     10 * for more details.
     11 */
     12#include <linux/fb.h>
     13#include <linux/amba/clcd-regs.h>
     14
     15enum {
     16	/* individual formats */
     17	CLCD_CAP_RGB444		= (1 << 0),
     18	CLCD_CAP_RGB5551	= (1 << 1),
     19	CLCD_CAP_RGB565		= (1 << 2),
     20	CLCD_CAP_RGB888		= (1 << 3),
     21	CLCD_CAP_BGR444		= (1 << 4),
     22	CLCD_CAP_BGR5551	= (1 << 5),
     23	CLCD_CAP_BGR565		= (1 << 6),
     24	CLCD_CAP_BGR888		= (1 << 7),
     25
     26	/* connection layouts */
     27	CLCD_CAP_444		= CLCD_CAP_RGB444 | CLCD_CAP_BGR444,
     28	CLCD_CAP_5551		= CLCD_CAP_RGB5551 | CLCD_CAP_BGR5551,
     29	CLCD_CAP_565		= CLCD_CAP_RGB565 | CLCD_CAP_BGR565,
     30	CLCD_CAP_888		= CLCD_CAP_RGB888 | CLCD_CAP_BGR888,
     31
     32	/* red/blue ordering */
     33	CLCD_CAP_RGB		= CLCD_CAP_RGB444 | CLCD_CAP_RGB5551 |
     34				  CLCD_CAP_RGB565 | CLCD_CAP_RGB888,
     35	CLCD_CAP_BGR		= CLCD_CAP_BGR444 | CLCD_CAP_BGR5551 |
     36				  CLCD_CAP_BGR565 | CLCD_CAP_BGR888,
     37
     38	CLCD_CAP_ALL		= CLCD_CAP_BGR | CLCD_CAP_RGB,
     39};
     40
     41struct backlight_device;
     42
     43struct clcd_panel {
     44	struct fb_videomode	mode;
     45	signed short		width;	/* width in mm */
     46	signed short		height;	/* height in mm */
     47	u32			tim2;
     48	u32			tim3;
     49	u32			cntl;
     50	u32			caps;
     51	unsigned int		bpp:8,
     52				fixedtimings:1,
     53				grayscale:1;
     54	unsigned int		connector;
     55	struct backlight_device	*backlight;
     56	/*
     57	 * If the B/R lines are switched between the CLCD
     58	 * and the panel we need to know this and not try to
     59	 * compensate with the BGR bit in the control register.
     60	 */
     61	bool			bgr_connection;
     62};
     63
     64struct clcd_regs {
     65	u32			tim0;
     66	u32			tim1;
     67	u32			tim2;
     68	u32			tim3;
     69	u32			cntl;
     70	unsigned long		pixclock;
     71};
     72
     73struct clcd_fb;
     74
     75/*
     76 * the board-type specific routines
     77 */
     78struct clcd_board {
     79	const char *name;
     80
     81	/*
     82	 * Optional.  Hardware capability flags.
     83	 */
     84	u32	caps;
     85
     86	/*
     87	 * Optional.  Check whether the var structure is acceptable
     88	 * for this display.
     89	 */
     90	int	(*check)(struct clcd_fb *fb, struct fb_var_screeninfo *var);
     91
     92	/*
     93	 * Compulsory.  Decode fb->fb.var into regs->*.  In the case of
     94	 * fixed timing, set regs->* to the register values required.
     95	 */
     96	void	(*decode)(struct clcd_fb *fb, struct clcd_regs *regs);
     97
     98	/*
     99	 * Optional.  Disable any extra display hardware.
    100	 */
    101	void	(*disable)(struct clcd_fb *);
    102
    103	/*
    104	 * Optional.  Enable any extra display hardware.
    105	 */
    106	void	(*enable)(struct clcd_fb *);
    107
    108	/*
    109	 * Setup platform specific parts of CLCD driver
    110	 */
    111	int	(*setup)(struct clcd_fb *);
    112
    113	/*
    114	 * mmap the framebuffer memory
    115	 */
    116	int	(*mmap)(struct clcd_fb *, struct vm_area_struct *);
    117
    118	/*
    119	 * Remove platform specific parts of CLCD driver
    120	 */
    121	void	(*remove)(struct clcd_fb *);
    122};
    123
    124struct amba_device;
    125struct clk;
    126
    127/* this data structure describes each frame buffer device we find */
    128struct clcd_fb {
    129	struct fb_info		fb;
    130	struct amba_device	*dev;
    131	struct clk		*clk;
    132	struct clcd_panel	*panel;
    133	struct clcd_board	*board;
    134	void			*board_data;
    135	void __iomem		*regs;
    136	u16			off_ienb;
    137	u16			off_cntl;
    138	u32			clcd_cntl;
    139	u32			cmap[16];
    140	bool			clk_enabled;
    141};
    142
    143static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
    144{
    145	struct fb_var_screeninfo *var = &fb->fb.var;
    146	u32 val, cpl;
    147
    148	/*
    149	 * Program the CLCD controller registers and start the CLCD
    150	 */
    151	val = ((var->xres / 16) - 1) << 2;
    152	val |= (var->hsync_len - 1) << 8;
    153	val |= (var->right_margin - 1) << 16;
    154	val |= (var->left_margin - 1) << 24;
    155	regs->tim0 = val;
    156
    157	val = var->yres;
    158	if (fb->panel->cntl & CNTL_LCDDUAL)
    159		val /= 2;
    160	val -= 1;
    161	val |= (var->vsync_len - 1) << 10;
    162	val |= var->lower_margin << 16;
    163	val |= var->upper_margin << 24;
    164	regs->tim1 = val;
    165
    166	val = fb->panel->tim2;
    167	val |= var->sync & FB_SYNC_HOR_HIGH_ACT  ? 0 : TIM2_IHS;
    168	val |= var->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : TIM2_IVS;
    169
    170	cpl = var->xres_virtual;
    171	if (fb->panel->cntl & CNTL_LCDTFT)	  /* TFT */
    172		/* / 1 */;
    173	else if (!var->grayscale)		  /* STN color */
    174		cpl = cpl * 8 / 3;
    175	else if (fb->panel->cntl & CNTL_LCDMONO8) /* STN monochrome, 8bit */
    176		cpl /= 8;
    177	else					  /* STN monochrome, 4bit */
    178		cpl /= 4;
    179
    180	regs->tim2 = val | ((cpl - 1) << 16);
    181
    182	regs->tim3 = fb->panel->tim3;
    183
    184	val = fb->panel->cntl;
    185	if (var->grayscale)
    186		val |= CNTL_LCDBW;
    187
    188	if (fb->panel->caps && fb->board->caps && var->bits_per_pixel >= 16) {
    189		/*
    190		 * if board and panel supply capabilities, we can support
    191		 * changing BGR/RGB depending on supplied parameters. Here
    192		 * we switch to what the framebuffer is providing if need
    193		 * be, so if the framebuffer is BGR but the display connection
    194		 * is RGB (first case) we switch it around. Vice versa mutatis
    195		 * mutandis if the framebuffer is RGB but the display connection
    196		 * is BGR, we flip it around.
    197		 */
    198		if (var->red.offset == 0)
    199			val &= ~CNTL_BGR;
    200		else
    201			val |= CNTL_BGR;
    202		if (fb->panel->bgr_connection)
    203			val ^= CNTL_BGR;
    204	}
    205
    206	switch (var->bits_per_pixel) {
    207	case 1:
    208		val |= CNTL_LCDBPP1;
    209		break;
    210	case 2:
    211		val |= CNTL_LCDBPP2;
    212		break;
    213	case 4:
    214		val |= CNTL_LCDBPP4;
    215		break;
    216	case 8:
    217		val |= CNTL_LCDBPP8;
    218		break;
    219	case 16:
    220		/*
    221		 * PL110 cannot choose between 5551 and 565 modes in its
    222		 * control register.  It is possible to use 565 with
    223		 * custom external wiring.
    224		 */
    225		if (amba_part(fb->dev) == 0x110 ||
    226		    var->green.length == 5)
    227			val |= CNTL_LCDBPP16;
    228		else if (var->green.length == 6)
    229			val |= CNTL_LCDBPP16_565;
    230		else
    231			val |= CNTL_LCDBPP16_444;
    232		break;
    233	case 32:
    234		val |= CNTL_LCDBPP24;
    235		break;
    236	}
    237
    238	regs->cntl = val;
    239	regs->pixclock = var->pixclock;
    240}
    241
    242static inline int clcdfb_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
    243{
    244	var->xres_virtual = var->xres = (var->xres + 15) & ~15;
    245	var->yres_virtual = var->yres = (var->yres + 1) & ~1;
    246
    247#define CHECK(e,l,h) (var->e < l || var->e > h)
    248	if (CHECK(right_margin, (5+1), 256) ||	/* back porch */
    249	    CHECK(left_margin, (5+1), 256) ||	/* front porch */
    250	    CHECK(hsync_len, (5+1), 256) ||
    251	    var->xres > 4096 ||
    252	    var->lower_margin > 255 ||		/* back porch */
    253	    var->upper_margin > 255 ||		/* front porch */
    254	    var->vsync_len > 32 ||
    255	    var->yres > 1024)
    256		return -EINVAL;
    257#undef CHECK
    258
    259	/* single panel mode: PCD = max(PCD, 1) */
    260	/* dual panel mode: PCD = max(PCD, 5) */
    261
    262	/*
    263	 * You can't change the grayscale setting, and
    264	 * we can only do non-interlaced video.
    265	 */
    266	if (var->grayscale != fb->fb.var.grayscale ||
    267	    (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
    268		return -EINVAL;
    269
    270#define CHECK(e) (var->e != fb->fb.var.e)
    271	if (fb->panel->fixedtimings &&
    272	    (CHECK(xres)		||
    273	     CHECK(yres)		||
    274	     CHECK(bits_per_pixel)	||
    275	     CHECK(pixclock)		||
    276	     CHECK(left_margin)		||
    277	     CHECK(right_margin)	||
    278	     CHECK(upper_margin)	||
    279	     CHECK(lower_margin)	||
    280	     CHECK(hsync_len)		||
    281	     CHECK(vsync_len)		||
    282	     CHECK(sync)))
    283		return -EINVAL;
    284#undef CHECK
    285
    286	var->nonstd = 0;
    287	var->accel_flags = 0;
    288
    289	return 0;
    290}