Example #1
0
static int sti_tvout_bind(struct device *dev, struct device *master, void *data)
{
	struct sti_tvout *tvout = dev_get_drvdata(dev);
	struct drm_device *drm_dev = data;
	unsigned int i;
	int ret;

	tvout->drm_dev = drm_dev;

	/* set preformatter matrix */
	for (i = 0; i < 8; i++) {
		tvout_write(tvout, rgb_to_ycbcr_601[i],
			TVO_CSC_MAIN_M0 + (i * 4));
		tvout_write(tvout, rgb_to_ycbcr_601[i],
			TVO_CSC_AUX_M0 + (i * 4));
	}

	sti_tvout_create_encoders(drm_dev, tvout);

	ret = component_bind_all(dev, drm_dev);
	if (ret)
		sti_tvout_destroy_encoders(tvout);

	return ret;
}
Example #2
0
static void sti_hda_encoder_disable(struct drm_encoder *encoder)
{
	struct sti_tvout *tvout = to_sti_tvout(encoder);

	/* reset VIP register */
	tvout_write(tvout, 0x0, TVO_VIP_HDF);

	/* power down HD DAC */
	tvout_write(tvout, 1, TVO_HD_DAC_CFG_OFF);
}
Example #3
0
/**
 * Start HDF VIP and HD DAC
 *
 * @tvout: pointer on tvout structure
 * @main_path: true if main path has to be used in the vip configuration
 *	  else aux path is used.
 */
static void tvout_hda_start(struct sti_tvout *tvout, bool main_path)
{
	struct device_node *node = tvout->dev->of_node;
	bool sel_input_logic_inverted = false;
	u32 tvo_in_vid_format;
	int val;

	dev_dbg(tvout->dev, "%s\n", __func__);

	if (main_path) {
		val = TVO_SYNC_MAIN_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT;
		val |= TVO_SYNC_MAIN_VTG_SET_3;
		tvout_write(tvout, val, TVO_HD_SYNC_SEL);
		tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT;
	} else {
		val = TVO_SYNC_AUX_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT;
		val |= TVO_SYNC_AUX_VTG_SET_3;
		tvout_write(tvout, val, TVO_HD_SYNC_SEL);
		tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT;
	}

	/* set color channel order */
	tvout_vip_set_color_order(tvout, TVO_VIP_HDF,
				  TVO_VIP_REORDER_CR_R_SEL,
				  TVO_VIP_REORDER_Y_G_SEL,
				  TVO_VIP_REORDER_CB_B_SEL);

	/* set clipping mode (EAV/SAV clipping) */
	tvout_vip_set_clip_mode(tvout, TVO_VIP_HDF, TVO_VIP_CLIP_EAV_SAV);

	/* set round mode (rounded to 10-bit per component) */
	tvout_vip_set_rnd(tvout, TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED);

	if (of_device_is_compatible(node, "st,stih407-tvout")) {
		/* set input video format */
		tvout_vip_set_in_vid_fmt(tvout,
			tvo_in_vid_format, TVO_IN_FMT_SIGNED);
		sel_input_logic_inverted = true;
	}

	/* Input selection */
	tvout_vip_set_sel_input(tvout, TVO_VIP_HDF, main_path,
				sel_input_logic_inverted,
				STI_TVOUT_VIDEO_OUT_YUV);

	/* power up HD DAC */
	tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF);
}
Example #4
0
static void sti_hdmi_encoder_disable(struct drm_encoder *encoder)
{
	struct sti_tvout *tvout = to_sti_tvout(encoder);

	/* reset VIP register */
	tvout_write(tvout, 0x0, TVO_VIP_HDMI);
}
Example #5
0
/**
 * Select the VIP input
 *
 * @tvout: tvout structure
 * @reg: register to set
 * @main_path: main or auxiliary path
 * @sel_input_logic_inverted: need to invert the logic
 * @sel_input: selected_input (main/aux + conv)
 */
static void tvout_vip_set_sel_input(struct sti_tvout *tvout,
				    int reg,
				    bool main_path,
				    bool sel_input_logic_inverted,
				    enum sti_tvout_video_out_type video_out)
{
	u32 sel_input;
	u32 val = tvout_read(tvout, reg);

	if (main_path)
		sel_input = TVO_VIP_SEL_INPUT_MAIN;
	else
		sel_input = TVO_VIP_SEL_INPUT_AUX;

	switch (video_out) {
	case STI_TVOUT_VIDEO_OUT_RGB:
		sel_input |= TVO_VIP_SEL_INPUT_BYPASSED;
		break;
	case STI_TVOUT_VIDEO_OUT_YUV:
		sel_input &= ~TVO_VIP_SEL_INPUT_BYPASSED;
		break;
	}

	/* on stih407 chip the sel_input bypass mode logic is inverted */
	if (sel_input_logic_inverted)
		sel_input = sel_input ^ TVO_VIP_SEL_INPUT_BYPASS_MASK;

	val &= ~TVO_VIP_SEL_INPUT_MASK;
	val |= sel_input;
	tvout_write(tvout, val, reg);
}
Example #6
0
static void sti_dvo_encoder_disable(struct drm_encoder *encoder)
{
	struct sti_tvout *tvout = to_sti_tvout(encoder);

	/* Reset VIP register */
	tvout_write(tvout, 0x0, TVO_VIP_DVO);
}
Example #7
0
/**
 * Start HDF VIP and HD DAC
 *
 * @tvout: pointer on tvout structure
 * @main_path: true if main path has to be used in the vip configuration
 *	  else aux path is used.
 */
static void tvout_hda_start(struct sti_tvout *tvout, bool main_path)
{
	u32 tvo_in_vid_format;
	int val;

	dev_dbg(tvout->dev, "%s\n", __func__);

	if (main_path) {
		DRM_DEBUG_DRIVER("main vip for HDF\n");
		/* Select the input sync for HD analog and HD DCS */
		val  = TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_HDDCS;
		val  = val << TVO_SYNC_HD_DCS_SHIFT;
		val |= TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_HDF;
		tvout_write(tvout, val, TVO_HD_SYNC_SEL);
		tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT;
	} else {
		DRM_DEBUG_DRIVER("aux vip for HDF\n");
		/* Select the input sync for HD analog and HD DCS */
		val  = TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_HDDCS;
		val  = val << TVO_SYNC_HD_DCS_SHIFT;
		val |= TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_HDF;
		tvout_write(tvout, val, TVO_HD_SYNC_SEL);
		tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT;
	}

	/* set color channel order */
	tvout_vip_set_color_order(tvout, TVO_VIP_HDF,
				  TVO_VIP_REORDER_CR_R_SEL,
				  TVO_VIP_REORDER_Y_G_SEL,
				  TVO_VIP_REORDER_CB_B_SEL);

	/* set clipping mode */
	tvout_vip_set_clip_mode(tvout, TVO_VIP_HDF, TVO_VIP_CLIP_DISABLED);

	/* set round mode (rounded to 10-bit per component) */
	tvout_vip_set_rnd(tvout, TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED);

	/* Set input video format */
	tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, TVO_IN_FMT_SIGNED);

	/* Input selection */
	tvout_vip_set_sel_input(tvout, TVO_VIP_HDF, main_path,
				STI_TVOUT_VIDEO_OUT_YUV);

	/* power up HD DAC */
	tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF);
}
Example #8
0
/**
 * Set the rounded value of a VIP
 *
 * @tvout: tvout structure
 * @reg: register to set
 * @rnd: rounded val per component
 */
static void tvout_vip_set_rnd(struct sti_tvout *tvout, int reg, u32 rnd)
{
	u32 val = tvout_read(tvout, reg);

	val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT);
	val |= rnd << TVO_VIP_RND_SHIFT;
	tvout_write(tvout, val, reg);
}
Example #9
0
/**
 * Set the clipping mode of a VIP
 *
 * @tvout: tvout structure
 * @reg: register to set
 * @range: clipping range
 */
static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, int reg, u32 range)
{
	u32 val = tvout_read(tvout, reg);

	val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT);
	val |= range << TVO_VIP_CLIP_SHIFT;
	tvout_write(tvout, val, reg);
}
Example #10
0
/**
 * Start VIP block for DVO output
 *
 * @tvout: pointer on tvout structure
 * @main_path: true if main path has to be used in the vip configuration
 *	  else aux path is used.
 */
static void tvout_dvo_start(struct sti_tvout *tvout, bool main_path)
{
	u32 tvo_in_vid_format;
	int val, tmp;

	dev_dbg(tvout->dev, "%s\n", __func__);

	if (main_path) {
		DRM_DEBUG_DRIVER("main vip for DVO\n");
		/* Select the input sync for dvo */
		tmp = TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_DVO;
		val  = tmp << TVO_SYNC_DVO_PAD_VSYNC_SHIFT;
		val |= tmp << TVO_SYNC_DVO_PAD_HSYNC_SHIFT;
		val |= tmp;
		tvout_write(tvout, val, TVO_DVO_SYNC_SEL);
		tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT;
	} else {
		DRM_DEBUG_DRIVER("aux vip for DVO\n");
		/* Select the input sync for dvo */
		tmp = TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_DVO;
		val  = tmp << TVO_SYNC_DVO_PAD_VSYNC_SHIFT;
		val |= tmp << TVO_SYNC_DVO_PAD_HSYNC_SHIFT;
		val |= tmp;
		tvout_write(tvout, val, TVO_DVO_SYNC_SEL);
		tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT;
	}

	/* Set color channel order */
	tvout_vip_set_color_order(tvout, TVO_VIP_DVO,
				  TVO_VIP_REORDER_CR_R_SEL,
				  TVO_VIP_REORDER_Y_G_SEL,
				  TVO_VIP_REORDER_CB_B_SEL);

	/* Set clipping mode */
	tvout_vip_set_clip_mode(tvout, TVO_VIP_DVO, TVO_VIP_CLIP_DISABLED);

	/* Set round mode (rounded to 8-bit per component) */
	tvout_vip_set_rnd(tvout, TVO_VIP_DVO, TVO_VIP_RND_8BIT_ROUNDED);

	/* Set input video format */
	tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, TVO_IN_FMT_SIGNED);

	/* Input selection */
	tvout_vip_set_sel_input(tvout, TVO_VIP_DVO, main_path,
				STI_TVOUT_VIDEO_OUT_RGB);
}
Example #11
0
/**
 * Select the input video signed or unsigned
 *
 * @tvout: tvout structure
 * @reg: register to set
 * @in_vid_signed: used video input format
 */
static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout,
		int reg, u32 in_vid_fmt)
{
	u32 val = tvout_read(tvout, reg);

	val &= ~TVO_IN_FMT_SIGNED;
	val |= in_vid_fmt;
	tvout_write(tvout, val, reg);
}
Example #12
0
/**
 * Set preformatter matrix
 *
 * @tvout: tvout structure
 * @mode: display mode structure
 */
static void tvout_preformatter_set_matrix(struct sti_tvout *tvout,
					  struct drm_display_mode *mode)
{
	unsigned int i;
	const u32 *pf_matrix;

	if (mode->vdisplay >= TVO_MIN_HD_HEIGHT)
		pf_matrix = rgb_to_ycbcr_709;
	else
		pf_matrix = rgb_to_ycbcr_601;

	for (i = 0; i < 8; i++) {
		tvout_write(tvout, *(pf_matrix + i),
			    TVO_CSC_MAIN_M0 + (i * 4));
		tvout_write(tvout, *(pf_matrix + i),
			    TVO_CSC_AUX_M0 + (i * 4));
	}
}
Example #13
0
/**
 * Start VIP block for HDMI output
 *
 * @tvout: pointer on tvout structure
 * @main_path: true if main path has to be used in the vip configuration
 *	  else aux path is used.
 */
static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path)
{
	struct device_node *node = tvout->dev->of_node;
	bool sel_input_logic_inverted = false;
	u32 tvo_in_vid_format;

	dev_dbg(tvout->dev, "%s\n", __func__);

	if (main_path) {
		DRM_DEBUG_DRIVER("main vip for hdmi\n");
		/* select the input sync for hdmi = VTG set 1 */
		tvout_write(tvout, TVO_SYNC_MAIN_VTG_SET_1, TVO_HDMI_SYNC_SEL);
		tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT;
	} else {
		DRM_DEBUG_DRIVER("aux vip for hdmi\n");
		/* select the input sync for hdmi = VTG set 1 */
		tvout_write(tvout, TVO_SYNC_AUX_VTG_SET_1, TVO_HDMI_SYNC_SEL);
		tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT;
	}

	/* set color channel order */
	tvout_vip_set_color_order(tvout, TVO_VIP_HDMI,
				  TVO_VIP_REORDER_CR_R_SEL,
				  TVO_VIP_REORDER_Y_G_SEL,
				  TVO_VIP_REORDER_CB_B_SEL);

	/* set clipping mode (Limited range RGB/Y) */
	tvout_vip_set_clip_mode(tvout, TVO_VIP_HDMI,
			TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y);

	/* set round mode (rounded to 8-bit per component) */
	tvout_vip_set_rnd(tvout, TVO_VIP_HDMI, TVO_VIP_RND_8BIT_ROUNDED);

	if (of_device_is_compatible(node, "st,stih407-tvout")) {
		/* set input video format */
		tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format,
					TVO_IN_FMT_SIGNED);
		sel_input_logic_inverted = true;
	}

	/* input selection */
	tvout_vip_set_sel_input(tvout, TVO_VIP_HDMI, main_path,
			sel_input_logic_inverted, STI_TVOUT_VIDEO_OUT_RGB);
}
Example #14
0
/**
 * Set the clipping mode of a VIP
 *
 * @tvout: tvout structure
 * @reg: register to set
 * @cr_r:
 * @y_g:
 * @cb_b:
 */
static void tvout_vip_set_color_order(struct sti_tvout *tvout, int reg,
				      u32 cr_r, u32 y_g, u32 cb_b)
{
	u32 val = tvout_read(tvout, reg);

	val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT);
	val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT);
	val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_B_SHIFT);
	val |= cr_r << TVO_VIP_REORDER_R_SHIFT;
	val |= y_g << TVO_VIP_REORDER_G_SHIFT;
	val |= cb_b << TVO_VIP_REORDER_B_SHIFT;

	tvout_write(tvout, val, reg);
}