/* * Copyright 2014 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. *
*/
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { /* don't try to enable hpd on eDP or LVDS avoid breaking the * aux dp channel on imac and help (but not completely fix) * https://bugzilla.redhat.com/show_bug.cgi?id=726143 * also avoid interrupt storms during dpms.
*/
tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp); continue;
}
staticint dce_v8_0_get_num_crtc(struct amdgpu_device *adev)
{ int num_crtc = 0;
switch (adev->asic_type) { case CHIP_BONAIRE: case CHIP_HAWAII:
num_crtc = 6; break; case CHIP_KAVERI:
num_crtc = 4; break; case CHIP_KABINI: case CHIP_MULLINS:
num_crtc = 2; break; default:
num_crtc = 0;
} return num_crtc;
}
void dce_v8_0_disable_dce(struct amdgpu_device *adev)
{ /*Disable VGA render and enabled crtc, if has DCE engine*/ if (amdgpu_atombios_has_dce_engine_info(adev)) {
u32 tmp; int crtc_enabled, i;
/* LVDS/eDP FMT is set up by atom */ if (amdgpu_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) return;
/* not needed for analog */ if ((amdgpu_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) ||
(amdgpu_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2)) return;
/* display watermark setup */ /** * dce_v8_0_line_buffer_adjust - Set up the line buffer * * @adev: amdgpu_device pointer * @amdgpu_crtc: the selected display controller * @mode: the current display mode on the selected display * controller * * Setup up the line buffer allocation for * the selected display controller (CIK). * Returns the line buffer size in pixels.
*/ static u32 dce_v8_0_line_buffer_adjust(struct amdgpu_device *adev, struct amdgpu_crtc *amdgpu_crtc, struct drm_display_mode *mode)
{
u32 tmp, buffer_alloc, i;
u32 pipe_offset = amdgpu_crtc->crtc_id * 0x8; /* * Line Buffer Setup * There are 6 line buffers, one for each display controllers. * There are 3 partitions per LB. Select the number of partitions * to enable based on the display width. For display widths larger * than 4096, you need use to use 2 display controllers and combine * them using the stereo blender.
*/ if (amdgpu_crtc->base.enabled && mode) { if (mode->crtc_hdisplay < 1920) {
tmp = 1;
buffer_alloc = 2;
} elseif (mode->crtc_hdisplay < 2560) {
tmp = 2;
buffer_alloc = 2;
} elseif (mode->crtc_hdisplay < 4096) {
tmp = 0;
buffer_alloc = (adev->flags & AMD_IS_APU) ? 2 : 4;
} else {
DRM_DEBUG_KMS("Mode too big for LB!\n");
tmp = 0;
buffer_alloc = (adev->flags & AMD_IS_APU) ? 2 : 4;
}
} else {
tmp = 1;
buffer_alloc = 0;
}
WREG32(mmPIPE0_DMIF_BUFFER_CONTROL + pipe_offset,
(buffer_alloc << PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT)); for (i = 0; i < adev->usec_timeout; i++) { if (RREG32(mmPIPE0_DMIF_BUFFER_CONTROL + pipe_offset) &
PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK) break;
udelay(1);
}
if (amdgpu_crtc->base.enabled && mode) { switch (tmp) { case 0: default: return 4096 * 2; case 1: return 1920 * 2; case 2: return 2560 * 2;
}
}
/* controller not enabled, so no lb used */ return 0;
}
/** * cik_get_number_of_dram_channels - get the number of dram channels * * @adev: amdgpu_device pointer * * Look up the number of video ram channels (CIK). * Used for display watermark bandwidth calculations * Returns the number of dram channels
*/ static u32 cik_get_number_of_dram_channels(struct amdgpu_device *adev)
{
u32 tmp = RREG32(mmMC_SHARED_CHMAP);
switch ((tmp & MC_SHARED_CHMAP__NOOFCHAN_MASK) >> MC_SHARED_CHMAP__NOOFCHAN__SHIFT) { case 0: default: return 1; case 1: return 2; case 2: return 4; case 3: return 8; case 4: return 3; case 5: return 6; case 6: return 10; case 7: return 12; case 8: return 16;
}
}
struct dce8_wm_params {
u32 dram_channels; /* number of dram channels */
u32 yclk; /* bandwidth per dram data pin in kHz */
u32 sclk; /* engine clock in kHz */
u32 disp_clk; /* display clock in kHz */
u32 src_width; /* viewport width */
u32 active_time; /* active display time in ns */
u32 blank_time; /* blank time in ns */ bool interlaced; /* mode is interlaced */
fixed20_12 vsc; /* vertical scale ratio */
u32 num_heads; /* number of active crtcs */
u32 bytes_per_pixel; /* bytes per pixel display + overlay */
u32 lb_size; /* line buffer allocated to pipe */
u32 vtaps; /* vertical scaler taps */
};
/** * dce_v8_0_dram_bandwidth - get the dram bandwidth * * @wm: watermark calculation data * * Calculate the raw dram bandwidth (CIK). * Used for display watermark bandwidth calculations * Returns the dram bandwidth in MBytes/s
*/ static u32 dce_v8_0_dram_bandwidth(struct dce8_wm_params *wm)
{ /* Calculate raw DRAM Bandwidth */
fixed20_12 dram_efficiency; /* 0.7 */
fixed20_12 yclk, dram_channels, bandwidth;
fixed20_12 a;
/** * dce_v8_0_dram_bandwidth_for_display - get the dram bandwidth for display * * @wm: watermark calculation data * * Calculate the dram bandwidth used for display (CIK). * Used for display watermark bandwidth calculations * Returns the dram bandwidth for display in MBytes/s
*/ static u32 dce_v8_0_dram_bandwidth_for_display(struct dce8_wm_params *wm)
{ /* Calculate DRAM Bandwidth and the part allocated to display. */
fixed20_12 disp_dram_allocation; /* 0.3 to 0.7 */
fixed20_12 yclk, dram_channels, bandwidth;
fixed20_12 a;
/** * dce_v8_0_data_return_bandwidth - get the data return bandwidth * * @wm: watermark calculation data * * Calculate the data return bandwidth used for display (CIK). * Used for display watermark bandwidth calculations * Returns the data return bandwidth in MBytes/s
*/ static u32 dce_v8_0_data_return_bandwidth(struct dce8_wm_params *wm)
{ /* Calculate the display Data return Bandwidth */
fixed20_12 return_efficiency; /* 0.8 */
fixed20_12 sclk, bandwidth;
fixed20_12 a;
/** * dce_v8_0_available_bandwidth - get the min available bandwidth * * @wm: watermark calculation data * * Calculate the min available bandwidth used for display (CIK). * Used for display watermark bandwidth calculations * Returns the min available bandwidth in MBytes/s
*/ static u32 dce_v8_0_available_bandwidth(struct dce8_wm_params *wm)
{ /* Calculate the Available bandwidth. Display can use this temporarily but not in average. */
u32 dram_bandwidth = dce_v8_0_dram_bandwidth(wm);
u32 data_return_bandwidth = dce_v8_0_data_return_bandwidth(wm);
u32 dmif_req_bandwidth = dce_v8_0_dmif_request_bandwidth(wm);
/** * dce_v8_0_average_bandwidth - get the average available bandwidth * * @wm: watermark calculation data * * Calculate the average available bandwidth used for display (CIK). * Used for display watermark bandwidth calculations * Returns the average available bandwidth in MBytes/s
*/ static u32 dce_v8_0_average_bandwidth(struct dce8_wm_params *wm)
{ /* Calculate the display mode Average Bandwidth * DisplayMode should contain the source and destination dimensions, * timing, etc.
*/
fixed20_12 bpp;
fixed20_12 line_time;
fixed20_12 src_width;
fixed20_12 bandwidth;
fixed20_12 a;
/** * dce_v8_0_average_bandwidth_vs_dram_bandwidth_for_display - check * average and available dram bandwidth * * @wm: watermark calculation data * * Check if the display average bandwidth fits in the display * dram bandwidth (CIK). * Used for display watermark bandwidth calculations * Returns true if the display fits, false if not.
*/ staticbool dce_v8_0_average_bandwidth_vs_dram_bandwidth_for_display(struct dce8_wm_params *wm)
{ if (dce_v8_0_average_bandwidth(wm) <=
(dce_v8_0_dram_bandwidth_for_display(wm) / wm->num_heads)) returntrue; else returnfalse;
}
/** * dce_v8_0_average_bandwidth_vs_available_bandwidth - check * average and available bandwidth * * @wm: watermark calculation data * * Check if the display average bandwidth fits in the display * available bandwidth (CIK). * Used for display watermark bandwidth calculations * Returns true if the display fits, false if not.
*/ staticbool dce_v8_0_average_bandwidth_vs_available_bandwidth(struct dce8_wm_params *wm)
{ if (dce_v8_0_average_bandwidth(wm) <=
(dce_v8_0_available_bandwidth(wm) / wm->num_heads)) returntrue; else returnfalse;
}
/** * dce_v8_0_check_latency_hiding - check latency hiding * * @wm: watermark calculation data * * Check latency hiding (CIK). * Used for display watermark bandwidth calculations * Returns true if the display fits, false if not.
*/ staticbool dce_v8_0_check_latency_hiding(struct dce8_wm_params *wm)
{
u32 lb_partitions = wm->lb_size / wm->src_width;
u32 line_time = wm->active_time + wm->blank_time;
u32 latency_tolerant_lines;
u32 latency_hiding;
fixed20_12 a;
/* set for high clocks */
latency_watermark_a = min_t(u32, dce_v8_0_latency_watermark(&wm_high), 65535);
/* possibly force display priority to high */ /* should really do this at mode validation time... */ if (!dce_v8_0_average_bandwidth_vs_dram_bandwidth_for_display(&wm_high) ||
!dce_v8_0_average_bandwidth_vs_available_bandwidth(&wm_high) ||
!dce_v8_0_check_latency_hiding(&wm_high) ||
(adev->mode_info.disp_priority == 2)) {
DRM_DEBUG_KMS("force priority to high\n");
}
/* set for low clocks */
latency_watermark_b = min_t(u32, dce_v8_0_latency_watermark(&wm_low), 65535);
/* possibly force display priority to high */ /* should really do this at mode validation time... */ if (!dce_v8_0_average_bandwidth_vs_dram_bandwidth_for_display(&wm_low) ||
!dce_v8_0_average_bandwidth_vs_available_bandwidth(&wm_low) ||
!dce_v8_0_check_latency_hiding(&wm_low) ||
(adev->mode_info.disp_priority == 2)) {
DRM_DEBUG_KMS("force priority to high\n");
}
lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
}
/* save values for DPM */
amdgpu_crtc->line_time = line_time;
amdgpu_crtc->wm_high = latency_watermark_a;
amdgpu_crtc->wm_low = latency_watermark_b; /* Save number of lines the linebuffer leads before the scanout */
amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines;
}
/** * dce_v8_0_bandwidth_update - program display watermarks * * @adev: amdgpu_device pointer * * Calculate and program the display watermarks and line * buffer allocation (CIK).
*/ staticvoid dce_v8_0_bandwidth_update(struct amdgpu_device *adev)
{ struct drm_display_mode *mode = NULL;
u32 num_heads = 0, lb_size; int i;
amdgpu_display_update_priority(adev);
for (i = 0; i < adev->mode_info.num_crtc; i++) { if (adev->mode_info.crtcs[i]->base.enabled)
num_heads++;
} for (i = 0; i < adev->mode_info.num_crtc; i++) {
mode = &adev->mode_info.crtcs[i]->base.mode;
lb_size = dce_v8_0_line_buffer_adjust(adev, adev->mode_info.crtcs[i], mode);
dce_v8_0_program_watermarks(adev, adev->mode_info.crtcs[i],
lb_size, num_heads);
}
}
staticvoid dce_v8_0_audio_get_connected_pins(struct amdgpu_device *adev)
{ int i;
u32 offset, tmp;
for (i = 0; i < adev->mode_info.audio.num_pins; i++) {
offset = adev->mode_info.audio.pin[i].offset;
tmp = RREG32_AUDIO_ENDPT(offset,
ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT); if (((tmp &
AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY_MASK) >>
AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY__SHIFT) == 1)
adev->mode_info.audio.pin[i].connected = false; else
adev->mode_info.audio.pin[i].connected = true;
}
}
staticstruct amdgpu_audio_pin *dce_v8_0_audio_get_pin(struct amdgpu_device *adev)
{ int i;
dce_v8_0_audio_get_connected_pins(adev);
for (i = 0; i < adev->mode_info.audio.num_pins; i++) { if (adev->mode_info.audio.pin[i].connected) return &adev->mode_info.audio.pin[i];
}
DRM_ERROR("No connected audio pins found!\n"); return NULL;
}
for (i = 0; i < adev->mode_info.audio.num_pins; i++) {
adev->mode_info.audio.pin[i].channels = -1;
adev->mode_info.audio.pin[i].rate = -1;
adev->mode_info.audio.pin[i].bits_per_sample = -1;
adev->mode_info.audio.pin[i].status_bits = 0;
adev->mode_info.audio.pin[i].category_code = 0;
adev->mode_info.audio.pin[i].connected = false;
adev->mode_info.audio.pin[i].offset = pin_offsets[i];
adev->mode_info.audio.pin[i].id = i; /* disable audio. it will be set up later */ /* XXX remove once we switch to ip funcs */
dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
}
return 0;
}
staticvoid dce_v8_0_audio_fini(struct amdgpu_device *adev)
{ if (!amdgpu_audio) return;
if (!adev->mode_info.audio.enabled) return;
adev->mode_info.audio.enabled = false;
}
/* * update the N and CTS parameters for a given pixel clock rate
*/ staticvoid dce_v8_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock)
{ struct drm_device *dev = encoder->dev; struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
uint32_t offset = dig->afmt->offset;
/* XXX two dtos; generally use dto0 for hdmi */ /* Express [24MHz / target pixel clock] as an exact rational * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
*/
WREG32(mmDCCG_AUDIO_DTO_SOURCE, (amdgpu_crtc->crtc_id << DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO0_SOURCE_SEL__SHIFT));
WREG32(mmDCCG_AUDIO_DTO0_PHASE, dto_phase);
WREG32(mmDCCG_AUDIO_DTO0_MODULE, dto_modulo);
}
/* * update the info frames with the data from the current display mode
*/ staticvoid dce_v8_0_afmt_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
{ struct drm_device *dev = encoder->dev; struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder);
u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; struct hdmi_avi_infoframe frame;
uint32_t offset, val;
ssize_t err; int bpc = 8;
if (!dig || !dig->afmt) return;
/* Silent, r600_hdmi_enable will raise WARN for us */ if (!dig->afmt->enabled) return;
offset = dig->afmt->offset;
/* hdmi deep color mode general control packets setup, if bpc > 8 */ if (encoder->crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc);
bpc = amdgpu_crtc->bpc;
}
/* disable audio prior to setting up hw */
dig->afmt->pin = dce_v8_0_audio_get_pin(adev);
dce_v8_0_audio_enable(adev, dig->afmt->pin, false);
val = RREG32(mmHDMI_CONTROL + offset);
val &= ~HDMI_CONTROL__HDMI_DEEP_COLOR_ENABLE_MASK;
val &= ~HDMI_CONTROL__HDMI_DEEP_COLOR_DEPTH_MASK;
switch (bpc) { case 0: case 6: case 8: case 16: default:
DRM_DEBUG("%s: Disabling hdmi deep color for %d bpc.\n",
connector->name, bpc); break; case 10:
val |= HDMI_CONTROL__HDMI_DEEP_COLOR_ENABLE_MASK;
val |= 1 << HDMI_CONTROL__HDMI_DEEP_COLOR_DEPTH__SHIFT;
DRM_DEBUG("%s: Enabling hdmi deep color 30 for 10 bpc.\n",
connector->name); break; case 12:
val |= HDMI_CONTROL__HDMI_DEEP_COLOR_ENABLE_MASK;
val |= 2 << HDMI_CONTROL__HDMI_DEEP_COLOR_DEPTH__SHIFT;
DRM_DEBUG("%s: Enabling hdmi deep color 36 for 12 bpc.\n",
connector->name); break;
}
WREG32(mmHDMI_CONTROL + offset, val);
WREG32(mmHDMI_VBI_PACKET_CONTROL + offset,
HDMI_VBI_PACKET_CONTROL__HDMI_NULL_SEND_MASK | /* send null packets when required */
HDMI_VBI_PACKET_CONTROL__HDMI_GC_SEND_MASK | /* send general control packets */
HDMI_VBI_PACKET_CONTROL__HDMI_GC_CONT_MASK); /* send general control packets every frame */
WREG32(mmHDMI_INFOFRAME_CONTROL0 + offset,
HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_SEND_MASK | /* enable audio info frames (frames won't be set until audio is enabled) */
HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_CONT_MASK); /* required for audio info values to be updated */
WREG32(mmAFMT_INFOFRAME_CONTROL0 + offset,
AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_UPDATE_MASK); /* required for audio info values to be updated */
WREG32(mmHDMI_INFOFRAME_CONTROL1 + offset,
(2 << HDMI_INFOFRAME_CONTROL1__HDMI_AUDIO_INFO_LINE__SHIFT)); /* anything other than 0 */
WREG32(mmHDMI_AUDIO_PACKET_CONTROL + offset,
(1 << HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_DELAY_EN__SHIFT) | /* set the default audio delay */
(3 << HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_PACKETS_PER_LINE__SHIFT)); /* should be suffient for all audio modes and small enough for all hblanks */
WREG32(mmAFMT_AUDIO_PACKET_CONTROL + offset,
AFMT_AUDIO_PACKET_CONTROL__AFMT_60958_CS_UPDATE_MASK); /* allow 60958 channel status fields to be updated */
/* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */
if (bpc > 8)
WREG32(mmHDMI_ACR_PACKET_CONTROL + offset,
HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_MASK); /* allow hw to sent ACR packets when required */ else
WREG32(mmHDMI_ACR_PACKET_CONTROL + offset,
HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE_MASK | /* select SW CTS value */
HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_MASK); /* allow hw to sent ACR packets when required */
WREG32_OR(mmHDMI_INFOFRAME_CONTROL0 + offset,
HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND_MASK | /* enable AVI info frames */
HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_CONT_MASK); /* required for audio info values to be updated */
WREG32_P(mmHDMI_INFOFRAME_CONTROL1 + offset,
(2 << HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE__SHIFT), /* anything other than 0 */
~HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE_MASK);
/* no fb bound */ if (!atomic && !crtc->primary->fb) {
DRM_DEBUG_KMS("No FB bound\n"); return 0;
}
if (atomic)
target_fb = fb; else
target_fb = crtc->primary->fb;
/* If atomic, assume fb object is pinned & idle & fenced and * just update base pointers
*/
obj = target_fb->obj[0];
abo = gem_to_amdgpu_bo(obj);
r = amdgpu_bo_reserve(abo, false); if (unlikely(r != 0)) return r;
if (!atomic) {
abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
r = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM); if (unlikely(r != 0)) {
amdgpu_bo_unreserve(abo); return -EINVAL;
}
}
fb_location = amdgpu_bo_gpu_offset(abo);
/* * The LUT only has 256 slots for indexing by a 8 bpc fb. Bypass the LUT * for > 8 bpc scanout to avoid truncation of fb indices to 8 msb's, to * retain the full precision throughout the pipeline.
*/
WREG32_P(mmGRPH_LUT_10BIT_BYPASS_CONTROL + amdgpu_crtc->crtc_offset,
(bypass_lut ? LUT_10BIT_BYPASS_EN : 0),
~LUT_10BIT_BYPASS_EN);
if (bypass_lut)
DRM_DEBUG_KMS("Bypassing hardware LUT due to 10 bit fb scanout.\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.