* arch/arm/src/sama5/sam_lcd.c
*
* Copyright (C) 2013-2014, 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* The Atmel sample code has a BSD compatible license that requires this
* copyright notice:
*
* Copyright (c) 2012, Atmel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the names NuttX nor Atmel nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
* SAMA5D3 Series Data Sheet
* Atmel NoOS sample code.
*/
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <inttypes.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/video/fb.h>
#include <nuttx/kmalloc.h>
#include <arch/board/board.h>
#include "arm_internal.h"
#include "hardware/sam_lcdc.h"
#include "hardware/sam_pinmap.h"
#include "sam_pio.h"
#include "sam_periphclks.h"
#include "sam_memories.h"
#include "sam_lcd.h"
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_SAMA5_LCDC_DEFBACKLIGHT
# define CONFIG_SAMA5_LCDC_DEFBACKLIGHT 0xf0
#endif
#define SAMA5_LCDC_BACKLIGHT_OFF 0x00
#if defined(CONFIG_FB_HWCURSOR) && !defined(CONFIG_SAMA5_LCDC_HCR)
# error CONFIG_FB_HWCURSOR=y but CONFIG_SAMA5_LCDC_HCR=n
#elif !defined(CONFIG_FB_HWCURSOR) && defined(CONFIG_SAMA5_LCDC_HCR)
# error CONFIG_FB_HWCURSOR=n but CONFIG_SAMA5_LCDC_HCR=y
#endif
#if defined(CONFIG_SAMA5_LCDC_BASE_RGB444)
# define SAMA5_LCDC_BASE_BPP 16
# define SAMA5_LCDC_BASE_COLOR_FMT FB_FMT_RGB12_444
#elif defined(CONFIG_SAMA5_LCDC_BASE_ARGB4444)
# define SAMA5_LCDC_BASE_BPP 16
# define SAMA5_LCDC_BASE_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_BASE_RGBA4444)
# define SAMA5_LCDC_BASE_BPP 16
# define SAMA5_LCDC_BASE_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_BASE_RGB565)
# define SAMA5_LCDC_BASE_BPP 16
# define SAMA5_LCDC_BASE_COLOR_FMT FB_FMT_RGB16_565
#elif defined(CONFIG_SAMA5_LCDC_BASE_TRGB1555)
# define SAMA5_LCDC_BASE_BPP 16
# define SAMA5_LCDC_BASE_COLOR_FMT FB_FMT_RGBT16
#elif defined(CONFIG_SAMA5_LCDC_BASE_RGB666)
# define SAMA5_LCDC_BASE_BPP 32
# define SAMA5_LCDC_BASE_COLOR_FMT RGB666
#elif defined(CONFIG_SAMA5_LCDC_BASE_RGB666P)
# define SAMA5_LCDC_BASE_BPP 24
# define SAMA5_LCDC_BASE_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_BASE_TRGB1666)
# define SAMA5_LCDC_BASE_BPP 32
# define SAMA5_LCDC_BASE_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_BASE_TRGBP)
# define SAMA5_LCDC_BASE_BPP 24
# define SAMA5_LCDC_BASE_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_BASE_RGB888P)
# define SAMA5_LCDC_BASE_BPP 24
# define SAMA5_LCDC_BASE_COLOR_FMT FB_FMT_RGB24
#elif defined(CONFIG_SAMA5_LCDC_BASE_RGB888)
# define SAMA5_LCDC_BASE_BPP 32
# define SAMA5_LCDC_BASE_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_BASE_TRGB1888)
# define SAMA5_LCDC_BASE_BPP 32
# define SAMA5_LCDC_BASE_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_BASE_ARGB8888)
# define SAMA5_LCDC_BASE_BPP 32
# define SAMA5_LCDC_BASE_COLOR_FMT FB_FMT_RGBA32
#elif defined(CONFIG_SAMA5_LCDC_BASE_RGBA8888)
# define SAMA5_LCDC_BASE_BPP 32
# define SAMA5_LCDC_BASE_COLOR_FMT FB_FMT_RGBA32
#else
# error Undefined or unrecognized base color format
#endif
#if defined(CONFIG_SAMA5_LCDC_OVR1_RGB444)
# define SAMA5_LCDC_OVR1_BPP 16
# define SAMA5_LCDC_OVR1_COLOR_FMT FB_FMT_RGB12_444
#elif defined(CONFIG_SAMA5_LCDC_OVR1_ARGB4444)
# define SAMA5_LCDC_OVR1_BPP 16
# define SAMA5_LCDC_OVR1_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR1_RGBA4444)
# define SAMA5_LCDC_OVR1_BPP 16
# define SAMA5_LCDC_OVR1_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR1_RGB565)
# define SAMA5_LCDC_OVR1_BPP 16
# define SAMA5_LCDC_OVR1_COLOR_FMT FB_FMT_RGB16_565
#elif defined(CONFIG_SAMA5_LCDC_OVR1_TRGB1555)
# define SAMA5_LCDC_OVR1_BPP 16
# define SAMA5_LCDC_OVR1_COLOR_FMT FB_FMT_RGBT16
#elif defined(CONFIG_SAMA5_LCDC_OVR1_RGB666)
# define SAMA5_LCDC_OVR1_BPP 32
# define SAMA5_LCDC_OVR1_COLOR_FMT RGB666
#elif defined(CONFIG_SAMA5_LCDC_OVR1_RGB666P)
# define SAMA5_LCDC_OVR1_BPP 24
# define SAMA5_LCDC_OVR1_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR1_TRGB1666)
# define SAMA5_LCDC_OVR1_BPP 32
# define SAMA5_LCDC_OVR1_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR1_TRGBP)
# define SAMA5_LCDC_OVR1_BPP 24
# define SAMA5_LCDC_OVR1_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR1_RGB888P)
# define SAMA5_LCDC_OVR1_BPP 24
# define SAMA5_LCDC_OVR1_COLOR_FMT FB_FMT_RGB24
#elif defined(CONFIG_SAMA5_LCDC_OVR1_RGB888)
# define SAMA5_LCDC_OVR1_BPP 32
# define SAMA5_LCDC_OVR1_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR1_TRGB1888)
# define SAMA5_LCDC_OVR1_BPP 32
# define SAMA5_LCDC_OVR1_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR1_ARGB8888)
# define SAMA5_LCDC_OVR1_BPP 32
# define SAMA5_LCDC_OVR1_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR1_RGBA8888)
# define SAMA5_LCDC_OVR1_BPP 32
# define SAMA5_LCDC_OVR1_COLOR_FMT FB_FMT_RGBA32
#elif defined(CONFIG_SAMA5_LCDC_OVR1)
# error Undefined or unrecognized overlay 1 color format
#endif
#if defined(CONFIG_SAMA5_LCDC_OVR2_RGB444)
# define SAMA5_LCDC_OVR2_BPP 16
# define SAMA5_LCDC_OVR2_COLOR_FMT FB_FMT_RGB12_444
#elif defined(CONFIG_SAMA5_LCDC_OVR2_ARGB4444)
# define SAMA5_LCDC_OVR2_BPP 16
# define SAMA5_LCDC_OVR2_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR2_RGBA4444)
# define SAMA5_LCDC_OVR2_BPP 16
# define SAMA5_LCDC_OVR2_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR2_RGB565)
# define SAMA5_LCDC_OVR2_BPP 16
# define SAMA5_LCDC_OVR2_COLOR_FMT FB_FMT_RGB16_565
#elif defined(CONFIG_SAMA5_LCDC_OVR2_TRGB1555)
# define SAMA5_LCDC_OVR2_BPP 16
# define SAMA5_LCDC_OVR2_COLOR_FMT FB_FMT_RGBT16
#elif defined(CONFIG_SAMA5_LCDC_OVR2_RGB666)
# define SAMA5_LCDC_OVR2_BPP 32
# define SAMA5_LCDC_OVR2_COLOR_FMT RGB666
#elif defined(CONFIG_SAMA5_LCDC_OVR2_RGB666P)
# define SAMA5_LCDC_OVR2_BPP 24
# define SAMA5_LCDC_OVR2_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR2_TRGB1666)
# define SAMA5_LCDC_OVR2_BPP 32
# define SAMA5_LCDC_OVR2_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR2_TRGBP)
# define SAMA5_LCDC_OVR2_BPP 24
# define SAMA5_LCDC_OVR2_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR2_RGB888P)
# define SAMA5_LCDC_OVR2_BPP 24
# define SAMA5_LCDC_OVR2_COLOR_FMT FB_FMT_RGB24
#elif defined(CONFIG_SAMA5_LCDC_OVR2_RGB888)
# define SAMA5_LCDC_OVR2_BPP 32
# define SAMA5_LCDC_OVR2_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR2_TRGB1888)
# define SAMA5_LCDC_OVR2_BPP 32
# define SAMA5_LCDC_OVR2_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR2_ARGB8888)
# define SAMA5_LCDC_OVR2_BPP 32
# define SAMA5_LCDC_OVR2_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_OVR2_RGBA8888)
# define SAMA5_LCDC_OVR2_BPP 32
# define SAMA5_LCDC_OVR2_COLOR_FMT FB_FMT_RGBA32
#elif defined(CONFIG_SAMA5_LCDC_OVR2)
# error Undefined or unrecognized overlay 2 color format
#endif
#if defined(CONFIG_SAMA5_LCDC_HEO_RGB444)
# define SAMA5_LCDC_HEO_BPP 16
# define SAMA5_LCDC_HEO_COLOR_FMT FB_FMT_RGB12_444
#elif defined(CONFIG_SAMA5_LCDC_HEO_ARGB4444)
# define SAMA5_LCDC_HEO_BPP 16
# define SAMA5_LCDC_HEO_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HEO_RGBA4444)
# define SAMA5_LCDC_HEO_BPP 16
# define SAMA5_LCDC_HEO_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HEO_RGB565)
# define SAMA5_LCDC_HEO_BPP 16
# define SAMA5_LCDC_HEO_COLOR_FMT FB_FMT_RGB16_565
#elif defined(CONFIG_SAMA5_LCDC_HEO_TRGB1555)
# define SAMA5_LCDC_HEO_BPP 16
# define SAMA5_LCDC_HEO_COLOR_FMT FB_FMT_RGBT16
#elif defined(CONFIG_SAMA5_LCDC_HEO_RGB666)
# define SAMA5_LCDC_HEO_BPP 32
# define SAMA5_LCDC_HEO_COLOR_FMT RGB666
#elif defined(CONFIG_SAMA5_LCDC_HEO_RGB666P)
# define SAMA5_LCDC_HEO_BPP 24
# define SAMA5_LCDC_HEO_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HEO_TRGB1666)
# define SAMA5_LCDC_HEO_BPP 32
# define SAMA5_LCDC_HEO_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HEO_TRGBP)
# define SAMA5_LCDC_HEO_BPP 24
# define SAMA5_LCDC_HEO_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HEO_RGB888P)
# define SAMA5_LCDC_HEO_BPP 24
# define SAMA5_LCDC_HEO_COLOR_FMT FB_FMT_RGB24
#elif defined(CONFIG_SAMA5_LCDC_HEO_RGB888)
# define SAMA5_LCDC_HEO_BPP 32
# define SAMA5_LCDC_HEO_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HEO_TRGB1888)
# define SAMA5_LCDC_HEO_BPP 32
# define SAMA5_LCDC_HEO_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HEO_ARGB8888)
# define SAMA5_LCDC_HEO_BPP 32
# define SAMA5_LCDC_HEO_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HEO_RGBA8888)
# define SAMA5_LCDC_HEO_BPP 32
# define SAMA5_LCDC_HEO_COLOR_FMT FB_FMT_RGBA32
#elif defined(CONFIG_SAMA5_LCDC_HEO)
# error Undefined or unrecognized HEO color format
#endif
#if defined(CONFIG_SAMA5_LCDC_HCR_RGB444)
# define SAMA5_LCDC_HCR_BPP 16
# define SAMA5_LCDC_HCR_COLOR_FMT FB_FMT_RGB12_444
#elif defined(CONFIG_SAMA5_LCDC_HCR_ARGB4444)
# define SAMA5_LCDC_HCR_BPP 16
# define SAMA5_LCDC_HCR_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HCR_RGBA4444)
# define SAMA5_LCDC_HCR_BPP 16
# define SAMA5_LCDC_HCR_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HCR_RGB565)
# define SAMA5_LCDC_HCR_BPP 16
# define SAMA5_LCDC_HCR_COLOR_FMT FB_FMT_RGB16_565
#elif defined(CONFIG_SAMA5_LCDC_HCR_TRGB1555)
# define SAMA5_LCDC_HCR_BPP 16
# define SAMA5_LCDC_HCR_COLOR_FMT FB_FMT_RGBT16
#elif defined(CONFIG_SAMA5_LCDC_HCR_RGB666)
# define SAMA5_LCDC_HCR_BPP 32
# define SAMA5_LCDC_HCR_COLOR_FMT RGB666
#elif defined(CONFIG_SAMA5_LCDC_HCR_RGB666P)
# define SAMA5_LCDC_HCR_BPP 24
# define SAMA5_LCDC_HCR_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HCR_TRGB1666)
# define SAMA5_LCDC_HCR_BPP 32
# define SAMA5_LCDC_HCR_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HCR_TRGBP)
# define SAMA5_LCDC_HCR_BPP 24
# define SAMA5_LCDC_HCR_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HCR_RGB888P)
# define SAMA5_LCDC_HCR_BPP 24
# define SAMA5_LCDC_HCR_COLOR_FMT FB_FMT_RGB24
#elif defined(CONFIG_SAMA5_LCDC_HCR_RGB888)
# define SAMA5_LCDC_HCR_BPP 32
# define SAMA5_LCDC_HCR_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HCR_TRGB1888)
# define SAMA5_LCDC_HCR_BPP 32
# define SAMA5_LCDC_HCR_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HCR_ARGB8888)
# define SAMA5_LCDC_HCR_BPP 32
# define SAMA5_LCDC_HCR_COLOR_FMT ???
#elif defined(CONFIG_SAMA5_LCDC_HCR_RGBA8888)
# define SAMA5_LCDC_HCR_BPP 32
# define SAMA5_LCDC_HCR_COLOR_FMT FB_FMT_RGBA32
#elif defined(CONFIG_SAMA5_LCDC_HCR)
# error Undefined or unrecognized cursor color format
#endif
#ifndef BOARD_LCDC_WIDTH
# error BOARD_LCDC_WIDTH must be defined in the board.h header file
#endif
#ifndef BOARD_LCDC_HEIGHT
# error BOARD_LCDC_HEIGHT must be defined in the board.h header file
#endif
#if SAMA5_LCDC_BASE_BPP == 16
# define SAMA5_BASE_STRIDE ((BOARD_LCDC_WIDTH * 16 + 7) / 8)
#elif SAMA5_LCDC_BASE_BPP == 24
# define SAMA5_BASE_STRIDE ((BOARD_LCDC_WIDTH * 24 + 7) / 8)
#elif SAMA5_LCDC_BASE_BPP == 32
# define SAMA5_BASE_STRIDE ((BOARD_LCDC_WIDTH * 32 + 7) / 8)
#else
# error Undefined or unrecognized base resolution
#endif
#define SAMA5_BASE_FBSIZE (SAMA5_BASE_STRIDE * BOARD_LCDC_HEIGHT)
#ifdef CONFIG_SAMA5_LCDC_OVR1
# ifndef CONFIG_SAMA5_LCDC_OVR1_MAXWIDTH
# define CONFIG_SAMA5_LCDC_OVR1_MAXWIDTH BOARD_LCDC_WIDTH
# endif
# if CONFIG_SAMA5_LCDC_OVR1_MAXWIDTH > BOARD_LCDC_WIDTH
# error Width of overlay 1 exceeds the width of the display
# endif
# ifndef CONFIG_SAMA5_LCDC_OVR1_MAXHEIGHT
# define CONFIG_SAMA5_LCDC_OVR1_MAXHEIGHT BOARD_LCDC_HEIGHT
# endif
# if CONFIG_SAMA5_LCDC_OVR1_MAXHEIGHT > BOARD_LCDC_HEIGHT
# error Height of overlay 1 exceeds the height of the display
# endif
# if SAMA5_LCDC_OVR1_BPP == 16
# define SAMA5_OVR1_STRIDE ((CONFIG_SAMA5_LCDC_OVR1_MAXWIDTH * 16 + 7) / 8)
# elif SAMA5_LCDC_OVR1_BPP == 24
# define SAMA5_OVR1_STRIDE ((CONFIG_SAMA5_LCDC_OVR1_MAXWIDTH * 24 + 7) / 8)
# elif SAMA5_LCDC_OVR1_BPP == 32
# define SAMA5_OVR1_STRIDE ((CONFIG_SAMA5_LCDC_OVR1_MAXWIDTH * 32 + 7) / 8)
# elif defined(CONFIG_SAMA5_LCDC_OVR1)
# error Undefined or unrecognized overlay 1 color resolution
# endif
# define SAMA5_OVR1_FBSIZE (SAMA5_OVR1_STRIDE * \
CONFIG_SAMA5_LCDC_OVR1_MAXHEIGHT)
#else
# define SAMA5_OVR1_FBSIZE (0)
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR2
# ifndef CONFIG_SAMA5_LCDC_OVR2_MAXWIDTH
# define CONFIG_SAMA5_LCDC_OVR2_MAXWIDTH BOARD_LCDC_WIDTH
# endif
# if CONFIG_SAMA5_LCDC_OVR2_MAXWIDTH > BOARD_LCDC_WIDTH
# error Width of overlay 2 exceeds the width of the display
# endif
# ifndef CONFIG_SAMA5_LCDC_OVR2_MAXHEIGHT
# define CONFIG_SAMA5_LCDC_OVR2_MAXHEIGHT BOARD_LCDC_HEIGHT
# endif
# if CONFIG_SAMA5_LCDC_OVR2_MAXHEIGHT > BOARD_LCDC_HEIGHT
# error Height of overlay 2 exceeds the height of the display
# endif
# if SAMA5_LCDC_OVR2_BPP == 16
# define SAMA5_OVR2_STRIDE ((CONFIG_SAMA5_LCDC_OVR2_MAXWIDTH * 16 + 7) / 8)
# elif SAMA5_LCDC_OVR2_BPP == 24
# define SAMA5_OVR2_STRIDE ((CONFIG_SAMA5_LCDC_OVR2_MAXWIDTH * 24 + 7) / 8)
# elif SAMA5_LCDC_OVR2_BPP == 32
# define SAMA5_OVR2_STRIDE ((CONFIG_SAMA5_LCDC_OVR2_MAXWIDTH * 32 + 7) / 8)
# elif defined(CONFIG_SAMA5_LCDC_OVR2)
# error Undefined or unrecognized overlay 2 color resolution
# endif
# define SAMA5_OVR2_FBSIZE (SAMA5_OVR2_STRIDE * \
CONFIG_SAMA5_LCDC_OVR2_MAXHEIGHT)
#else
# define SAMA5_OVR2_FBSIZE (0)
#endif
#ifdef CONFIG_SAMA5_LCDC_HEO
# ifndef CONFIG_SAMA5_LCDC_HEO_MAXWIDTH
# define CONFIG_SAMA5_LCDC_HEO_MAXWIDTH BOARD_LCDC_WIDTH
# endif
# if CONFIG_SAMA5_LCDC_HEO_MAXWIDTH > BOARD_LCDC_WIDTH
# error Width of HEO exceeds the width of the display
# endif
# ifndef CONFIG_SAMA5_LCDC_HEO_MAXHEIGHT
# define CONFIG_SAMA5_LCDC_HEO_MAXHEIGHT BOARD_LCDC_HEIGHT
# endif
# if CONFIG_SAMA5_LCDC_HEO_MAXHEIGHT > BOARD_LCDC_HEIGHT
# error Height of HEO exceeds the height of the display
# endif
# if SAMA5_LCDC_HEO_BPP == 16
# define SAMA5_HEO_STRIDE ((CONFIG_SAMA5_LCDC_HEO_MAXWIDTH * 16 + 7) / 8)
# elif SAMA5_LCDC_HEO_BPP == 24
# define SAMA5_HEO_STRIDE ((CONFIG_SAMA5_LCDC_HEO_MAXWIDTH * 24 + 7) / 8)
# elif SAMA5_LCDC_HEO_BPP == 32
# define SAMA5_HEO_STRIDE ((CONFIG_SAMA5_LCDC_HEO_MAXWIDTH * 32 + 7) / 8)
# elif defined(CONFIG_SAMA5_LCDC_HEO)
# error Undefined or unrecognized HEO color resolution
# endif
# define SAMA5_HEO_FBSIZE (SAMA5_HEO_STRIDE * \
CONFIG_SAMA5_LCDC_HEO_MAXHEIGHT)
#else
# define SAMA5_HEO_FBSIZE (0)
#endif
#ifdef CONFIG_SAMA5_LCDC_HCR
# ifndef CONFIG_SAMA5_LCDC_HCR_MAXWIDTH
# define CONFIG_SAMA5_LCDC_HCR_MAXWIDTH BOARD_LCDC_WIDTH
# endif
# if CONFIG_SAMA5_LCDC_HCR_MAXWIDTH > BOARD_LCDC_WIDTH
# error Width of the hardware cursor exceeds the width of the display
# endif
# ifndef CONFIG_SAMA5_LCDC_HCR_MAXHEIGHT
# define CONFIG_SAMA5_LCDC_HCR_MAXHEIGHT BOARD_LCDC_HEIGHT
# endif
# if CONFIG_SAMA5_LCDC_HCR_MAXHEIGHT > BOARD_LCDC_HEIGHT
# error Height of the hardware cursor exceeds the height of the display
# endif
# if SAMA5_LCDC_HCR_BPP == 16
# define SAMA5_HCR_STRIDE ((CONFIG_SAMA5_LCDC_HCR_MAXWIDTH * 16 + 7) / 8)
# elif SAMA5_LCDC_HCR_BPP == 24
# define SAMA5_HCR_STRIDE ((CONFIG_SAMA5_LCDC_HCR_MAXWIDTH * 24 + 7) / 8)
# elif SAMA5_LCDC_HCR_BPP == 32
# define SAMA5_HCR_STRIDE ((CONFIG_SAMA5_LCDC_HCR_MAXWIDTH * 32 + 7) / 8)
# elif defined(CONFIG_SAMA5_LCDC_HCR)
# error Undefined or unrecognized cursor color resolution
# endif
# define SAMA5_HCR_FBSIZE (SAMA5_HCR_STRIDE * \
CONFIG_SAMA5_LCDC_HCR_MAXHEIGHT)
#else
# define SAMA5_HCR_FBSIZE (0)
#endif
#define SAMA5_TOTAL_FBSIZE (SAMA5_BASE_FBSIZE + SAMA5_OVR1_FBSIZE + \
SAMA5_OVR2_FBSIZE + SAMA5_HEO_FBSIZE + \
SAMA5_HCR_FBSIZE)
#undef SAMA5_HAVE_POSITION
#undef SAMA5_HAVE_SIZE
#undef SAMA5_HAVE_PSTRIDE
#if defined(CONFIG_SAMA5_LCDC_OVR1) || defined(CONFIG_SAMA5_LCDC_OVR2) || \
defined(CONFIG_SAMA5_LCDC_HEO)
# define SAMA5_HAVE_POSITION 1
# define SAMA5_HAVE_SIZE 1
# define SAMA5_HAVE_PSTRIDE 1
#elif defined(CONFIG_SAMA5_LCDC_HCR)
# define SAMA5_HAVE_POSITION 1
# define SAMA5_HAVE_SIZE 1
#endif
#ifndef CONFIG_DEBUG_LCD_INFO
# undef CONFIG_SAMA5_LCDC_REGDEBUG
#endif
#define LCDC_FLAG_BOTTOMUP (1 << 0)
#define LCDC_FLAG_RIGHTLEFT (1 << 1)
#define SAMA5_LCDC_BASE_DSCR (CONFIG_SAMA5_LCDC_FB_VBASE+0)
#define SAMA5_LCDC_OVR2_DSCR (CONFIG_SAMA5_LCDC_FB_VBASE + \
SIZEOF_SAM_DSCR_S)
#define SAMA5_LCDC_OVR1_DSCR (CONFIG_SAMA5_LCDC_FB_VBASE+2 * \
SIZEOF_SAM_DSCR_S)
#define SAMA5_LCDC_HEO_DSCR (CONFIG_SAMA5_LCDC_FB_VBASE + \
3 * SIZEOF_SAM_DSCR_S)
#define SAMA5_LCDC_HCR_DSCR (CONFIG_SAMA5_LCDC_FB_VBASE + \
6 * SIZEOF_SAM_DSCR_S)
#define SAMA5_LCDC_DSCR_SIZE (7 * SIZEOF_SAM_DSCR_S)
#define SAMA5_LCDC_DSCR_END (CONFIG_SAMA5_LCDC_FB_VBASE + \
SAMA5_LCDC_DSCR_SIZE)
* will use any skirts before or after the framebuffer memory as a guard
* against wild framebuffer writes.
*/
#define SAMA5_LCDC_BUFFER_SIZE (CONFIG_SAMA5_LCDC_FB_SIZE - \
SAMA5_LCDC_DSCR_SIZE)
#define SAMA5_LCDC_BUFFER_FREE (SAMA5_LCDC_BUFFER_SIZE - SAMA5_TOTAL_FBSIZE)
#define SAMA5_LCDC_BUFFER_START (SAMA5_LCDC_DSCR_END + \
SAMA5_LCDC_BUFFER_FREE / 2)
#if SAMA5_LCDC_BUFFER_FREE < 0
# error "SAMA5_LCDC_BUFFER_SIZE not large enough for frame buffers"
#endif
#define SAMA5_LCDC_BUFFER_BASE SAMA5_LCDC_BUFFER_START
#define SAMA5_LCDC_ENDBUF_BASE (SAMA5_LCDC_BUFFER_BASE + SAMA5_BASE_FBSIZE)
#ifdef CONFIG_SAMA5_LCDC_OVR1
# define SAMA5_LCDC_BUFFER_OVR1 SAMA5_LCDC_ENDBUF_BASE
# define SAMA5_LCDC_ENDBUF_OVR1 (SAMA5_LCDC_BUFFER_OVR1 + SAMA5_OVR1_FBSIZE)
#else
# define SAMA5_LCDC_ENDBUF_OVR1 SAMA5_LCDC_ENDBUF_BASE
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR2
# define SAMA5_LCDC_BUFFER_OVR2 SAMA5_LCDC_ENDBUF_OVR1
# define SAMA5_LCDC_ENDBUF_OVR2 (SAMA5_LCDC_BUFFER_OVR2 + SAMA5_OVR2_FBSIZE)
#else
# define SAMA5_LCDC_ENDBUF_OVR2 SAMA5_LCDC_ENDBUF_OVR1
#endif
#ifdef CONFIG_SAMA5_LCDC_HEO
# define SAMA5_LCDC_BUFFER_HEO SAMA5_LCDC_ENDBUF_OVR2
# define SAMA5_LCDC_ENDBUF_HEO (SAMA5_LCDC_BUFFER_HEO + SAMA5_HEO_FBSIZE)
#else
# define SAMA5_LCDC_ENDBUF_HEO SAMA5_LCDC_ENDBUF_OVR2
#endif
#ifdef CONFIG_SAMA5_LCDC_HCR
# define SAMA5_LCDC_BUFFER_HCR SAMA5_LCDC_ENDBUF_HEO
# define SAMA5_LCDC_ENDBUF_HCR (SAMA5_LCDC_BUFFER_HCR + SAMA5_HCR_FBSIZE)
#else
# define SAMA5_LCDC_ENDBUF_HCR SAMA5_LCDC_ENDBUF_HEO
#endif
#ifdef SAMA5_HAVE_LCDC_HCRCH
# define LCDC_NLAYERS 5
#else
# define LCDC_NLAYERS 4
#endif
#define LAYER(i) g_lcdc.layer[i]
#define LAYER_BASE g_lcdc.layer[LCDC_LAYER_BASE]
#define LAYER_OVR1 g_lcdc.layer[LCDC_LAYER_OVR1]
#define LAYER_OVR2 g_lcdc.layer[LCDC_LAYER_OVR2]
#define LAYER_HEO g_lcdc.layer[LCDC_LAYER_HEO]
#ifdef SAMA5_HAVE_LCDC_HCRCH
# define LAYER_HCR g_lcdc.layer[LCDC_LAYER_HCR]
#endif
* Private Types
****************************************************************************/
enum sam_layer_e
{
LCDC_LAYER_BASE = 0,
LCDC_LAYER_OVR1,
LCDC_LAYER_OVR2,
LCDC_LAYER_HEO
#ifdef SAMA5_HAVE_LCDC_HCRCH
, LCDC_LAYER_HCR
#endif
};
enum sam_rotation_e
{
LCDC_ROT_0 = 0,
LCDC_ROT_90,
LCDC_ROT_180,
LCDC_ROT_270
};
struct sam_layer_s
{
struct sam_dscr_s *dscr;
uint8_t *framebuffer;
uint8_t lid;
uint8_t rotation;
uint8_t flags;
uint8_t bpp;
#ifdef CONFIG_FB_CMAP
uint8_t offset;
uint8_t nclut;
#endif
};
struct sam_lcdc_s
{
struct sam_layer_s layer[LCDC_NLAYERS];
#ifdef CONFIG_FB_HWCURSOR
struct fb_cursorpos_s cpos;
#ifdef CONFIG_FB_HWCURSORSIZE
struct fb_cursorsize_s csize;
#endif
#endif
#ifdef CONFIG_SAMA5_LCDC_REGDEBUG
bool wrlast;
uintptr_t addrlast;
uint32_t vallast;
int ntimes;
#endif
};
* Private Function Prototypes
****************************************************************************/
#ifdef CONFIG_SAMA5_LCDC_REGDEBUG
static bool sam_checkreg(bool wr, uint32_t regval, uintptr_t address);
static uint32_t sam_getreg(uintptr_t addr);
static void sam_putreg(uintptr_t addr, uint32_t val);
#else
# define sam_getreg(addr) getreg32(addr)
# define sam_putreg(addr,val) putreg32(val,addr)
#endif
static void sam_wait_lcdstatus(uint32_t mask, uint32_t value);
* configuration of each color plane.
*/
static int sam_base_getvideoinfo(struct fb_vtable_s *vtable,
struct fb_videoinfo_s *vinfo);
static int sam_base_getplaneinfo(struct fb_vtable_s *vtable,
int planeno, struct fb_planeinfo_s *pinfo);
* mapping
*/
#ifdef CONFIG_FB_CMAP
static int sam_base_getcmap(struct fb_vtable_s *vtable,
struct fb_cmap_s *cmap);
static int sam_base_putcmap(struct fb_vtable_s *vtable,
const struct fb_cmap_s *cmap);
#endif
* cursor
*/
#ifdef CONFIG_FB_HWCURSOR
static int sam_hcr_getcursor(struct fb_vtable_s *vtable,
struct fb_cursorattrib_s *attrib);
static int sam_hcr_setcursor(struct fb_vtable_s *vtable,
struct fb_setcursor_s *settings);
#endif
static void sam_dmasetup(int lid, struct sam_dscr_s *dscr, uint8_t *buffer);
#if 0
static void sam_setposition(int lid, uint32_t x, uint32_t y)
#endif
#ifdef CONFIG_FB_CMAP
static int sam_setclut(struct sam_layer_s *layer,
const struct fb_cmap_s *cmap);
static int sam_getclut(struct sam_layer_s *layer,
struct fb_cmap_s *cmap);
#endif
static void sam_pio_config(void);
static void sam_backlight(uint32_t level);
static void sam_base_disable(void);
static void sam_ovr1_disable(void);
static void sam_ovr2_disable(void);
static void sam_heo_disable(void);
#ifdef SAMA5_HAVE_LCDC_HCRCH
static void sam_hcr_disable(void);
#endif
static void sam_lcd_disable(void);
static void sam_layer_orientation(void);
static void sam_layer_color(void);
static void sam_lcd_enable(void);
static void sam_layer_configure(void);
#ifdef CONFIG_SAMA5_LCDC_HEO
static uint32_t sam_scalefactor(uint32_t wnew, uint32_t oldw);
#endif
static void sam_show_layer(struct sam_layer_s *layer,
uint32_t dispx, uint32_t dispy,
uint32_t dispw, uint32_t disph,
uint32_t imgw, uint32_t imgh);
static void sam_show_base(void);
#ifdef CONFIG_SAMA5_LCDC_HCR
static void sam_show_hcr(void);
#endif
* Private Data
****************************************************************************/
static const struct fb_videoinfo_s g_base_videoinfo =
{
.fmt = SAMA5_LCDC_BASE_COLOR_FMT,
.xres = BOARD_LCDC_WIDTH,
.yres = BOARD_LCDC_HEIGHT,
.nplanes = 1,
};
static struct sam_lcdc_s g_lcdc;
static const struct fb_vtable_s g_base_vtable =
{
.getvideoinfo = sam_base_getvideoinfo,
.getplaneinfo = sam_base_getplaneinfo,
#ifdef CONFIG_FB_CMAP
.getcmap = sam_base_getcmap,
.putcmap = sam_base_putcmap,
#endif
#ifdef CONFIG_FB_HWCURSOR
.getcursor = sam_hcr_getcursor,
.setcursor = sam_hcr_setcursor,
#endif
};
static pio_pinset_t g_lcdcpins[] =
{
PIO_LCD_DAT0, PIO_LCD_DAT2, PIO_LCD_DAT1, PIO_LCD_DAT3,
PIO_LCD_DAT4, PIO_LCD_DAT5, PIO_LCD_DAT6, PIO_LCD_DAT7,
PIO_LCD_DAT8, PIO_LCD_DAT9, PIO_LCD_DAT10, PIO_LCD_DAT11,
#if BOARD_LCDC_OUTPUT_BPP > 12
PIO_LCD_DAT12, PIO_LCD_DAT13, PIO_LCD_DAT14, PIO_LCD_DAT15,
#if BOARD_LCDC_OUTPUT_BPP > 16
PIO_LCD_DAT16, PIO_LCD_DAT17,
#if BOARD_LCDC_OUTPUT_BPP > 18
PIO_LCD_DAT18, PIO_LCD_DAT19, PIO_LCD_DAT20,
PIO_LCD_DAT21, PIO_LCD_DAT22, PIO_LCD_DAT23,
#endif
#endif
#endif
PIO_LCD_PWM, PIO_LCD_DISP, PIO_LCD_VSYNC, PIO_LCD_HSYNC,
PIO_LCD_PCK, PIO_LCD_DEN
};
#define SAMA5_LCDC_NPINCONFIGS (sizeof(g_lcdcpins) / sizeof(pio_pinset_t))
* layers.
*/
static const uintptr_t g_layerenable[LCDC_NLAYERS] =
{
SAM_LCDC_BASECHER,
SAM_LCDC_OVR1CHER,
SAM_LCDC_OVR2CHER,
SAM_LCDC_HEOCHER
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRCHER
#endif
};
#if 0
static const uintptr_t g_layerdisable[LCDC_NLAYERS] =
{
SAM_LCDC_BASECHDR,
SAM_LCDC_OVR1CHDR,
SAM_LCDC_OVR2CHDR,
SAM_LCDC_HEOCHDR
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRCHDR
#endif
};
#endif
#if 0
static const uintptr_t g_layerstatus[LCDC_NLAYERS] =
{
SAM_LCDC_BASECHSR,
SAM_LCDC_OVR1CHSR,
SAM_LCDC_OVR2CHSR,
SAM_LCDC_HEOCHSR
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRCHSR
#endif
};
#endif
static const uintptr_t g_layerblend[LCDC_NLAYERS] =
{
SAM_LCDC_BASECFG4,
SAM_LCDC_OVR1CFG9,
SAM_LCDC_OVR2CFG9,
SAM_LCDC_HEOCFG12
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRCFG9
#endif
};
static const uintptr_t g_layerhead[LCDC_NLAYERS] =
{
SAM_LCDC_BASEHEAD,
SAM_LCDC_OVR1HEAD,
SAM_LCDC_OVR2HEAD,
SAM_LCDC_HEOHEAD
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRHEAD
#endif
};
static const uintptr_t g_layeraddr[LCDC_NLAYERS] =
{
SAM_LCDC_BASEADDR,
SAM_LCDC_OVR1ADDR,
SAM_LCDC_OVR2ADDR,
SAM_LCDC_HEOADDR
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRADDR
#endif
};
static const uintptr_t g_layerctrl[LCDC_NLAYERS] =
{
SAM_LCDC_BASECTRL,
SAM_LCDC_OVR1CTRL,
SAM_LCDC_OVR2CTRL,
SAM_LCDC_HEOCTRL
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRCTRL
#endif
};
static const uintptr_t g_layernext[LCDC_NLAYERS] =
{
SAM_LCDC_BASENEXT,
SAM_LCDC_OVR1NEXT,
SAM_LCDC_OVR2NEXT,
SAM_LCDC_HEONEXT
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRNEXT
#endif
};
static const uintptr_t g_layercfg[LCDC_NLAYERS] =
{
SAM_LCDC_BASECFG0,
SAM_LCDC_OVR1CFG0,
SAM_LCDC_OVR2CFG0,
SAM_LCDC_HEOCFG0
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRCFG0
#endif
};
#if 0
static const uintptr_t g_layercolor[LCDC_NLAYERS] =
{
SAM_LCDC_BASECFG1,
SAM_LCDC_OVR1CFG1,
SAM_LCDC_OVR2CFG1,
SAM_LCDC_HEOCFG1
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRCFG1
#endif
};
#endif
#ifdef SAMA5_HAVE_POSITION
static const uintptr_t g_layerpos[LCDC_NLAYERS] =
{
0,
SAM_LCDC_OVR1CFG2,
SAM_LCDC_OVR2CFG2,
SAM_LCDC_HEOCFG2
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRCFG2
#endif
};
#endif
#ifdef SAMA5_HAVE_SIZE
static const uintptr_t g_layersize[LCDC_NLAYERS] =
{
0,
SAM_LCDC_OVR1CFG3,
SAM_LCDC_OVR2CFG3,
SAM_LCDC_HEOCFG3
#ifdef SAMA5_HAVE_LCDC_HCRCH
, SAM_LCDC_HCRCFG3
#endif
};
#endif
static const uintptr_t g_layerstride[LCDC_NLAYERS] =
{
SAM_LCDC_BASECFG2,
SAM_LCDC_OVR1CFG4,
SAM_LCDC_OVR2CFG4,
SAM_LCDC_HEOCFG5,
#ifdef SAMA5_HAVE_LCDC_HCRCH
SAM_LCDC_HCRCFG4
#endif
};
#ifdef SAMA5_HAVE_PSTRIDE
static const uintptr_t g_layerpstride[LCDC_NLAYERS] =
{
0,
SAM_LCDC_OVR1CFG5,
SAM_LCDC_OVR2CFG5,
SAM_LCDC_HEOCFG6,
0,
};
#endif
#ifdef CONFIG_FB_CMAP
static const uintptr_t g_layerclut[LCDC_NLAYERS] =
{
SAM_LCDC_BASECLUT,
SAM_LCDC_OVR1CLUT,
SAM_LCDC_OVR2CLUT,
SAM_LCDC_HEOCLUT,
#ifdef SAMA5_HAVE_LCDC_HCRCH
SAM_LCDC_HCRCLUT,
#endif
};
#endif
* Private Functions
****************************************************************************/
* Name: sam_checkreg
*
* Description:
* Check if the current register access is a duplicate of the preceding.
*
* Input Parameters:
* regval - The value to be written
* address - The address of the register to write to
*
* Returned Value:
* true: This is the first register access of this type.
* flase: This is the same as the preceding register access.
*
****************************************************************************/
#ifdef CONFIG_SAMA5_LCDC_REGDEBUG
static bool sam_checkreg(bool wr, uint32_t regval, uintptr_t address)
{
if (wr == g_lcdc.wrlast &&
regval == g_lcdc.vallast &&
address == g_lcdc.addrlast)
{
g_lcdc.ntimes++;
return false;
}
else
{
if (g_lcdc.ntimes > 0)
{
lcdinfo("...[Repeats %d times]...\n", g_lcdc.ntimes);
}
g_lcdc.wrlast = wr;
g_lcdc.vallast = regval;
g_lcdc.addrlast = address;
g_lcdc.ntimes = 0;
}
return true;
}
#endif
* Name: sam_getreg
*
* Description:
* Read any 32-bit register using an absolute
*
****************************************************************************/
#ifdef CONFIG_SAMA5_LCDC_REGDEBUG
static uint32_t sam_getreg(uintptr_t address)
{
uint32_t regval = getreg32(address);
if (sam_checkreg(false, regval, address))
{
lcdinfo("%" PRIx32 " ->%" PRIx32 "\n", address, regval);
}
return regval;
}
#endif
* Name: sam_putreg
*
* Description:
* Write to any 32-bit register using an absolute address
*
****************************************************************************/
#ifdef CONFIG_SAMA5_LCDC_REGDEBUG
static void sam_putreg(uintptr_t address, uint32_t regval)
{
if (sam_checkreg(true, regval, address))
{
lcdinfo("%" PRIx32 " <-%" PRIx32 "\n", address, regval);
}
putreg32(regval, address);
}
#endif
* Name: sam_wait_lcdstatus
*
* Description:
* Wait for the masked set of bits in the LCDC status register to take a
* specific value.
*
****************************************************************************/
static void sam_wait_lcdstatus(uint32_t mask, uint32_t value)
{
while ((sam_getreg(SAM_LCDC_LCDSR) & mask) != value);
}
* Name: sam_base_getvideoinfo
****************************************************************************/
static int sam_base_getvideoinfo(struct fb_vtable_s *vtable,
struct fb_videoinfo_s *vinfo)
{
lcdinfo("vtable=%p vinfo=%p\n", vtable, vinfo);
if (vtable && vinfo)
{
memcpy(vinfo, &g_base_videoinfo, sizeof(struct fb_videoinfo_s));
return OK;
}
lcderr("ERROR: Returning EINVAL\n");
return -EINVAL;
}
* Name: sam_base_getplaneinfo
****************************************************************************/
static int sam_base_getplaneinfo(struct fb_vtable_s *vtable, int planeno,
struct fb_planeinfo_s *pinfo)
{
lcdinfo("vtable=%p planeno=%d pinfo=%p\n", vtable, planeno, pinfo);
if (vtable && planeno == 0 && pinfo)
{
pinfo->fbmem = (void *)LAYER_BASE.framebuffer;
pinfo->fblen = SAMA5_BASE_FBSIZE;
pinfo->stride = SAMA5_BASE_STRIDE;
pinfo->display = 0;
pinfo->bpp = LAYER_BASE.bpp;
return OK;
}
lcderr("ERROR: Returning EINVAL\n");
return -EINVAL;
}
* Name: sam_base_getcmap
****************************************************************************/
#ifdef CONFIG_FB_CMAP
static int sam_base_getcmap(struct fb_vtable_s *vtable,
struct fb_cmap_s *cmap)
{
return sam_getclut(&LAYER_BASE, cmap);
}
#endif
* Name: sam_base_putcmap
****************************************************************************/
#ifdef CONFIG_FB_CMAP
static int sam_base_putcmap(struct fb_vtable_s *vtable,
const struct fb_cmap_s *cmap)
{
return sam_setclut(&LAYER_BASE, cmap);
}
#endif
* Name: sam_hcr_getcursor
****************************************************************************/
#ifdef CONFIG_FB_HWCURSOR
static int sam_hcr_getcursor(struct fb_vtable_s *vtable,
struct fb_cursorattrib_s *attrib)
{
lcdinfo("vtable=%p attrib=%p\n", vtable, attrib);
if (vtable && attrib)
{
#ifdef CONFIG_FB_HWCURSORIMAGE
attrib->fmt = SAMA5_HCR_COLOR_FMT;
#endif
lcdinfo("pos: (x=%d, y=%d)\n", g_lcdc.cpos.x, g_lcdc.cpos.y);
attrib->pos = g_lcdc.cpos;
#ifdef CONFIG_FB_HWCURSORSIZE
attrib->mxsize.h = CONFIG_SAMA5_LCDC_HCR_HEIGHT;
attrib->mxsize.w = CONFIG_SAMA5_LCDC_HCR_WIDTH;
lcdinfo("size: (h=%d, w=%d)\n", g_lcdc.csize.h, g_lcdc.csize.w);
attrib->size = g_lcdc.csize;
#endif
return OK;
}
lcderr("ERROR: Returning EINVAL\n");
return -EINVAL;
}
#endif
* Name: sam_hcr_setcursor
****************************************************************************/
#ifdef CONFIG_FB_HWCURSOR
static int sam_hcr_setcursor(struct fb_vtable_s *vtable,
struct fb_setcursor_s *settings)
{
lcdinfo("vtable=%p settings=%p\n", vtable, settings);
if (vtable && settings)
{
lcdinfo("flags: %02x\n", settings->flags);
if ((flags & FB_CUR_SETPOSITION) != 0)
{
g_lcdc.cpos = settings->pos;
lcdinfo("pos: (h:%d, w:%d)\n", g_lcdc.cpos.x, g_lcdc.cpos.y);
}
#ifdef CONFIG_FB_HWCURSORSIZE
if ((flags & FB_CUR_SETSIZE) != 0)
{
g_lcdc.csize = settings->size;
lcdinfo("size: (h:%d, w:%d)\n", g_lcdc.csize.h, g_lcdc.csize.w);
}
#endif
#ifdef CONFIG_FB_HWCURSORIMAGE
if ((flags & FB_CUR_SETIMAGE) != 0)
{
lcdinfo("image: (h:%d, w:%d) @ %p\n",
settings->img.height, settings->img.width,
settings->img.image);
}
#endif
return OK;
}
lcderr("ERROR: Returning EINVAL\n");
return -EINVAL;
}
#endif
* Name: sam_dmasetup
*
* Description:
* Configure the channel DMA
*
****************************************************************************/
static void sam_dmasetup(int lid, struct sam_dscr_s *dscr, uint8_t *buffer)
{
uintptr_t physbuffer;
uintptr_t physdscr;
physbuffer = sam_physramaddr((uintptr_t)buffer);
physdscr = sam_physramaddr((uintptr_t)dscr);
*
* 2. Write the channel descriptor (DSCR) structure in the system memory by
* writing DSCR.CHXADDR Frame base address, DSCR.CHXCTRL channel control
* and DSCR.CHXNEXT next descriptor location.
* 3. If more than one descriptor is expected, the DFETCH field of
* DSCR.CHXCTRL is set to one to enable the descriptor fetch operation.
*/
dscr->addr = (uint32_t)physbuffer;
dscr->ctrl = LCDC_BASECTRL_DFETCH;
dscr->next = (uint32_t)physdscr;
if ((sam_getreg(g_layerblend[lid]) & LCDC_BASECFG4_DMA) != 0)
{
* 31.6.2.4 DMA Dynamic Linking of a New Transfer Descriptor:
*
* 2. Write the address of the new structure in the CHXHEAD register.
* 3. Add the new structure to the queue of descriptors by writing one
* to the A2QEN field of the CHXCHER register.
*/
sam_putreg(g_layerhead[lid], physdscr);
sam_putreg(g_layerenable[lid], LCDC_BASECHER_A2Q);
}
else
{
*
* 4. Write the DSCR.CHXNEXT register with the address location
* of the descriptor structure and set DFETCH field of the
* DSCR.CHXCTRL register to one.
*/
sam_putreg(g_layeraddr[lid], physbuffer);
sam_putreg(g_layerctrl[lid], LCDC_BASECTRL_DFETCH);
sam_putreg(g_layernext[lid], physdscr);
}
#if defined(CONFIG_DEBUG_GRAPHICS) && defined(CONFIG_DEBUG_INFO)
lcdinfo("DMA descriptor: addr=%" PRIx32 " ctrl=%" PRIx32 " next=%"
PRIx32 "\n", dscr->addr, dscr->ctrl, dscr->next);
lcdinfo("DMA registers[%d]: head=%" PRIx32 " addr=%" PRIx32 " ctrl=%"
PRIx32 " next=%" PRIx32 "\n",
lid, sam_getreg(g_layerhead[lid]), sam_getreg(g_layeraddr[lid]),
sam_getreg(g_layerctrl[lid]), sam_getreg(g_layernext[lid]));
#endif
}
* Name: sam_setposition
*
* Description:
* Set the new position of a move-able layer (any layer except the base
* layer).
*
****************************************************************************/
#if 0
static void sam_setposition(int lid, uint32_t x, uint32_t y)
{
uintptr_t regaddr;
uintptr_t regval;
uint32_t h;
uint32_t w;
regaddr = g_layersize[lid];
if (regaddr)
{
regval = sam_getreg(regaddr);
w = (regval & LCDC_OVR1CFG3_XSIZE_MASK) >> LCDC_OVR1CFG3_XSIZE_SHIFT;
h = (regval & LCDC_OVR1CFG3_YSIZE_MASK) >> LCDC_OVR1CFG3_YSIZE_SHIFT;
if (x + w >= BOARD_LCDC_WIDTH)
{
x = BOARD_LCDC_WIDTH - w;
}
if (y + h >= BOARD_LCDC_HEIGHT)
{
y = BOARD_LCDC_HEIGHT - h;
}
regaddr = g_layerpos[lid];
if (regaddr)
{
sam_putreg(regaddr, LCDC_OVR1CFG2_XPOS(x) | LCDC_OVR1CFG2_YPOS(y));
regaddr = g_layerstatus[lid];
if ((sam_getreg(regaddr) & LCDC_OVR1CHSR_CH) != 0)
{
regaddr = g_layerenable[lid];
sam_putreg(regaddr, LCDC_OVR1CHER_UPDATE);
}
}
}
}
#endif
* Name: sam_setclut
*
* Description:
* Set a range of CLUT values for any layer
*
****************************************************************************/
#ifdef CONFIG_FB_CMAP
static int sam_setclut(struct sam_layer_s *layer,
const struct fb_cmap_s *cmap)
{
uintptr_t regaddr;
uint32_t offset;
uint32_t rgb;
unsigned int len;
unsigned int end;
int i;
lcdinfo("layer=%d cmap=%p first=%d len=%d\n",
layer->lid, cmap, cmap->first, cmap->len);
DEBUGASSERT(layer && cmap);
offset = (uint32_t)cmap->first;
len = (unsigned int)cmap->len;
if (offset >= SAM_LCDC_NCLUT)
{
lcderr("ERROR: CLUT offset is out of range: %d\n", offset);
return -EINVAL;
}
if (offset + len > SAM_LCDC_NCLUT)
{
len = SAM_LCDC_NCLUT - offset;
}
if (offset < layer->offset)
{
layer->offset = offset;
}
end = offset + len;
if (end > (layer->offset + layer->nclut))
{
layer->nclut = end - layer->offset;
}
regaddr = g_layerclut[layer->lid] + offset << 2;
for (i = 0; i < len; i++)
{
rgb = (uint32_t)cmap->red[i] << LCDC_BASECLUT_RCLUT_SHIFT |
(uint32_t)cmap->green[i] << LCDC_BASECLUT_GCLUT_SHIFT |
(uint32_t)cmap->blue[i] << LCDC_BASECLUT_BCLUT_SHIFT;
#ifdef CONFIG_SAMA5_LCDC_TRANSPARENCY
if (camp->transp)
{
rgb |= (uint32_t)cmap->transp[i] << LCDC_OVR1CLUT_ACLUT_SHIFT;
}
#endif
sam_putreg(regaddr, clut[i]);
regaddr += sizeof(uint32_t);
}
return OK;
}
#endif
* Name: sam_getclut
*
* Description:
* Get a range of CLUT values for any layer
*
****************************************************************************/
#ifdef CONFIG_FB_CMAP
static int sam_getclut(struct sam_layer_s *layer,
struct fb_cmap_s *cmap)
{
uintptr_t regaddr;
uintptr_t regval;
int i;
lcdinfo("layer=%d cmap=%p first=%d len=%d\n",
layer->lid, cmap, layer->offset, layer->nclut);
DEBUGASSERT(layer && cmap);
cmap->first = layer->offset;
cmap->len = layer->nclut;
regaddr = g_layerclut[layer->lid] + (uint32_t)cmap->first << 2;
for (i = 0; i < (int)cmap->len; i++)
{
regval = getreg(regaddr);
regaddr += sizeof(uint32_t);
cmap->red[i] = (uint8_t)
(regval & LCDC_BASECLUT_RCLUT_MASK) << LCDC_BASECLUT_RCLUT_SHIFT;
cmap->green[i] = (uint8_t)
(regval & LCDC_BASECLUT_GCLUT_MASK) << LCDC_BASECLUT_GCLUT_SHIFT;
cmap->blue[i] = (uint8_t)
(regval & LCDC_BASECLUT_GCLUT_MASK) << LCDC_BASECLUT_BCLUT_SHIFT;
#ifdef CONFIG_SAMA5_LCDC_TRANSPARENCY
cmap->transp[i] = (uint8_t)
(regval & LCDC_OVR1CLUT_ACLUT_MASK) << LCDC_OVR1CLUT_ACLUT_SHIFT;
#endif
}
return OK;
}
#endif
* Name: sam_pio_config
*
* Description:
* Configure PIO pins for use with the LCDC
*
****************************************************************************/
static void sam_pio_config(void)
{
int i;
lcdinfo("Configuring pins\n");
for (i = 0; i < SAMA5_LCDC_NPINCONFIGS; i++)
{
sam_configpio(g_lcdcpins[i]);
}
}
* Name: sam_backlight
*
* Description:
* Set the backlight level
*
****************************************************************************/
static void sam_backlight(uint32_t level)
{
uint32_t regval;
if (level == SAMA5_LCDC_BACKLIGHT_OFF)
{
sam_putreg(SAM_LCDC_LCDDIS, LCDC_LCDDIS_PWM);
sam_wait_lcdstatus(LCDC_LCDSR_SIP | LCDC_LCDSR_PWM, 0);
}
#ifdef CONFIG_SAMA5_LCDC_BACKLIGHT
else
{
regval = sam_getreg(SAM_LCDC_LCDCFG6);
regval &= ~LCDC_LCDCFG6_PWMCVAL_MASK;
regval |= LCDC_LCDCFG6_PWMCVAL(level);
sam_putreg(SAM_LCDC_LCDCFG6, regval);
sam_putreg(SAM_LCDC_LCDEN, LCDC_LCDEN_PWM);
}
#endif
}
* Name: sam_base_disable
*
* Description:
* Disable the base layer
*
****************************************************************************/
static void sam_base_disable(void)
{
struct sam_dscr_s *dscr;
uintptr_t physaddr;
uint32_t regval;
dscr = LAYER_BASE.dscr;
DEBUGASSERT(dscr);
* will disable the channel at the end of the frame.
*/
regval = sam_getreg(SAM_LCDC_BASECTRL);
regval &= ~LCDC_BASECTRL_DFETCH;
sam_putreg(SAM_LCDC_BASECTRL, regval);
* channel at the end of the frame.
*/
physaddr = sam_physramaddr((uintptr_t)dscr);
dscr->next = physaddr;
sam_putreg(SAM_LCDC_BASENEXT, physaddr);
* the channel at the end of the frame.
*/
sam_putreg(SAM_LCDC_BASECHDR, LCDC_BASECHDR_CH);
* the channel immediately. This may occur in the middle of the image.
*/
* successfully disabled.
*/
while ((sam_getreg(SAM_LCDC_BASECHSR) & LCDC_BASECHSR_CH) != 0);
}
* Name: sam_ovr1_disable
*
* Description:
* Disable the overlay 1 layer
*
****************************************************************************/
static void sam_ovr1_disable(void)
{
struct sam_dscr_s *dscr;
uintptr_t physaddr;
uint32_t regval;
dscr = LAYER_OVR1.dscr;
DEBUGASSERT(dscr);
* will disable the channel at the end of the frame.
*/
dscr->ctrl &= ~LCDC_OVR1CTRL_DFETCH;
regval = sam_getreg(SAM_LCDC_OVR1CTRL);
regval &= ~LCDC_OVR1CTRL_DFETCH;
sam_putreg(SAM_LCDC_OVR1CTRL, regval);
* channel at the end of the frame.
*/
physaddr = sam_physramaddr((uintptr_t)dscr);
dscr->next = physaddr;
sam_putreg(SAM_LCDC_OVR1NEXT, physaddr);
* the channel at the end of the frame.
*/
sam_putreg(SAM_LCDC_OVR1CHDR, LCDC_OVR1CHDR_CH);
* the channel immediately. This may occur in the middle of the image.
*/
* successfully disabled.
*/
while ((sam_getreg(SAM_LCDC_OVR1CHSR) & LCDC_OVR1CHSR_CH) != 0);
}
* Name: sam_ovr2_disable
*
* Description:
* Disable the overlay 2 layer
*
****************************************************************************/
static void sam_ovr2_disable(void)
{
struct sam_dscr_s *dscr;
uintptr_t physaddr;
uint32_t regval;
dscr = LAYER_OVR2.dscr;
DEBUGASSERT(dscr);
* will disable the channel at the end of the frame.
*/
dscr->ctrl &= ~LCDC_OVR2CTRL_DFETCH;
regval = sam_getreg(SAM_LCDC_OVR2CTRL);
regval &= ~LCDC_OVR2CTRL_DFETCH;
sam_putreg(SAM_LCDC_OVR2CTRL, regval);
* channel at the end of the frame.
*/
physaddr = sam_physramaddr((uintptr_t)dscr);
dscr->next = physaddr;
sam_putreg(SAM_LCDC_OVR2NEXT, physaddr);
* the channel at the end of the frame.
*/
sam_putreg(SAM_LCDC_OVR2CHDR, LCDC_OVR2CHDR_CH);
* the channel immediately. This may occur in the middle of the image.
*/
* successfully disabled.
*/
while ((sam_getreg(SAM_LCDC_OVR2CHSR) & LCDC_OVR2CHSR_CH) != 0);
}
* Name: sam_heo_disable
*
* Description:
* Disable the High End Overlay (HEO) layer
*
****************************************************************************/
static void sam_heo_disable(void)
{
struct sam_dscr_s *dscr;
uintptr_t physaddr;
uint32_t regval;
dscr = LAYER_HEO.dscr;
DEBUGASSERT(dscr);
* will disable the channel at the end of the frame.
*/
dscr[0].ctrl &= ~LCDC_HEOCTRL_DFETCH;
dscr[1].ctrl &= ~LCDC_HEOUCTRL_DFETCH;
dscr[2].ctrl &= ~LCDC_HEOVCTRL_DFETCH;
regval = sam_getreg(SAM_LCDC_HEOCTRL);
regval &= ~LCDC_HEOCTRL_DFETCH;
sam_putreg(SAM_LCDC_HEOCTRL, regval);
regval = sam_getreg(SAM_LCDC_HEOUCTRL);
regval &= ~LCDC_HEOUCTRL_DFETCH;
sam_putreg(SAM_LCDC_HEOUCTRL, regval);
regval = sam_getreg(SAM_LCDC_HEOVCTRL);
regval &= ~LCDC_HEOVCTRL_DFETCH;
sam_putreg(SAM_LCDC_HEOVCTRL, regval);
* channel at the end of the frame.
*/
physaddr = sam_physramaddr((uintptr_t)&dscr[0]);
dscr[0].next = physaddr;
sam_putreg(SAM_LCDC_HEONEXT, physaddr);
physaddr = sam_physramaddr((uintptr_t)&dscr[1]);
dscr[1].next = physaddr;
sam_putreg(SAM_LCDC_HEOUNEXT, physaddr);
physaddr = sam_physramaddr((uintptr_t)&dscr[2]);
dscr[2].next = physaddr;
sam_putreg(SAM_LCDC_HEOVNEXT, physaddr);
* the channel at the end of the frame.
*/
sam_putreg(SAM_LCDC_HEOCHDR, LCDC_HEOCHDR_CH);
* the channel immediately. This may occur in the middle of the image.
*/
* successfully disabled.
*/
while ((sam_getreg(SAM_LCDC_HEOCHSR) & LCDC_HEOCHSR_CH) != 0);
}
* Name: sam_hcr_disable
*
* Description:
* Disable the Hardware Cursor Channel (HCR) layer
*
****************************************************************************/
#ifdef SAMA5_HAVE_LCDC_HCRCH
static void sam_hcr_disable(void)
{
struct sam_dscr_s *dscr;
uintptr_t physaddr;
uint32_t regval;
dscr = LAYER_HCR.dscr;
DEBUGASSERT(dscr);
* will disable the channel at the end of the frame.
*/
dscr->ctrl &= ~LCDC_HCRCTRL_DFETCH;
regval = sam_getreg(SAM_LCDC_HCRCTRL);
regval &= ~LCDC_HCRCTRL_DFETCH;
sam_putreg(SAM_LCDC_HCRCTRL, regval);
* channel at the end of the frame.
*/
physaddr = sam_physramaddr((uintptr_t)dscr);
dscr->next = physaddr;
sam_putreg(SAM_LCDC_HCRNEXT, physaddr);
* the channel at the end of the frame.
*/
sam_putreg(SAM_LCDC_HCRCHDR, LCDC_HCRCHDR_CH);
* the channel immediately. This may occur in the middle of the image.
*/
* successfully disabled.
*/
while ((sam_getreg(SAM_LCDC_HCRCHSR) & LCDC_HCRCHSR_CH) != 0);
}
#endif
* Name: sam_lcd_disable
*
* Description:
* Disable the LCD peripheral
*
****************************************************************************/
static void sam_lcd_disable(void)
{
sam_base_disable();
sam_ovr1_disable();
sam_ovr2_disable();
sam_heo_disable();
#ifdef SAMA5_HAVE_LCDC_HCRCH
sam_hcr_disable();
#endif
sam_putreg(SAM_LCDC_BASECFG4, 0);
sam_backlight(SAMA5_LCDC_BACKLIGHT_OFF);
* register.
*/
sam_putreg(SAM_LCDC_LCDDIS, LCDC_LCDDIS_DISP);
* is no longer activated.
*/
sam_wait_lcdstatus(LCDC_LCDSR_SIP | LCDC_LCDSR_DISP, 0);
* of the LCDC_LCDDIS register.
*/
sam_putreg(SAM_LCDC_LCDDIS, LCDC_LCDDIS_SYNC);
* synchronization is off.
*/
sam_wait_lcdstatus(LCDC_LCDSR_SIP | LCDC_LCDSR_LCD, 0);
* LCDC_LCDDIS register.
*/
sam_putreg(SAM_LCDC_LCDDIS, LCDC_LCDDIS_CLK);
* Clock is disabled.
*/
sam_wait_lcdstatus(LCDC_LCDSR_SIP | LCDC_LCDSR_CLK, 0);
sam_lcdc_disableclk();
sam_putreg(SAM_PMC_SCDR, PMC_LCDCK);
}
* Name: sam_layer_orientation
*
* Description:
* Configure LCDC layer orientation
*
****************************************************************************/
static void sam_layer_orientation(void)
{
LAYER_BASE.flags = 0;
#if defined(CONFIG_SAMA5_LCDC_BASE_ROT90)
LAYER_BASE.rotation = LCDC_ROT_90;
#elif defined(CONFIG_SAMA5_LCDC_BASE_ROT180)
LAYER_BASE.rotation = LCDC_ROT_180;
#elif defined(CONFIG_SAMA5_LCDC_BASE_ROT270)
LAYER_BASE.rotation = LCDC_ROT_270;
#else
LAYER_BASE.rotation = LCDC_ROT_0;
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR1
LAYER_OVR1.flags = 0;
#ifdef CONFIG_SAMA5_LCDC_OVR1_BOTTOMUP
LAYER_OVR1.flags |= LCDC_FLAG_BOTTOMUP;
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR1_RIGHTLEFT
LAYER_OVR1.flags |= LCDC_FLAG_RIGHTLEFT;
#endif
#if defined(CONFIG_SAMA5_LCDC_OVR1_ROT90)
LAYER_OVR1.rotation = LCDC_ROT_90;
#elif defined(CONFIG_SAMA5_LCDC_OVR1_ROT180)
LAYER_OVR1.rotation = LCDC_ROT_180;
#elif defined(CONFIG_SAMA5_LCDC_OVR1_ROT270)
LAYER_OVR1.rotation = LCDC_ROT_270;
#else
LAYER_OVR1.rotation = LCDC_ROT_0;
#endif
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR2
LAYER_OVR2.flags = 0;
#ifdef CONFIG_SAMA5_LCDC_OVR2_BOTTOMUP
LAYER_OVR2.flags |= LCDC_FLAG_BOTTOMUP;
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR2_RIGHTLEFT
LAYER_OVR2.flags |= LCDC_FLAG_RIGHTLEFT;
#endif
#if defined(CONFIG_SAMA5_LCDC_OVR2_ROT90)
LAYER_OVR2.rotation = LCDC_ROT_90;
#elif defined(CONFIG_SAMA5_LCDC_OVR2_ROT180)
LAYER_OVR2.rotation = LCDC_ROT_180;
#elif defined(CONFIG_SAMA5_LCDC_OVR2_ROT270)
LAYER_OVR2.rotation = LCDC_ROT_270;
#else
LAYER_OVR2.rotation = LCDC_ROT_0;
#endif
#endif
#ifdef CONFIG_SAMA5_LCDC_HEO
LAYER_HEO.flags = 0;
#ifdef CONFIG_SAMA5_LCDC_HEO_BOTTOMUP
LAYER_HEO.flags |= LCDC_FLAG_BOTTOMUP;
#endif
#ifdef CONFIG_SAMA5_LCDC_HEO_RIGHTLEFT
LAYER_HEO.flags |= LCDC_FLAG_RIGHTLEFT;
#endif
#if defined(CONFIG_SAMA5_LCDC_HEO_ROT90)
LAYER_HEO.rotation = LCDC_ROT_90;
#elif defined(CONFIG_SAMA5_LCDC_HEO_ROT180)
LAYER_HEO.rotation = LCDC_ROT_180;
#elif defined(CONFIG_SAMA5_LCDC_HEO_ROT270)
LAYER_HEO.rotation = LCDC_ROT_270;
#else
LAYER_HEO.rotation = LCDC_ROT_0;
#endif
#endif
#ifdef CONFIG_SAMA5_LCDC_HCR
LAYER_HCR.flags = 0;
#if defined(CONFIG_SAMA5_LCDC_HCR_ROT90)
LAYER_HCR.rotation = LCDC_ROT_90;
#elif defined(CONFIG_SAMA5_LCDC_HCR_ROT180)
LAYER_HCR.rotation = LCDC_ROT_180;
#elif defined(CONFIG_SAMA5_LCDC_HCR_ROT270)
LAYER_HCR.rotation = LCDC_ROT_270;
#else
LAYER_HCR.rotation = LCDC_ROT_0;
#endif
#endif
}
* Name: sam_layer_color
*
* Description:
* Configure LCDC layer color mode
*
****************************************************************************/
static void sam_layer_color(void)
{
#ifdef CONFIG_FB_CMAP
LAYER_BASE.offset = SAM_LCDC_NCLUT - 1;
LAYER_OVR1.offset = SAM_LCDC_NCLUT - 1;
LAYER_OVR2.offset = SAM_LCDC_NCLUT - 1;
LAYER_HEO.offset = SAM_LCDC_NCLUT - 1;
LAYER_HCR.offset = SAM_LCDC_NCLUT - 1;
#endif
#if defined(CONFIG_SAMA5_LCDC_BASE_RGB888P)
LAYER_BASE.bpp = 24;
sam_putreg(SAM_LCDC_BASECFG0,
LCDC_BASECFG0_DLBO | LCDC_BASECFG0_BLEN_INCR16);
sam_putreg(SAM_LCDC_BASECFG1,
LCDC_BASECFG1_24BPP_RGB888P);
# elif defined(CONFIG_SAMA5_LCDC_BASE_RGB565)
LAYER_BASE.bpp = 16;
sam_putreg(SAM_LCDC_BASECFG0,
LCDC_BASECFG0_DLBO | LCDC_BASECFG0_BLEN_INCR16);
sam_putreg(SAM_LCDC_BASECFG1,
LCDC_BASECFG1_16BPP_RGB565);
#elif defined(CONFIG_SAMA5_LCDC_BASE_RGBA8888)
LAYER_BASE.bpp = 32;
sam_putreg(SAM_LCDC_BASECFG0,
LCDC_BASECFG0_DLBO | LCDC_BASECFG0_BLEN_INCR16);
sam_putreg(SAM_LCDC_BASECFG1,
LCDC_BASECFG1_32BPP_RGBA8888);
#elif defined(CONFIG_SAMA5_LCDC_BASE_ARGB8888)
LAYER_BASE.bpp = 32;
sam_putreg(SAM_LCDC_BASECFG0,
LCDC_BASECFG0_DLBO | LCDC_BASECFG0_BLEN_INCR16);
sam_putreg(SAM_LCDC_BASECFG1,
LCDC_BASECFG1_32BPP_ARGB8888);
#else
# error Support for this resolution is not yet implemented
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR1
# if defined(CONFIG_SAMA5_LCDC_OVR1_RGB888P)
LAYER_OVR1.bpp = 24;
sam_putreg(SAM_LCDC_OVR1CFG0,
LCDC_OVR1CFG0_DLBO | LCDC_BASECFG0_BLEN_INCR16 |
LCDC_OVR1CFG0_ROTDIS);
sam_putreg(SAM_LCDC_OVR1CFG1,
LCDC_OVR1CFG1_24BPP_RGB888P);
sam_putreg(SAM_LCDC_OVR1CFG9,
LCDC_OVR1CFG9_GA(0xff) | LCDC_OVR1CFG9_GAEN);
# elif defined(CONFIG_SAMA5_LCDC_OVR1_RGB565)
LAYER_OVR1.bpp = 16;
sam_putreg(SAM_LCDC_OVR1CFG0,
LCDC_OVR1CFG0_DLBO | LCDC_BASECFG0_BLEN_INCR16 |
LCDC_OVR1CFG0_ROTDIS);
sam_putreg(SAM_LCDC_OVR1CFG1,
LCDC_OVR1CFG1_16BPP_RGB565);
sam_putreg(SAM_LCDC_OVR1CFG9,
LCDC_OVR1CFG9_GA(0xff) | LCDC_OVR1CFG9_GAEN);
# else
# error Support for this resolution is not yet implemented
# endif
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR2
# if defined(CONFIG_SAMA5_LCDC_OVR2_RGB888P)
LAYER_OVR2.bpp = 24;
sam_putreg(SAM_LCDC_OVR2CFG0,
LCDC_OVR2CFG0_DLBO | LCDC_BASECFG0_BLEN_INCR16 |
LCDC_OVR2CFG0_ROTDIS;
sam_putreg(SAM_LCDC_OVR2CFG1,
LCDC_OVR2CFG1_24BPP_RGB888P);
sam_putreg(SAM_LCDC_OVR2CFG9,
LCDC_OVR2CFG9_GA(0xff) | LCDC_OVR2CFG9_GAEN;
# elif defined(CONFIG_SAMA5_LCDC_OVR2_RGB565)
LAYER_OVR2.bpp = 16;
sam_putreg(SAM_LCDC_OVR2CFG0,
LCDC_OVR2CFG0_DLBO | LCDC_BASECFG0_BLEN_INCR16 |
LCDC_OVR2CFG0_ROTDIS);
sam_putreg(SAM_LCDC_OVR2CFG1,
LCDC_OVR2CFG1_16BPP_RGB565);
sam_putreg(SAM_LCDC_OVR2CFG9,
LCDC_OVR2CFG9_GA(0xff) | LCDC_OVR2CFG9_GAEN);
# else
# error Support for this resolution is not yet implemented
# endif
#endif
#ifdef CONFIG_SAMA5_LCDC_HEO
# if defined(CONFIG_SAMA5_LCDC_HEO_RGB888P)
LAYER_HEO.bpp = 24;
sam_putreg(SAM_LCDC_HEOCFG0,
LCDC_HEOCFG0_DLBO | LCDC_HEOCFG0_BLEN_INCR16 |
LCDC_HEOCFG0_ROTDIS);
sam_putreg(SAM_LCDC_HEOCFG1,
LCDC_HEOCFG1_24BPP_RGB888P);
sam_putreg(SAM_LCDC_HEOCFG12,
LCDC_HEOCFG12_GA(0xff) | LCDC_HEOCFG12_GAEN);
# elif defined(CONFIG_SAMA5_LCDC_HEO_RGB565)
LAYER_HEO.bpp = 16;
sam_putreg(SAM_LCDC_HEOCFG0,
LCDC_HEOCFG0_DLBO | LCDC_HEOCFG0_BLEN_INCR16 |
LCDC_HEOCFG0_ROTDIS);
sam_putreg(SAM_LCDC_HEOCFG1,
LCDC_HEOCFG1_16BPP_RGB565);
sam_putreg(SAM_LCDC_HEOCFG9,
LCDC_HEOCFG9_GA(0xff) | LCDC_HEOCFG9_GAEN);
# else
# error Support for this resolution is not yet implemented
# endif
#endif
#ifdef SAMA5_HAVE_LCDC_HCRCH
#ifdef CONFIG_SAMA5_LCDC_HCR
# if defined(CONFIG_SAMA5_LCDC_HCR_RGB888P)
LAYER_HCR.bpp = 24;
sam_putreg(SAM_LCDC_HCRCFG0,
LCDC_HCRCFG0_DLBO | LCDC_HCRCFG0_BLEN_INCR16);
sam_putreg(SAM_LCDC_HCRCFG1,
LCDC_HCRCFG1_24BPP_RGB888P;
sam_putreg(SAM_LCDC_HCRCFG7,
0x000000);
sam_putreg(SAM_LCDC_HCRCFG8,
0xffffff);
sam_putreg(SAM_LCDC_HCRCFG9,
LCDC_HCRCFG9_GAEN(0xff) | LCDC_HCRCFG9_GAEN);
# elif defined(CONFIG_SAMA5_LCDC_HCR_RGB565)
LAYER_HCR.bpp = 16;
sam_putreg(SAM_LCDC_HCRCFG0,
LCDC_HCRCFG0_DLBO | LCDC_HCRCFG0_BLEN_INCR16 |
LCDC_HCRCFG0_ROTDIS);
sam_putreg(SAM_LCDC_HCRCFG1,
LCDC_HCRCFG1_16BPP_RGB565);
sam_putreg(SAM_LCDC_HCRCFG9,
LCDC_HCRCFG9_GA(0xff) | LCDC_HCRCFG9_GAEN);
# else
# error Support for this resolution is not yet implemented
# endif
#endif
#endif
}
* Name: sam_lcd_enable
*
* Description:
* Enable the LCD for normal use
*
****************************************************************************/
static void sam_lcd_enable(void)
{
uint32_t regval;
uint32_t div;
sam_lcdc_enableclk();
sam_putreg(SAM_PMC_SCER, PMC_LCDCK);
#ifdef BOARD_LCDC_MCK_MUL2
div = (2*BOARD_MCK_FREQUENCY + (BOARD_LCDC_PIXELCLOCK - 1)) /
BOARD_LCDC_PIXELCLOCK;
#else
div = (BOARD_MCK_FREQUENCY + (BOARD_LCDC_PIXELCLOCK - 1)) /
BOARD_LCDC_PIXELCLOCK;
#endif
DEBUGASSERT(div > 1);
regval = LCDC_LCDCFG0_CGDISBASE | LCDC_LCDCFG0_CLKDIV(div - 2);
#ifdef BOARD_LCDC_PIXCLK_INV
regval |= LCDC_LCDCFG0_CLKPOL;
#endif
#ifdef BOARD_LCDC_PWMCLK
regval |= LCDC_LCDCFG0_CLKPWMSEL;
#endif
#ifdef BOARD_LCDC_MCK_MUL2
regval |= LCDC_LCDCFG0_CLKSEL;
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR1
regval |= LCDC_LCDCFG0_CGDISOVR1;
#endif
#ifdef CONFIG_SAMA5_LCDC_OVR2
regval |= LCDC_LCDCFG0_CGDISOVR2;
#endif
#ifdef CONFIG_SAMA5_LCDC_HEO
regval |= LCDC_LCDCFG0_CGDISHEO;
#endif
#ifdef CONFIG_SAMA5_LCDC_HCR
regval |= LCDC_LCDCFG0_CGDISHCR;
#endif
sam_putreg(SAM_LCDC_LCDCFG0, regval);
regval = LCDC_LCDCFG1_HSPW(BOARD_LCDC_HSPW - 1) |
LCDC_LCDCFG1_VSPW(BOARD_LCDC_VSPW - 1);
sam_putreg(SAM_LCDC_LCDCFG1, regval);
regval = LCDC_LCDCFG2_VFPW(BOARD_LCDC_VFPW - 1) |
LCDC_LCDCFG2_VBPW(BOARD_LCDC_VBPW);
sam_putreg(SAM_LCDC_LCDCFG2, regval);
regval = LCDC_LCDCFG3_HFPW(BOARD_LCDC_HFPW - 1) |
LCDC_LCDCFG3_HBPW(BOARD_LCDC_HBPW - 1);
sam_putreg(SAM_LCDC_LCDCFG3, regval);
regval = LCDC_LCDCFG4_PPL(BOARD_LCDC_WIDTH - 1) |
LCDC_LCDCFG4_RPF(BOARD_LCDC_HEIGHT - 1);
sam_putreg(SAM_LCDC_LCDCFG4, regval);
regval = LCDC_LCDCFG5_HSPOL | LCDC_LCDCFG5_VSPOL |
LCDC_LCDCFG5_VSPDLYS | LCDC_LCDCFG5_DISPDLY |
LCDC_LCDCFG5_GUARDTIME(BOARD_LCDC_GUARDTIME);
#if BOARD_LCDC_OUTPUT_BPP == 16
regval |= LCDC_LCDCFG5_MODE_12BPP;
#elif BOARD_LCDC_OUTPUT_BPP == 16
regval |= LCDC_LCDCFG5_MODE_16BPP;
#elif BOARD_LCDC_OUTPUT_BPP == 18
regval |= LCDC_LCDCFG5_MODE_18BPP;
#elif BOARD_LCDC_OUTPUT_BPP == 24
regval |= LCDC_LCDCFG5_MODE_24BPP;
#else
# error Unknown or undefined output resolution
#endif
sam_putreg(SAM_LCDC_LCDCFG5, regval);
regval = BOARD_LCDC_PWMPS | BOARD_LCDC_PWMPOL |
LCDC_LCDCFG6_PWMCVAL(CONFIG_SAMA5_LCDC_DEFBACKLIGHT);
sam_putreg(SAM_LCDC_LCDCFG6, regval);
* LCDC_LCDEN register.
*/
sam_putreg(SAM_LCDC_LCDEN, LCDC_LCDEN_CLK);
* is running.
*/
sam_wait_lcdstatus(LCDC_LCDSR_SIP | LCDC_LCDSR_CLK, LCDC_LCDSR_CLK);
* SYNCEN field of the LCDC_LCDEN register.
*/
sam_putreg(SAM_LCDC_LCDEN, LCDC_LCDEN_SYNC);
* synchronization is up.
*/
sam_wait_lcdstatus(LCDC_LCDSR_SIP | LCDC_LCDSR_LCD, LCDC_LCDSR_LCD);
* the LCDC_LCDEN register.
*/
sam_putreg(SAM_LCDC_LCDEN, LCDC_LCDEN_DISP);
* signal is activated.
*/
sam_wait_lcdstatus(LCDC_LCDSR_SIP | LCDC_LCDSR_DISP, LCDC_LCDSR_DISP);
}
* Name: sam_layer_configure
*
* Description:
* Configure layer layer structures, DMA descriptor memory, and
* framebuffers
*
****************************************************************************/
static void sam_layer_configure(void)
{
memset(&LAYER_BASE, 0, sizeof(struct sam_layer_s));
LAYER_BASE.dscr = (struct sam_dscr_s *)SAMA5_LCDC_BASE_DSCR;
LAYER_BASE.lid = LCDC_LAYER_BASE;
LAYER_BASE.framebuffer = (uint8_t *)SAMA5_LCDC_BUFFER_BASE;
memset(&LAYER_OVR1, 0, sizeof(struct sam_layer_s));
LAYER_OVR1.dscr = (struct sam_dscr_s *)SAMA5_LCDC_OVR1_DSCR;
LAYER_OVR1.lid = LCDC_LAYER_OVR1;
#ifdef CONFIG_SAMA5_LCDC_OVR1
LAYER_OVR1.framebuffer = (uint8_t *)SAMA5_LCDC_BUFFER_OVR1;
#endif
memset(&LAYER_OVR2, 0, sizeof(struct sam_layer_s));
LAYER_OVR2.dscr = (struct sam_dscr_s *)SAMA5_LCDC_OVR2_DSCR;
LAYER_OVR2.lid = LCDC_LAYER_OVR2;
#ifdef CONFIG_SAMA5_LCDC_OVR2
LAYER_OVR2.framebuffer = (uint8_t *)SAMA5_LCDC_BUFFER_OVR2;
#endif
memset(&LAYER_HEO, 0, sizeof(struct sam_layer_s));
LAYER_HEO.dscr = (struct sam_dscr_s *)SAMA5_LCDC_HEO_DSCR;
LAYER_HEO.lid = LCDC_LAYER_HEO;
#ifdef CONFIG_SAMA5_LCDC_HEO
LAYER_HEO.framebuffer = (uint8_t *)SAMA5_LCDC_BUFFER_HEO;
#endif
#ifdef SAMA5_HAVE_LCDC_HCRCH
memset(&LAYER_HCR, 0, sizeof(struct sam_layer_s));
LAYER_HCR.dscr = (struct sam_dscr_s *)SAMA5_LCDC_HCR_DSCR;
LAYER_HCR.lid = LCDC_LAYER_HCR;
#ifdef CONFIG_SAMA5_LCDC_HCR
LAYER_HCR.framebuffer = (uint8_t *)SAMA5_LCDC_BUFFER_HCR;
#endif
#endif
}
* Name: sam_scalefactor
*
* Description:
* Calculate HEO scale factor
*
* Input Parameters:
* oldw - the old image width
* neww - The new image width
*
****************************************************************************/
#ifdef CONFIG_SAMA5_LCDC_HEO
static uint32_t sam_scalefactor(uint32_t oldw, uint32_t neww)
{
return 2048 * (neww + 1) / (oldw + 1);
}
#endif
* Name: sam_show_layer
*
* Description:
* Show the give layer with the specified orientation and (perhaps)
* scaling.
*
****************************************************************************/
static void sam_show_layer(struct sam_layer_s *layer,
uint32_t dispx, uint32_t dispy,
uint32_t dispw, uint32_t disph,
uint32_t imgw, uint32_t imgh)
{
struct sam_dscr_s *dscr;
uint8_t *buffer;
uintptr_t cfgaddr;
uintptr_t regaddr;
uint32_t padding = 0;
uint32_t regval;
uint32_t bytesprow;
uint32_t bytespp;
uint32_t bprow;
bool bottomup;
bool rightleft;
int lid;
DEBUGASSERT(layer && layer->dscr);
if (dispx + dispw > BOARD_LCDC_WIDTH)
{
dispw = BOARD_LCDC_WIDTH - dispx;
}
if (dispy + disph > BOARD_LCDC_HEIGHT)
{
disph = BOARD_LCDC_HEIGHT - dispy;
}
if (dispw <= 0)
{
dispw = 1;
}
if (disph <= 0)
{
disph = 1;
}
if (imgw <= 0)
{
imgw = 1;
}
if (imgh <= 0)
{
imgh = 1;
}
bytespp = (uint32_t)layer->bpp >> 3;
bprow = imgw * (uint32_t)layer->bpp;
bytesprow = bprow >> 3;
if ((bprow & 7) != 0)
{
bytesprow++;
}
padding = 0;
if ((bytesprow & 3) != 0)
{
padding = 4 - (bytesprow & 0x3);
}
bottomup = (layer->flags & LCDC_FLAG_BOTTOMUP) != 0;
rightleft = (layer->flags & LCDC_FLAG_RIGHTLEFT) != 0;
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
rightleft = false;
}
#endif
dscr = layer->dscr;
lid = layer->lid;
buffer = layer->framebuffer;
cfgaddr = g_layercfg[lid];
if ((!rightleft && !bottomup && layer->rotation == LCDC_ROT_0) ||
(rightleft && bottomup && layer->rotation == LCDC_ROT_180))
{
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0);
}
#endif
regaddr = g_layerstride[lid];
sam_putreg(regaddr, padding);
}
else if ((rightleft && !bottomup && layer->rotation == LCDC_ROT_0) ||
(!rightleft && bottomup && layer->rotation == LCDC_ROT_180))
{
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0 - 2*bytespp);
}
#endif
regaddr = g_layerstride[lid];
sam_putreg(regaddr, 2*bytesprow + padding - 2*bytespp);
buffer = (uint8_t *)
((uint32_t)layer->framebuffer + bytespp * (imgw - 1));
}
else if ((!rightleft && bottomup && layer->rotation == LCDC_ROT_0) ||
(rightleft && !bottomup && layer->rotation == LCDC_ROT_180))
{
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0);
}
#endif
regaddr = g_layerstride[lid];
sam_putreg(regaddr, 0 - (2*bytesprow + padding));
buffer = (uint8_t *)
((uintptr_t)layer->framebuffer + (bytesprow + padding) * (imgh - 1));
}
else if ((rightleft && bottomup && layer->rotation == LCDC_ROT_0) ||
(!rightleft && !bottomup && layer->rotation == LCDC_ROT_180))
{
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0 - 2*bytespp;
}
#endif
regaddr = g_layerstride[lid];
sam_putreg(regaddr, 0 - (2*bytespp + padding));
buffer = (uint8_t *)
((uint32_t)layer->framebuffer +
(bytesprow + padding) * (imgh - 1) +
bytespp * (imgw - 1));
}
else if ((!rightleft && !bottomup && layer->rotation == LCDC_ROT_90) ||
(rightleft && bottomup && layer->rotation == LCDC_ROT_270))
{
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0 - (bytespp + bytesprow + padding));
}
#endif
regaddr = g_layerstride[lid];
sam_putreg(regaddr, (bytesprow + padding) * (imgh - 1));
buffer = (uint8_t *)
((uint32_t)layer->framebuffer +
(bytesprow + padding) * (imgh - 1));
}
else if ((!rightleft && !bottomup && layer->rotation == LCDC_ROT_270) ||
(rightleft && bottomup && layer->rotation == LCDC_ROT_90))
{
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, bytesprow + padding - bytespp);
}
#endif
regaddr = g_layerstride[lid];
sam_putreg(regaddr,
0 - 2 * bytespp - (bytesprow + padding) * (imgh - 1));
buffer = (uint8_t *)
((uintptr_t)layer->framebuffer + bytespp * (imgw - 1));
}
else if ((rightleft && !bottomup && layer->rotation == LCDC_ROT_90) ||
(!rightleft && bottomup && layer->rotation == LCDC_ROT_270))
{
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, 0 - (bytespp + bytesprow + padding));
}
#endif
regaddr = g_layerstride[lid];
sam_putreg(regaddr,
0 - 2 * bytespp + (bytesprow + padding) * (imgh - 1));
buffer = (uint8_t *)
((uintptr_t)layer->framebuffer +
(bytesprow + padding) * (imgh - 1) +
(bytespp) * (imgw - 1));
}
else if ((!rightleft && bottomup && layer->rotation == 90) ||
(rightleft && !bottomup && layer->rotation == LCDC_ROT_270))
{
regval = sam_getreg(cfgaddr);
regval |= LCDC_HEOCFG0_ROTDIS;
sam_putreg(cfgaddr, regval);
#ifdef SAMA5_HAVE_PSTRIDE
regaddr = g_layerpstride[lid];
if (regaddr)
{
sam_putreg(regaddr, bytesprow + padding - bytespp);
}
#endif
regaddr = g_layerstride[lid];
sam_putreg(regaddr, 0 - (bytesprow + padding) * (imgh - 1));
}
sam_dmasetup(lid, dscr, buffer);
#ifdef SAMA5_HAVE_POSITION
regaddr = g_layerpos[lid];
if (regaddr)
{
sam_putreg(regaddr,
LCDC_HEOCFG2_XPOS(dispx) | LCDC_HEOCFG2_YPOS(dispy));
}
#endif
#ifdef SAMA5_HAVE_SIZE
regaddr = g_layersize[lid];
if (regaddr)
{
sam_putreg(regaddr,
LCDC_HEOCFG3_XSIZE(dispw - 1) |
LCDC_HEOCFG3_YSIZE(disph - 1);
}
#endif
#ifdef CONFIG_SAMA5_LCDC_HEO
if (lid == LCDC_HEO)
{
uint32_t srcw;
uint32_t srch;
if (layer->rotation == LCDC_ROT_90 || layer->rotation == LCDC_ROT_270)
{
srcw = imgh;
srch = imgw;
}
else
{
srcw = imgw;
srch = imgh;
}
sam_putreg(SAM_LCDC_HEOCFG4,
LCDC_HEOCFG4_XMEM_SIZE(srcw - 1) |
LCDC_HEOCFG4_YMEM_SIZE(srch - 1));
if (dispw != srcw || disph != srch)
{
uint16_t xfactor;
uint16_t yfactor;
xfactor = sam_scalefactor(dispw, srcw);
yfactor = sam_scalefactor(disph, srch);
sam_putreg(LCDC_HEOCFG13,
LCDC_HEOCFG13_YFACTOR(yfactor) |
LCDC_HEOCFG13_XFACTOR(xfactor) |
LCDC_HEOCFG13_SCALEN;
}
else
{
sam_putreg(LCDC_HEOCFG13, 0);
}
}
#endif
if (buffer)
{
regaddr = g_layerblend[lid];
regval = sam_getreg(regaddr);
regval |= LCDC_HEOCFG12_DMA | LCDC_HEOCFG12_OVR;
sam_putreg(regaddr, regval);
}
* CHXCHER register.
*/
regaddr = g_layerenable[lid];
sam_putreg(regaddr, LCDC_HEOCHER_UPDATE | LCDC_HEOCHER_CH);
* loaded.
*/
}
* Name: sam_show_base
*
* Description:
* Show the base layer
*
****************************************************************************/
static void sam_show_base(void)
{
sam_show_layer(&LAYER_BASE, 0, 0,
BOARD_LCDC_WIDTH, BOARD_LCDC_HEIGHT,
BOARD_LCDC_WIDTH, BOARD_LCDC_HEIGHT);
}
* Name: sam_show_hcr
*
* Description:
* Show the hardware cursor layer
*
****************************************************************************/
#ifdef CONFIG_SAMA5_LCDC_HCR
static void sam_show_hcr(void)
{
uint32_t regval;
sam_putreg(SAM_LCDC_HCRCFG7, 0x00000000);
sam_putreg(SAM_LCDC_HCRCFG8, 0xffffffff);
regval = sam_getreg(SAM_LCDC_HCRCFG9);
regval |= LCDC_HCRCFG9_CRKEY;
sam_putreg(SAM_LCDC_HCRCFG9, regval);
sam_show_layer(&LAYER_HCR,
(BOARD_LCDC_WIDTH - CONFIG_SAMA5_LCDC_HCR_MAXWIDTH) / 2,
(BOARD_LCDC_HEIGHT - CONFIG_SAMA5_LCDC_HCR_MAXHEIGHT) / 2,
CONFIG_SAMA5_LCDC_HCR_MAXWIDTH, CONFIG_SAMA5_LCDC_HCR_MAXHEIGHT,
CONFIG_SAMA5_LCDC_HCR_MAXWIDTH, CONFIG_SAMA5_LCDC_HCR_MAXHEIGHT);
}
#endif
* Public Functions
****************************************************************************/
* Name: up_fbinitialize
*
* Description:
* Initialize the framebuffer video hardware associated with the display.
*
* Input Parameters:
* display - In the case of hardware with multiple displays, this
* specifies the display. Normally this is zero.
*
* Returned Value:
* Zero is returned on success; a negated errno value is returned on any
* failure.
*
****************************************************************************/
int up_fbinitialize(int display)
{
#if defined(CONFIG_SAMA5_LCDC_OVR1) && defined(CONFIG_SAMA5_LCDC_HEO)
uint32_t regval;
#endif
lcdinfo("Entry\n");
* framebuffers
*/
sam_layer_configure();
sam_lcd_disable();
sam_pio_config();
lcdinfo("Configuring the LCD controller\n");
sam_lcdc_enableclk();
sam_putreg(SAM_PMC_SCER, PMC_LCDCK);
sam_putreg(SAM_LCDC_LCDIDR, LCDC_LCDINT_ALL);
sam_layer_orientation();
sam_layer_color();
sam_lcdclear(CONFIG_SAMA5_LCDC_BACKCOLOR);
lcdinfo("Enabling the display\n");
sam_lcd_enable();
sam_show_base();
#if defined(CONFIG_SAMA5_LCDC_OVR1) && defined(CONFIG_SAMA5_LCDC_HEO)
regval = sam_getreg(SAM_LCDC_HEOCFG12);
regval |= LCDC_HEOCFG12_VIDPRI;
sam_putreg(SAM_LCDC_HEOCFG12, regval);
sam_putreg(SAM_LCDC_HEOCHER, LCDC_HEOCHER_UPDATE);
#endif
#ifdef CONFIG_SAMA5_LCDC_HCR
sam_show_hcr();
#endif
*
* REVISIT: Backlight level could be dynamically adjustable
*/
sam_backlight(CONFIG_SAMA5_LCDC_DEFBACKLIGHT);
return OK;
}
* Name: up_fbgetvplane
*
* Description:
* Return a a reference to the framebuffer object for the specified video
* plane of the specified plane. Many OSDs support multiple planes of
* video.
*
* Input Parameters:
* display - In the case of hardware with multiple displays, this
* specifies the display. Normally this is zero.
* vplane - Identifies the plane being queried.
*
* Returned Value:
* A non-NULL pointer to the frame buffer access structure is returned on
* success; NULL is returned on any failure.
*
****************************************************************************/
struct fb_vtable_s *up_fbgetvplane(int display, int vplane)
{
lcdinfo("vplane: %d\n", vplane);
if (vplane == 0)
{
return (struct fb_vtable_s *)&g_base_vtable;
}
else
{
return NULL;
}
}
* Name: up_fbuninitialize
*
* Description:
* Uninitialize the framebuffer support for the specified display.
*
* Input Parameters:
* display - In the case of hardware with multiple displays, this
* specifies the display. Normally this is zero.
*
* Returned Value:
* None
*
****************************************************************************/
void up_fbuninitialize(int display)
{
sam_lcd_disable();
}
* Name: sam_lcdclear
*
* Description:
* This is a non-standard LCD interface just for the SAMA5. Clearing the
* display in the normal way by writing a sequences of runs that covers
* the entire display can be slow. Here the display is cleared by simply
* setting all video memory to the specified color.
*
****************************************************************************/
void sam_lcdclear(nxgl_mxpixel_t color)
{
#if SAMA5_LCDC_BASE_BPP == 16
uint16_t *dest = (uint16_t *)LAYER_BASE.framebuffer;
int i;
lcdinfo("Clearing display: BPP=16 color=%04jx framebuffer=%p size=%d\n",
(intmax_t)color, LAYER_BASE.framebuffer, SAMA5_BASE_FBSIZE);
for (i = 0; i < SAMA5_BASE_FBSIZE; i += sizeof(uint16_t))
{
*dest++ = (uint16_t)color;
}
#elif SAMA5_LCDC_BASE_BPP == 24
uint8_t *dest = (uint8_t *)LAYER_BASE.framebuffer;
uint8_t r;
uint8_t g;
uint8_t b;
int i;
lcdinfo("Clearing display: BPP=24 color=%" PRIx32
" framebuffer=%x size=%d\n", color, *dest, SAMA5_BASE_FBSIZE);
b = color & 0xff;
g = (color >> 8) & 0xff;
r = (color >> 16) & 0xff;
for (i = 0; i < SAMA5_BASE_FBSIZE; i += 3*sizeof(uint8_t))
{
*dest++ = b;
*dest++ = g;
*dest++ = r;
}
#elif SAMA5_LCDC_BASE_BPP == 32
uint32_t *dest = (uint32_t *)LAYER_BASE.framebuffer;
int i;
lcdinfo("Clearing display: BPP=32 color=%" PRIx32
" framebuffer=%" PRIx32 " size=%d\n",
color, *dest, SAMA5_BASE_FBSIZE);
for (i = 0; i < SAMA5_BASE_FBSIZE; i += sizeof(uint32_t))
{
*dest++ = (uint32_t)color;
}
#endif
}