drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/dispnv04/i2c/ch7006_mode.c
Extension
.c
Size
15939 bytes
Lines
471
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

abs(best_freq - mode->mode.clock)) {
				best_freq = freq;
				best_n = n;
				best_m = m;
			}
		}
	}

	regs[CH7006_PLLOV] = bitf(CH7006_PLLOV_N_8, best_n) |
		bitf(CH7006_PLLOV_M_8, best_m);

	regs[CH7006_PLLM] = bitf(CH7006_PLLM_0, best_m);
	regs[CH7006_PLLN] = bitf(CH7006_PLLN_0, best_n);

	if (best_n < 108)
		regs[CH7006_PLL_CONTROL] |= CH7006_PLL_CONTROL_CAPACITOR;
	else
		regs[CH7006_PLL_CONTROL] &= ~CH7006_PLL_CONTROL_CAPACITOR;

	ch7006_dbg(client, "n=%d m=%d f=%d c=%d\n",
		   best_n, best_m, best_freq, best_n < 108);
}

void ch7006_setup_power_state(struct drm_encoder *encoder)
{
	struct ch7006_priv *priv = to_ch7006_priv(encoder);
	uint8_t *power = &priv->state.regs[CH7006_POWER];
	int subconnector;

	subconnector = priv->select_subconnector ? priv->select_subconnector :
							priv->subconnector;

	*power = CH7006_POWER_RESET;

	if (priv->last_dpms == DRM_MODE_DPMS_ON) {
		switch (subconnector) {
		case DRM_MODE_SUBCONNECTOR_SVIDEO:
			*power |= bitfs(CH7006_POWER_LEVEL, CVBS_OFF);
			break;
		case DRM_MODE_SUBCONNECTOR_Composite:
			*power |= bitfs(CH7006_POWER_LEVEL, SVIDEO_OFF);
			break;
		case DRM_MODE_SUBCONNECTOR_SCART:
			*power |= bitfs(CH7006_POWER_LEVEL, NORMAL) |
				CH7006_POWER_SCART;
			break;
		}

	} else {
		if (priv->chip_version >= 0x20)
			*power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF);
		else
			*power |= bitfs(CH7006_POWER_LEVEL, POWER_OFF);
	}
}

void ch7006_setup_properties(struct drm_encoder *encoder)
{
	struct i2c_client *client = nouveau_i2c_encoder_get_client(encoder);
	struct ch7006_priv *priv = to_ch7006_priv(encoder);
	struct ch7006_state *state = &priv->state;
	const struct ch7006_tv_norm_info *norm = &ch7006_tv_norms[priv->norm];
	const struct ch7006_mode *ch_mode = priv->mode;
	const struct drm_display_mode *mode = &ch_mode->mode;
	uint8_t *regs = state->regs;
	int flicker, contrast, hpos, vpos;
	uint64_t scale, aspect;

	flicker = interpolate(0, 2, 3, priv->flicker);
	regs[CH7006_FFILTER] = bitf(CH7006_FFILTER_TEXT, flicker) |
		bitf(CH7006_FFILTER_LUMA, flicker) |
		bitf(CH7006_FFILTER_CHROMA, 1);

	contrast = interpolate(0, 5, 7, priv->contrast);
	regs[CH7006_CONTRAST] = bitf(CH7006_CONTRAST_0, contrast);

	scale = norm->vtotal*fixed1;
	do_div(scale, mode->vtotal);

	aspect = ch_mode->enc_hdisp*fixed1;
	do_div(aspect, ch_mode->enc_vdisp);

	hpos = round_fixed((norm->hvirtual * aspect - mode->hdisplay * scale)
			   * priv->hmargin * mode->vtotal) / norm->vtotal / 100 / 4;

	setbitf(state, CH7006_POV, HPOS_8, hpos);
	setbitf(state, CH7006_HPOS, 0, hpos);

	vpos = max(0, norm->vdisplay - round_fixed(mode->vdisplay*scale)
		   + norm->voffset) * priv->vmargin / 100 / 2;

Annotation

Implementation Notes