diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/evergreen_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen_hdmi.c | 85 |
1 files changed, 19 insertions, 66 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 327c08b54180..4fdecc2b4040 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -24,6 +24,7 @@ * Authors: Christian König * Rafał Miłecki */ +#include <linux/hdmi.h> #include <drm/drmP.h> #include <drm/radeon_drm.h> #include "radeon.h" @@ -54,79 +55,18 @@ static void evergreen_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t cloc } /* - * calculate the crc for a given info frame - */ -static void evergreen_hdmi_infoframe_checksum(uint8_t packetType, - uint8_t versionNumber, - uint8_t length, - uint8_t *frame) -{ - int i; - frame[0] = packetType + versionNumber + length; - for (i = 1; i <= length; i++) - frame[0] += frame[i]; - frame[0] = 0x100 - frame[0]; -} - -/* * build a HDMI Video Info Frame */ -static void evergreen_hdmi_videoinfoframe( - struct drm_encoder *encoder, - uint8_t color_format, - int active_information_present, - uint8_t active_format_aspect_ratio, - uint8_t scan_information, - uint8_t colorimetry, - uint8_t ex_colorimetry, - uint8_t quantization, - int ITC, - uint8_t picture_aspect_ratio, - uint8_t video_format_identification, - uint8_t pixel_repetition, - uint8_t non_uniform_picture_scaling, - uint8_t bar_info_data_valid, - uint16_t top_bar, - uint16_t bottom_bar, - uint16_t left_bar, - uint16_t right_bar -) +static void evergreen_hdmi_update_avi_infoframe(struct drm_encoder *encoder, + void *buffer, size_t size) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; uint32_t offset = dig->afmt->offset; + uint8_t *frame = buffer + 3; - uint8_t frame[14]; - - frame[0x0] = 0; - frame[0x1] = - (scan_information & 0x3) | - ((bar_info_data_valid & 0x3) << 2) | - ((active_information_present & 0x1) << 4) | - ((color_format & 0x3) << 5); - frame[0x2] = - (active_format_aspect_ratio & 0xF) | - ((picture_aspect_ratio & 0x3) << 4) | - ((colorimetry & 0x3) << 6); - frame[0x3] = - (non_uniform_picture_scaling & 0x3) | - ((quantization & 0x3) << 2) | - ((ex_colorimetry & 0x7) << 4) | - ((ITC & 0x1) << 7); - frame[0x4] = (video_format_identification & 0x7F); - frame[0x5] = (pixel_repetition & 0xF); - frame[0x6] = (top_bar & 0xFF); - frame[0x7] = (top_bar >> 8); - frame[0x8] = (bottom_bar & 0xFF); - frame[0x9] = (bottom_bar >> 8); - frame[0xA] = (left_bar & 0xFF); - frame[0xB] = (left_bar >> 8); - frame[0xC] = (right_bar & 0xFF); - frame[0xD] = (right_bar >> 8); - - evergreen_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame); /* Our header values (type, version, length) should be alright, Intel * is using the same. Checksum function also seems to be OK, it works * fine for audio infoframe. However calculated value is always lower @@ -154,7 +94,10 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; + struct hdmi_avi_infoframe frame; uint32_t offset; + ssize_t err; /* Silent, r600_hdmi_enable will raise WARN for us */ if (!dig->afmt->enabled) @@ -200,9 +143,19 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode WREG32(HDMI_GC + offset, 0); /* unset HDMI_GC_AVMUTE */ - evergreen_hdmi_videoinfoframe(encoder, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0); + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + if (err < 0) { + DRM_ERROR("failed to setup AVI infoframe: %zd\n", err); + return; + } + + err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer)); + if (err < 0) { + DRM_ERROR("failed to pack AVI infoframe: %zd\n", err); + return; + } + evergreen_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer)); evergreen_hdmi_update_ACR(encoder, mode->clock); /* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */ |