iBoot/drivers/apple/dither/dither.c

265 lines
7.1 KiB
C

/*
* Copyright (C) 2009-2013 Apple Inc. All rights reserved.
*
* This document is the property of Apple Inc.
* It is considered confidential and proprietary.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Apple Inc.
*/
#include <debug.h>
#include <lib/env.h>
#include <platform/soc/hwregbase.h>
#include <drivers/dither.h>
#if DITHER_VERSION == 2
#include "dither_v2.h"
#elif DITHER_VERSION == 3
#include "dither_v3.h"
#else
#include "dither_v4.h"
#endif
#ifndef DITHER_BASE_ADDR
#error "DITHER base addr for AppleDither Block is not defined"
#endif
static uint8_t dither_type;
#if DITHER_VERSION == 4
#ifndef TARGET_DITHER_INBITSREDUCTION
#define TARGET_DITHER_INBITSREDUCTION 2
#endif
#ifndef TARGET_DITHER_EDOUTTOSTINWIDTH
#define TARGET_DITHER_EDOUTTOSTINWIDTH 3
#endif
#ifndef TARGET_DITHER_DITHEROUTWIDTH
#define TARGET_DITHER_DITHEROUTWIDTH 3
#endif
#ifndef TARGET_DITHER_ST_METHOD_MAX
#define TARGET_DITHER_ST_METHOD_MAX 3
#endif
#ifndef TARGET_DITHER_ST_METHOD_POP
#define TARGET_DITHER_ST_METHOD_POP 0
#endif
#ifndef TARGET_DITHER_ST_PHASE
#define TARGET_DITHER_ST_PHASE 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC0
#define TARGET_DITHER_ST_SKEWLOC0 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC1
#define TARGET_DITHER_ST_SKEWLOC1 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC2
#define TARGET_DITHER_ST_SKEWLOC2 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC3
#define TARGET_DITHER_ST_SKEWLOC3 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC4
#define TARGET_DITHER_ST_SKEWLOC4 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC5
#define TARGET_DITHER_ST_SKEWLOC5 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC6
#define TARGET_DITHER_ST_SKEWLOC6 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC7
#define TARGET_DITHER_ST_SKEWLOC7 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC8
#define TARGET_DITHER_ST_SKEWLOC8 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC9
#define TARGET_DITHER_ST_SKEWLOC9 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC10
#define TARGET_DITHER_ST_SKEWLOC10 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC11
#define TARGET_DITHER_ST_SKEWLOC11 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC12
#define TARGET_DITHER_ST_SKEWLOC12 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC13
#define TARGET_DITHER_ST_SKEWLOC13 0
#endif
#ifndef TARGET_DITHER_ST_SKEWLOC14
#define TARGET_DITHER_ST_SKEWLOC14 0
#endif
void dither_init(uint32_t display_width, uint32_t display_height, uint32_t display_depth)
#else
void dither_init(uint32_t display_depth)
#endif
{
//Fixing the value for now. When the request comes to use a Blue noise, please ask how to make
//the decision: Based on Target or based on number of dithering bits
dither_type = DITHER_SPATIO_TEMPORAL;
#ifdef TARGET_DITHER_TYPE
dither_type = TARGET_DITHER_TYPE;
#endif //TARGET_DITHER_TYPE
#if DITHER_VERSION == 2
//Number of bits reduced by the dithering algorithm core.
rDITHER_METHOD = (4 << 4) | ((display_depth <= 18) ? 0x3 : 0x2);
rDITHER_BOOST_POP = (display_depth <= 18) ? 0x1 : 0x0;
rDITHER_OUTPUT_WIDTH = (display_depth <=18) ? 0x0 : 0x1;
#endif
#if DITHER_VERSION == 3
switch(dither_type) {
case DITHER_SPATIO_TEMPORAL:
dprintf(DEBUG_SPEW, "Spatial_temporal Dither\n");
//Bypass BN
//<rdar://problem/11389221> [FPGA DEBUG]: Disabling certains backend blocks via ADBE0:MODE_CTL doesn't disable them
rDITHER_BN_OP_CFG = (1 << 29);
rDITHER_ST_METHOD = (0x4 << 4);
if (display_depth == 24)
rDITHER_ST_METHOD |= (0x1 << 13) | (0x2 << 0);
else if (display_depth <= 18)
rDITHER_ST_METHOD |= (0x1 << 13) | (0x3 << 0);
else
panic("unexpected display depth");
break;
case DITHER_BLUE_NOISE:
// Note: If bn_dither_enable is set and st_dither_enable is cleared, the
// spatio/temporal dither stage must also be disabled internally
// (see DITHER Register Spec.) by setting SPAT_TEMP_METHOD.mode to 0x4 and
// SPAT_TEMP_METHOD.depth to 0x0
dprintf(DEBUG_SPEW, "Blue_noise Dither\n");
rDITHER_ST_METHOD |= (0x4 << 13);
rDITHER_ST_METHOD &= ~(0xf); //clear depth
rDITHER_BN_OP_CFG = 1;
uint32_t thr_bit;
switch(display_depth) {
case 24:
thr_bit = DITHER_BN_CONST_THR2BIT;
break;
case 18:
thr_bit = DITHER_BN_CONST_THR4BIT;
rDITHER_BN_OP_CFG |= (0x1 << 24) | (0x1 << 20) | (0x1 << 16);
break;
default:
panic("unexpected display depth");
}
rDITHER_BN_CONST = (thr_bit << 16 | thr_bit << 8 | thr_bit << 0);
break;
case DITHER_NONE:
default:
dprintf(DEBUG_SPEW, "%d is not a supported dithering type. Disabling dithering\n", dither_type);
//bypassed and clock-gated if both st_dither_enable and bn_dither_enable are
//cleared
rDITHER_ST_METHOD = 0;
rDITHER_BN_OP_CFG = (1 << 29);
break;
}
#endif
#if DITHER_VERSION == 4
rDITHER_ACTIVEREGIONSTART = 0 << 16 | 0; //Set active region start
rDITHER_ACTIVEREGIONSIZE = display_height << 16 | display_width; //Set Active Region
// Setup for 8-bit panel with VRR
rDITHER_INBITSREDUCTION = TARGET_DITHER_INBITSREDUCTION;
rDITHER_EDOUTTOSTINWIDTH = TARGET_DITHER_EDOUTTOSTINWIDTH;
rDITHER_DITHEROUTWIDTH = TARGET_DITHER_DITHEROUTWIDTH;
switch(dither_type) {
case DITHER_SPATIO_TEMPORAL:
dprintf(DEBUG_SPEW, "Spatial_temporal Dither\n");
rDITHER_ST_METHOD |= (TARGET_DITHER_ST_METHOD_MAX << 13) | (TARGET_DITHER_ST_METHOD_POP << 8);
if (display_depth == 24)
rDITHER_ST_METHOD |= (0x2 << 0);
else if (display_depth <= 18)
rDITHER_ST_METHOD |= (0x3 << 0);
else
panic("unexpected display depth");
rDITHER_ST_PHASE = TARGET_DITHER_ST_PHASE;
rDITHER_ST_SKEWLOC0 = TARGET_DITHER_ST_SKEWLOC0;
rDITHER_ST_SKEWLOC1 = TARGET_DITHER_ST_SKEWLOC1;
rDITHER_ST_SKEWLOC2 = TARGET_DITHER_ST_SKEWLOC2;
rDITHER_ST_SKEWLOC3 = TARGET_DITHER_ST_SKEWLOC3;
rDITHER_ST_SKEWLOC4 = TARGET_DITHER_ST_SKEWLOC4;
rDITHER_ST_SKEWLOC5 = TARGET_DITHER_ST_SKEWLOC5;
rDITHER_ST_SKEWLOC6 = TARGET_DITHER_ST_SKEWLOC6;
rDITHER_ST_SKEWLOC7 = TARGET_DITHER_ST_SKEWLOC7;
rDITHER_ST_SKEWLOC8 = TARGET_DITHER_ST_SKEWLOC8;
rDITHER_ST_SKEWLOC9 = TARGET_DITHER_ST_SKEWLOC9;
rDITHER_ST_SKEWLOC10 = TARGET_DITHER_ST_SKEWLOC10;
rDITHER_ST_SKEWLOC11 = TARGET_DITHER_ST_SKEWLOC11;
rDITHER_ST_SKEWLOC12 = TARGET_DITHER_ST_SKEWLOC12;
rDITHER_ST_SKEWLOC13 = TARGET_DITHER_ST_SKEWLOC13;
rDITHER_ST_SKEWLOC14 = TARGET_DITHER_ST_SKEWLOC14;
rDITHER_ENABLE |= (1 << 1);
break;
case DITHER_ERROR_DIFFUSION:
dprintf(DEBUG_SPEW, "Error Diffusion Dither\n");
rDITHER_ED_THRESHOLDRED = (8192 << 2);
rDITHER_ED_THRESHOLDGREEN = (8192 << 2);
rDITHER_ED_THRESHOLDBLUE = (8192 << 2);
rDITHER_ENABLE |= (1 << 0);
break;
case DITHER_NONE:
default:
dprintf(DEBUG_SPEW, "%d is not a supported dithering type. Disabling dithering\n", dither_type);
//bypassed and clock-gated if both st_dither_enable and bn_dither_enable are
//cleared
rDITHER_ST_METHOD = 0;
break;
}
//double buffer registers. force them to update
rDITHER_UPDATECONTROL = DITHER_UPDATECONTROL_UPDATEENABLETIMING |
DITHER_UPDATECONTROL_UPDATEREQTIMING ;
#endif
}
void dither_set_enable(bool enable)
{
#if DITHER_VERSION == 2
if (enable) {
rDITHER_ENABLE = (dither_type == DITHER_SPATIO_TEMPORAL)? (1 << 0) : (1 << 1);
} else {
rDITHER_ENABLE = 0;
}
#endif
}