mirror of
https://github.com/apache/nuttx.git
synced 2026-08-02 12:49:00 +00:00
This commit brings in an initial LCD driver sof the AM335x architecture. This is a work in progress and so depends on EXPERIMENTAL. The code is nearly compete, missing some clock configureation settings. It does compile properly.
Squashed commit of the following:
arch/arm/src/am335x/am335x_lcdc.c: LCD driver now compiles.
arch/arm/src/am335x/am335x_lcd.c: This brings the LCD driver to code complete. Have not yet attempted to compile.
arch/arm/src/am335x/am335x_edid.c: Framebuffer is pre-allocated. In verification of video mode, include a test to assure that the video mode can be supported by the pre-allocated framebuffer memory.
arch/arm/src/am335x/am335x_lcd.c: At a little bit of LCD initialization logic. There is a long way to go.
arch/arm/src/am335x/am335x_edid.c: Add am335x_lcd_videomode() which provides an alternative way of initializing the LCD controller.
arch/arm/src/am335x/am335x_edid.c: edit.h has move to include/nuttx/video.
arch/arm/src/am335x/hardware/am335x_cm.h: Fix a typo in a macro name.
arch/arm/src/am335x/am335x_edid.c: Integrate video/edid support.
arch/arm/src/am335x/am335x_edid.c: Fall back to VGA mode is not valid videomode is availabe in the EDID data.
arch/arm/src/am335x/am335x_edid.c: Fixes for a partially clean compile.
arch/arm/src/am335x/am335x_edid.c: Add basic logic to convert EDID montor descriptions into a form usable for LCD configuration.
arch/arm/src/am335x: Add framework (only) for an LCD driver. Initial commit is simply the LPC54 framebuffer driver with naming changes.
This commit is contained in:
parent
2b25d56bfd
commit
b58f598d31
6 changed files with 1668 additions and 8 deletions
|
|
@ -94,16 +94,18 @@ config AM335X_GPIO
|
|||
bool "GPIO"
|
||||
default n
|
||||
|
||||
config AM335X_LCDC
|
||||
bool "LCD controller"
|
||||
default n
|
||||
depends on VIDEO && EXPERIMENTAL
|
||||
select VIDEO_EDID
|
||||
|
||||
config AM335X_TSC
|
||||
bool "Touchscreen Controller"
|
||||
default n
|
||||
|
||||
config AM335X_LCDC
|
||||
bool "LCD Controller"
|
||||
default n
|
||||
|
||||
config AM335X_CPSW
|
||||
bool "Ethernet subsustem"
|
||||
bool "Ethernet subsystem"
|
||||
default n
|
||||
|
||||
config AM335X_PWMSS
|
||||
|
|
@ -248,4 +250,121 @@ config AM335X_DDR_MAPSIZE
|
|||
plus the size of the available heap. NOTE that RAM_SIZE may not
|
||||
include all of SDRAM up to the end of mapped region.
|
||||
|
||||
menu "LCD Configuration"
|
||||
depends on AM335X_LCDC
|
||||
|
||||
config AM335X_LCDC_VRAMBASE
|
||||
hex "Video RAM base address"
|
||||
default 0xa0010000
|
||||
---help---
|
||||
Base address of the video RAM frame buffer. The default is
|
||||
(AM335X_EXTDRAM_CS0 + 0x00010000)
|
||||
|
||||
config AM335X_LCDC_USE_CLKIN
|
||||
bool "Use optional input clock"
|
||||
default n
|
||||
|
||||
config AM335X_LCDC_CLKIN_FREQUENCY
|
||||
int "Input clock frequency"
|
||||
default 0
|
||||
depends on AM335X_LCDC_USE_CLKIN
|
||||
|
||||
config AM335X_LCDC_REFRESH_FREQ
|
||||
int "LCD refesh rate (Hz)"
|
||||
default 50
|
||||
---help---
|
||||
LCD refesh rate (Hz)
|
||||
|
||||
choice
|
||||
prompt "Bits per pixel"
|
||||
default AM335X_LCDC_BPP16_565
|
||||
|
||||
config AM335X_LCDC_BPP1
|
||||
bool "1 BPP"
|
||||
|
||||
config AM335X_LCDC_BPP2
|
||||
bool "2 BPP"
|
||||
|
||||
config AM335X_LCDC_BPP4
|
||||
bool "4 BPP"
|
||||
|
||||
config AM335X_LCDC_BPP8
|
||||
bool "8 BPP"
|
||||
|
||||
config AM335X_LCDC_BPP12_444
|
||||
bool "12 bpp, 4:4:4 mode"
|
||||
|
||||
config AM335X_LCDC_BPP16_565
|
||||
bool "16 BPP, 5:6:5 mode"
|
||||
|
||||
config AM335X_LCDC_BPP24
|
||||
bool "24 BPP, 8:8:8 mode (packed)"
|
||||
|
||||
config AM335X_LCDC_BPP32
|
||||
bool "32 BPP, 8:8:8 mode (unpacked)"
|
||||
|
||||
endchoice
|
||||
|
||||
config AM335X_LCDC_BGR
|
||||
bool "Blue-Green-Red color order"
|
||||
default n
|
||||
depends on !AM335X_LCDC_MONOCHROME
|
||||
---help---
|
||||
This option selects BGR color order vs. default RGB
|
||||
|
||||
config AM335X_LCDC_BACKCOLOR
|
||||
hex "Initial background color"
|
||||
default 0x0
|
||||
---help---
|
||||
Initial background color
|
||||
|
||||
config AM335X_LCDC_ACBIAS
|
||||
int "AC bias pin frequency"
|
||||
default 255
|
||||
range 0 255
|
||||
|
||||
config AM335X_LCDC_ACBIAS_PINT
|
||||
int "AC bias pin transitions per interrupt"
|
||||
default 0
|
||||
range 0 15
|
||||
|
||||
choice
|
||||
prompt "DMA burst size"
|
||||
default AM335X_LCDC_DMA_BURST16
|
||||
|
||||
config AM335X_LCDC_DMA_BURST1
|
||||
bool "1"
|
||||
|
||||
config AM335X_LCDC_DMA_BURST2
|
||||
bool "2"
|
||||
|
||||
config AM335X_LCDC_DMA_BURST4
|
||||
bool "4"
|
||||
|
||||
config AM335X_LCDC_DMA_BURST8
|
||||
bool "8"
|
||||
|
||||
config AM335X_LCDC_DMA_BURST16
|
||||
bool "16"
|
||||
|
||||
endchoice
|
||||
|
||||
config AM335X_LCDC_FDD
|
||||
int "Palette loading delay"
|
||||
default 128
|
||||
range 0 255
|
||||
|
||||
config AM335X_LCDC_SYNC_EDGE
|
||||
bool "HSYNC/VSYNC rise or fall"
|
||||
default n
|
||||
|
||||
config AM335X_LCDC_SYNC_CTRL
|
||||
bool "Hsync/Vsync pixel clock control on/off"
|
||||
default y
|
||||
|
||||
config AM335X_LCDC_PIXCLK_INVERT
|
||||
bool "Invert pixel clock"
|
||||
default y
|
||||
|
||||
endmenu # LCD Configuration
|
||||
endif # ARCH_CHIP_AM335X
|
||||
|
|
|
|||
|
|
@ -133,4 +133,8 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_AM335X_GPIO_IRQ),y)
|
||||
CHIP_CSRCS += am335x_gpioirq.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AM335X_LCDC),y)
|
||||
CHIP_CSRCS += am335x_lcdc.c am335x_edid.c
|
||||
endif
|
||||
|
|
|
|||
402
arch/arm/src/am335x/am335x_edid.c
Normal file
402
arch/arm/src/am335x/am335x_edid.c
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/am335x/am335x_wdog.c
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* The LCD driver derives from the LPC54xx LCD driver but also includes
|
||||
* information from the FreeBSD AM335x LCD driver which was released under
|
||||
* a two-clause BSD license:
|
||||
*
|
||||
* Copyright 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name NuttX 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/video/edid.h>
|
||||
|
||||
#include "am335x_lcdc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor definitions Functions
|
||||
****************************************************************************/
|
||||
|
||||
#define MODE_HBP(mode) ((mode)->htotal - (mode)->hsync_end)
|
||||
#define MODE_HFP(mode) ((mode)->hsync_start - (mode)->hdisplay)
|
||||
#define MODE_HSW(mode) ((mode)->hsync_end - (mode)->hsync_start)
|
||||
#define MODE_VBP(mode) ((mode)->vtotal - (mode)->vsync_end)
|
||||
#define MODE_VFP(mode) ((mode)->vsync_start - (mode)->vdisplay)
|
||||
#define MODE_VSW(mode) ((mode)->vsync_end - (mode)->vsync_start)
|
||||
|
||||
#define MAX_PIXEL_CLOCK 126000
|
||||
#define MAX_BANDWIDTH (1280*1024*60)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_edid
|
||||
*
|
||||
* Description:
|
||||
* Return the vertical refresh rate for this video mode.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t
|
||||
am335x_videomode_vrefresh(FAR const struct edid_videomode_s *videomode)
|
||||
{
|
||||
uint32_t refresh;
|
||||
|
||||
/* Calculate vertical refresh rate */
|
||||
|
||||
refresh = (videomode->dotclock * 1000 / videomode->htotal);
|
||||
refresh = (refresh + videomode->vtotal / 2) / videomode->vtotal;
|
||||
|
||||
if (videomode->flags & VID_INTERLACE)
|
||||
{
|
||||
refresh *= 2;
|
||||
}
|
||||
|
||||
if (videomode->flags & VID_DBLSCAN)
|
||||
{
|
||||
refresh /= 2;
|
||||
}
|
||||
|
||||
return refresh;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_videomode_valid
|
||||
*
|
||||
* Description:
|
||||
* Return true if the provided video mode is valid.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool
|
||||
am335x_videomode_valid(FAR const struct edid_videomode_s *videomode,
|
||||
FAR const struct am335x_fbinfo_s *fbinfo)
|
||||
{
|
||||
size_t fbstride;
|
||||
size_t fbsize;
|
||||
uint32_t hbp;
|
||||
uint32_t hfp;
|
||||
uint32_t hsw;
|
||||
uint32_t vbp;
|
||||
uint32_t vfp;
|
||||
uint32_t vsw;
|
||||
uint32_t vrefresh;
|
||||
|
||||
if (videomode->dotclock > MAX_PIXEL_CLOCK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (videomode->hdisplay & 0xf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (videomode->vdisplay > 2048)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check ranges for timing parameters */
|
||||
|
||||
hbp = MODE_HBP(videomode) - 1;
|
||||
hfp = MODE_HFP(videomode) - 1;
|
||||
hsw = MODE_HSW(videomode) - 1;
|
||||
vbp = MODE_VBP(videomode);
|
||||
vfp = MODE_VFP(videomode);
|
||||
vsw = MODE_VSW(videomode) - 1;
|
||||
|
||||
if (hbp > 0x3ff)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hfp > 0x3ff)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hsw > 0x3ff)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vbp > 0xff)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vfp > 0xff)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vsw > 0x3f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vrefresh = am335x_videomode_vrefresh(videomode);
|
||||
if (videomode->vdisplay * videomode->hdisplay * vrefresh > MAX_BANDWIDTH)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Finally, make sure that the framebuffer buffer region is large enough
|
||||
* to support this video mode.
|
||||
*/
|
||||
|
||||
fbstride = (videomode->hdisplay * AM335X_BPP + 7) >> 3;
|
||||
fbsize = videomode->vdisplay * fbstride;
|
||||
|
||||
if (fbsize > fbinfo->fbsize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_pickmode
|
||||
*
|
||||
* Description:
|
||||
* If there is access to Extended Display Identification Data (EDIDI),
|
||||
* then the board-specific logic may read the EDID data and use this
|
||||
* function to select an appropriate video mode.
|
||||
*
|
||||
* edid_parse() should be used to convert the raw EDID data into the
|
||||
* digested form of struct edid_info.
|
||||
*
|
||||
* The returned video mode may be used to both (1) configure HDMI and (2)
|
||||
* initialize the AM335x LCD controller.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static const struct edid_videomode_s *
|
||||
am335x_lcd_pickmode(FAR struct edid_info_s *ei,
|
||||
FAR const struct am335x_fbinfo_s *fbinfo)
|
||||
{
|
||||
FAR const struct edid_videomode_s *videomode;
|
||||
int n;
|
||||
|
||||
/* Get standard VGA as default */
|
||||
|
||||
videomode = NULL;
|
||||
|
||||
/* Pick a video mode -- First check if we can support the preferred mode. */
|
||||
|
||||
if (ei->edid_preferred_mode != NULL)
|
||||
{
|
||||
if (am335x_videomode_valid(ei->edid_preferred_mode, fbinfo))
|
||||
{
|
||||
videomode = ei->edid_preferred_mode;
|
||||
return videomode;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort video modes by refresh rate, aspect ratio (*), then resolution.
|
||||
* Preferred mode or largest mode is first in the list and other modes
|
||||
* are sorted on closest match to that mode.
|
||||
*/
|
||||
|
||||
edid_sort_modes(ei->edid_modes, &ei->edid_preferred_mode, ei->edid_nmodes);
|
||||
|
||||
/* Pick the first valid mode in the list */
|
||||
|
||||
for (n = 0; n < ei->edid_nmodes; n++)
|
||||
{
|
||||
if (am335x_videomode_valid(&ei->edid_modes[n], fbinfo))
|
||||
{
|
||||
videomode = &ei->edid_modes[n];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return videomode;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_videomode
|
||||
*
|
||||
* Description:
|
||||
* If the video mod is known, then the board-specific logic may read the
|
||||
* use this function to convert the video mode data to an instance of
|
||||
* struct am335x_panel_info_s which then may be used to initialize the
|
||||
* the LCD/
|
||||
*
|
||||
* Input Parameters:
|
||||
* videomode - A reference to the desired video mode.
|
||||
* panel - A user provided location to receive the panel data.
|
||||
*
|
||||
* Returned value:
|
||||
* None. Always succeeds.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void am335x_lcd_videomode(FAR const struct edid_videomode_s *videomode,
|
||||
FAR struct am335x_panel_info_s *panel)
|
||||
{
|
||||
lcdinfo("Detected videomode: %dx%d @ %dKHz\n",
|
||||
videomode->hdisplay, videomode->vdisplay,
|
||||
am335x_videomode_vrefresh(videomode));
|
||||
|
||||
panel->width = videomode->hdisplay;
|
||||
panel->height = videomode->vdisplay;
|
||||
panel->hfp = videomode->hsync_start - videomode->hdisplay;
|
||||
panel->hbp = videomode->htotal - videomode->hsync_end;
|
||||
panel->hsw = videomode->hsync_end - videomode->hsync_start;
|
||||
panel->vfp = videomode->vsync_start - videomode->vdisplay;
|
||||
panel->vbp = videomode->vtotal - videomode->vsync_end;
|
||||
panel->vsw = videomode->vsync_end - videomode->vsync_start;
|
||||
panel->pixelclk_active = true;
|
||||
|
||||
/* Logic for HSYNC should be reversed */
|
||||
|
||||
panel->hsync_active = ((videomode->flags & VID_NHSYNC) != 0);
|
||||
panel->vsync_active = ((videomode->flags & VID_NVSYNC) == 0);
|
||||
panel->pixclk = videomode->dotclock * 1000;
|
||||
|
||||
/* Set other values to the default */
|
||||
|
||||
#ifdef CONFIG_AM335X_LCDC_SYNC_EDGE
|
||||
panel->sync_edge = true;
|
||||
#else
|
||||
panel->sync_edge = false;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AM335X_LCDC_SYNC_CTRL
|
||||
panel->sync_ctrl = true;
|
||||
#else
|
||||
panel->sync_ctrl = false;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AM335X_LCDC_PIXCLK_INVERT
|
||||
panel->pixelclk_active = true;
|
||||
#else
|
||||
panel->pixelclk_active = false;
|
||||
#endif
|
||||
|
||||
panel->acbias = CONFIG_AM335X_LCDC_ACBIAS;
|
||||
panel->acbias_pint = CONFIG_AM335X_LCDC_ACBIAS_PINT;
|
||||
panel->dma_burstsz = AM335X_LCD_DMA_BURSTSZ;
|
||||
panel->bpp = AM335X_BPP; /* REVISIT */
|
||||
panel->fdd = CONFIG_AM335X_LCDC_FDD;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_edid
|
||||
*
|
||||
* Description:
|
||||
* If there is access to Extended Display Identification Data (EDID),
|
||||
* then the board-specific logic may read the EDID data and use this
|
||||
* function to initialize an instance of struct am335x_panel_info_s.
|
||||
*
|
||||
* The returned video mode may optionally be returned to configure HDMI.
|
||||
*
|
||||
* Input Parameters:
|
||||
* edid - A reference to the raw EDID data.
|
||||
* len - The length of the EDID data in bytes
|
||||
* panel - A user provided location to receive the panel data.
|
||||
* selected - A user provided location to receive the selected video mode.
|
||||
* fbinfo - Provides information about the pre-allocate framebuffer
|
||||
* memory.
|
||||
*
|
||||
* Returned value:
|
||||
* None. Always succeeds. The logic will fallback to VGA mode if no
|
||||
* EDID data is provided or if there is no valid video mode in the EDID
|
||||
* data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void am335x_lcd_edid(FAR const uint8_t *edid, size_t edid_len,
|
||||
FAR struct am335x_panel_info_s *panel,
|
||||
FAR struct edid_videomode_s *selected,
|
||||
FAR const struct am335x_fbinfo_s *fbinfo)
|
||||
{
|
||||
FAR const struct edid_videomode_s *videomode = NULL;
|
||||
struct edid_info_s ei;
|
||||
|
||||
/* Do we have EDID data? */
|
||||
|
||||
if (edid != NULL && edid_len > 0)
|
||||
{
|
||||
/* Parse the EDID data */
|
||||
|
||||
if (edid_parse(edid, &ei) == 0)
|
||||
{
|
||||
videomode = am335x_lcd_pickmode(&ei, fbinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcderr("ERROR: Failed to parse EDID\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Use standard VGA as fallback */
|
||||
|
||||
if (videomode == NULL)
|
||||
{
|
||||
videomode = edid_mode_lookup("640x480x60");
|
||||
DEBUGASSERT(videomode != NULL);
|
||||
}
|
||||
|
||||
/* Initialize the LCD using the selected video mode */
|
||||
|
||||
am335x_lcd_videomode(videomode, panel);
|
||||
|
||||
/* Return the selected video mode */
|
||||
|
||||
if (selected != NULL)
|
||||
{
|
||||
memcpy(selected, videomode, sizeof(struct edid_videomode_s));
|
||||
}
|
||||
}
|
||||
821
arch/arm/src/am335x/am335x_lcdc.c
Normal file
821
arch/arm/src/am335x/am335x_lcdc.c
Normal file
|
|
@ -0,0 +1,821 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/am225x/am335x_lcd.c
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* This driver derives from the LPC54xx LCD driver but also includes
|
||||
* information from the FreeBSD AM335x LCD driver which was released under
|
||||
* a two-clause BSD license:
|
||||
*
|
||||
* Copyright 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name NuttX 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <semaphore.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/video/fb.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "am335x_pinmux.h"
|
||||
#include "am335x_config.h"
|
||||
#include "am335x_gpio.h"
|
||||
#include "am335x_lcdc.h"
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Get information about the video controller configuration and the
|
||||
* configuration of each color plane.
|
||||
*/
|
||||
|
||||
static int am335x_getvideoinfo(FAR struct fb_vtable_s *vtable,
|
||||
FAR struct fb_videoinfo_s *vinfo);
|
||||
static int am335x_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
|
||||
FAR struct fb_planeinfo_s *pinfo);
|
||||
|
||||
/* The following is provided only if the video hardware supports RGB color
|
||||
* mapping
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FB_CMAP
|
||||
static int am335x_getcmap(FAR struct fb_vtable_s *vtable,
|
||||
FAR struct fb_cmap_s *cmap);
|
||||
static int am335x_putcmap(FAR struct fb_vtable_s *vtable,
|
||||
FAR const struct fb_cmap_s *cmap);
|
||||
#endif
|
||||
|
||||
/* The following is provided only if the video hardware supports a hardware
|
||||
* cursor
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FB_HWCURSOR
|
||||
static int am335x_getcursor(FAR struct fb_vtable_s *vtable,
|
||||
FAR struct fb_cursorattrib_s *attrib);
|
||||
static int am335x_setcursor(FAR struct fb_vtable_s *vtable,
|
||||
FAR struct fb_setcursor_s *settings);
|
||||
#endif
|
||||
|
||||
/* Miscellaneous internal functions */
|
||||
|
||||
static int am335x_lcd_interrupt(int irq, void *context, void *arg);
|
||||
static uint32_t am335x_lcd_divisor(uint32_t reference, uint32_t freq);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* The framebuffer object -- There is no private state information in this
|
||||
* framebuffer driver.
|
||||
*/
|
||||
|
||||
struct fb_vtable_s g_fbinterface =
|
||||
{
|
||||
.getvideoinfo = am335x_getvideoinfo,
|
||||
.getplaneinfo = am335x_getplaneinfo,
|
||||
#ifdef CONFIG_FB_CMAP
|
||||
.getcmap = am335x_getcmap,
|
||||
.putcmap = am335x_putcmap,
|
||||
#endif
|
||||
#ifdef CONFIG_FB_HWCURSOR
|
||||
.getcursor = am335x_getcursor,
|
||||
.setcursor = am335x_setcursor,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct am335x_lcd_dev_s
|
||||
{
|
||||
/* Saved panel configuration */
|
||||
|
||||
struct am335x_panel_info_s panel;
|
||||
|
||||
sem_t exclsem; /* Assure mutually exclusive access */
|
||||
nxgl_coord_t stride; /* Width of framebuffer in bytes */
|
||||
size_t fbsize; /* Size of the framebuffer allocation */
|
||||
FAR void *fbmem; /* Allocated framebuffer memory (virtual) */
|
||||
FAR void *fbphys; /* Allocated framebuffer memory (physical) */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Since there is only a single LCD controller, its state structure can be
|
||||
* allocated in .bss.
|
||||
*/
|
||||
|
||||
static struct am335x_lcd_dev_s g_lcddev;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_getvideoinfo
|
||||
****************************************************************************/
|
||||
|
||||
static int am335x_getvideoinfo(FAR struct fb_vtable_s *vtable,
|
||||
FAR struct fb_videoinfo_s *vinfo)
|
||||
{
|
||||
struct am335x_lcd_dev_s *priv = &g_lcddev;
|
||||
|
||||
lcdinfo("vtable=%p vinfo=%p\n", vtable, vinfo);
|
||||
if (vtable && vinfo)
|
||||
{
|
||||
vinfo->fmt = AM335X_COLOR_FMT; /* REVISIT */
|
||||
vinfo->xres = priv->panel.width;
|
||||
vinfo->yres = priv->panel.height;
|
||||
vinfo->nplanes = 1;
|
||||
#ifdef CONFIG_FB_OVERLAY
|
||||
vinfo->noverlays = 0;
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
|
||||
lcderr("ERROR: Returning EINVAL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_getplaneinfo
|
||||
****************************************************************************/
|
||||
|
||||
static int am335x_getplaneinfo(FAR struct fb_vtable_s *vtable, int planeno,
|
||||
FAR struct fb_planeinfo_s *pinfo)
|
||||
{
|
||||
struct am335x_lcd_dev_s *priv = &g_lcddev;
|
||||
|
||||
lcdinfo("vtable=%p planeno=%d pinfo=%p\n", vtable, planeno, pinfo);
|
||||
|
||||
if (vtable != NULL && planeno == 0 && pinfo != NULL)
|
||||
{
|
||||
#ifdef CONFIG_BUILD_KERNEL
|
||||
pinfo->fbmem = priv->fbphys;
|
||||
#else
|
||||
pinfo->fbmem = priv->fbmem;
|
||||
#endif
|
||||
pinfo->fblen = priv->fbsize;
|
||||
pinfo->stride = priv->stride;
|
||||
pinfo->display = 0;
|
||||
pinfo->bpp = priv->panel.bpp;
|
||||
return OK;
|
||||
}
|
||||
|
||||
lcderr("ERROR: Returning EINVAL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_getcmap
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FB_CMAP
|
||||
static int am335x_getcmap(FAR struct fb_vtable_s *vtable,
|
||||
FAR struct fb_cmap_s *cmap)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_putcmap
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FB_CMAP
|
||||
static int am335x_putcmap(FAR struct fb_vtable_s *vtable,
|
||||
FAR const struct fb_cmap_s *cmap)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_getcursor
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FB_HWCURSOR
|
||||
static int am335x_getcursor(FAR struct fb_vtable_s *vtable,
|
||||
FAR struct fb_cursorattrib_s *attrib)
|
||||
{
|
||||
lcdinfo("vtable=%p attrib=%p\n", vtable, attrib);
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_setcursor
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_FB_HWCURSOR
|
||||
static int am335x_setcursor(FAR struct fb_vtable_s *vtable,
|
||||
FAR struct fb_setcursor_s *settings)
|
||||
{
|
||||
lcdinfo("vtable=%p settings=%p\n", vtable, settings);
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_interrupt
|
||||
****************************************************************************/
|
||||
|
||||
static int am335x_lcd_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
struct am335x_lcd_dev_s *priv = (struct am335x_lcd_dev_s *)arg;
|
||||
uint32_t regval;
|
||||
|
||||
regval = getreg32(AM335X_LCD_IRQ_STAT);
|
||||
putreg32(AM335X_LCD_IRQ_STAT, regval);
|
||||
|
||||
/* Read value back to make sure it reached the hardware */
|
||||
|
||||
regval = getreg32(AM335X_LCD_IRQ_STAT);
|
||||
if ((regval & LCD_IRQ_SYNC) != 0 || (regval & LCD_IRQ_PL) != 0)
|
||||
{
|
||||
regval = getreg32(AM335X_LCD_RASTER_CTRL);
|
||||
regval &= ~LCD_RASTER_CTRL_LCD_EN;
|
||||
putreg32(AM335X_LCD_RASTER_CTRL, regval);
|
||||
|
||||
regval = getreg32(AM335X_LCD_RASTER_CTRL);
|
||||
regval |= LCD_RASTER_CTRL_LCD_EN;
|
||||
putreg32(AM335X_LCD_RASTER_CTRL, regval);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((regval & LCD_IRQ_EOF0) != 0)
|
||||
{
|
||||
putreg32(AM335X_LCD_DMA_FB0_BASE, priv->fbphys);
|
||||
putreg32(AM335X_LCD_DMA_FB0_CEIL,
|
||||
priv->fbphys + priv->fbsize - 1);
|
||||
regval &= ~LCD_IRQ_EOF0;
|
||||
}
|
||||
|
||||
if ((regval & LCD_IRQ_EOF1) != 0)
|
||||
{
|
||||
putreg32(AM335X_LCD_DMA_FB1_BASE, priv->fbphys);
|
||||
putreg32(AM335X_LCD_DMA_FB1_CEIL,
|
||||
priv->fbphys + priv->fbsize - 1);
|
||||
regval &= ~LCD_IRQ_EOF1;
|
||||
}
|
||||
|
||||
if ((regval & LCD_IRQ_FUF) != 0)
|
||||
{
|
||||
/* TODO: Handle FUF */
|
||||
|
||||
regval &= ~LCD_IRQ_FUF;
|
||||
}
|
||||
|
||||
if ((regval & LCD_IRQ_ACB) != 0)
|
||||
{
|
||||
/* TODO: Handle ACB */
|
||||
|
||||
regval &= ~LCD_IRQ_ACB;
|
||||
}
|
||||
|
||||
done:
|
||||
putreg32(AM335X_LCD_END_INT, 0);
|
||||
|
||||
/* Read value back to make sure it reached the hardware */
|
||||
|
||||
regval = getreg32(AM335X_LCD_END_INT);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_divisor
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t am335x_lcd_divisor(uint32_t reference, uint32_t freq)
|
||||
{
|
||||
uint32_t div;
|
||||
uint32_t delta;
|
||||
uint32_t mindelta;
|
||||
int i;
|
||||
|
||||
mindelta = freq;
|
||||
div = 255;
|
||||
|
||||
/* Raster mode case: divisors are in range from 2 to 255 */
|
||||
|
||||
for (i = 2; i < 255; i++)
|
||||
{
|
||||
delta = reference / i - freq;
|
||||
if (delta < 0)
|
||||
{
|
||||
delta = -delta;
|
||||
}
|
||||
|
||||
if (delta < mindelta)
|
||||
{
|
||||
div = i;
|
||||
mindelta = delta;
|
||||
}
|
||||
}
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the AM335x for use the display described by the provided
|
||||
* instance of struct am335x_panel_info_s.
|
||||
*
|
||||
* This function must be called by board specific logic to initialize the
|
||||
* LCD. Normally the calling sequence is as follows:
|
||||
*
|
||||
* 1a. Graphics application starts and initializes the NX server via
|
||||
* boardctl(BOARDIOC_NX_START). This calls the graphics
|
||||
* initialization function nxmu_start() which, in turn, will call
|
||||
* up_fbinitialize(). Or,
|
||||
* 1b. The framebuffer character driver is initialized and calls
|
||||
* up_fbinitialize().
|
||||
* 2. The function up_fbinitialize() must reside in board specific logic
|
||||
* under configs/. It must create the instance of struct
|
||||
* am335x_panel_info_s and call this function with that instance.
|
||||
*
|
||||
* For a directly connected LCD, either (1) the struct am335x_panel_info_s
|
||||
* may be initialized with constant data or (2) the desired video mode can
|
||||
* obtained via lookup from edid_mode_lookup() and the struct
|
||||
* am335x_panel_info_s can be created with am335x_lcd_videomode().
|
||||
*
|
||||
* If there is access to Extended Display Identification Data (EDID), then
|
||||
* the board-specific logic may read the EDID data and use
|
||||
* am335x_lcd_edid() to use the EDID data to initialize the struct
|
||||
* am335x_panel_info_s instance.
|
||||
*
|
||||
* Input Parameters:
|
||||
* panel - Provides information about the connect LCD panel.
|
||||
* fbinfo - Provides information about the pre-allocate framebuffer
|
||||
* memory.
|
||||
*
|
||||
* Returned value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned in
|
||||
* the the case of a failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am335x_lcd_initialize(FAR const struct am335x_panel_info_s *panel,
|
||||
FAR const struct am335x_fbinfo_s *fbinfo)
|
||||
{
|
||||
struct am335x_lcd_dev_s *priv = &g_lcddev;
|
||||
uint32_t regval;
|
||||
uint32_t reffreq;
|
||||
uint32_t timing0;
|
||||
uint32_t timing1;
|
||||
uint32_t timing2;
|
||||
uint32_t logburst;
|
||||
uint32_t hbp;
|
||||
uint32_t hfp;
|
||||
uint32_t hsw;
|
||||
uint32_t vbp;
|
||||
uint32_t vfp;
|
||||
uint32_t vsw;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
int div;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(panel != NULL && fbinfo != NULL);
|
||||
|
||||
/* Configure LCD pins */
|
||||
|
||||
lcdinfo("Configuring pins\n");
|
||||
|
||||
#if !defined(CONFIG_AM335X_LCDC_BPP16_565) && !defined(CONFIG_AM335X_LCDC_BPP12_444)
|
||||
am335x_gpio_config(GPIO_LCD_DATA0);
|
||||
am335x_gpio_config(GPIO_LCD_DATA1);
|
||||
am335x_gpio_config(GPIO_LCD_DATA2);
|
||||
#endif
|
||||
#ifndef CONFIG_AM335X_LCDC_BPP12_444
|
||||
am335x_gpio_config(GPIO_LCD_DATA3);
|
||||
#endif
|
||||
am335x_gpio_config(GPIO_LCD_DATA4);
|
||||
am335x_gpio_config(GPIO_LCD_DATA5);
|
||||
am335x_gpio_config(GPIO_LCD_DATA6);
|
||||
am335x_gpio_config(GPIO_LCD_DATA7);
|
||||
|
||||
#if AM335X_BPP > 8 /* Or STN 8-BPP Dual panel */
|
||||
#if !defined(CONFIG_AM335X_LCDC_BPP16_565) && !defined(CONFIG_AM335X_LCDC_BPP12_444)
|
||||
am335x_gpio_config(GPIO_LCD_DATA8);
|
||||
am335x_gpio_config(GPIO_LCD_DATA9);
|
||||
#endif
|
||||
#ifndef CONFIG_AM335X_LCDC_BPP12_444
|
||||
am335x_gpio_config(GPIO_LCD_DATA10);
|
||||
am335x_gpio_config(GPIO_LCD_DATA11);
|
||||
#endif
|
||||
am335x_gpio_config(GPIO_LCD_DATA12);
|
||||
am335x_gpio_config(GPIO_LCD_DATA13);
|
||||
am335x_gpio_config(GPIO_LCD_DATA14);
|
||||
am335x_gpio_config(GPIO_LCD_DATA15);
|
||||
#endif
|
||||
|
||||
#if AM335X_BPP > 16 || defined(CONFIG_AM335X_LCDC_TFTPANEL)
|
||||
#if !defined(CONFIG_AM335X_LCDC_BPP16_565) && !defined(CONFIG_AM335X_LCDC_BPP12_444)
|
||||
am335x_gpio_config(GPIO_LCD_DATA16);
|
||||
am335x_gpio_config(GPIO_LCD_DATA17);
|
||||
am335x_gpio_config(GPIO_LCD_DATA18);
|
||||
#endif
|
||||
#ifndef CONFIG_AM335X_LCDC_BPP12_444
|
||||
am335x_gpio_config(GPIO_LCD_DATA19);
|
||||
#endif
|
||||
am335x_gpio_config(GPIO_LCD_DATA20);
|
||||
am335x_gpio_config(GPIO_LCD_DATA21);
|
||||
am335x_gpio_config(GPIO_LCD_DATA22);
|
||||
am335x_gpio_config(GPIO_LCD_DATA23);
|
||||
#endif
|
||||
|
||||
/* Other pins */
|
||||
|
||||
am335x_gpio_config(GPIO_LCD_HSYNC);
|
||||
am335x_gpio_config(GPIO_LCD_VSYNC);
|
||||
am335x_gpio_config(GPIO_LCD_AC_BIAS_EN);
|
||||
am335x_gpio_config(GPIO_LCD_MEMORY_CLK_1);
|
||||
am335x_gpio_config(GPIO_LCD_MEMORY_CLK_2);
|
||||
|
||||
/* Initialize the device state singleton */
|
||||
|
||||
sem_init(&priv->exclsem, 0, 1);
|
||||
memcpy(&priv->panel, panel, sizeof(struct am335x_panel_info_s));
|
||||
|
||||
/* Save framebuffer information */
|
||||
|
||||
priv->fbmem = fbinfo->fbmem;
|
||||
priv->fbphys = fbinfo->fbphys;
|
||||
priv->stride = (priv->panel.width * priv->panel.bpp + 7) >> 3;
|
||||
priv->fbsize = priv->stride * priv->panel.height;
|
||||
DEBUGASSERT(priv->fbsize <= fbinfo->fbsize);
|
||||
|
||||
/* Attach the LCD interrupt */
|
||||
|
||||
ret = irq_attach(AM335X_IRQ_LCDC, am335x_lcd_interrupt, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
lcderr("ERROR: Failed to attach LCDC interrupt.");
|
||||
}
|
||||
|
||||
/* Enable clocking to the LCD peripheral */
|
||||
/* REVISIT: Need to (1) set the initial pixel clock and (2) set
|
||||
* LCDC related bits in PRCM to enable clocking to the LCDC.
|
||||
* Reference: http://fxr.watson.org/fxr/source/arm/ti/am335x/am335x_prcm.c#L819
|
||||
*/
|
||||
|
||||
lcdinfo("Enable clocking to the LCD controller\n");
|
||||
#if 0 /* FIXEME */
|
||||
ti_prcm_clk_enable(LCDC_CLK);
|
||||
#endif
|
||||
#warning Missing logic
|
||||
|
||||
/* Adjust clock to get double of requested pixel clock frequency
|
||||
* HDMI/DVI displays are very sensitive to error in frequency value.
|
||||
* Reference: http://fxr.watson.org/fxr/source/arm/ti/am335x/am335x_prcm.c#L718
|
||||
*/
|
||||
|
||||
#warning Missing logic
|
||||
#if 0 /* FIXEME */
|
||||
if (ti_prcm_clk_set_source_freq(LCDC_CLK, priv->panel.pixclk * 2))
|
||||
#endif
|
||||
{
|
||||
lcderr("ERROR: Can't set source frequency\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* Read back the actual reference clock frequency */
|
||||
/* Reference: http://fxr.watson.org/fxr/source/arm/ti/am335x/am335x_prcm.c#L701 */
|
||||
|
||||
#warning Missing logic
|
||||
#if 0 /* FIXEME */
|
||||
if (ti_prcm_clk_get_source_freq(LCDC_CLK, &reffreq))
|
||||
#endif
|
||||
{
|
||||
lcderr("ERROR: Can't get reference frequency\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* Panel initialization */
|
||||
|
||||
/* Put the LCD framebuffer memory in a known state */
|
||||
|
||||
am335x_lcdclear(CONFIG_AM335X_LCDC_BACKCOLOR);
|
||||
|
||||
/* Only raster mode is supported */
|
||||
|
||||
regval = LCD_CTRL_MODE_RASTER;
|
||||
div = am335x_lcd_divisor(reffreq, priv->panel.pixclk);
|
||||
regval |= (div << LCD_CTRL_CLKDIV_SHIFT);
|
||||
putreg32(AM335X_LCD_CTRL, regval);
|
||||
|
||||
/* Set timing */
|
||||
|
||||
timing0 = timing1 = timing2 = 0;
|
||||
|
||||
hbp = priv->panel.hbp - 1;
|
||||
hfp = priv->panel.hfp - 1;
|
||||
hsw = priv->panel.hsw - 1;
|
||||
|
||||
vbp = priv->panel.vbp;
|
||||
vfp = priv->panel.vfp;
|
||||
vsw = priv->panel.vsw - 1;
|
||||
|
||||
height = priv->panel.height - 1;
|
||||
width = priv->panel.width - 1;
|
||||
|
||||
/* Horizontal back porch */
|
||||
|
||||
timing0 |= (hbp & 0xff) << LCD_RASTER_TIMING_0_HBP_SHIFT;
|
||||
timing2 |= ((hbp >> 8) & 3) << LCD_RASTER_TIMING_2_HBP_HBITS_SHIFT;
|
||||
|
||||
/* Horizontal front porch */
|
||||
|
||||
timing0 |= (hfp & 0xff) << LCD_RASTER_TIMING_0_HFP_SHIFT;
|
||||
timing2 |= ((hfp >> 8) & 3) << LCD_RASTER_TIMING_2_HFP_HBITS_SHIFT;
|
||||
|
||||
/* Horizontal sync width */
|
||||
|
||||
timing0 |= (hsw & 0x3f) << LCD_RASTER_TIMING_0_HSW_SHIFT;
|
||||
timing2 |= ((hsw >> 6) & 0xf) << LCD_RASTER_TIMING_2_HSW_HBITS_SHIFT;
|
||||
|
||||
/* Vertical back porch, front porch, sync width */
|
||||
|
||||
timing1 |= (vbp & 0xff) << LCD_RASTER_TIMING_1_VBP_SHIFT;
|
||||
timing1 |= (vfp & 0xff) << LCD_RASTER_TIMING_1_VFP_SHIFT;
|
||||
timing1 |= (vsw & 0x3f) << LCD_RASTER_TIMING_1_VSW_SHIFT;
|
||||
|
||||
/* Pixels per line */
|
||||
|
||||
timing0 |= ((width >> 10) & 1) << LCD_RASTER_TIMING_0_PPLLSB_SHIFT;
|
||||
timing0 |= ((width >> 4) & 0x3f) << LCD_RASTER_TIMING_0_PPLLSB_SHIFT;
|
||||
|
||||
/* Lines per panel */
|
||||
|
||||
timing1 |= (height & 0x3ff) << LCD_RASTER_TIMING_1_LPP_SHIFT;
|
||||
timing2 |= ((height >> 10) & 1) << LCD_RASTER_TIMING_2_LPP_B10_SHIFT;
|
||||
|
||||
/* Clock signal settings */
|
||||
|
||||
if (priv->panel.sync_ctrl)
|
||||
{
|
||||
timing2 |= LCD_RASTER_TIMING_2_PHSVS_ON;
|
||||
}
|
||||
|
||||
if (priv->panel.sync_edge)
|
||||
{
|
||||
timing2 |= LCD_RASTER_TIMING_2_PHSVS_RF;
|
||||
}
|
||||
|
||||
if (!priv->panel.hsync_active)
|
||||
{
|
||||
timing2 |= LCD_RASTER_TIMING_2_IHS;
|
||||
}
|
||||
|
||||
if (!priv->panel.vsync_active)
|
||||
{
|
||||
timing2 |= LCD_RASTER_TIMING_2_IVS;
|
||||
}
|
||||
|
||||
if (!priv->panel.pixelclk_active)
|
||||
{
|
||||
timing2 |= LCD_RASTER_TIMING_2_IPC;
|
||||
}
|
||||
|
||||
/* AC bias */
|
||||
|
||||
timing2 |= (priv->panel.acbias << LCD_RASTER_TIMING_2_ACB_SHIFT);
|
||||
timing2 |= (priv->panel.acbias_pint << LCD_RASTER_TIMING_2_ACBI_SHIFT);
|
||||
|
||||
putreg32(AM335X_LCD_RASTER_TIMING_0, timing0);
|
||||
putreg32(AM335X_LCD_RASTER_TIMING_1, timing1);
|
||||
putreg32(AM335X_LCD_RASTER_TIMING_2, timing2);
|
||||
|
||||
/* DMA settings */
|
||||
|
||||
regval = LCD_DMA_CTRL_FRAME_MODE;
|
||||
|
||||
/* Find power of 2 for current burst size */
|
||||
|
||||
switch (priv->panel.dma_burstsz)
|
||||
{
|
||||
case 1:
|
||||
logburst = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
logburst = 1;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
logburst = 2;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
logburst = 3;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
default:
|
||||
logburst = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
regval |= (logburst << LCD_DMA_CTRL_BURST_SIZE_SHIFT);
|
||||
|
||||
/* XXX: FIFO TH */
|
||||
|
||||
regval |= (0 << LCD_DMA_CTRL_TH_FIFO_RDY_SHIFT);
|
||||
putreg32(AM335X_LCD_DMA_CTRL, regval);
|
||||
|
||||
putreg32(AM335X_LCD_DMA_FB0_BASE, priv->fbphys);
|
||||
putreg32(AM335X_LCD_DMA_FB0_BASE, priv->fbphys + priv->fbsize - 1);
|
||||
putreg32(AM335X_LCD_DMA_FB1_BASE, priv->fbphys);
|
||||
putreg32(AM335X_LCD_DMA_FB1_CEIL, priv->fbphys + priv->fbsize - 1);
|
||||
|
||||
/* Enable LCD */
|
||||
|
||||
regval = LCD_RASTER_CTRL_LCD_TFT;
|
||||
regval |= (priv->panel.fdd << LCD_RASTER_CTRL_REQDLY_SHIFT);
|
||||
regval |= LCD_RASTER_CTRL_DATA;
|
||||
|
||||
if (priv->panel.bpp >= 24)
|
||||
{
|
||||
regval |= LCD_RASTER_CTRL_TFT24;
|
||||
}
|
||||
|
||||
if (priv->panel.bpp == 32)
|
||||
{
|
||||
regval |= LCD_RASTER_CTRL_TFT24_UNPACKED;
|
||||
}
|
||||
|
||||
putreg32(AM335X_LCD_RASTER_CTRL, regval);
|
||||
|
||||
putreg32(AM335X_LCD_CLKC_ENABLE,
|
||||
LCD_CLKC_ENABLE_CORE | LCD_CLKC_ENABLE_LIDD |
|
||||
LCD_CLKC_ENABLE_DMA);
|
||||
|
||||
putreg32(AM335X_LCD_CLKC_RESET, LCD_CLKC_RESET_MAIN);
|
||||
up_udelay(100);
|
||||
putreg32(AM335X_LCD_CLKC_RESET, 0);
|
||||
|
||||
regval = LCD_IRQ_DONE | LCD_IRQ_RR_DONE | LCD_IRQ_SYNC | LCD_IRQ_ACB |
|
||||
LCD_IRQ_PL | LCD_IRQ_FUF | LCD_IRQ_EOF0 | LCD_IRQ_EOF1;
|
||||
putreg32(AM335X_LCD_IRQ_EN_SET, regval);
|
||||
|
||||
regval = getreg32(AM335X_LCD_RASTER_CTRL);
|
||||
regval |= LCD_RASTER_CTRL_LCD_EN;
|
||||
putreg32(AM335X_LCD_RASTER_CTRL, regval);
|
||||
|
||||
putreg32(AM335X_LCD_SYSC, LCD_SYSC_IDLE_SMART | LCD_SYSC_STANDBY_SMART);
|
||||
|
||||
#ifdef CONFIG_AM335X_LCDC_BACKLIGHT
|
||||
/* Turn on the back light
|
||||
* REVISIT: Current assumes a discrete ON/OFF control. Needs additional
|
||||
* support for backlight level control.
|
||||
*/
|
||||
|
||||
am335x_backlight(true);
|
||||
#endif
|
||||
|
||||
/* Enable interrupts at the interrupt controller */
|
||||
|
||||
up_enable_irq(AM335X_IRQ_LCDC);
|
||||
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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane)
|
||||
{
|
||||
lcdinfo("vplane: %d\n", vplane);
|
||||
if (vplane == 0)
|
||||
{
|
||||
return &g_fbinterface;
|
||||
}
|
||||
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)
|
||||
{
|
||||
#ifdef CONFIG_AM335X_LCDC_BACKLIGHT
|
||||
/* Turn off the back light */
|
||||
|
||||
am335x_backlight(false);
|
||||
#endif
|
||||
|
||||
/* Disable the LCD controller */
|
||||
#warning Missing Logic
|
||||
|
||||
/* Disable clocking to the LCD peripheral */
|
||||
#warning Missing Logic
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcdclear
|
||||
*
|
||||
* Description:
|
||||
* This is a non-standard LCD interface just for the AM335x. 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 VRAM memory to the specified color.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void am335x_lcdclear(nxgl_mxpixel_t color)
|
||||
{
|
||||
struct am335x_lcd_dev_s *priv = &g_lcddev;
|
||||
#if AM335X_BPP > 16
|
||||
uint32_t *dest = (uint32_t *)priv->fbmem;
|
||||
int incr = sizeof(uint32_t);
|
||||
#else
|
||||
uint16_t *dest = (uint16_t *)priv->fbmem;
|
||||
int incr = sizeof(uint16_t);
|
||||
#endif
|
||||
int i;
|
||||
|
||||
lcdinfo("Clearing display: color=%04x VRAM=%p size=%lu\n",
|
||||
color, priv->fbmem, (unsigned long)priv->fbsize);
|
||||
|
||||
for (i = 0; i < priv->fbsize; i += incr)
|
||||
{
|
||||
*dest++ = color;
|
||||
}
|
||||
}
|
||||
314
arch/arm/src/am335x/am335x_lcdc.h
Normal file
314
arch/arm/src/am335x/am335x_lcdc.h
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/am335x/am335x_lcdc.h
|
||||
*
|
||||
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* The LCD driver derives from the LPC54xx LCD driver but also includes
|
||||
* information from the FreeBSD AM335x LCD driver which was released under
|
||||
* a two-clause BSD license:
|
||||
*
|
||||
* Copyright 2013 Oleksandr Tymoshenko <gonzo@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name NuttX 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* The LPC54 LCD driver uses the common framebuffer interfaces declared in
|
||||
* include/nuttx/video/fb.h.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_AM335X_AM335X_LCDC_H
|
||||
#define __ARCH_ARM_SRC_AM335X_AM335X_LCDC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/nx/nxglib.h>
|
||||
|
||||
#include "hardware/am335x_lcd.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
/* Background color */
|
||||
|
||||
#ifndef CONFIG_AM335X_LCDC_BACKCOLOR
|
||||
# warning "Assuming background color == 16"
|
||||
# define CONFIG_AM335X_LCDC_BACKCOLOR 0 /* Initial background color */
|
||||
#endif
|
||||
|
||||
/* Default characteristics (may be overridden via struct am335x_panel_info_s */
|
||||
|
||||
/* Bits per pixel / color format */
|
||||
|
||||
#undef AM335X_COLOR_FMT
|
||||
#if defined(CONFIG_AM335X_LCDC_BPP1)
|
||||
# define AM335X_BPP 1
|
||||
# define AM335X_COLOR_FMT FB_FMT_Y1
|
||||
#elif defined(CONFIG_AM335X_LCDC_BPP2)
|
||||
# define AM335X_BPP 2
|
||||
# define AM335X_COLOR_FMT FB_FMT_Y2
|
||||
#elif defined(CONFIG_AM335X_LCDC_BPP4)
|
||||
# define AM335X_BPP 4
|
||||
# define AM335X_COLOR_FMT FB_FMT_Y4
|
||||
#elif defined(CONFIG_AM335X_LCDC_BPP8)
|
||||
# define AM335X_BPP 8
|
||||
# define AM335X_COLOR_FMT FB_FMT_Y8
|
||||
#elif defined(CONFIG_AM335X_LCDC_BPP12_444)
|
||||
# define AM335X_BPP 1 12
|
||||
# define AM335X_COLOR_FMT FB_FMT_RGB12_444
|
||||
#elif defined(CONFIG_AM335X_LCDC_BPP16_565)
|
||||
# define AM335X_BPP 16
|
||||
# define AM335X_COLOR_FMT FB_FMT_RGB16_565
|
||||
#elif defined(CONFIG_AM335X_LCDC_BPP24)
|
||||
# define AM335X_BPP 24 RGB */
|
||||
# define AM335X_COLOR_FMT FB_FMT_RGB24
|
||||
#else
|
||||
# warning "Assuming 16 BPP 5:6:5"
|
||||
# define AM335X_BPP 16
|
||||
# define CONFIG_AM335X_LCDC_BPP16_565 1
|
||||
# define AM335X_COLOR_FMT FB_FMT_RGB16_565
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_AM335X_LCDC_ACBIAS
|
||||
# warning "Assuming AC bias == 255"
|
||||
# define CONFIG_AM335X_LCDC_ACBIAS 255
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_AM335X_LCDC_ACBIAS_PINT
|
||||
# warning "Assuming AC bias per interrupt == 0"
|
||||
# define CONFIG_AM335X_LCDC_ACBIAS_PINT 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AM335X_LCDC_DMA_BURST1)
|
||||
# define AM335X_LCD_DMA_BURSTSZ 1
|
||||
#elif defined(CONFIG_AM335X_LCDC_DMA_BURST2)
|
||||
# define AM335X_LCD_DMA_BURSTSZ 2
|
||||
#elif defined(CONFIG_AM335X_LCDC_DMA_BURST4)
|
||||
# define AM335X_LCD_DMA_BURSTSZ 4
|
||||
#elif defined(CONFIG_AM335X_LCDC_DMA_BURST8)
|
||||
# define AM335X_LCD_DMA_BURSTSZ 8
|
||||
#elif defined(CONFIG_AM335X_LCDC_DMA_BURST16)
|
||||
# define AM335X_LCD_DMA_BURSTSZ 16
|
||||
#else
|
||||
# warning "Assuming DMA burst size == 16"
|
||||
# define CONFIG_AM335X_LCDC_DMA_BURST16 1
|
||||
# define AM335X_LCD_DMA_BURSTSZ 16
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_AM335X_LCDC_FDD
|
||||
# warning "Assuming FDD == 128"
|
||||
# define CONFIG_AM335X_LCDC_FDD 128
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Describes the LCD panel configuration */
|
||||
|
||||
struct am335x_panel_info_s
|
||||
{
|
||||
bool hsync_active; /* HSync active */
|
||||
bool vsync_active; /* Invert VSync */
|
||||
bool sync_edge; /* HSYNC/VSYNC rise or fall */
|
||||
bool sync_ctrl; /* Hsync/Vsync pixel clock control on/off */
|
||||
bool pixelclk_active; /* Invert pixel clock */
|
||||
|
||||
uint32_t width; /* Display width (pixels) */
|
||||
uint32_t height; /* Display height (lines) */
|
||||
uint32_t hfp; /* Horizontal front porch (pixels) */
|
||||
uint32_t hbp; /* Horizontal back porch (pixels) */
|
||||
uint32_t hsw; /* HSync width */
|
||||
uint32_t vfp; /* Vertical front porch (lines) */
|
||||
uint32_t vbp; /* Vertical back porch (lines) */
|
||||
uint32_t vsw; /* VSync width */
|
||||
uint32_t pixclk; /* Pixel clock */
|
||||
|
||||
uint32_t acbias; /* AC bias pin frequency */
|
||||
uint32_t acbias_pint; /* AC bias pins transitions per interrupt */
|
||||
uint32_t dma_burstsz; /* DMA burst size */
|
||||
uint32_t bpp; /* Bits per pixel */
|
||||
uint32_t fdd; /* Palette loading delay */
|
||||
};
|
||||
|
||||
/* A special memory region is set aside for the framebuffer. This region
|
||||
* must be set aside in the linker script and assigned a virtual address
|
||||
* during initialization. The framebuffer memory region must be non-
|
||||
* cached.
|
||||
*/
|
||||
|
||||
struct am335x_fbinfo_s
|
||||
{
|
||||
FAR void *fbmem; /* Virtual address of the framebuffer */
|
||||
FAR void *fbphys; /* Physical address of the framebuffer */
|
||||
size_t fbsize; /* Size of the framebuffer region */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the AM335x for use the display described by the provided
|
||||
* instance of struct am335x_panel_info_s.
|
||||
*
|
||||
* This function must be called by board specific logic to initialize the
|
||||
* LCD. Normally the calling sequence is as follows:
|
||||
*
|
||||
* 1a. Graphics application starts and initializes the NX server via
|
||||
* boardctl(BOARDIOC_NX_START). This calls the graphics
|
||||
* initialization function nxmu_start() which, in turn, will call
|
||||
* up_fbinitialize(). Or,
|
||||
* 1b. The framebuffer character driver is initialized and calls
|
||||
* up_fbinitialize().
|
||||
* 2. The function up_fbinitialize() must reside in board specific logic
|
||||
* under configs/. It must create the instance of struct
|
||||
* am335x_panel_info_s and call this function with that instance.
|
||||
*
|
||||
* For a directly connected LCD, either (1) the struct am335x_panel_info_s
|
||||
* may be initialized with constant data or (2) the desired video mode can
|
||||
* obtained via lookup from edid_mode_lookup() and the struct
|
||||
* am335x_panel_info_s can be created with am335x_lcd_videomode().
|
||||
*
|
||||
* If there is access to Extended Display Identification Data (EDID), then
|
||||
* the board-specific logic may read the EDID data and use
|
||||
* am335x_lcd_edid() to use the EDID data to initialize the struct
|
||||
* am335x_panel_info_s instance.
|
||||
*
|
||||
* Input Parameters:
|
||||
* panel - Provides information about the connect LCD panel.
|
||||
* fbinfo - Provides information about the pre-allocate framebuffer
|
||||
* memory.
|
||||
*
|
||||
* Returned value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned in
|
||||
* the the case of a failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am335x_lcd_initialize(FAR const struct am335x_panel_info_s *panel,
|
||||
FAR const struct am335x_fbinfo_s *fbinfo);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcdclear
|
||||
*
|
||||
* Description:
|
||||
* This is a non-standard LCD interface just for the AM335x. 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 VRAM memory to the specified color.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void am335x_lcdclear(nxgl_mxpixel_t color);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_videomode
|
||||
*
|
||||
* Description:
|
||||
* If the video mod is known, then the board-specific logic may read the
|
||||
* use this function to convert the video mode data to an instance of
|
||||
* struct am335x_panel_info_s which then may be used to initialize the
|
||||
* the LCD/
|
||||
*
|
||||
* Input Parameters:
|
||||
* videomode - A reference to the desired video mode.
|
||||
* panel - A user provided location to receive the panel data.
|
||||
*
|
||||
* Returned value:
|
||||
* None. Always succeeds.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct edid_videomode_s; /* Forward reference */
|
||||
|
||||
void am335x_lcd_videomode(FAR const struct edid_videomode_s *videomode,
|
||||
FAR struct am335x_panel_info_s *panel);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_lcd_edid
|
||||
*
|
||||
* Description:
|
||||
* If there is access to Extended Display Identification Data (EDID),
|
||||
* then the board-specific logic may read the EDID data and use this
|
||||
* function to initialize an instance of struct am335x_panel_info_s.
|
||||
*
|
||||
* The returned video mode may optionally be returned to configure HDMI.
|
||||
*
|
||||
* Input Parameters:
|
||||
* edid - A reference to the raw EDID data.
|
||||
* len - The length of the EDID data in bytes
|
||||
* panel - A user provided location to receive the panel data.
|
||||
* selected - A user provided location to receive the selected video mode.
|
||||
* fbinfo - Provides information about the pre-allocate framebuffer
|
||||
* memory.
|
||||
*
|
||||
* Returned value:
|
||||
* None. Always succeeds. The logic will fallback to VGA mode if no
|
||||
* EDID data is provided or if there is no valid video mode in the EDID
|
||||
* data.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void am335x_lcd_edid(FAR const uint8_t *edid, size_t edid_len,
|
||||
FAR struct am335x_panel_info_s *panel,
|
||||
FAR struct edid_videomode_s *selected,
|
||||
FAR const struct am335x_fbinfo_s *fbinfo);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am335x_backlight
|
||||
*
|
||||
* Description:
|
||||
* If CONFIG_AM335X_LCDC_BACKLIGHT is defined, then the board-specific
|
||||
* logic must provide this interface to turn the backlight on and off.
|
||||
*
|
||||
* REVISIT: Current assumes a discrete ON/OFF control. Needs additional
|
||||
* support for backlight level control.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_AM335X_LCDC_BACKLIGHT
|
||||
void am335x_backlight(bool blon);
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_AM335X_AM335X_LCDC_H */
|
||||
|
|
@ -175,8 +175,8 @@
|
|||
#define LCD_RASTER_CTRL_REQDLY_MASK (255 << LCD_RASTER_CTRL_REQDLY_SHIFT)
|
||||
#define LCD_RASTER_CTRL_PALMODE_SHIFT (20) /* Bits 20-21: Palette Loading Mode */
|
||||
#define LCD_RASTER_CTRL_PALMODE_MASK (3 << LCD_RASTER_CTRL_PALMODE_SHIFT)
|
||||
# define LCD_RASTER_CTRL_PALLET_DATA (0 << LCD_RASTER_CTRL_PALMODE_SHIFT) /* Palette and data loading */
|
||||
# define LCD_RASTER_CTRL_PALLET (1 << LCD_RASTER_CTRL_PALMODE_SHIFT) /* Palette loading only */
|
||||
# define LCD_RASTER_CTRL_PALETTE_DATA (0 << LCD_RASTER_CTRL_PALMODE_SHIFT) /* Palette and data loading */
|
||||
# define LCD_RASTER_CTRL_PALETTE (1 << LCD_RASTER_CTRL_PALMODE_SHIFT) /* Palette loading only */
|
||||
# define LCD_RASTER_CTRL_DATA (2 << LCD_RASTER_CTRL_PALMODE_SHIFT) /* Data loading only For Raw Data (12/16/24 bpp) framebuffers, no palette lookup is employed */
|
||||
#define LCD_RASTER_CTRL_NIB_MODE (1 << 22) /* Bit 22: Nibble Mode */
|
||||
#define LCD_RASTER_CTRL_TFT_MAP (1 << 23) /* Bit 23: TFT Mode Alternate Signal Mapping for Palettized framebuffer */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue