Пример #1
0
static void adv7511_set_config(struct drm_encoder *encoder, void *c)
{
	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
	struct adv7511_video_config *config = c;
	bool output_format_422, output_format_ycbcr;
	unsigned int mode;
	uint8_t infoframe[17];

	if (config->hdmi_mode) {
		mode = ADV7511_HDMI_CFG_MODE_HDMI;

		switch (config->avi_infoframe.colorspace) {
		case HDMI_COLORSPACE_YUV444:
			output_format_422 = false;
			output_format_ycbcr = true;
			break;
		case HDMI_COLORSPACE_YUV422:
			output_format_422 = true;
			output_format_ycbcr = true;
			break;
		default:
			output_format_422 = false;
			output_format_ycbcr = false;
			break;
		}
	} else {
		mode = ADV7511_HDMI_CFG_MODE_DVI;
		output_format_422 = false;
		output_format_ycbcr = false;
	}

	adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);

	adv7511_set_colormap(adv7511, config->csc_enable,
			     config->csc_coefficents,
			     config->csc_scaling_factor);

	regmap_update_bits(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, 0x81,
			   (output_format_422 << 7) | output_format_ycbcr);

	regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
			   ADV7511_HDMI_CFG_MODE_MASK, mode);

	hdmi_avi_infoframe_pack(&config->avi_infoframe, infoframe,
				sizeof(infoframe));

	/* The AVI infoframe id is not configurable */
	regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
			  infoframe + 1, sizeof(infoframe) - 1);

	adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
}
Пример #2
0
static void hdmi_core_write_avi_infoframe(struct hdmi_core_data *core,
	struct hdmi_avi_infoframe *frame)
{
	void __iomem *av_base = hdmi_av_base(core);
	u8 data[HDMI_INFOFRAME_SIZE(AVI)];
	int i;

	hdmi_avi_infoframe_pack(frame, data, sizeof(data));

	print_hex_dump_debug("AVI: ", DUMP_PREFIX_NONE, 16, 1, data,
		HDMI_INFOFRAME_SIZE(AVI), false);

	for (i = 0; i < sizeof(data); ++i) {
		hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_BASE + i * 4,
			data[i]);
	}
}
Пример #3
0
static void
tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
{
	struct hdmi_avi_infoframe frame;
	u8 buf[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
	ssize_t len;

	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);

	frame.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;

	len = hdmi_avi_infoframe_pack(&frame, buf, sizeof(buf));
	if (len < 0) {
		dev_err(&priv->hdmi->dev,
			"hdmi_avi_infoframe_pack() failed: %zd\n", len);
		return;
	}

	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf, len);
}
Пример #4
0
static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
					   struct drm_display_mode *mode)
{
	struct hdmi_avi_infoframe frame;
	u8 buffer[17];
	int i, ret;

	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
	if (ret < 0) {
		DRM_ERROR("Failed to get infoframes from mode\n");
		return ret;
	}

	ret = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
	if (ret < 0) {
		DRM_ERROR("Failed to pack infoframes\n");
		return ret;
	}

	for (i = 0; i < sizeof(buffer); i++)
		writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i));

	return 0;
}
Пример #5
0
/*
 * update the info frames with the data from the current display mode
 */
void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
{
	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;
	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)
		return;
	offset = dig->afmt->offset;

	r600_audio_set_clock(encoder, mode->clock);

	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
	       HDMI0_NULL_SEND); /* send null packets when required */

	WREG32(HDMI0_AUDIO_CRC_CONTROL + offset, 0x1000);

	if (ASIC_IS_DCE32(rdev)) {
		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
		       HDMI0_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
		WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
		       AFMT_AUDIO_SAMPLE_SEND | /* send audio packets */
		       AFMT_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
	} else {
		WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset,
		       HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
		       HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
		       HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
		       HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */
	}

	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
	       HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */
	       HDMI0_ACR_SOURCE); /* select SW CTS value */

	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
	       HDMI0_NULL_SEND | /* send null packets when required */
	       HDMI0_GC_SEND | /* send general control packets */
	       HDMI0_GC_CONT); /* send general control packets every frame */

	/* TODO: HDMI0_AUDIO_INFO_UPDATE */
	WREG32(HDMI0_INFOFRAME_CONTROL0 + offset,
	       HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
	       HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
	       HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
	       HDMI0_AUDIO_INFO_CONT); /* send audio info frames every frame/field */

	WREG32(HDMI0_INFOFRAME_CONTROL1 + offset,
	       HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
	       HDMI0_AUDIO_INFO_LINE(2)); /* anything other than 0 */

	WREG32(HDMI0_GC + offset, 0); /* unset HDMI0_GC_AVMUTE */

	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;
	}

	r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));
	r600_hdmi_update_ACR(encoder, mode->clock);

	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
	WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF);
	WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF);
	WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001);
	WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);

	r600_hdmi_audio_workaround(encoder);
}
Пример #6
0
/*
 * update the info frames with the data from the current display mode
 */
void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
{
	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;
	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
	struct hdmi_avi_infoframe frame;
	uint32_t offset;
	uint32_t acr_ctl;
	ssize_t err;

	if (!dig || !dig->afmt)
		return;

	/* Silent, r600_hdmi_enable will raise WARN for us */
	if (!dig->afmt->enabled)
		return;
	offset = dig->afmt->offset;

	/* disable audio prior to setting up hw */
	dig->afmt->pin = r600_audio_get_pin(rdev);
	r600_audio_enable(rdev, dig->afmt->pin, false);

	r600_audio_set_dto(encoder, mode->clock);

	WREG32_P(HDMI0_AUDIO_PACKET_CONTROL + offset,
		 HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */
		 HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */
		 HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */
		 HDMI0_60958_CS_UPDATE, /* allow 60958 channel status fields to be updated */
		 ~(HDMI0_AUDIO_SAMPLE_SEND |
		   HDMI0_AUDIO_DELAY_EN_MASK |
		   HDMI0_AUDIO_PACKETS_PER_LINE_MASK |
		   HDMI0_60958_CS_UPDATE));

	/* DCE 3.0 uses register that's normally for CRC_CONTROL */
	acr_ctl = ASIC_IS_DCE3(rdev) ? DCE3_HDMI0_ACR_PACKET_CONTROL :
				       HDMI0_ACR_PACKET_CONTROL;
	WREG32_P(acr_ctl + offset,
		 HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
		 HDMI0_ACR_AUTO_SEND, /* allow hw to sent ACR packets when required */
		 ~(HDMI0_ACR_SOURCE |
		   HDMI0_ACR_AUTO_SEND));

	WREG32_OR(HDMI0_VBI_PACKET_CONTROL + offset,
		  HDMI0_NULL_SEND | /* send null packets when required */
		  HDMI0_GC_SEND | /* send general control packets */
		  HDMI0_GC_CONT); /* send general control packets every frame */

	WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset,
		  HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
		  HDMI0_AVI_INFO_CONT | /* send AVI info frames every frame/field */
		  HDMI0_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
		  HDMI0_AUDIO_INFO_UPDATE); /* required for audio info values to be updated */

	WREG32_P(HDMI0_INFOFRAME_CONTROL1 + offset,
		 HDMI0_AVI_INFO_LINE(2) | /* anything other than 0 */
		 HDMI0_AUDIO_INFO_LINE(2), /* anything other than 0 */
		 ~(HDMI0_AVI_INFO_LINE_MASK |
		   HDMI0_AUDIO_INFO_LINE_MASK));

	WREG32_AND(HDMI0_GC + offset,
		   ~HDMI0_GC_AVMUTE); /* unset HDMI0_GC_AVMUTE */

	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;
	}

	r600_hdmi_update_avi_infoframe(encoder, buffer, sizeof(buffer));

	/* fglrx duplicates INFOFRAME_CONTROL0 & INFOFRAME_CONTROL1 ops here */

	WREG32_AND(HDMI0_GENERIC_PACKET_CONTROL + offset,
		   ~(HDMI0_GENERIC0_SEND |
		     HDMI0_GENERIC0_CONT |
		     HDMI0_GENERIC0_UPDATE |
		     HDMI0_GENERIC1_SEND |
		     HDMI0_GENERIC1_CONT |
		     HDMI0_GENERIC0_LINE_MASK |
		     HDMI0_GENERIC1_LINE_MASK));

	r600_hdmi_update_ACR(encoder, mode->clock);

	WREG32_P(HDMI0_60958_0 + offset,
		 HDMI0_60958_CS_CHANNEL_NUMBER_L(1),
		 ~(HDMI0_60958_CS_CHANNEL_NUMBER_L_MASK |
		   HDMI0_60958_CS_CLOCK_ACCURACY_MASK));

	WREG32_P(HDMI0_60958_1 + offset,
		 HDMI0_60958_CS_CHANNEL_NUMBER_R(2),
		 ~HDMI0_60958_CS_CHANNEL_NUMBER_R_MASK);

	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
	WREG32(HDMI0_RAMP_CONTROL0 + offset, 0x00FFFFFF);
	WREG32(HDMI0_RAMP_CONTROL1 + offset, 0x007FFFFF);
	WREG32(HDMI0_RAMP_CONTROL2 + offset, 0x00000001);
	WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);

	/* enable audio after to setting up hw */
	r600_audio_enable(rdev, dig->afmt->pin, true);
}