drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/sti/sti_hdmi_tx3g4c28phy.c
Extension
.c
Size
6012 bytes
Lines
216
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct plldividers_s {
	uint32_t min;
	uint32_t max;
	uint32_t idf;
	uint32_t odf;
};

/*
 * Functional specification recommended values
 */
#define NB_PLL_MODE 5
static struct plldividers_s plldividers[NB_PLL_MODE] = {
	{0, 20000000, 1, ODF_DIV_8},
	{20000000, 42500000, 2, ODF_DIV_8},
	{42500000, 85000000, 4, ODF_DIV_4},
	{85000000, 170000000, 8, ODF_DIV_2},
	{170000000, 340000000, 16, ODF_DIV_1}
};

#define NB_HDMI_PHY_CONFIG 2
static struct hdmi_phy_config hdmiphy_config[NB_HDMI_PHY_CONFIG] = {
	{0, 250000000, {0x0, 0x0, 0x0, 0x0} },
	{250000000, 300000000, {0x1110, 0x0, 0x0, 0x0} },
};

/**
 * sti_hdmi_tx3g4c28phy_start - Start hdmi phy macro cell tx3g4c28
 *
 * @hdmi: pointer on the hdmi internal structure
 *
 * Return false if an error occur
 */
static bool sti_hdmi_tx3g4c28phy_start(struct sti_hdmi *hdmi)
{
	u32 ckpxpll = hdmi->mode.clock * 1000;
	u32 val, tmdsck, idf, odf, pllctrl = 0;
	bool foundplldivides = false;
	int i;

	DRM_DEBUG_DRIVER("ckpxpll = %dHz\n", ckpxpll);

	for (i = 0; i < NB_PLL_MODE; i++) {
		if (ckpxpll >= plldividers[i].min &&
		    ckpxpll < plldividers[i].max) {
			idf = plldividers[i].idf;
			odf = plldividers[i].odf;
			foundplldivides = true;
			break;
		}
	}

	if (!foundplldivides) {
		DRM_ERROR("input TMDS clock speed (%d) not supported\n",
			  ckpxpll);
		goto err;
	}

	/* Assuming no pixel repetition and 24bits color */
	tmdsck = ckpxpll;
	pllctrl |= 40 << PLL_CFG_NDIV_SHIFT;

	if (tmdsck > HDMI_1_3_TMDS_CHAR_RATE_MAX_HZ) {
		DRM_ERROR("output TMDS clock (%d) out of range\n", tmdsck);
		goto err;
	}

	pllctrl |= idf << PLL_CFG_IDF_SHIFT;
	pllctrl |= odf << PLL_CFG_ODF_SHIFT;

	/*
	 * Configure and power up the PHY PLL
	 */
	hdmi->event_received = false;
	DRM_DEBUG_DRIVER("pllctrl = 0x%x\n", pllctrl);
	hdmi_write(hdmi, (pllctrl | PLL_CFG_EN), HDMI_SRZ_PLL_CFG);

	/* wait PLL interrupt */
	wait_event_interruptible_timeout(hdmi->wait_event,
					 hdmi->event_received == true,
					 msecs_to_jiffies
					 (HDMI_TIMEOUT_PLL_LOCK));

	if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_DLL_LCK) == 0) {
		DRM_ERROR("hdmi phy pll not locked\n");
		goto err;
	}

	DRM_DEBUG_DRIVER("got PHY PLL Lock\n");

	val = (HDMI_SRZ_CFG_EN |

Annotation

Implementation Notes