iBoot/drivers/apple/adbe/adbe_v3.c

164 lines
5.5 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (C) 2012-2014 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 "adbe_regs_v3.h"
#include <debug.h>
#include <drivers/display.h>
#include <lib/paint.h>
#include <platform/gpiodef.h>
#include <lib/syscfg.h>
#include <platform.h>
#include <platform/soc/chipid.h>
#include <platform/soc/hwclocks.h>
#include <platform/soc/hwregbase.h>
#include <drivers/dither.h>
#include <drivers/dpb.h>
#include <drivers/adbe/adbe.h>
struct adbe_v3_tuneable {
char *name;
uint32_t adbe0_vblank_clk_gate_wakeup;
uint32_t adbe0_vblank_clk_gate_idle;
uint32_t adbe0_tunable_nrt_ctl;
uint32_t adbe0_aap_support;
};
#include <target/adbe_settings.h>
static bool is_video_mode = true;
static struct adbe_v3_tuneable *adbe_tuneables_info;
static const int32_t adbe_tuneables_list_size = sizeof(adbe_tuneables) / sizeof(struct adbe_v3_tuneable);
void adbe_init(struct display_timing *timing)
{
const char *env;
int32_t cnt;
env = env_get("adbe-tunable");
if (env == 0) env = "default";
for (cnt = 0; cnt < adbe_tuneables_list_size; cnt++) {
if (strcmp(env, adbe_tuneables[cnt].name)) continue;
adbe_tuneables_info = adbe_tuneables + cnt;
}
if (adbe_tuneables_info == 0) {
dprintf(DEBUG_INFO, "Failed to find adbe tunables info, bailing adbe_init()\n");
return;
}
rADBE_ACTIVE_SIZE = ADBE_ACTIVE_SIZE_VERTICAL(timing->v_active) | ADBE_ACTIVE_SIZE_HORIZONTAL(timing->h_active);
rADBE_FRONT_PORCH = ADBE_FRONT_PORCH_VERTICAL(timing->v_front_porch) | ADBE_FRONT_PORCH_HORIZONTAL(timing->h_front_porch );
rADBE_SYNC_PULSE = ADBE_SYNC_PULSE_VERTICAL(timing->v_pulse_width) | ADBE_SYNC_PULSE_HORIZONTAL(timing->h_pulse_width);
rADBE_BACK_PORCH = ADBE_BACK_PORCH_VERTICAL(timing->v_back_porch) | ADBE_BACK_PORCH_HORIZONTAL(timing->h_back_porch);
//rdar://16085315 Errata Samsungs DSIM_MDRESOL.MainStandby register field description.
rADBE_NRT_CTL &= ~ADBE_NRT_CTL_TE_MODE_MASK;
rADBE_NRT_CTL |= (ADBE_NRT_CTL_VSYNC_POLARITY(timing->neg_vsync) | ADBE_NRT_CTL_HSYNC_POLARITY(timing->neg_hsync));
rADBE_RT_CTL |= ADBE_RT_CTL_FRAME_COUNT_ENABLE;
rADBE_NRT_CTL |= ADBE_NRT_CTL_SCAN_SELECT_PROG_CHG;
#ifdef TARGET_ADBE0_VBLANK_POSITION
rADBE_VBLANK_POSITION = TARGET_ADBE0_VBLANK_POSITION;
#endif
adbe_tuneables_info->adbe0_vblank_clk_gate_wakeup = timing->v_back_porch + timing->v_front_porch + timing->v_pulse_width - 5;
rADBE_VBLANK_CLK_GATE =
(ADBE_VBLANK_CLK_GATE_WAKEUP(adbe_tuneables_info->adbe0_vblank_clk_gate_wakeup) |
adbe_tuneables_info->adbe0_vblank_clk_gate_idle);
//Set AAP
rADBE_NRT_CTL |= (adbe_tuneables_info->adbe0_aap_support) ? ADBE_NRT_CTL_AAP_ENABLE: 0;
// Dither
#ifdef WITH_HW_DITHER
uint8_t dither_type = DITHER_SPATIO_TEMPORAL;
#ifdef TARGET_DITHER_TYPE
dither_type = TARGET_DITHER_TYPE;
#endif //TARGET_DITHER_TYPE
//Dithering gets enabled in this block, no need to call into dithering to enable
//We need to enable to block to access their corresponding registers
switch(dither_type) {
case DITHER_SPATIO_TEMPORAL:
rADBE_NRT_CTL |= ADBE_NRT_CTL_ST_DITHER_ENABLE;
break;
case DITHER_BLUE_NOISE:
rADBE_NRT_CTL |= ADBE_NRT_CTL_BN_DITHER_ENABLE;
break;
case DITHER_NONE:
default:
rADBE_NRT_CTL &= ~(ADBE_NRT_CTL_ST_DITHER_ENABLE | ADBE_NRT_CTL_BN_DITHER_ENABLE);
break;
}
dither_init(timing->display_depth);
#endif
rADBE_NRT_CTL |= adbe_tuneables_info->adbe0_tunable_nrt_ctl;
//Underrun setup
rADBE_FIFO_CONFIG = ADBE_FIFO_CONFIG_UNDERRUN_MODE_STICKY | ADBE_FIFO_CONFIG_UNDERRUN_CH0(0x3FF);
}
static void adbe_enable_timing_generator_v3_video_mode(bool enable)
{
if (enable) {
rADBE_RT_CTL |= ADBE_RT_CTL_VFTG_ENABLE_VID_EN; // Enable VFTG
while ((rADBE_RT_CTL & ADBE_RT_CTL_VFTG_STATUS_EN) == 0); // Wait for it to be enabled
} else {
rADBE_RT_CTL &= ~ADBE_RT_CTL_VFTG_ENABLE_VID_EN; // Disable VFTG
while ((rADBE_RT_CTL & ADBE_RT_CTL_VFTG_STATUS_EN) == ADBE_RT_CTL_VFTG_STATUS_EN); // Wait for it to be disabled
}
}
static void adbe_enable_timing_generator_v3_command_mode(bool enable)
{
if (enable) {
rADBE_RT_CTL |= ADBE_RT_CTL_VFTG_ENABLE_CMD_EN; // Enable VFTG
while ((rADBE_RT_CTL & ADBE_RT_CTL_VFTG_STATUS_EN) == 0); // Wait for it to be enabled
} else {
rADBE_RT_CTL &= ~ADBE_RT_CTL_VFTG_ENABLE_CMD_EN; // Disable VFTG
while ((rADBE_RT_CTL & ADBE_RT_CTL_VFTG_STATUS_EN) == ADBE_RT_CTL_VFTG_STATUS_EN); // Wait for it to be disabled
}
}
void adbe_enable_timing_generator(bool enable)
{
#ifdef TARGET_DISP_VIDEO_MODE
is_video_mode = TARGET_DISP_VIDEO_MODE;
#endif //TARGET_DISP_VIDEO_MODE
if (is_video_mode) {
rADBE_RT_CTL |= (ADBE_RT_CTL_UPDATE_ENABLE_TIMING_READY | ADBE_RT_CTL_UPDATE_REQ_TIMING_NOSYNC);
adbe_enable_timing_generator_v3_video_mode(enable);
} else {
rADBE_NRT_CTL |= ADBE_NRT_CTL_TE_MODE_POS | ADBE_NRT_CTL_VFTG_MODE_COMMAND | ADBE_NRT_CTL_TE_ENABLE_SEL_SW;
rADBE_RT_CTL |= (ADBE_RT_CTL_UPDATE_ENABLE_TIMING_READY | ADBE_RT_CTL_UPDATE_REQ_TIMING_NOSYNC);
adbe_enable_timing_generator_v3_command_mode(enable);
}
}
bool adbe_get_enable_timing_generator(void)
{
#ifdef TARGET_DISP_VIDEO_MODE
is_video_mode = TARGET_DISP_VIDEO_MODE;
#endif //TARGET_DISP_VIDEO_MODE
if (is_video_mode) {
return ((rADBE_RT_CTL & ADBE_RT_CTL_VFTG_ENABLE_VID_EN) == (uint32_t)ADBE_RT_CTL_VFTG_ENABLE_VID_EN);
} else {
return ((rADBE_RT_CTL & ADBE_RT_CTL_VFTG_ENABLE_CMD_EN) == (uint32_t)ADBE_RT_CTL_VFTG_ENABLE_CMD_EN);
}
}