Commit 2858b0b0 authored by Robert Sprowson's avatar Robert Sprowson Committed by ROOL
Browse files

Add GraphicsV_VetMode2 implementation

Check the control list for an ExtraBytes entry, and use that to remove the restriction on rows being a multiple of 8 pixels by adding padding at the end (via the ROWINC register in DISPC).
Also add missing check on the VIDC list passed to vet mode being type 3.
Don't bother calling the platform code if we know the pixel format isn't supported.
Ensure TV-out & fixed displays vet the DMA parameters.

Version 0.44. Tagged as 'OMAPVideo-0_44'
parent c4ac11e3
/* (0.43)
/* (0.44)
*
* This file is automatically maintained by srccommit, do not edit manually.
*
*/
#define Module_MajorVersion_CMHG 0.43
#define Module_MajorVersion_CMHG 0.44
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 05 Feb 2020
#define Module_Date_CMHG 04 Apr 2020
#define Module_MajorVersion "0.43"
#define Module_Version 43
#define Module_MajorVersion "0.44"
#define Module_Version 44
#define Module_MinorVersion ""
#define Module_Date "05 Feb 2020"
#define Module_Date "04 Apr 2020"
#define Module_ApplicationDate "05-Feb-20"
#define Module_ApplicationDate "04-Apr-20"
#define Module_ComponentName "OMAPVideo"
#define Module_FullVersion "0.43"
#define Module_HelpVersion "0.43 (05 Feb 2020)"
#define Module_LibraryVersionInfo "0:43"
#define Module_FullVersion "0.44"
#define Module_HelpVersion "0.44 (04 Apr 2020)"
#define Module_LibraryVersionInfo "0:44"
......@@ -309,6 +309,16 @@ static int do_setmode(_kernel_swi_regs *r)
o->y = 0;
o->format = format;
o->stride = (o->buf_w*pixel_format_bpp[o->format])>>3;
const ControlList *c = params->ControlList;
while (c->index != -1)
{
if (c->index == ControlList_ExtraBytes)
{
o->stride += c->value;
break;
}
c++;
}
o->target = default_display;
o->highprio = true; /* TODO: Be more intelligent with how we assign priority (e.g. rotated, downscaled, or high BPP overlay may require more bandwidth per-pixel than desktop) */
o->enabled = true;
......@@ -392,34 +402,71 @@ static int do_setdmaaddress(_kernel_swi_regs *r)
return 0;
}
static int do_vetmode(_kernel_swi_regs *r)
static vetresult vetmode_internal(const VIDCList3 *params, uint32_t *extrabytes)
{
/* Only support head 0 */
if (r->r[4] & 0xff0000)
{
return 1;
}
/* TODO - Needs updating for display rotation, etc. */
r->r[4] = 0;
const VIDCList3 *params = (const VIDCList3 *) r->r[0];
/* Check the type is one supported */
if (params->Type != 3)
return VET_BAD;
/* Determine interlace setting */
int interlace = params->SyncPol & (SyncPol_Interlace | SyncPol_InterlaceFields);
/* Check value is one supported */
if ((interlace != 0) && (interlace != (SyncPol_Interlace | SyncPol_InterlaceFields)))
return 1;
return VET_BAD;
/* Check colour depth */
pixelformat format = getformat(params);
if(format == PIXELFORMAT_MAX)
return 1;
return VET_BAD;
vetresult vr;
const modelocked_t *modelocked = modelocked_read_lock();
bool ok = checkformat(modelocked->default_display,format) && (headattrs[modelocked->default_display].vetmode)(modelocked->default_display,params,interlace,format);
if (!checkformat(modelocked->default_display,format))
{
vr = VET_BAD;
}
else
{
vr = headattrs[modelocked->default_display].vetmode(modelocked->default_display,params,interlace,format,extrabytes);
}
modelocked_read_unlock();
if (!ok)
return vr;
}
static int do_vetmode(_kernel_swi_regs *r, bool tryextra)
{
/* Only support head 0 */
if (r->r[4] & 0xff0000)
{
return 1;
/* Mode looks good */
r->r[0] = 0;
}
uint32_t extrabytes = 0;
vetresult vr = vetmode_internal((const VIDCList3 *) r->r[0],&extrabytes);
r->r[4] = 0;
if (tryextra)
{
/* Try harder for VetMode2 */
if (vr == VET_BAD)
{
r->r[0] = GVVetMode2_Result_Unsupported;
}
else if (vr == VET_OK)
{
r->r[0] = GVVetMode2_Result_SysFramestore;
}
else /* VET_BETTER_EXTRABYTES */
{
r->r[0] = GVVetMode2_Result_SysFramestore |
GVVetMode2_ExtraBytes_Invalid;
}
r->r[1] = 32; /* 32 byte buffer alignment? */
r->r[2] = extrabytes;
}
else
{
/* State our conclusion */
r->r[0] = (vr == VET_OK) ? 0 : 1;
}
return 0;
}
......@@ -685,6 +732,7 @@ static int do_readinfo(_kernel_swi_regs *r)
int controllist[] = {
ControlList_NColour,
ControlList_ModeFlags,
ControlList_ExtraBytes,
ControlList_Terminator
};
switch(r->r[0])
......@@ -975,7 +1023,8 @@ int graphicsv_handler(_kernel_swi_regs *r,void *pw)
case GraphicsV_SetBlank: ret = do_setblank(r); break;
case GraphicsV_UpdatePointer: ret = do_updatepointer(r); break;
case GraphicsV_SetDMAAddress: ret = do_setdmaaddress(r); break;
case GraphicsV_VetMode: ret = do_vetmode(r); break;
case GraphicsV_VetMode: ret = do_vetmode(r, false); break;
case GraphicsV_VetMode2: ret = do_vetmode(r, true); break;
case GraphicsV_DisplayFeatures: ret = do_displayfeatures(r); break;
case GraphicsV_FramestoreAddress: ret = do_framestoreaddress(r); break;
case GraphicsV_WritePaletteEntry: ret = do_writepaletteentry(r); break;
......
......@@ -52,6 +52,13 @@ typedef enum
TARGET_MAX,
} overlaytarget;
typedef enum
{
VET_OK,
VET_BAD,
VET_BETTER_EXTRABYTES /* only for VetMode2 */
} vetresult;
typedef enum
{
TVMODE_NTSC_601,
......@@ -298,7 +305,7 @@ typedef struct
pixelformat has already been checked against the formats the head supports
Return true if mode is OK
*/
bool (*vetmode)(overlaytarget target,const VIDCList3 *params,bool interlace,pixelformat format);
vetresult (*vetmode)(overlaytarget target,const VIDCList3 *params,bool interlace,pixelformat format,uint32_t *extrabytes);
/* Prepare for a mode change by calculating the modelocked_head_t value:
* mode, x, y, enabled, interlaced will already be filled in with the expected values, but can be tweaked further if necessary
......
......@@ -383,41 +383,76 @@ overlaytarget omap_pick_display(void)
return target;
}
static bool omap3_vetmode_lcd(overlaytarget target,const VIDCList3 *params,bool interlace,pixelformat format)
static vetresult vet_dma(const VIDCList3 *params,uint32_t *extrabytes)
{
/* Check DMA is at least a word multiple */
uint32_t bpl, padding = 0;
const ControlList *c = params->ControlList;
while (c->index != -1)
{
if (c->index == ControlList_ExtraBytes)
{
padding = c->value; /* Bytes */
break;
}
c++;
}
bpl = params->HorizDisplaySize * (1 << params->PixelDepth) + (padding << 3); /* Bits per line */
if ((bpl % 32) == 0)
{
/* Already a word multiple as proposed */
*extrabytes = padding;
return VET_OK;
}
if (bpl & 7)
{
/* Can only append whole bytes of padding */
return VET_BAD;
}
*extrabytes = ((32 - (bpl % 32)) >> 3) + padding;
return VET_BETTER_EXTRABYTES;
}
static vetresult omap3_vetmode_lcd(overlaytarget target,const VIDCList3 *params,bool interlace,pixelformat format,uint32_t *extrabytes)
{
(void) target;
(void) format;
/* Always accept if we're using fixed LCD timings */
/* Ignore provided timing parameters if we're using fixed LCD timings.
Screen dimensions are ignored as well - we just crop the image if
it's too big. */
if(hwconfig->lcd_configs[current_lcd].max_pixelrate == 0)
return true;
{
/* However, DMA parameters are still important */
return vet_dma(params,extrabytes);
}
/* Check interlace */
if(interlace)
return false;
return VET_BAD;
/* Check pixel rate */
if(params->PixelRate > hwconfig->lcd_configs[current_lcd].max_pixelrate)
return false;
return VET_BAD;
/* Use a lower limit of 15MHz on the pixel rate. The limiting factor appears to be the TFP410, which according to the datasheet only supports down to 25MHz, but appears to be stable down to 15MHz. Anything lower can result in picture instability.
https://www.riscosopen.org/forum/forums/3/topics/2583?page=1#posts-33233
*/
if(params->PixelRate < 15000)
return false;
return VET_BAD;
/* Check screen size */
if((params->HorizDisplaySize-1 > REG_MAX(DISPC_SIZE_LCD_PPL))
|| ((params->VertiDisplaySize<<interlace)-1 > REG_MAX(DISPC_SIZE_LCD_LPP))
|| (params->HorizDisplaySize & 0x7)) /* Width must be multiple of 8 pixels for STALLMODE=0 */
return false;
return VET_BAD;
/* Check required REGM, REGN values */
clock_divider_t div = calculate_dss_clock_divider(params->PixelRate*1000);
if((div.regm > REG_MAX(DSI_PLL_CONFIGURATION1_DSI_PLL_REGM)) || (div.regn > REG_MAX(DSI_PLL_CONFIGURATION1_DSI_PLL_REGN)))
return false;
return VET_BAD;
/* Now check mode timings */
if((params->HorizBackPorch+params->HorizLeftBorder > hwconfig->max_porch)
|| (params->HorizFrontPorch+params->HorizRightBorder > hwconfig->max_porch)
|| (params->VertiBackPorch+params->VertiTopBorder > hwconfig->max_porch)
|| (params->VertiFrontPorch+params->VertiBottomBorder > hwconfig->max_porch))
return false;
return VET_BAD;
if(hwconfig->max_sync <= 64)
{
/* Old OMAP3 chips have very tight porch & sync limits, which
......@@ -430,37 +465,40 @@ static bool omap3_vetmode_lcd(overlaytarget target,const VIDCList3 *params,bool
shifted to the front/back porch instead. */
if((params->HorizSyncWidth+params->HorizBackPorch+params->HorizLeftBorder+params->HorizFrontPorch+params->HorizRightBorder > hwconfig->max_sync+2*hwconfig->max_porch)
|| (params->VertiSyncWidth+params->VertiBackPorch+params->VertiTopBorder+params->VertiFrontPorch+params->VertiBottomBorder > hwconfig->max_sync+2*hwconfig->max_porch))
return false;
return VET_BAD;
}
else
{
if((params->HorizSyncWidth > hwconfig->max_sync)
|| (params->VertiSyncWidth > hwconfig->max_sync))
return false;
return VET_BAD;
}
if((params->HorizSyncWidth < 1)
|| (params->HorizBackPorch+params->HorizLeftBorder < 1)
|| (params->HorizFrontPorch+params->HorizRightBorder < 1)
|| (params->VertiSyncWidth < 1))
return false;
return VET_BAD;
/* Check (HBP+HSW+HFP)*PCD > 8 */
uint32_t val = params->HorizBackPorch + params->HorizLeftBorder
+ params->HorizSyncWidth + params->HorizFrontPorch
+ params->HorizRightBorder;
if (val <= 4) /* We always used PCD of 2 */
return false;
return VET_BAD;
return true;
/* Check DMA parameters are acceptable */
return vet_dma(params,extrabytes);
}
static bool omap3_vetmode_tv(overlaytarget target,const VIDCList3 *params,bool interlace,pixelformat format)
static vetresult omap3_vetmode_tv(overlaytarget target,const VIDCList3 *params,bool interlace,pixelformat format,uint32_t *extrabytes)
{
(void) target;
(void) params;
(void) interlace;
(void) format;
/* We accept anything, and just crop it to fit the screen */
return true;
(void) extrabytes;
/* Timing parameters are ignored - we just use standard NTSC/PAL
timings. The displayed screen will be cropped if it's too big. */
return vet_dma(params,extrabytes);
}
static void omap3_prepmode_lcd(overlaytarget target,modelocked_head_t *state,pixelformat format)
......
......@@ -268,38 +268,72 @@ overlaytarget omap_pick_display(void)
return TARGET_LCD2;
}
static bool omap4_vetmode_lcd2(overlaytarget target,const VIDCList3 *params,bool interlace,pixelformat format)
static vetresult vet_dma(const VIDCList3 *params,uint32_t *extrabytes)
{
/* Check DMA is at least a word multiple */
uint32_t bpl, padding = 0;
const ControlList *c = params->ControlList;
while (c->index != -1)
{
if (c->index == ControlList_ExtraBytes)
{
padding = c->value; /* Bytes */
break;
}
c++;
}
bpl = params->HorizDisplaySize * (1 << params->PixelDepth) + (padding << 3); /* Bits per line */
if ((bpl % 32) == 0)
{
/* Already a word multiple as proposed */
*extrabytes = padding;
return VET_OK;
}
if (bpl & 7)
{
/* Can only append whole bytes of padding */
return VET_BAD;
}
*extrabytes = ((32 - (bpl % 32)) >> 3) + padding;
return VET_BETTER_EXTRABYTES;
}
static vetresult omap4_vetmode_lcd2(overlaytarget target,const VIDCList3 *params,bool interlace,pixelformat format,uint32_t *extrabytes)
{
(void) target;
(void) format;
/* Always accept if we're using fixed LCD timings */
/* Ignore provided timing parameters if we're using fixed LCD timings.
Screen dimensions are ignored as well - we just crop the image if
it's too big. */
if(hwconfig->lcd_configs[current_lcd].max_pixelrate == 0)
return true;
{
/* However, DMA parameters are still important */
return vet_dma(params,extrabytes);
}
/* Check interlace */
if(interlace)
return false;
return VET_BAD;
/* Check pixel rate */
if(params->PixelRate > hwconfig->lcd_configs[current_lcd].max_pixelrate)
return false;
return VET_BAD;
/* Use a lower limit of 15MHz on the pixel rate. The limiting factor appears to be the TFP410, which according to the datasheet only supports down to 25MHz, but appears to be stable down to 15MHz. Anything lower can result in picture instability.
https://www.riscosopen.org/forum/forums/3/topics/2583?page=1#posts-33233
*/
if(params->PixelRate < 15000)
return false;
return VET_BAD;
/* Check screen size */
if((params->HorizDisplaySize-1 > REG_MAX(DISPC_SIZE_LCD_PPL))
|| ((params->VertiDisplaySize<<interlace)-1 > REG_MAX(DISPC_SIZE_LCD_LPP))
|| (params->HorizDisplaySize & 0x7)) /* Width must be multiple of 8 pixels for STALLMODE=0 */
return false;
|| ((params->VertiDisplaySize<<interlace)-1 > REG_MAX(DISPC_SIZE_LCD_LPP)))
return VET_BAD;
/* Check required REGM, REGN values */
clock_divider_t div = calculate_dss_clock_divider(params->PixelRate*1000);
if((div.regm > REG_MAX(DSI_PLL_CONFIGURATION1_DSI_PLL_REGM)) || (div.regn > REG_MAX(DSI_PLL_CONFIGURATION1_DSI_PLL_REGN)))
return false;
return VET_BAD;
/* Check for BMP8 erratum (in connection with pcd==1) */
if ((params->PixelDepth <= 3) && (div.pcd == 1))
return false;
return VET_BAD;
/* Now check mode timings */
if((params->HorizSyncWidth > hwconfig->max_sync)
|| (params->HorizBackPorch+params->HorizLeftBorder > hwconfig->max_porch)
......@@ -307,20 +341,21 @@ static bool omap4_vetmode_lcd2(overlaytarget target,const VIDCList3 *params,bool
|| (params->VertiSyncWidth > hwconfig->max_sync)
|| (params->VertiBackPorch+params->VertiTopBorder > hwconfig->max_porch)
|| (params->VertiFrontPorch+params->VertiBottomBorder > hwconfig->max_porch))
return false;
return VET_BAD;
if((params->HorizSyncWidth < 1)
|| (params->HorizBackPorch+params->HorizLeftBorder < 1)
|| (params->HorizFrontPorch+params->HorizRightBorder < 1)
|| (params->VertiSyncWidth < 1))
return false;
return VET_BAD;
/* Check (HBP+HSW+HFP)*PCD > 8 */
uint32_t val = params->HorizBackPorch + params->HorizLeftBorder
+ params->HorizSyncWidth + params->HorizFrontPorch
+ params->HorizRightBorder;
if (val * div.pcd <= 8)
return false;
return VET_BAD;
return true;
/* Check DMA parameters are acceptable */
return vet_dma(params,extrabytes);
}
static void omap4_prepmode_lcd2(overlaytarget target,modelocked_head_t *state,pixelformat format)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment