Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4a9f822f authored by Francisco Jerez's avatar Francisco Jerez Committed by Ben Skeggs
Browse files

drm/nv17-nv4x: Attempt to init some external TMDS transmitters.



sil164 and friends are the most common, usually they just need to be
poked once because a fixed configuration is enough for any modes and
clocks, so they worked without this patch if the BIOS had done a good
job on POST. Display couldn't survive a suspend/resume cycle though.
Unfortunately, BIOS scripts are useless here.

Signed-off-by: default avatarFrancisco Jerez <currojerez@riseup.net>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent d2f4e892
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -5982,7 +5982,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
		}
		break;
	case OUTPUT_TMDS:
		if (dcb->version >= 0x22)
			entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4;
		else if (dcb->version >= 0x30)
			entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8;
		else if (dcb->version >= 0x40)
			entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;

		break;
	case 0xe:
		/* weird g80 mobile type that "nv" treats as a terminator */
@@ -6272,6 +6278,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
		dcb->i2c_table = &bios->data[i2ctabptr];
		if (dcb->version >= 0x30)
			dcb->i2c_default_indices = dcb->i2c_table[4];

		/*
		 * Parse the "management" I2C bus, used for hardware
		 * monitoring and some external TMDS transmitters.
		 */
		if (dcb->version >= 0x22) {
			int idx = (dcb->version >= 0x40 ?
				   dcb->i2c_default_indices & 0xf :
				   2);

			read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
					   idx, &dcb->i2c[idx]);
		}
	}

	if (entries > DCB_MAX_NUM_ENTRIES)
+1 −0
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ struct dcb_entry {
		} dpconf;
		struct {
			struct sor_conf sor;
			int slave_addr;
		} tmdsconf;
	};
	bool i2c_upper_default;
+7 −12
Original line number Diff line number Diff line
@@ -37,12 +37,6 @@
#include "nouveau_connector.h"
#include "nouveau_hw.h"

static inline struct drm_encoder_slave_funcs *
get_slave_funcs(struct nouveau_encoder *enc)
{
	return to_encoder_slave(to_drm_encoder(enc))->slave_funcs;
}

static struct nouveau_encoder *
find_encoder_by_type(struct drm_connector *connector, int type)
{
@@ -360,6 +354,7 @@ nouveau_connector_set_property(struct drm_connector *connector,
{
	struct nouveau_connector *nv_connector = nouveau_connector(connector);
	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
	struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
	struct drm_device *dev = connector->dev;
	int ret;

@@ -432,8 +427,8 @@ nouveau_connector_set_property(struct drm_connector *connector,
	}

	if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV)
		return get_slave_funcs(nv_encoder)->
			set_property(to_drm_encoder(nv_encoder), connector, property, value);
		return get_slave_funcs(encoder)->set_property(
			encoder, connector, property, value);

	return -EINVAL;
}
@@ -545,6 +540,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_connector *nv_connector = nouveau_connector(connector);
	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
	struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
	int ret = 0;

	/* destroy the native mode, the attached monitor could have changed.
@@ -580,8 +576,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
	}

	if (nv_encoder->dcb->type == OUTPUT_TV)
		ret = get_slave_funcs(nv_encoder)->
			get_modes(to_drm_encoder(nv_encoder), connector);
		ret = get_slave_funcs(encoder)->get_modes(encoder, connector);

	if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS ||
	    nv_connector->dcb->type == DCB_CONNECTOR_eDP)
@@ -597,6 +592,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
	struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
	struct nouveau_connector *nv_connector = nouveau_connector(connector);
	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
	struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
	unsigned min_clock = 25000, max_clock = min_clock;
	unsigned clock = mode->clock;

@@ -623,8 +619,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
			max_clock = 350000;
		break;
	case OUTPUT_TV:
		return get_slave_funcs(nv_encoder)->
			mode_valid(to_drm_encoder(nv_encoder), mode);
		return get_slave_funcs(encoder)->mode_valid(encoder, mode);
	case OUTPUT_DP:
		if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7)
			max_clock = nv_encoder->dp.link_nr * 270000;
+1 −1
Original line number Diff line number Diff line
@@ -410,7 +410,7 @@ enum nv04_fp_display_regs {

struct nv04_crtc_reg {
	unsigned char MiscOutReg;     /* */
	uint8_t CRTC[0x9f];
	uint8_t CRTC[0xa0];
	uint8_t CR58[0x10];
	uint8_t Sequencer[5];
	uint8_t Graphics[9];
+6 −0
Original line number Diff line number Diff line
@@ -71,6 +71,12 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)
	return &enc->base.base;
}

static inline struct drm_encoder_slave_funcs *
get_slave_funcs(struct drm_encoder *enc)
{
	return to_encoder_slave(enc)->slave_funcs;
}

struct nouveau_connector *
nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
Loading