From b54c811990b00b53158247e1daa019a6bda9c278 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 5 Oct 2011 04:25:50 +0000 Subject: [PATCH] * add encoder code to handle setting up and adjusting encoders * reorganize mode set code to match layout of linux DRM driver * add initial DPMS code * add lots of TODOs git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42801 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/accelerants/radeon_hd/display.cpp | 19 +++- src/add-ons/accelerants/radeon_hd/display.h | 3 +- src/add-ons/accelerants/radeon_hd/encoder.cpp | 95 ++++++++++++++++++- src/add-ons/accelerants/radeon_hd/encoder.h | 3 + src/add-ons/accelerants/radeon_hd/hooks.cpp | 10 ++ src/add-ons/accelerants/radeon_hd/mode.cpp | 76 +++++++++++---- src/add-ons/accelerants/radeon_hd/mode.h | 1 + 7 files changed, 178 insertions(+), 29 deletions(-) diff --git a/src/add-ons/accelerants/radeon_hd/display.cpp b/src/add-ons/accelerants/radeon_hd/display.cpp index 9cf967b2bf..aa6deb1480 100644 --- a/src/add-ons/accelerants/radeon_hd/display.cpp +++ b/src/add-ons/accelerants/radeon_hd/display.cpp @@ -431,6 +431,7 @@ detect_connectors() OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { // Found an encoder + // TODO : it may be possible to have more then one encoder int32 k; for (k = 0; k < enc_obj->ucNumberOfObjects; k++) { uint16 encoder_obj @@ -526,7 +527,6 @@ detect_connectors() // drm_encoder_helper_add break; } - //encoder_object_id = grph_obj_id; encoder_object_id = encoder_id; } } @@ -1076,17 +1076,30 @@ display_crtc_set_dtd(uint8 crtc_id, display_mode *mode) void -display_crtc_power(uint8 crt_id, int command) +display_crtc_power(uint8 crtc_id, int command) { int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC); ENABLE_CRTC_PS_ALLOCATION args; memset(&args, 0, sizeof(args)); - args.ucCRTC = crt_id; + args.ucCRTC = crtc_id; args.ucEnable = command; atom_execute_table(gAtomContext, index, (uint32*)&args); } +void +display_crtc_memreq(uint8 crtc_id, int command) +{ + int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq); + ENABLE_CRTC_PS_ALLOCATION args; + + memset(&args, 0, sizeof(args)); + + args.ucCRTC = crtc_id; + args.ucEnable = command; + + atom_execute_table(gAtomContext, index, (uint32*)&args); +} diff --git a/src/add-ons/accelerants/radeon_hd/display.h b/src/add-ons/accelerants/radeon_hd/display.h index d0fa8b0daf..aa95b385aa 100644 --- a/src/add-ons/accelerants/radeon_hd/display.h +++ b/src/add-ons/accelerants/radeon_hd/display.h @@ -73,7 +73,8 @@ void display_crtc_fb_set_legacy(uint8 crtc_id, display_mode *mode); void display_crtc_fb_set_dce1(uint8 crtc_id, display_mode *mode); void display_crtc_set(uint8 crtc_id, display_mode *mode); void display_crtc_set_dtd(uint8 crtc_id, display_mode *mode); -void display_crtc_power(uint8 crt_id, int command); +void display_crtc_power(uint8 crtc_id, int command); +void display_crtc_memreq(uint8 crtc_id, int command); #endif /* RADEON_HD_DISPLAY_H */ diff --git a/src/add-ons/accelerants/radeon_hd/encoder.cpp b/src/add-ons/accelerants/radeon_hd/encoder.cpp index 0f820e4bc8..38b15f854f 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.cpp +++ b/src/add-ons/accelerants/radeon_hd/encoder.cpp @@ -37,7 +37,7 @@ union crtc_source_param { void -encoder_assign_crtc(uint8 crtc_id) +encoder_assign_crtc(uint8 id) { int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); union crtc_source_param args; @@ -50,7 +50,7 @@ encoder_assign_crtc(uint8 crtc_id) != B_OK) return; - uint16 connector_index = gDisplay[crtc_id]->connector_index; + uint16 connector_index = gDisplay[id]->connector_index; uint16 encoder_id = gConnector[connector_index]->encoder_object_id; switch (frev) { @@ -58,7 +58,7 @@ encoder_assign_crtc(uint8 crtc_id) switch (crev) { case 1: default: - args.v1.ucCRTC = crtc_id; + args.v1.ucCRTC = id; switch (encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_TMDS1: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: @@ -102,7 +102,7 @@ encoder_assign_crtc(uint8 crtc_id) } break; case 2: - args.v2.ucCRTC = crtc_id; + args.v2.ucCRTC = id; args.v2.ucEncodeMode = display_get_encoder_mode(connector_index); switch (encoder_id) { @@ -170,3 +170,90 @@ encoder_assign_crtc(uint8 crtc_id) // TODO : encoder_crtc_scratch_regs? } + + +void +encoder_mode_set(uint8 id, uint32 pixelClock) +{ + uint32 connector_index = gDisplay[id]->connector_index; + + switch (gConnector[connector_index]->encoder_object_id) { + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + encoder_analog_setup(id, pixelClock, ATOM_ENABLE); + break; + case ENCODER_OBJECT_ID_INTERNAL_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: + case ENCODER_OBJECT_ID_INTERNAL_LVDS: + case ENCODER_OBJECT_ID_INTERNAL_LVTM1: + TRACE("%s: TODO for digital encoder setup\n", __func__); + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + TRACE("%s: TODO for DIG encoder setup\n", __func__); + break; + case ENCODER_OBJECT_ID_INTERNAL_DDI: + case ENCODER_OBJECT_ID_INTERNAL_DVO1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: + TRACE("%s: TODO for DVO encoder setup\n", __func__); + break; + default: + TRACE("%s: TODO for unknown encoder setup!\n", __func__); + } + +} + + +void +encoder_analog_setup(uint8 id, uint32 pixelClock, int command) +{ + TRACE("%s\n", __func__); + + uint32 connector_index = gDisplay[id]->connector_index; + + int index = 0; + DAC_ENCODER_CONTROL_PS_ALLOCATION args; + memset(&args, 0, sizeof(args)); + + switch (gConnector[connector_index]->encoder_object_id) { + case ENCODER_OBJECT_ID_INTERNAL_DAC1: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: + index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); + break; + case ENCODER_OBJECT_ID_INTERNAL_DAC2: + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: + index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); + break; + } + + args.ucAction = command; + args.ucDacStandard = ATOM_DAC1_PS2; + // TODO : or ATOM_DAC1_CV if ATOM_DEVICE_CV_SUPPORT + // TODO : or ATOM_DAC1_PAL or ATOM_DAC1_NTSC if else + + args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); + + atom_execute_table(gAtomContext, index, (uint32*)&args); +} + + +void +encoder_output_lock(bool lock) +{ + TRACE("%s: %s\n", __func__, lock ? "true" : "false"); + uint32 bios_6_scratch = Read32(OUT, R600_BIOS_6_SCRATCH); + + if (lock) { + bios_6_scratch |= ATOM_S6_CRITICAL_STATE; + bios_6_scratch &= ~ATOM_S6_ACC_MODE; + } else { + bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE; + bios_6_scratch |= ATOM_S6_ACC_MODE; + } + + Write32(OUT, R600_BIOS_6_SCRATCH, bios_6_scratch); +} diff --git a/src/add-ons/accelerants/radeon_hd/encoder.h b/src/add-ons/accelerants/radeon_hd/encoder.h index 380906c5b0..ccd1736fca 100644 --- a/src/add-ons/accelerants/radeon_hd/encoder.h +++ b/src/add-ons/accelerants/radeon_hd/encoder.h @@ -10,6 +10,9 @@ void encoder_assign_crtc(uint8 crt_id); +void encoder_mode_set(uint8 id, uint32 pixelClock); +void encoder_analog_setup(uint8 id, uint32 pixelClock, int command); +void encoder_output_lock(bool lock); #endif /* RADEON_HD_ENCODER_H */ diff --git a/src/add-ons/accelerants/radeon_hd/hooks.cpp b/src/add-ons/accelerants/radeon_hd/hooks.cpp index 68c4ea737d..63d6f54494 100644 --- a/src/add-ons/accelerants/radeon_hd/hooks.cpp +++ b/src/add-ons/accelerants/radeon_hd/hooks.cpp @@ -34,6 +34,16 @@ get_accelerant_hook(uint32 feature, void *data) return (void*)radeon_accelerant_retrace_semaphore; */ + /* DPMS */ + /* + case B_DPMS_CAPABILITIES: + return (void*)radeon_dpms_capabilities; + case B_DPMS_MODE: + return (void*)radeon_dpms_mode; + case B_SET_DPMS_MODE: + return (void*)radeon_dpms_set; + */ + /* mode configuration */ case B_ACCELERANT_MODE_COUNT: return (void*)radeon_accelerant_mode_count; diff --git a/src/add-ons/accelerants/radeon_hd/mode.cpp b/src/add-ons/accelerants/radeon_hd/mode.cpp index 1b6dbc9aaa..c4a73298da 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.cpp +++ b/src/add-ons/accelerants/radeon_hd/mode.cpp @@ -97,48 +97,82 @@ radeon_get_edid_info(void* info, size_t size, uint32* edid_version) } +void +radeon_dpms_set(int mode) +{ + switch(mode) { + case B_DPMS_ON: + for (uint8 id = 0; id < MAX_DISPLAY; id++) { + if (gDisplay[id]->active == false) + continue; + display_crtc_power(id, ATOM_ENABLE); + display_crtc_memreq(id, ATOM_ENABLE); + display_crtc_blank(id, ATOM_DISABLE); + } + break; + case B_DPMS_STAND_BY: + case B_DPMS_SUSPEND: + case B_DPMS_OFF: + for (uint8 id = 0; id < MAX_DISPLAY; id++) { + if (gDisplay[id]->active == false) + continue; + display_crtc_blank(id, ATOM_ENABLE); + display_crtc_memreq(id, ATOM_DISABLE); + display_crtc_power(id, ATOM_DISABLE); + } + break; + } +} + + status_t radeon_set_display_mode(display_mode *mode) { // TODO : multi-monitor? for now we use VESA and not gDisplay edid + radeon_dpms_set(B_DPMS_OFF); // Set mode on each display for (uint8 id = 0; id < MAX_DISPLAY; id++) { - display_crtc_lock(id, ATOM_ENABLE); - // Skip if display is inactive - if (gDisplay[id]->active == false) { - display_crtc_blank(id, ATOM_ENABLE); - display_crtc_power(id, ATOM_DISABLE); - display_crtc_lock(id, ATOM_DISABLE); + if (gDisplay[id]->active == false) continue; - } - // uint32 connector_index = gDisplay[id]->connector_index; - // uint32 connector_type = gConnector[connector_index]->connector_type; - // uint32 encoder_type = gConnector[connector_index]->encoder_type; + // *** encoder prep + encoder_output_lock(true); + // encoder DPMS OFF - encoder_assign_crtc(id); + // *** CRT controler prep + display_crtc_lock(id, ATOM_ENABLE); - // TODO : the first id is the pll we use... this won't work for - // more then two monitors - pll_set(id, mode->timing.pixel_clock, id); - // Program CRT Controller + // *** CRT controler mode set + // TODO program SS + pll_set(0, mode->timing.pixel_clock, id); + // TODO : check if pll 0 is used and use pll 1 if so display_crtc_set_dtd(id, mode); + + // TODO : vvvv : atombios_crtc_set_base display_crtc_fb_set_dce1(id, mode); - //display_crtc_fb_set_legacy(id, mode); + // display_crtc_fb_set_legacy(id, mode); + // atombios_overscan_setup display_crtc_scale(id, mode); - // Power CRT Controller - display_crtc_blank(id, ATOM_DISABLE); - display_crtc_power(id, ATOM_ENABLE); - //PLLPower(gDisplay[id]->connection_id, RHD_POWER_ON); + // *** encoder mode set + encoder_mode_set(id, mode->timing.pixel_clock); + encoder_assign_crtc(id); + + // *** CRT controler commit display_crtc_lock(id, ATOM_DISABLE); - // commit + + + // *** encoder commit + // encoder DPMS OFF + encoder_output_lock(false); } + radeon_dpms_set(B_DPMS_ON); + int32 crtstatus = Read32(CRT, D1CRTC_STATUS); TRACE("CRT0 Status: 0x%X\n", crtstatus); crtstatus = Read32(CRT, D2CRTC_STATUS); diff --git a/src/add-ons/accelerants/radeon_hd/mode.h b/src/add-ons/accelerants/radeon_hd/mode.h index 1527978c97..215a17c949 100644 --- a/src/add-ons/accelerants/radeon_hd/mode.h +++ b/src/add-ons/accelerants/radeon_hd/mode.h @@ -29,6 +29,7 @@ status_t create_mode_list(void); bool is_mode_supported(display_mode* mode); status_t is_mode_sane(display_mode *mode); +void radeon_dpms_set(int mode); #endif /*RADEON_HD_MODE_H*/