first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (C) 2011,2015 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 <drivers/display.h>
|
||||
#include <drivers/displayport/displayport.h>
|
||||
#include <drivers/displayport.h>
|
||||
#include <drivers/power.h>
|
||||
#include <platform/gpio.h>
|
||||
#include <platform/gpiodef.h>
|
||||
#include <lib/env.h>
|
||||
#include <sys/task.h>
|
||||
|
||||
#include "edp.h"
|
||||
|
||||
#define kHPDTimeout (186 * 1000)
|
||||
|
||||
/*
|
||||
* Panel ID is based on "DP Panel Vendor ID spec, v1.5"
|
||||
*/
|
||||
|
||||
static u_int32_t edp_panel_id;
|
||||
static u_int32_t edp_dot_pitch;
|
||||
static u_int32_t edp_default_color;
|
||||
static u_int32_t edp_voltage_offset;
|
||||
static u_int32_t edp_backlight_cal;
|
||||
static u_int8_t edp_raw_panel_id[kEDPRawPanelIdLength];
|
||||
static dp_t edp_display_config;
|
||||
|
||||
int edp_quiesce(void);
|
||||
static void edp_panel_enable(bool enable);
|
||||
|
||||
int edp_init(struct display_timing *timing, enum colorspace color, u_int32_t *display_id)
|
||||
{
|
||||
int result;
|
||||
utime_t HPDTime = 0;
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "edp_init()\n");
|
||||
|
||||
// Save the display's dot pitch
|
||||
edp_dot_pitch = timing->dot_pitch;
|
||||
memcpy(&edp_display_config, timing->display_config, sizeof(dp_t));
|
||||
|
||||
// Kick off eDP controller
|
||||
if ((result = displayport_init_with_timing_info(timing)) != 0)
|
||||
goto error;
|
||||
|
||||
// Power-up the display
|
||||
edp_panel_enable(true);
|
||||
|
||||
//Wait for HPD to allow enough time for TCON to to be ready
|
||||
if (dp_controller_wait_for_edp_hpd(&HPDTime) == false) {
|
||||
dprintf(DEBUG_CRITICAL, "timeout waiting for HPD\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (edp_panel_id == 0) {
|
||||
edp_panel_id = env_get_uint("pinot-panel-id", 0);
|
||||
}
|
||||
if (edp_panel_id == 0) {
|
||||
// read the panel ID
|
||||
result = displayport_get_raw_panel_id(edp_raw_panel_id);
|
||||
if (result != 0) {
|
||||
dprintf(DEBUG_CRITICAL, "edp_init(): read of edp panel id failed\n");
|
||||
} else {
|
||||
edp_panel_id = edp_raw_panel_id[0] << 24; // Build ID
|
||||
edp_panel_id |= edp_raw_panel_id[1] << 16; // Panel Vendor ID
|
||||
edp_panel_id |= edp_raw_panel_id[2] << 8; // Program ID
|
||||
edp_panel_id |= edp_raw_panel_id[3] << 0; // Silicon Vendor/Model ID
|
||||
|
||||
edp_default_color = (edp_raw_panel_id[0] & 1) ? 0x00000000 : 0x00FFFFFF;
|
||||
edp_voltage_offset = edp_raw_panel_id[4];
|
||||
edp_backlight_cal = edp_raw_panel_id[5];
|
||||
}
|
||||
}
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "edp_init(): edp_panel_id: 0x%08x\n", edp_panel_id);
|
||||
dprintf(DEBUG_CRITICAL, "edp_init(): edp_default_color: 0x%08x\n", edp_default_color);
|
||||
dprintf(DEBUG_CRITICAL, "edp_init(): edp_backlight_cal: 0x%08x\n", edp_backlight_cal);
|
||||
|
||||
// Ignore the real default color and use black
|
||||
edp_default_color = 0x00000000;
|
||||
|
||||
if (edp_panel_id == 0) {
|
||||
dprintf(DEBUG_CRITICAL, "panel_id = 0\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// the HPD signal causes the rest of the DP initialization to occur on the dp_controller_task
|
||||
// we hold the rest of the enable to prevent racing this task and hence violating the panel's timing requirement
|
||||
utime_t timeout = HPDTime + kHPDTimeout;
|
||||
dp_device_wait_started(timeout);
|
||||
|
||||
// Enable the CLCD
|
||||
display_set_enable(true, &edp_default_color);
|
||||
|
||||
*display_id = edp_panel_id;
|
||||
|
||||
// Adjust display voltage offset
|
||||
#if WITH_HW_POWER_DIALOG
|
||||
if (edp_voltage_offset != 0) {
|
||||
bool fixed_boost = env_get_bool("fixed-lcm-boost", false);
|
||||
power_set_display_voltage_offset(edp_voltage_offset, fixed_boost);
|
||||
}
|
||||
#endif
|
||||
|
||||
//Allow enough time before enabling backlight. Per spec at least 134ms (T4 + T5 + T6 + T7) after seeing HPD.
|
||||
dp_controller_wait_for_HPD_to_BL(HPDTime);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
edp_quiesce();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int edp_quiesce(void)
|
||||
{
|
||||
dprintf(DEBUG_CRITICAL, "edp_quiesce()\n");
|
||||
|
||||
displayport_quiesce();
|
||||
edp_panel_enable(false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void edp_panel_enable(bool enable)
|
||||
{
|
||||
#if PMU_LCD_PWR_EN
|
||||
power_set_gpio(GPIO_PMU_LCD_PWR_EN, 1, enable);
|
||||
#else
|
||||
gpio_write(GPIO_LCD_PWR_EN, enable);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if WITH_DEVICETREE
|
||||
|
||||
#include <lib/devicetree.h>
|
||||
|
||||
int edp_update_device_tree(DTNode *edp_node, DTNode *lcd_node, DTNode *clcd_node, DTNode *backlight_node)
|
||||
{
|
||||
u_int32_t propSize;
|
||||
char *propName;
|
||||
void *propData;
|
||||
|
||||
if (edp_panel_id == 0) return -1;
|
||||
|
||||
propName = "lcd-panel-id";
|
||||
if (FindProperty(edp_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = edp_panel_id;
|
||||
}
|
||||
|
||||
propName = "raw-panel-id";
|
||||
if (FindProperty(edp_node, &propName, &propData, &propSize)) {
|
||||
if (propSize > sizeof(edp_raw_panel_id)) propSize = sizeof(edp_raw_panel_id);
|
||||
memcpy(propData, edp_raw_panel_id, propSize);
|
||||
}
|
||||
|
||||
propName = "pre_configured";
|
||||
if (FindProperty(edp_node, &propName, &propData, &propSize)) {
|
||||
if (propSize >= sizeof(u_int8_t))
|
||||
((u_int32_t *)propData)[0] = displayport_video_configured() ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
if (lcd_node != NULL) {
|
||||
|
||||
propName = "alpm-enable";
|
||||
if (FindProperty(lcd_node, &propName, &propData, &propSize)) {
|
||||
if (propSize == sizeof(uint32_t)) {
|
||||
uint32_t data = dp_device_is_alpm_enabled();
|
||||
((uint32_t*)propData)[0] = data;
|
||||
}
|
||||
}
|
||||
|
||||
propName = "lcd-panel-id";
|
||||
if (FindProperty(lcd_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = edp_panel_id;
|
||||
}
|
||||
|
||||
propName = "raw-panel-id";
|
||||
if (FindProperty(lcd_node, &propName, &propData, &propSize)) {
|
||||
if (propSize > sizeof(edp_raw_panel_id)) propSize = sizeof(edp_raw_panel_id);
|
||||
memcpy(propData, edp_raw_panel_id, propSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (clcd_node != NULL) {
|
||||
propName = "display-default-color";
|
||||
if (FindProperty(clcd_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = edp_default_color;
|
||||
}
|
||||
|
||||
propName = "dot-pitch";
|
||||
if (FindProperty(clcd_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = edp_dot_pitch;
|
||||
}
|
||||
propName = "vrr-version";
|
||||
if (FindProperty(clcd_node, &propName, &propData, &propSize)) {
|
||||
if (propSize == sizeof(uint32_t)) {
|
||||
uint32_t data = edp_display_config.vrr_on << 31 | edp_display_config.vrr_enable;
|
||||
((uint32_t*)propData)[0] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (backlight_node != NULL) {
|
||||
propName = "display-backlight-calibration";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = edp_backlight_cal;
|
||||
}
|
||||
propName = "backlight-id";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
if (((u_int32_t *)propData)[0] == 0xffffffff) {
|
||||
// We are moving DP panel program-id by 1000 to not collide with
|
||||
// MIPI panel program ids
|
||||
((u_int32_t *)propData)[0] = ((edp_panel_id >> 8) & 0xff) + 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2011 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.
|
||||
*/
|
||||
#ifndef __DRIVERS_EDP_H
|
||||
#define __DRIVERS_EDP_H
|
||||
|
||||
#endif /* ! __DRIVERS_EDP_H */
|
||||
@@ -0,0 +1,16 @@
|
||||
# Copyright (C) 2011 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.
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OPTIONS += \
|
||||
WITH_HW_DISPLAY_EDP=1
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/edp.o
|
||||
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 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 <drivers/display.h>
|
||||
#include <drivers/mipi.h>
|
||||
#include <drivers/power.h>
|
||||
#include <platform/gpio.h>
|
||||
#include <platform/gpiodef.h>
|
||||
#include <lib/env.h>
|
||||
#include <lib/paint.h>
|
||||
#include <sys/task.h>
|
||||
#include <target.h>
|
||||
|
||||
#include "pinot.h"
|
||||
|
||||
/* Update to Display Sequence spec 080-4502-04 v20,
|
||||
* <rdar://problem/10885711> hold the specs. The only change is to
|
||||
* use 7 ms instead of 6ms for the delay after reset. */
|
||||
|
||||
/* This code is compliant with Display Sequence spec 080-4502-04 v19,
|
||||
* <rdar://problem/8153868> holds the spec. As repeated below, Type 1
|
||||
* does not adhere to the spec and never will. Type 2 comments and
|
||||
* diagram references are relative to that document. */
|
||||
|
||||
/* The Pinot driver type (1, 2 or 3) really should come from the panel
|
||||
* ID. However, we have a timing constraint on Type 2 and 3 drivers that
|
||||
* needs to be honored before the panel ID can be read. Therefore we
|
||||
* bind each target to its appropriate driver type and confirm with
|
||||
* the ID. Type 1 is rare/legacy at this point, so most default to 2.
|
||||
* Type 3 was introduced to improve on displayON sequence */
|
||||
#ifndef PINOT_TYPE
|
||||
#define PINOT_TYPE (2)
|
||||
#endif
|
||||
|
||||
static u_int32_t pinot_panel_id;
|
||||
static u_int32_t pinot_dot_pitch;
|
||||
static u_int32_t pinot_default_color;
|
||||
static u_int32_t pinot_voltage_offset;
|
||||
static u_int32_t pinot_backlight_cal;
|
||||
static u_int8_t pinot_raw_panel_id[15];
|
||||
|
||||
static void pinot_enable_reset(bool enable);
|
||||
static void pinot_enable_power(bool enable);
|
||||
|
||||
static int panel_id_2_class(u_int32_t panel_id)
|
||||
{
|
||||
int driver, panel_class;
|
||||
|
||||
driver = panel_id & 0x3f;
|
||||
|
||||
if (driver > DISP_IC_NUGGET)
|
||||
panel_class = 3;
|
||||
else if (driver < DISP_IC_LIBERTY)
|
||||
panel_class = 1;
|
||||
else
|
||||
panel_class = 2;
|
||||
|
||||
return panel_class;
|
||||
}
|
||||
|
||||
static void pinot_read_panel_id(void)
|
||||
{
|
||||
u_int32_t length;
|
||||
int result;
|
||||
int panel_class, driver;
|
||||
|
||||
if (pinot_panel_id == 0) {
|
||||
pinot_panel_id = env_get_uint("pinot-panel-id", 0);
|
||||
}
|
||||
if (pinot_panel_id == 0) {
|
||||
// read the panel ID
|
||||
length = sizeof(pinot_raw_panel_id);
|
||||
pinot_raw_panel_id[0] = DSIM_CMD_DEVICE_ID;
|
||||
result = mipi_dsim_read_long_command(DSIM_TYPE_GEN_READ_1P, pinot_raw_panel_id, &length);
|
||||
if ((result != 0) || (length < 3)) {
|
||||
dprintf(DEBUG_CRITICAL, "pinot_init(): read of pinot panel id failed\n");
|
||||
return;
|
||||
} else {
|
||||
pinot_panel_id = pinot_raw_panel_id[0] << 24; // Build ID
|
||||
pinot_panel_id |= pinot_raw_panel_id[1] << 16; // Panel Vendor ID
|
||||
pinot_panel_id |= (pinot_raw_panel_id[3] & 0xF0) << 8; // Program ID
|
||||
pinot_panel_id |= (pinot_raw_panel_id[2] & 0xF0) << 4; //
|
||||
pinot_panel_id |= (pinot_raw_panel_id[3] & 0x07) << 3; // Driver Vendor ID
|
||||
pinot_panel_id |= (pinot_raw_panel_id[2] & 0x07) << 0; //
|
||||
pinot_panel_id |= (pinot_raw_panel_id[2] & 0x08) << 4; // Auto Boot Bit
|
||||
pinot_panel_id |= (pinot_raw_panel_id[3] & 0x08) << 3; // Default Color Bit
|
||||
|
||||
pinot_default_color = ((pinot_raw_panel_id[3] >> 3) & 1) ? 0x00000000 : 0x00FFFFFF;
|
||||
pinot_voltage_offset = pinot_raw_panel_id[4];
|
||||
pinot_backlight_cal = pinot_raw_panel_id[5];
|
||||
}
|
||||
}
|
||||
|
||||
driver = pinot_panel_id & 0x3f;
|
||||
if (driver == DISP_IC_LIBERTY)
|
||||
pinot_backlight_cal = target_lookup_backlight_cal((pinot_panel_id >> 24) & 3);
|
||||
|
||||
panel_class = panel_id_2_class(pinot_panel_id);
|
||||
|
||||
//PINOT_TYPE should be removed eventually, but validating old HW has the correct values
|
||||
if ((PINOT_TYPE != panel_class) && (panel_class > 3))
|
||||
panic("Mismatch between PINOT_TYPE and panel ID");
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "pinot_init(): pinot_panel_id: 0x%08x\n", pinot_panel_id);
|
||||
dprintf(DEBUG_CRITICAL, "pinot_init(): pinot_default_color: 0x%08x\n", pinot_default_color);
|
||||
dprintf(DEBUG_CRITICAL, "pinot_init(): pinot_backlight_cal: 0x%08x\n", pinot_backlight_cal);
|
||||
}
|
||||
|
||||
int pinot_init(struct display_timing *timing, enum colorspace color, u_int32_t *display_id)
|
||||
{
|
||||
utime_t start_time;
|
||||
int panel_class;
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "pinot_init()\n");
|
||||
|
||||
// Save the display's dot pitch
|
||||
pinot_dot_pitch = timing->dot_pitch;
|
||||
|
||||
if (PINOT_TYPE < 2) {
|
||||
/*******************************************************************************
|
||||
* The Type 1 sequence is FROZEN as of Durango and shall NEVER BE TOUCHED AGAIN.
|
||||
* There are known excursions from the display sequencing spec.
|
||||
******************************************************************************/
|
||||
|
||||
// Reset the display and wait
|
||||
pinot_enable_reset(true);
|
||||
task_sleep(10 * 1000);
|
||||
|
||||
// Initialize the MIPI-DSI logic
|
||||
mipi_dsim_init(timing, color);
|
||||
|
||||
// Release the display from reset and wait
|
||||
pinot_enable_reset(false);
|
||||
task_sleep(7 * 1000);
|
||||
|
||||
// Send a NOP LP command. Renasas requires a command before HS clock, but we
|
||||
// can't send the sleep-out until after ID read (for Samsung).
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_NOP, 0x00);
|
||||
|
||||
// Be sure the NOP has been transmitted completely, before going HS.
|
||||
// We "know" that 10us is enough.
|
||||
spin(10);
|
||||
|
||||
// Enable the high speed clock and wait
|
||||
mipi_dsim_enable_high_speed(true);
|
||||
task_sleep(25 * 1000);
|
||||
|
||||
// Read the panel ID from the display chip. If we don't have a valid panel ID, we
|
||||
// run the quiesce sequence and bail out.
|
||||
pinot_read_panel_id();
|
||||
if (pinot_panel_id == 0) {
|
||||
mipi_dsim_quiesce();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// For Renesas Pinot, it is necessary to video- and CLCD-enable before sleep-out.
|
||||
// The delivery of a VSS packet packet lets the chip fix a latchup condition.
|
||||
|
||||
// For old SOCs the MIPI video data output must be enabled before CLCD <rdar://problem/5891347>
|
||||
// MIPI will leave the link in LP mode until it receives VSYNC from CLCD.
|
||||
mipi_dsim_enable_video(true);
|
||||
|
||||
// Ignore the real default color and paint black; program CLCD, start frame timing, take a breath
|
||||
pinot_default_color = 0x00000000;
|
||||
display_set_enable(true, &pinot_default_color);
|
||||
spin(100);
|
||||
|
||||
// Tell the panel to exit sleep, wait 7 frames
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_EXIT_SLEEP, 0x00);
|
||||
display_delay_frames(7);
|
||||
|
||||
// Turn display on and wait 7 frames before letting the backlight be turned on
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_DISPLAY_ON, 0x00);
|
||||
display_delay_frames(7);
|
||||
} else {
|
||||
// Reset the display, and make sure it has power
|
||||
pinot_enable_reset(true);
|
||||
pinot_enable_power(true);
|
||||
// initialize MIPI-DSI while waiting T1
|
||||
// Offset mipi_dsim_init giving the panel 100us to see the reset
|
||||
// This is important for the iBoot -> iBEC transition
|
||||
start_time = system_time();
|
||||
spin(100);
|
||||
mipi_dsim_init(timing, color);
|
||||
while (!time_has_elapsed(start_time, 10 * 1000)) task_yield();
|
||||
|
||||
// Release the display from reset and wait T2.
|
||||
pinot_enable_reset(false);
|
||||
task_sleep(7 * 1000);
|
||||
|
||||
// T4 and T5 are underway, since PWREN is trigger from reset on these drivers.
|
||||
|
||||
// Tell the panel to exit sleep, then wait T3 plus transmission time (~8us)
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_EXIT_SLEEP, 0x00);
|
||||
spin(12);
|
||||
|
||||
// Enable the high speed clock and wait T6, latch the start time for T7.
|
||||
// Note that T6 technically ends when the panel ID read reaches the display driver,
|
||||
// but we're being conservative and measuring until we queue the LP command.
|
||||
mipi_dsim_enable_high_speed(true);
|
||||
start_time = system_time();
|
||||
task_sleep(25 * 1000);
|
||||
|
||||
// Read the panel ID from the display chip. If we don't have a valid panel ID, we
|
||||
// run the quiesce sequence and bail out.
|
||||
pinot_read_panel_id();
|
||||
if (pinot_panel_id == 0) {
|
||||
mipi_dsim_quiesce();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Paint the panel's native color, enable the CLCD and wait 100us
|
||||
display_set_enable(true, &pinot_default_color);
|
||||
|
||||
// Finish waiting for T7 then send display-on command
|
||||
while (!time_has_elapsed(start_time, 100 * 1000)) task_yield();
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_DISPLAY_ON, 0x00);
|
||||
|
||||
// We can now enable video data after all LP commands are sent.
|
||||
mipi_dsim_enable_video(true);
|
||||
|
||||
// Now the native color is transmitting to the display. We should guarantee a couple
|
||||
// frames of native color before we switch to the black background that we want
|
||||
// the user to see. This delay is part of T9, and we'll do the overlapping T8
|
||||
// delay after setting the background to black.
|
||||
panel_class = panel_id_2_class(pinot_panel_id);
|
||||
if (panel_class > 2 ) {
|
||||
display_delay_frames(1);
|
||||
} else {
|
||||
display_delay_frames(3);
|
||||
}
|
||||
|
||||
// Draw black, wait T8 (and the final two frames of T9) before we allow backlight enable.
|
||||
paint_set_bgcolor(0, 0, 0);
|
||||
paint_update_image();
|
||||
display_delay_frames(2);
|
||||
}
|
||||
|
||||
#ifdef GPIO_LCD_CHKSUM
|
||||
// Turn off pull-down on LCD_CHKSUM
|
||||
gpio_configure_pupdn(GPIO_LCD_CHKSUM, GPIO_NO_PUPDN);
|
||||
#endif
|
||||
|
||||
*display_id = pinot_panel_id;
|
||||
|
||||
#if WITH_HW_POWER
|
||||
// Adjust analog display voltage offset (down) if necessary
|
||||
if (pinot_voltage_offset != 0) {
|
||||
bool fixed_boost = env_get_bool("fixed-lcm-boost", false);
|
||||
power_set_display_voltage_offset(pinot_voltage_offset, fixed_boost);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pinot_quiesce(void)
|
||||
{
|
||||
dprintf(DEBUG_CRITICAL, "pinot_quiesce()\n");
|
||||
|
||||
/*******************************************************************************
|
||||
* The Type 1 sequence is FROZEN as of Durango and shall NEVER BE TOUCHED AGAIN.
|
||||
* There are known excursions from the display sequencing spec. Any changes to
|
||||
* the common code below must be done in a way that preserves Type 1.
|
||||
******************************************************************************/
|
||||
|
||||
// Wait for T10 (not for Type 1) then send display-off and sleep-in
|
||||
if (PINOT_TYPE >= 2)
|
||||
display_delay_frames(1);
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_DISPLAY_OFF, 0x00);
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_ENTER_SLEEP, 0x00);
|
||||
|
||||
// Wait for T12 (which covers T11) then stop clock, reset MIPI and display driver
|
||||
display_delay_frames(6);
|
||||
// Because of LP transmission uncertainty of up to 2 frames, we need to pad the
|
||||
// delay. We only do it for Type 2 displays because Type 1 is frozen.
|
||||
if (PINOT_TYPE >= 2)
|
||||
display_delay_frames(2);
|
||||
|
||||
display_set_enable(false, NULL);
|
||||
|
||||
mipi_dsim_enable_high_speed(false);
|
||||
mipi_dsim_quiesce();
|
||||
pinot_enable_reset(true);
|
||||
pinot_enable_power(false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pinot_enable_reset(bool enable)
|
||||
{
|
||||
gpio_write(GPIO_LCD_RST, enable ^ GPIO_LCD_RST_POLARITY ^ 1);
|
||||
}
|
||||
|
||||
static void pinot_enable_power(bool enable)
|
||||
{
|
||||
#ifdef GPIO_LCD_PWR_EN
|
||||
gpio_write(GPIO_LCD_PWR_EN, enable);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if WITH_DEVICETREE
|
||||
|
||||
#include <lib/devicetree.h>
|
||||
|
||||
int pinot_update_device_tree(DTNode *pinot_node, DTNode *clcd_node, DTNode *backlight_node)
|
||||
{
|
||||
u_int32_t propSize;
|
||||
char *propName;
|
||||
void *propData;
|
||||
|
||||
if (pinot_panel_id == 0) return -1;
|
||||
|
||||
propName = "lcd-panel-id";
|
||||
if (FindProperty(pinot_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = pinot_panel_id;
|
||||
}
|
||||
|
||||
propName = "raw-panel-id";
|
||||
if (FindProperty(pinot_node, &propName, &propData, &propSize)) {
|
||||
if (propSize > sizeof(pinot_raw_panel_id)) propSize = sizeof(pinot_raw_panel_id);
|
||||
memcpy(propData, pinot_raw_panel_id, propSize);
|
||||
}
|
||||
|
||||
if (clcd_node != NULL) {
|
||||
propName = "display-default-color";
|
||||
if (FindProperty(clcd_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = pinot_default_color;
|
||||
}
|
||||
|
||||
propName = "dot-pitch";
|
||||
if (FindProperty(clcd_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = pinot_dot_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
if (backlight_node != NULL) {
|
||||
propName = "display-backlight-calibration";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = pinot_backlight_cal;
|
||||
}
|
||||
propName = "backlight-id";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
if (((u_int32_t *)propData)[0] == 0xffffffff) {
|
||||
((u_int32_t *)propData)[0] = (pinot_panel_id >> 8) & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2011 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.
|
||||
*/
|
||||
#ifndef __DRIVERS_PINOT_H
|
||||
#define __DRIVERS_PINOT_H
|
||||
|
||||
#define DISP_IC_LIBERTY (8)
|
||||
#define DISP_IC_MLC (9)
|
||||
#define DISP_IC_NUGGET (13)
|
||||
#define DISP_IC_NUGGET_B0 (14)
|
||||
|
||||
|
||||
#endif /* ! __DRIVERS_PINOT_H */
|
||||
@@ -0,0 +1,16 @@
|
||||
# Copyright (C) 2008 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.
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OPTIONS += \
|
||||
WITH_HW_DISPLAY_PINOT=1
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/pinot.o
|
||||
@@ -0,0 +1,16 @@
|
||||
# Copyright (C) 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.
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OPTIONS += \
|
||||
WITH_HW_DISPLAY_SUMMIT=1
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/summit.o
|
||||
@@ -0,0 +1,774 @@
|
||||
/*
|
||||
* Copyright (C) 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 <drivers/display.h>
|
||||
#include <drivers/mipi.h>
|
||||
#include <drivers/power.h>
|
||||
#include <platform/gpio.h>
|
||||
#include <platform/gpiodef.h>
|
||||
#include <lib/env.h>
|
||||
#include <lib/paint.h>
|
||||
#include <sys/task.h>
|
||||
#include <target.h>
|
||||
#ifdef WITH_HW_DISPLAY_PMU
|
||||
#include <drivers/display_pmu.h>
|
||||
#endif //WITH_HW_DISPLAY_PMU
|
||||
|
||||
#include "summit.h"
|
||||
|
||||
#define SUMMIT_DISABLE_DSI_PROTOCOL_ERROR_WA 1
|
||||
static u_int32_t summit_panel_id;
|
||||
static u_int32_t summit_dot_pitch;
|
||||
static u_int32_t summit_default_color;
|
||||
static u_int32_t summit_ldo_voltage;
|
||||
static u_int32_t summit_boost_voltage;
|
||||
static u_int32_t summit_backlight_cal;
|
||||
static u_int8_t summit_raw_panel_id[15];
|
||||
static uint32_t summit_sram_address[4]; //COL:start and end
|
||||
//Page:start and end
|
||||
|
||||
static void summit_enable_reset(bool enable);
|
||||
static void summit_enable_power(bool enable);
|
||||
static void summit_set_brightness(uint16_t level);
|
||||
static void summit_enable_brightness_control(bool enable);
|
||||
static void summit_set_packet_length(uint16_t length);
|
||||
static void summit_sram_update(struct display_timing *timing);
|
||||
#ifdef SUMMIT_DISABLE_DSI_PROTOCOL_ERROR_WA
|
||||
static void summit_disable_dsi_protocol_error_wa(bool lock_mcs);
|
||||
#endif
|
||||
struct display_timing *mipi_timing;
|
||||
|
||||
|
||||
static int panel_id_2_class(u_int32_t panel_id)
|
||||
{
|
||||
int driver, panel_class = 1;
|
||||
|
||||
driver = panel_id & 0x3f;
|
||||
|
||||
if (driver > DISP_IC_SUMMIT_A0)
|
||||
panel_class = 2;
|
||||
|
||||
return panel_class;
|
||||
}
|
||||
|
||||
static void summit_read_panel_id(void)
|
||||
{
|
||||
u_int32_t length;
|
||||
int result;
|
||||
int panel_class, driver;
|
||||
|
||||
if (summit_panel_id == 0) {
|
||||
summit_panel_id = env_get_uint("summit-panel-id", 0);
|
||||
}
|
||||
if (summit_panel_id == 0) {
|
||||
|
||||
// read the panel ID
|
||||
length = sizeof(summit_raw_panel_id);
|
||||
summit_raw_panel_id[0] = DSIM_CMD_DEVICE_ID;
|
||||
result = mipi_dsim_read_long_command(DSIM_TYPE_GEN_READ_1P, summit_raw_panel_id, &length);
|
||||
if ((result != 0) || (length < 3)) {
|
||||
dprintf(DEBUG_CRITICAL, "summit_init(): read of summit panel id failed\n");
|
||||
return;
|
||||
} else {
|
||||
summit_panel_id = summit_raw_panel_id[0] << 24; // Build ID
|
||||
summit_panel_id |= summit_raw_panel_id[1] << 16; // Panel Vendor ID
|
||||
summit_panel_id |= (summit_raw_panel_id[3] & 0xF0) << 8; // Program ID
|
||||
summit_panel_id |= (summit_raw_panel_id[2] & 0xF0) << 4; //
|
||||
summit_panel_id |= (summit_raw_panel_id[3] & 0x07) << 3; // Driver Vendor ID
|
||||
summit_panel_id |= (summit_raw_panel_id[2] & 0x07) << 0; //
|
||||
summit_panel_id |= (summit_raw_panel_id[2] & 0x08) << 4; // Auto Boot Bit
|
||||
summit_panel_id |= (summit_raw_panel_id[3] & 0x08) << 3; // Default Color Bit
|
||||
|
||||
summit_default_color = ((summit_raw_panel_id[3] >> 3) & 1) ? 0x00000000 : 0x00FFFFFF;
|
||||
summit_ldo_voltage = summit_raw_panel_id[4];
|
||||
summit_boost_voltage = summit_raw_panel_id[5];
|
||||
}
|
||||
}
|
||||
|
||||
driver = summit_panel_id & 0x3f;
|
||||
panel_class = panel_id_2_class(summit_panel_id);
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "summit_init(): summit_panel_id: 0x%08x\n", summit_panel_id);
|
||||
dprintf(DEBUG_CRITICAL, "summit_init(): summit_default_color: 0x%08x\n", summit_default_color);
|
||||
dprintf(DEBUG_CRITICAL, "summit_init(): summit_ldo_voltage: 0x%08x\n", summit_ldo_voltage);
|
||||
dprintf(DEBUG_CRITICAL, "summit_init(): summit_boost_voltage: 0x%08x\n", summit_boost_voltage);
|
||||
}
|
||||
|
||||
static void summit_enable_reset(bool enable)
|
||||
{
|
||||
#ifdef GPIO_PMU_LCD_RST
|
||||
power_gpio_configure(GPIO_PMU_LCD_RST, enable ? 0 : 0x38);
|
||||
#else
|
||||
gpio_write(GPIO_LCD_RST, enable ^ GPIO_LCD_RST_POLARITY ^ 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void summit_enable_power(bool enable)
|
||||
{
|
||||
#ifdef GPIO_PMU_LCD_PWR_EN
|
||||
power_set_gpio(GPIO_PMU_LCD_PWR_EN, 1, 1);
|
||||
#endif
|
||||
#ifdef PMU_LCD_PWR_DVDD
|
||||
#ifdef PMU_LCD_PWR_VCI
|
||||
if (enable) {
|
||||
power_enable_ldo(PMU_LCD_PWR_DVDD, enable);
|
||||
power_enable_ldo(PMU_LCD_PWR_VCI, enable);
|
||||
} else {
|
||||
power_enable_ldo(PMU_LCD_PWR_VCI, enable);
|
||||
spin(54 * 1000);
|
||||
power_enable_ldo(PMU_LCD_PWR_DVDD, enable);
|
||||
}
|
||||
#endif // PMU_LCD_PWR_VCI
|
||||
#endif // PMU_LCD_PWR_DVDD
|
||||
#ifdef GPIO_LCD_PWR_EN
|
||||
gpio_write(GPIO_LCD_PWR_EN, enable);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int summit_init_video_mode(struct display_timing *timing, enum colorspace color, u_int32_t *display_id)
|
||||
{
|
||||
utime_t start_time;
|
||||
int panel_driver;
|
||||
UInt8 data[26] = "";
|
||||
uint16_t brightness_level = 0xff03;
|
||||
|
||||
// Reset the display, and make sure it has power
|
||||
summit_enable_reset(true);
|
||||
summit_enable_power(true);
|
||||
// initialize MIPI-DSI while waiting T1
|
||||
// Offset mipi_dsim_init giving the panel 100us to see the reset
|
||||
// This is important for the iBoot -> iBEC transition
|
||||
start_time = system_time();
|
||||
spin(100);
|
||||
mipi_dsim_init(timing, color);
|
||||
while (!time_has_elapsed(start_time, 10 * 1000)) task_yield();
|
||||
|
||||
// Release the display from reset and wait T2.
|
||||
summit_enable_reset(false);
|
||||
task_sleep(7 * 1000);
|
||||
|
||||
// T4 and T5 are underway, since PWREN is trigger from reset on these drivers.
|
||||
|
||||
// Enable the high speed clock and wait T6, latch the start time for T7.
|
||||
// Note that T6 technically ends when the panel ID read reaches the display driver,
|
||||
// but we're being conservative and measuring until we queue the LP command.
|
||||
mipi_dsim_enable_high_speed(true);
|
||||
start_time = system_time();
|
||||
task_sleep(25 * 1000);
|
||||
|
||||
// set packet length
|
||||
summit_set_packet_length(0x20);
|
||||
|
||||
spin(1 * 1000);
|
||||
|
||||
// Read the panel ID from the display chip. If we don't have a valid panel ID, we
|
||||
// run the quiesce sequence and bail out.
|
||||
summit_read_panel_id();
|
||||
if (summit_panel_id == 0) {
|
||||
mipi_dsim_quiesce();
|
||||
return -1;
|
||||
}
|
||||
|
||||
panel_driver = summit_panel_id & 0x3f;
|
||||
|
||||
if (panel_driver == DISP_IC_SUMMIT_A0) {
|
||||
summit_set_brightness(brightness_level);
|
||||
|
||||
summit_enable_brightness_control(true);
|
||||
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_EXIT_SLEEP, 0x00);
|
||||
|
||||
spin(5 * 1000);
|
||||
|
||||
//Unlock MCS registers
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE_1P, 0xB0, 0xAC);
|
||||
|
||||
spin(1 * 1000);
|
||||
|
||||
//6. Set to internal oscillator
|
||||
data[0] = 0xC9;
|
||||
data[1] = 0xF7;
|
||||
data[2] = 0xF8;
|
||||
data[3] = 0x02;
|
||||
data[4] = 0x02;
|
||||
data[5] = 0x02;
|
||||
mipi_dsim_send_long_command(DSIM_TYPE_GEN_LONG_WRITE, data, 6);
|
||||
|
||||
spin(5 * 1000);
|
||||
|
||||
#if SUMMIT_DISABLE_DSI_PROTOCOL_ERROR_WA
|
||||
summit_disable_dsi_protocol_error_wa(false);
|
||||
#endif //SUMMIT_DISABLE_DSI_PROTOCOL_ERROR_WA
|
||||
|
||||
|
||||
// Paint the panel's native color, enable the CLCD and wait 100us
|
||||
display_set_enable(true, &summit_default_color);
|
||||
spin(32*1000);
|
||||
|
||||
// Finish waiting for T7 then send display-on command
|
||||
//while (!time_has_elapsed(start_time, 100 * 1000)) task_yield();
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_DISPLAY_ON, 0x00);
|
||||
|
||||
//8. Set up some more MCS registers that weren't programmed correctly in OTP
|
||||
data[0] = 0xCE;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x10;
|
||||
data[3] = 0x10;
|
||||
data[4] = 0x10;
|
||||
mipi_dsim_send_long_command(DSIM_TYPE_GEN_LONG_WRITE, data, 5);
|
||||
|
||||
spin(1 * 1000);
|
||||
|
||||
data[0] = 0xCF;
|
||||
data[1] = 0x15;
|
||||
mipi_dsim_send_long_command(DSIM_TYPE_GEN_LONG_WRITE, data, 2);
|
||||
|
||||
//lock MCS registers
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE_1P, 0xB0, 0xCA);
|
||||
|
||||
// We can now enable video data after all LP commands are sent.
|
||||
mipi_dsim_enable_video(true);
|
||||
|
||||
// Now the native color is transmitting to the display. We should guarantee a couple
|
||||
// frames of native color before we switch to the black background that we want
|
||||
// the user to see. This delay is part of T9, and we'll do the overlapping T8
|
||||
// delay after setting the background to black.
|
||||
display_delay_frames(3);
|
||||
|
||||
// Draw black, wait T8 (and the final two frames of T9) before we allow backlight enable.
|
||||
paint_set_bgcolor(0, 0, 0);
|
||||
paint_update_image();
|
||||
display_delay_frames(2);
|
||||
|
||||
#ifdef GPIO_LCD_CHKSUM
|
||||
// Turn off pull-down on LCD_CHKSUM
|
||||
gpio_configure_pupdn(GPIO_LCD_CHKSUM, GPIO_NO_PUPDN);
|
||||
#endif
|
||||
} else {
|
||||
|
||||
#ifdef WITH_HW_DISPLAY_PMU
|
||||
display_pmu_init();
|
||||
#endif // WITH_HW_DISPLAY_PMU
|
||||
|
||||
// We can now enable video data after all LP commands are sent.
|
||||
mipi_dsim_enable_video(true);
|
||||
|
||||
// Paint the panel's native color, enable the CLCD and wait 100us
|
||||
display_set_enable(true, &summit_default_color);
|
||||
display_delay_frames(1);
|
||||
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_EXIT_SLEEP, 0x00);
|
||||
|
||||
spin(5 * 1000);
|
||||
|
||||
summit_set_brightness(brightness_level);
|
||||
summit_enable_brightness_control(true);
|
||||
|
||||
#if SUMMIT_DISABLE_DSI_PROTOCOL_ERROR_WA
|
||||
summit_disable_dsi_protocol_error_wa(true);
|
||||
#endif //SUMMIT_DISABLE_DSI_PROTOCOL_ERROR_WA
|
||||
|
||||
// Paint the panel's native color, enable the CLCD and wait 100us
|
||||
display_set_enable(true, &summit_default_color);
|
||||
spin(32*1000);
|
||||
|
||||
// Finish waiting for T7 then send display-on command
|
||||
//while (!time_has_elapsed(start_time, 100 * 1000)) task_yield();
|
||||
display_delay_frames(5);
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_DISPLAY_ON, 0x00);
|
||||
|
||||
// Now the native color is transmitting to the display. We should guarantee a couple
|
||||
// frames of native color before we switch to the black background that we want
|
||||
// the user to see. This delay is part of T9, and we'll do the overlapping T8
|
||||
// delay after setting the background to black.
|
||||
display_delay_frames(1);
|
||||
|
||||
// Draw black, wait T8 (and the final two frames of T9) before we allow backlight enable.
|
||||
paint_set_bgcolor(0, 0, 0);
|
||||
paint_update_image();
|
||||
display_delay_frames(2);
|
||||
|
||||
#ifdef GPIO_LCD_CHKSUM
|
||||
// Turn off pull-down on LCD_CHKSUM
|
||||
gpio_configure_pupdn(GPIO_LCD_CHKSUM, GPIO_NO_PUPDN);
|
||||
#endif
|
||||
}
|
||||
|
||||
*display_id = summit_panel_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int summit_do_panel_calibration()
|
||||
{
|
||||
UInt8 data[] = { 0x51, 0xff, 0x3};
|
||||
|
||||
return mipi_dsim_send_long_command(DSIM_TYPE_GEN_LUT_WRITE, data, 3);
|
||||
}
|
||||
|
||||
static int summit_init_cmd_mode(struct display_timing *timing, enum colorspace color, u_int32_t *display_id)
|
||||
{
|
||||
utime_t start_time;
|
||||
uint32_t brightness_level;
|
||||
|
||||
mipi_timing = timing;
|
||||
|
||||
// Reset the display, and make sure it has power
|
||||
summit_enable_reset(true);
|
||||
summit_enable_power(true);
|
||||
|
||||
// initialize MIPI-DSI while waiting T1
|
||||
// Offset mipi_dsim_init giving the panel 1.5 ms to see the reset
|
||||
start_time = system_time();
|
||||
mipi_dsim_init(timing, color);
|
||||
while (!time_has_elapsed(start_time, 15 * 100)) task_yield();
|
||||
|
||||
// Release the display from reset and wait T2.
|
||||
summit_enable_reset(false);
|
||||
task_sleep(5 * 1000);
|
||||
|
||||
// Enable the high speed clock and latch the start time for T4.
|
||||
// Note that T4 technically ends when the panel ID read reaches the display driver,
|
||||
// but we're being conservative and measuring until we queue the LP command.
|
||||
mipi_dsim_enable_high_speed(true);
|
||||
start_time = system_time();
|
||||
|
||||
// set packet length
|
||||
summit_set_packet_length(0x20);
|
||||
|
||||
spin(1 * 1000);
|
||||
|
||||
// Read the panel ID from the display chip. If we don't have a valid panel ID, we
|
||||
// run the quiesce sequence and bail out.
|
||||
summit_read_panel_id();
|
||||
if (summit_panel_id == 0) {
|
||||
mipi_dsim_quiesce();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WITH_HW_DISPLAY_PMU
|
||||
display_pmu_init();
|
||||
#endif // WITH_HW_DISPLAY_PMU
|
||||
|
||||
//Wait for T4 to complete
|
||||
while (!time_has_elapsed(start_time, 5 * 1000)) task_yield();
|
||||
|
||||
summit_sram_update(timing);
|
||||
|
||||
//summit based panels set brightness vs backlight.
|
||||
//brightness_level = env_get_uint("backlight-level", 0xffff);
|
||||
brightness_level = 0xff03;
|
||||
summit_set_brightness(brightness_level);
|
||||
|
||||
summit_enable_brightness_control(true);
|
||||
|
||||
//Sleep out and latch for T5a
|
||||
start_time = system_time();
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_EXIT_SLEEP, 0x00);
|
||||
while (!time_has_elapsed(start_time, 5 * 1000)) task_yield();
|
||||
|
||||
// Finish waiting for T5 then send display-on command
|
||||
while (!time_has_elapsed(start_time, 108 * 1000)) task_yield();
|
||||
|
||||
#if SUMMIT_DISABLE_DSI_PROTOCOL_ERROR_WA
|
||||
summit_disable_dsi_protocol_error_wa(true);
|
||||
#endif //SUMMIT_DISABLE_DSI_PROTOCOL_ERROR_WA
|
||||
//Display On
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_DISPLAY_ON, 0x00);
|
||||
|
||||
// We can now enable video data after all LP commands are sent.
|
||||
mipi_dsim_enable_video(true);
|
||||
|
||||
// Paint the panel's native color, enable adp/adbe
|
||||
display_set_enable(true, &summit_default_color);
|
||||
|
||||
paint_set_bgcolor(0, 0, 0);
|
||||
paint_update_image();
|
||||
display_delay_frames(1);
|
||||
|
||||
*display_id = summit_panel_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void summit_set_brightness(uint16_t level)
|
||||
{
|
||||
UInt8 data[3] = "";
|
||||
|
||||
data[0] = 0x51;
|
||||
data[1] = (level >> 2) & 0xff;
|
||||
data[2] = (level & 0x3);
|
||||
mipi_dsim_send_long_command(DSIM_TYPE_GEN_LUT_WRITE, data, 3);
|
||||
|
||||
}
|
||||
|
||||
static void summit_enable_brightness_control(bool enable)
|
||||
{
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE_1P, 0x53, enable ? 0x20 : 0);
|
||||
}
|
||||
|
||||
static void summit_set_packet_length(uint16_t length)
|
||||
{
|
||||
mipi_dsim_send_short_command(0x37, length & 0xff, (length >> 8) & 0xff);
|
||||
}
|
||||
|
||||
#define SUMMIT_STARTING_COLUMN_ADDRESS 0x0
|
||||
#define SUMMIT_STARTING_PAGE_ADDRESS 0x0
|
||||
|
||||
static void summit_sram_update(struct display_timing *timing)
|
||||
{
|
||||
uint8_t data[5] = "";
|
||||
uint16_t sram_start_addr, sram_end_addr;
|
||||
|
||||
sram_end_addr = (timing->h_active - 1);
|
||||
sram_start_addr = SUMMIT_STARTING_COLUMN_ADDRESS;
|
||||
summit_sram_address[0] = sram_start_addr;
|
||||
summit_sram_address[1] = sram_end_addr;
|
||||
data[0] = 0x2a;
|
||||
data[1] = ((sram_start_addr >> 8) & 0xff);
|
||||
data[2] = ((sram_start_addr >> 0) & 0xff);
|
||||
data[3] = ((sram_end_addr >> 8) & 0xff);
|
||||
data[4] = ((sram_end_addr >> 0) & 0xff);
|
||||
mipi_dsim_send_long_command(0x39, data, sizeof(data));
|
||||
|
||||
sram_end_addr = (timing->v_active - 1);
|
||||
sram_start_addr = SUMMIT_STARTING_COLUMN_ADDRESS;
|
||||
summit_sram_address[2] = sram_start_addr;
|
||||
summit_sram_address[3] = sram_end_addr;
|
||||
data[0] = 0x2b;
|
||||
data[1] = ((sram_start_addr >> 8) & 0xff);
|
||||
data[2] = ((sram_start_addr >> 0) & 0xff);
|
||||
data[3] = ((sram_end_addr >> 8) & 0xff);
|
||||
data[4] = ((sram_end_addr >> 0) & 0xff);
|
||||
mipi_dsim_send_long_command(0x39, data, sizeof(data));
|
||||
|
||||
data[0] = 0x2c;
|
||||
data[1] = 0xff;
|
||||
mipi_dsim_send_long_command(0x39, data, 2);
|
||||
}
|
||||
|
||||
//
|
||||
//Global functions
|
||||
//
|
||||
|
||||
int summit_init(struct display_timing *timing, enum colorspace color, u_int32_t *display_id)
|
||||
{
|
||||
bool is_video_mode = true;
|
||||
|
||||
#ifdef TARGET_DISP_VIDEO_MODE
|
||||
is_video_mode = TARGET_DISP_VIDEO_MODE;
|
||||
#endif //TARGET_DISP_VIDEO_MODE
|
||||
|
||||
dprintf(DEBUG_CRITICAL, "summit_init %s mode()\n", is_video_mode ? "video" : "command");
|
||||
|
||||
// Save the display's dot pitch
|
||||
summit_dot_pitch = timing->dot_pitch;
|
||||
|
||||
if (is_video_mode) {
|
||||
return summit_init_video_mode(timing, color, display_id);
|
||||
} else {
|
||||
return summit_init_cmd_mode(timing, color, display_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int summit_quiesce(void)
|
||||
{
|
||||
// send display-off and wait T7
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_DISPLAY_OFF, 0x00);
|
||||
spin(18 * 1000);
|
||||
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE, DSIM_CMD_ENTER_SLEEP, 0x00);
|
||||
|
||||
// Wait for T8 then stop clock, reset MIPI and display driver
|
||||
display_delay_frames(6);
|
||||
// Because of LP transmission uncertainty of up to 2 frames, we need to pad the
|
||||
// delay. We only do it for Type 2 displays because Type 1 is frozen.
|
||||
display_delay_frames(2);
|
||||
|
||||
mipi_dsim_enable_high_speed(false);
|
||||
mipi_dsim_quiesce();
|
||||
summit_enable_reset(true);
|
||||
summit_enable_power(false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SUMMIT_DISABLE_DSI_PROTOCOL_ERROR_WA
|
||||
static void summit_disable_dsi_protocol_error_wa(bool lock_mcs)
|
||||
{
|
||||
uint8_t data1[6] = "";
|
||||
uint32_t length;
|
||||
|
||||
if (lock_mcs) {
|
||||
//Unlock MCS registers
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE_1P, 0xB0, 0xAC);
|
||||
spin(1 * 1000);
|
||||
}
|
||||
|
||||
data1[0] = 0xd4;
|
||||
data1[1] = 0x07;
|
||||
data1[2] = 0xc0;
|
||||
data1[3] = 0x80;
|
||||
data1[4] = 0x00;
|
||||
data1[5] = 0x80;
|
||||
length = sizeof(data1);
|
||||
mipi_dsim_send_long_command(DSIM_TYPE_GEN_LONG_WRITE, data1, length);
|
||||
|
||||
if (lock_mcs) {
|
||||
//lock MCS registers
|
||||
mipi_dsim_send_short_command(DSIM_TYPE_DSC_WRITE_1P, 0xB0, 0xCA);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int8_t summit_get_raw_panel_id(uint8_t *raw_panel_id, size_t raw_panel_id_length)
|
||||
{
|
||||
RELEASE_ASSERT(raw_panel_id != NULL);
|
||||
RELEASE_ASSERT(raw_panel_id_length >= sizeof(summit_raw_panel_id));
|
||||
|
||||
bcopy(summit_raw_panel_id, raw_panel_id, sizeof(summit_raw_panel_id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if WITH_DEVICETREE
|
||||
|
||||
#include <lib/devicetree.h>
|
||||
|
||||
int summit_update_device_tree(DTNode *summit_node, DTNode *clcd_node, DTNode *backlight_node)
|
||||
{
|
||||
u_int32_t propSize;
|
||||
char *propName;
|
||||
void *propData;
|
||||
char *PropNameFuncDisable = "function-backlight_inval";
|
||||
char *PropNameFuncEnable = "function-backlight_enable";
|
||||
char *PropNameFuncUpdate = "function-backlight_update";
|
||||
char *PropNameFuncNoUpdate = "function-backlight_noupdate";
|
||||
|
||||
if (summit_panel_id == 0) return -1;
|
||||
|
||||
propName = "lcd-panel-id";
|
||||
if (FindProperty(summit_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = summit_panel_id;
|
||||
}
|
||||
|
||||
propName = "raw-panel-id";
|
||||
if (FindProperty(summit_node, &propName, &propData, &propSize)) {
|
||||
if (propSize > sizeof(summit_raw_panel_id)) propSize = sizeof(summit_raw_panel_id);
|
||||
memcpy(propData, summit_raw_panel_id, propSize);
|
||||
}
|
||||
#ifdef TARGET_DISP_VIDEO_MODE
|
||||
//tell the os if video or command mode
|
||||
propName = "video-mode";
|
||||
if (FindProperty(summit_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = TARGET_DISP_VIDEO_MODE;
|
||||
}
|
||||
#endif //TARGET_DISP_VIDEO_MODE
|
||||
propName = "sram-addresses";
|
||||
if (FindProperty(summit_node, &propName, &propData, &propSize)) {
|
||||
memcpy(propData, summit_sram_address, sizeof(summit_sram_address));
|
||||
}
|
||||
|
||||
if (clcd_node != NULL) {
|
||||
propName = "display-default-color";
|
||||
if (FindProperty(clcd_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = summit_default_color;
|
||||
}
|
||||
|
||||
propName = "dot-pitch";
|
||||
if (FindProperty(clcd_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = summit_dot_pitch;
|
||||
}
|
||||
|
||||
#ifdef TARGET_DISP_VIDEO_MODE
|
||||
//tell the os if video or command mode
|
||||
propName = "video-mode";
|
||||
if (FindProperty(clcd_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = TARGET_DISP_VIDEO_MODE;
|
||||
}
|
||||
#endif //TARGET_DISP_VIDEO_MODE
|
||||
}
|
||||
|
||||
if (backlight_node != NULL) {
|
||||
propName = "function-backlight_enable";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
memset(propName, 0, strlen(propName));
|
||||
strlcpy(propName, PropNameFuncDisable, strlen(PropNameFuncDisable) + 1);
|
||||
}
|
||||
propName = "function-backlight_enable-sum";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
memset(propName, 0, strlen(propName));
|
||||
strlcpy(propName, PropNameFuncEnable, strlen(PropNameFuncEnable) + 1);
|
||||
}
|
||||
propName = "function-backlight_update";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
memset(propName, 0, strlen(propName));
|
||||
strlcpy(propName, PropNameFuncNoUpdate, strlen(PropNameFuncNoUpdate) + 1);
|
||||
}
|
||||
|
||||
propName = "function-backlight_update-sum";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
memset(propName, 0, strlen(propName));
|
||||
strlcpy(propName, PropNameFuncUpdate, strlen(PropNameFuncUpdate) + 1);
|
||||
}
|
||||
propName = "display-backlight-calibration";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
((u_int32_t *)propData)[0] = summit_backlight_cal;
|
||||
}
|
||||
propName = "backlight-id";
|
||||
if (FindProperty(backlight_node, &propName, &propData, &propSize)) {
|
||||
if (((u_int32_t *)propData)[0] == 0xffffffff) {
|
||||
((u_int32_t *)propData)[0] = (summit_panel_id >> 8) & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//FOR DEBUG ONLY WHEN NEEDED
|
||||
#if 0
|
||||
static int32_t panelFill(uint32_t width, uint32_t height, uint8_t red, uint8_t green, uint8_t blue )
|
||||
{
|
||||
int32_t err;
|
||||
uint32_t x, y;
|
||||
uint8_t *ptr;
|
||||
uint8_t *dummyLine;
|
||||
uint32_t lineBytes;
|
||||
|
||||
printf("width %d height %d red 0x%x green 0x%x blue 0x%x\n", width, height, red, green, blue);
|
||||
lineBytes = width * 3;
|
||||
dummyLine = (uint8_t *) malloc(lineBytes + 1);
|
||||
if (dummyLine == NULL ) return -1;
|
||||
|
||||
ptr = &dummyLine[1];
|
||||
printf("%s %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
*ptr++ = red;
|
||||
*ptr++ = green;
|
||||
*ptr++ = blue;
|
||||
}
|
||||
printf("%s %d\n", __FUNCTION__, __LINE__);
|
||||
#define MIPI_DSI_LONG_DCS_WRITE 0x39
|
||||
#define MIPI_DCS_COMMAND_WRITE_MEMORY_START 0x2C
|
||||
#define MIPI_DCS_COMMAND_WRITE_MEMORY_CONTINUE 0x3C
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
if (y == 0) {
|
||||
dummyLine[0] = MIPI_DCS_COMMAND_WRITE_MEMORY_START;
|
||||
err = mipi_dsim_send_long_command( MIPI_DSI_LONG_DCS_WRITE, dummyLine, lineBytes + 1 );
|
||||
if (err)
|
||||
goto PANEL_FILL_ERROR;
|
||||
} else {
|
||||
dummyLine[0] = MIPI_DCS_COMMAND_WRITE_MEMORY_CONTINUE;
|
||||
err = mipi_dsim_send_long_command( MIPI_DSI_LONG_DCS_WRITE, dummyLine, lineBytes + 1 );
|
||||
if (err)
|
||||
goto PANEL_FILL_ERROR;
|
||||
}
|
||||
|
||||
spin(1000);
|
||||
}
|
||||
|
||||
PANEL_FILL_ERROR:
|
||||
free( dummyLine);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#include <sys/menu.h>
|
||||
|
||||
static int do_mipi(int argc, struct cmd_arg *args)
|
||||
{
|
||||
if (argc < 3) {
|
||||
puts("not enough arguments.\n");
|
||||
usage:
|
||||
printf("%s readshort <cmd>\n", args[0].str);
|
||||
printf("%s readlong <cmd> <length>\n", args[0].str);
|
||||
printf("%s writeshort <cmd> <data0> <data1>\n", args[0].str);
|
||||
printf("%s writelong <cmd> <data0> <data1> ...\n", args[0].str);
|
||||
printf("%s fill <r> <g> <b> \n", args[0].str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cmd = args[2].u;
|
||||
|
||||
if (!strcmp("readshort", args[1].str)) {
|
||||
uint8_t data[32];
|
||||
int err;
|
||||
|
||||
err = mipi_dsim_read_short_command(cmd, data);
|
||||
if (err < 0) {
|
||||
printf("error %d reading from mipi\n", err);
|
||||
} else {
|
||||
hexdump(data, sizeof(data));
|
||||
}
|
||||
} else if (!strcmp("readlong", args[1].str)) {
|
||||
uint8_t data[16];
|
||||
int err;
|
||||
uint32_t len = 32;
|
||||
|
||||
data[0] = args[3].u;
|
||||
printf("reading from reg 0x%x length %d\n", data[0], len);
|
||||
err = mipi_dsim_read_long_command(cmd, data, &len);
|
||||
if (err < 0) {
|
||||
printf("error %d reading from mipi\n", err);
|
||||
} else {
|
||||
hexdump(data, len);
|
||||
}
|
||||
} else if (!strcmp("writeshort", args[1].str)) {
|
||||
u_int8_t data[2];
|
||||
int err;
|
||||
|
||||
data[0] = args[3].u;
|
||||
data[1] = args[4].u;
|
||||
|
||||
printf("writing cmd 0x%x data0 0x%x data1 0x%x\n", cmd, data[0], data[1]);
|
||||
err = mipi_dsim_send_short_command(cmd, data[0], data[1]);
|
||||
} else if (!strcmp("writelong", args[1].str)) {
|
||||
u_int8_t data[64];
|
||||
size_t len, i;
|
||||
int err;
|
||||
|
||||
len = argc - 3;
|
||||
if (len > sizeof(data)) len = sizeof(data);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
data[i] = args[i+3].u;
|
||||
printf("data[%d]=0x%x\n", i, data[i]);
|
||||
}
|
||||
|
||||
printf("writing %d bytes of data\n", len);
|
||||
err = mipi_dsim_send_long_command(cmd, data, len);
|
||||
if (err < 0)
|
||||
printf("error %d writing to mipi\n", err);
|
||||
} else if (!strcmp("fill", args[1].str)) {
|
||||
int err;
|
||||
|
||||
printf("filling width %d height %d r 0x%x g 0%x b 0x%x\n", args[2].u, args[3].u, args[4].u, args[5].u, args[6].u);
|
||||
err = panelFill(args[2].u, args[3].u, args[4].u, args[5].u, args[6].u);
|
||||
if (err < 0) {
|
||||
printf("error %d reading from mipi\n", err);
|
||||
}
|
||||
} else if (!strcmp("writeshort", args[1].str)) {
|
||||
} else {
|
||||
puts("unrecognized command.\n");
|
||||
goto usage;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#if WITH_RECOVERY_MODE
|
||||
MENU_COMMAND_DEBUG(mipi, do_mipi, "[read/write] mipi commands", NULL);
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
#ifndef __DRIVERS_SUMMIT_H
|
||||
#define __DRIVERS_SUMMIT_H
|
||||
|
||||
#define DISP_IC_SUMMIT_A0 (0x12)
|
||||
#define DISP_IC_SUMMIT_B0 (0x13)
|
||||
|
||||
|
||||
#endif /* ! __DRIVERS_SUMMIT_H */
|
||||
@@ -0,0 +1,16 @@
|
||||
# Copyright (C) 2008 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.
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OPTIONS += \
|
||||
WITH_HW_DISPLAY_TMDS=1
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/tmds.o
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2008 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 <drivers/display.h>
|
||||
#include <drivers/iic.h>
|
||||
#include <platform/clocks.h>
|
||||
#include <platform/gpio.h>
|
||||
#include <platform/gpiodef.h>
|
||||
|
||||
#include "tmds.h"
|
||||
|
||||
int tmds_init(struct display_timing *timing, enum colorspace color, u_int32_t *display_id)
|
||||
{
|
||||
u_int8_t data[2];
|
||||
|
||||
clock_set_frequency(timing->host_clock_id, 0, 0, 0, 0, timing->pixel_clock);
|
||||
/* XXX what about CLCD dithering? */
|
||||
|
||||
gpio_configure(GPIO_LCD_VCLK, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_VSYNC, GPIO_CFG_FUNC1); // XXX GPIO OUT_1 eventually
|
||||
gpio_configure(GPIO_LCD_HSYNC, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_VDEN, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_VDEN, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D0, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D1, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D2, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D3, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D4, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D5, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D6, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D7, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D8, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D9, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D10, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D11, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D12, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D13, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D14, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D15, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D16, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D17, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D18, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D19, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D20, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D21, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D22, GPIO_CFG_FUNC1);
|
||||
gpio_configure(GPIO_LCD_D23, GPIO_CFG_FUNC1);
|
||||
|
||||
data[0] = kTFP_DE_CTL;
|
||||
data[1] = 0; /* Active high DE is assumed */
|
||||
if (!timing->neg_hsync)
|
||||
data[1] |= kTFP_DE_CTL_HS_POL;
|
||||
if (!timing->neg_vsync)
|
||||
data[1] |= kTFP_DE_CTL_VS_POL;
|
||||
iic_write(TMDS_IIC_BUS, kTFP_ADDR_W, data, 2);
|
||||
|
||||
data[0] = kTFP_CTL_1_MODE;
|
||||
data[1] = kTFP_CTL_1_MODE_nPD | kTFP_CTL_1_MODE_BSEL;
|
||||
if (timing->neg_vclk)
|
||||
data[1] |= kTFP_CTL_1_MODE_EDGE;
|
||||
iic_write(TMDS_IIC_BUS, kTFP_ADDR_W, data, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tmds_quiesce(void)
|
||||
{
|
||||
dprintf(DEBUG_CRITICAL, "tmds_quiesce()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
#ifndef __TMDS_H
|
||||
#define __TMDS_H
|
||||
|
||||
/* Definitions for the TI TFP410 */
|
||||
|
||||
enum {
|
||||
kTFP_ADDR_R = 0x7f,
|
||||
kTFP_ADDR_W = 0x7e
|
||||
};
|
||||
|
||||
enum {
|
||||
kTFP_CTL_1_MODE = 0x08,
|
||||
kTFP_CTL_2_MODE = 0x09,
|
||||
kTFP_CTL_3_MODE = 0x0a,
|
||||
|
||||
kTFP_DE_DLY = 0x32,
|
||||
kTFP_DE_CTL = 0x33,
|
||||
kTFP_DE_TOP = 0x34
|
||||
};
|
||||
|
||||
enum {
|
||||
kTFP_CTL_1_MODE_nPD = (1 << 0),
|
||||
kTFP_CTL_1_MODE_EDGE = (1 << 1),
|
||||
kTFP_CTL_1_MODE_BSEL = (1 << 2),
|
||||
kTFP_CTL_1_MODE_DSEL = (1 << 3),
|
||||
kTFP_CTL_1_MODE_HEN = (1 << 4),
|
||||
kTFP_CTL_1_MODE_VEN = (1 << 5),
|
||||
kTFP_CTL_1_MODE_TDIS = (1 << 6)
|
||||
};
|
||||
|
||||
enum {
|
||||
kTFP_DE_CTL_DE_DLY8 = (1 << 0),
|
||||
kTFP_DE_CTL_HS_POL = (1 << 4),
|
||||
kTFP_DE_CTL_VS_POL = (1 << 5),
|
||||
kTFP_DE_CTL_DE_GEN = (1 << 6)
|
||||
};
|
||||
|
||||
#endif /* __TMDS_H */
|
||||
Reference in new issue
Block a user