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

Commit 9cc2a685 authored by Shawn Guo's avatar Shawn Guo
Browse files

drm: zte: add function to configure vou_ctrl dividers



The clock control module (CRM) cannot always provide desired frequency
for all VOU output devices.  That's why VOU integrates a few dividers
to further divide the clocks from CRM.  Let's add an interface for
configuring these dividers.

Signed-off-by: default avatarShawn Guo <shawn.guo@linaro.org>
Reviewed-by: default avatarSean Paul <seanpaul@chromium.org>
parent 831a8d5e
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
@@ -72,6 +72,13 @@ struct zx_crtc_bits {
	u32 sec_vactive_mask;
	u32 interlace_select;
	u32 pi_enable;
	u32 div_vga_shift;
	u32 div_pic_shift;
	u32 div_tvenc_shift;
	u32 div_hdmi_pnx_shift;
	u32 div_hdmi_shift;
	u32 div_inf_shift;
	u32 div_layer_shift;
};

static const struct zx_crtc_bits main_crtc_bits = {
@@ -83,6 +90,13 @@ static const struct zx_crtc_bits main_crtc_bits = {
	.sec_vactive_mask = SEC_VACT_MAIN_MASK,
	.interlace_select = MAIN_INTERLACE_SEL,
	.pi_enable = MAIN_PI_EN,
	.div_vga_shift = VGA_MAIN_DIV_SHIFT,
	.div_pic_shift = PIC_MAIN_DIV_SHIFT,
	.div_tvenc_shift = TVENC_MAIN_DIV_SHIFT,
	.div_hdmi_pnx_shift = HDMI_MAIN_PNX_DIV_SHIFT,
	.div_hdmi_shift = HDMI_MAIN_DIV_SHIFT,
	.div_inf_shift = INF_MAIN_DIV_SHIFT,
	.div_layer_shift = LAYER_MAIN_DIV_SHIFT,
};

static const struct zx_crtc_bits aux_crtc_bits = {
@@ -94,6 +108,13 @@ static const struct zx_crtc_bits aux_crtc_bits = {
	.sec_vactive_mask = SEC_VACT_AUX_MASK,
	.interlace_select = AUX_INTERLACE_SEL,
	.pi_enable = AUX_PI_EN,
	.div_vga_shift = VGA_AUX_DIV_SHIFT,
	.div_pic_shift = PIC_AUX_DIV_SHIFT,
	.div_tvenc_shift = TVENC_AUX_DIV_SHIFT,
	.div_hdmi_pnx_shift = HDMI_AUX_PNX_DIV_SHIFT,
	.div_hdmi_shift = HDMI_AUX_DIV_SHIFT,
	.div_inf_shift = INF_AUX_DIV_SHIFT,
	.div_layer_shift = LAYER_AUX_DIV_SHIFT,
};

struct zx_crtc {
@@ -236,6 +257,64 @@ void vou_inf_disable(enum vou_inf_id id, struct drm_crtc *crtc)
	zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
}

void zx_vou_config_dividers(struct drm_crtc *crtc,
			    struct vou_div_config *configs, int num)
{
	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
	struct zx_vou_hw *vou = zcrtc->vou;
	const struct zx_crtc_bits *bits = zcrtc->bits;
	int i;

	/* Clear update flag bit */
	zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE, 0);

	for (i = 0; i < num; i++) {
		struct vou_div_config *cfg = configs + i;
		u32 reg, shift;

		switch (cfg->id) {
		case VOU_DIV_VGA:
			reg = VOU_CLK_SEL;
			shift = bits->div_vga_shift;
			break;
		case VOU_DIV_PIC:
			reg = VOU_CLK_SEL;
			shift = bits->div_pic_shift;
			break;
		case VOU_DIV_TVENC:
			reg = VOU_DIV_PARA;
			shift = bits->div_tvenc_shift;
			break;
		case VOU_DIV_HDMI_PNX:
			reg = VOU_DIV_PARA;
			shift = bits->div_hdmi_pnx_shift;
			break;
		case VOU_DIV_HDMI:
			reg = VOU_DIV_PARA;
			shift = bits->div_hdmi_shift;
			break;
		case VOU_DIV_INF:
			reg = VOU_DIV_PARA;
			shift = bits->div_inf_shift;
			break;
		case VOU_DIV_LAYER:
			reg = VOU_DIV_PARA;
			shift = bits->div_layer_shift;
			break;
		default:
			continue;
		}

		/* Each divider occupies 3 bits */
		zx_writel_mask(vou->vouctl + reg, 0x7 << shift,
			       cfg->val << shift);
	}

	/* Set update flag bit to get dividers effected */
	zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE,
		       DIV_PARA_UPDATE);
}

static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
{
	zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
+25 −0
Original line number Diff line number Diff line
@@ -36,6 +36,31 @@ void vou_inf_hdmi_audio_sel(struct drm_crtc *crtc,
void vou_inf_enable(enum vou_inf_id id, struct drm_crtc *crtc);
void vou_inf_disable(enum vou_inf_id id, struct drm_crtc *crtc);

enum vou_div_id {
	VOU_DIV_VGA,
	VOU_DIV_PIC,
	VOU_DIV_TVENC,
	VOU_DIV_HDMI_PNX,
	VOU_DIV_HDMI,
	VOU_DIV_INF,
	VOU_DIV_LAYER,
};

enum vou_div_val {
	VOU_DIV_1 = 0,
	VOU_DIV_2 = 1,
	VOU_DIV_4 = 3,
	VOU_DIV_8 = 7,
};

struct vou_div_config {
	enum vou_div_id id;
	enum vou_div_val val;
};

void zx_vou_config_dividers(struct drm_crtc *crtc,
			    struct vou_div_config *configs, int num);

int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe);
void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe);

+16 −0
Original line number Diff line number Diff line
@@ -176,11 +176,27 @@
#define VOU_INF_DATA_SEL		0x08
#define VOU_SOFT_RST			0x14
#define VOU_CLK_SEL			0x18
#define VGA_AUX_DIV_SHIFT		29
#define VGA_MAIN_DIV_SHIFT		26
#define PIC_MAIN_DIV_SHIFT		23
#define PIC_AUX_DIV_SHIFT		20
#define VOU_CLK_VL2_SEL			BIT(8)
#define VOU_CLK_VL1_SEL			BIT(7)
#define VOU_CLK_VL0_SEL			BIT(6)
#define VOU_CLK_GL1_SEL			BIT(5)
#define VOU_CLK_GL0_SEL			BIT(4)
#define VOU_DIV_PARA			0x1c
#define DIV_PARA_UPDATE			BIT(31)
#define TVENC_AUX_DIV_SHIFT		28
#define HDMI_AUX_PNX_DIV_SHIFT		25
#define HDMI_MAIN_PNX_DIV_SHIFT		22
#define HDMI_AUX_DIV_SHIFT		19
#define HDMI_MAIN_DIV_SHIFT		16
#define TVENC_MAIN_DIV_SHIFT		13
#define INF_AUX_DIV_SHIFT		9
#define INF_MAIN_DIV_SHIFT		6
#define LAYER_AUX_DIV_SHIFT		3
#define LAYER_MAIN_DIV_SHIFT		0
#define VOU_CLK_REQEN			0x20
#define VOU_CLK_EN			0x24
#define VOU_INF_HDMI_CTRL		0x30