Пример #1
0
static void set_display_intf(struct mdp5_kms *mdp5_kms,
		struct mdp5_interface *intf)
{
	unsigned long flags;
	u32 intf_sel;

	spin_lock_irqsave(&mdp5_kms->resource_lock, flags);
	intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL);

	switch (intf->num) {
	case 0:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF0__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF0(intf->type);
		break;
	case 1:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF1__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF1(intf->type);
		break;
	case 2:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF2__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF2(intf->type);
		break;
	case 3:
		intf_sel &= ~MDP5_DISP_INTF_SEL_INTF3__MASK;
		intf_sel |= MDP5_DISP_INTF_SEL_INTF3(intf->type);
		break;
	default:
		BUG();
		break;
	}

	mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, intf_sel);
	spin_unlock_irqrestore(&mdp5_kms->resource_lock, flags);
}
Пример #2
0
static inline
u32 ctl_read(struct mdp5_ctl *ctl, u32 reg)
{
	struct mdp5_kms *mdp5_kms = get_kms(ctl->ctlm);

	(void)ctl->reg_offset; /* TODO use this instead of mdp5_write */
	return mdp5_read(mdp5_kms, reg);
}
Пример #3
0
static void mdp5_irq_mdp(struct mdp_kms *mdp_kms)
{
	struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
	struct drm_device *dev = mdp5_kms->dev;
	struct msm_drm_private *priv = dev->dev_private;
	unsigned int id;
	uint32_t status, enable;

	enable = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_EN(0));
	status = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_STATUS(0)) & enable;
	mdp5_write(mdp5_kms, REG_MDP5_MDP_INTR_CLEAR(0), status);

	VERB("status=%08x", status);

	mdp_dispatch_irqs(mdp_kms, status);

	for (id = 0; id < priv->num_crtcs; id++)
		if (status & mdp5_crtc_vblank(priv->crtcs[id]))
			drm_handle_vblank(dev, id);
}
Пример #4
0
static void read_hw_revision(struct mdp5_kms *mdp5_kms,
		uint32_t *major, uint32_t *minor)
{
	uint32_t version;

	mdp5_enable(mdp5_kms);
	version = mdp5_read(mdp5_kms, REG_MDSS_HW_VERSION);
	mdp5_disable(mdp5_kms);

	*major = FIELD(version, MDSS_HW_VERSION_MAJOR);
	*minor = FIELD(version, MDSS_HW_VERSION_MINOR);

	DBG("MDP5 version v%d.%d", *major, *minor);
}
Пример #5
0
static void read_mdp_hw_revision(struct mdp5_kms *mdp5_kms,
				 u32 *major, u32 *minor)
{
	struct device *dev = &mdp5_kms->pdev->dev;
	u32 version;

	pm_runtime_get_sync(dev);
	version = mdp5_read(mdp5_kms, REG_MDP5_HW_VERSION);
	pm_runtime_put_sync(dev);

	*major = FIELD(version, MDP5_HW_VERSION_MAJOR);
	*minor = FIELD(version, MDP5_HW_VERSION_MINOR);

	dev_info(dev, "MDP5 version v%d.%d", *major, *minor);
}
Пример #6
0
irqreturn_t mdp5_irq(struct msm_kms *kms)
{
	struct mdp_kms *mdp_kms = to_mdp_kms(kms);
	struct mdp5_kms *mdp5_kms = to_mdp5_kms(mdp_kms);
	uint32_t intr;

	intr = mdp5_read(mdp5_kms, REG_MDSS_HW_INTR_STATUS);

	VERB("intr=%08x", intr);

	if (intr & MDSS_HW_INTR_STATUS_INTR_MDP) {
		mdp5_irq_mdp(mdp_kms);
		intr &= ~MDSS_HW_INTR_STATUS_INTR_MDP;
	}

	while (intr) {
		irq_hw_number_t hwirq = fls(intr) - 1;
		generic_handle_irq(irq_find_mapping(
				mdp5_kms->irqcontroller.domain, hwirq));
		intr &= ~(1 << hwirq);
	}

	return IRQ_HANDLED;
}
Пример #7
0
static int mdp5_hw_init(struct msm_kms *kms)
{
	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
	struct drm_device *dev = mdp5_kms->dev;
	uint32_t version, major, minor;
	int ret = 0;

	pm_runtime_get_sync(dev->dev);

	mdp5_enable(mdp5_kms);
	version = mdp5_read(mdp5_kms, REG_MDP5_MDP_VERSION);
	mdp5_disable(mdp5_kms);

	major = FIELD(version, MDP5_MDP_VERSION_MAJOR);
	minor = FIELD(version, MDP5_MDP_VERSION_MINOR);

	DBG("found MDP5 version v%d.%d", major, minor);

	if ((major != 1) || ((minor != 0) && (minor != 2))) {
		dev_err(dev->dev, "unexpected MDP version: v%d.%d\n",
				major, minor);
		ret = -ENXIO;
		goto out;
	}

	mdp5_kms->rev = minor;

	/* Magic unknown register writes:
	 *
	 *    W VBIF:0x004 00000001      (mdss_mdp.c:839)
	 *    W MDP5:0x2e0 0xe9          (mdss_mdp.c:839)
	 *    W MDP5:0x2e4 0x55          (mdss_mdp.c:839)
	 *    W MDP5:0x3ac 0xc0000ccc    (mdss_mdp.c:839)
	 *    W MDP5:0x3b4 0xc0000ccc    (mdss_mdp.c:839)
	 *    W MDP5:0x3bc 0xcccccc      (mdss_mdp.c:839)
	 *    W MDP5:0x4a8 0xcccc0c0     (mdss_mdp.c:839)
	 *    W MDP5:0x4b0 0xccccc0c0    (mdss_mdp.c:839)
	 *    W MDP5:0x4b8 0xccccc000    (mdss_mdp.c:839)
	 *
	 * Downstream fbdev driver gets these register offsets/values
	 * from DT.. not really sure what these registers are or if
	 * different values for different boards/SoC's, etc.  I guess
	 * they are the golden registers.
	 *
	 * Not setting these does not seem to cause any problem.  But
	 * we may be getting lucky with the bootloader initializing
	 * them for us.  OTOH, if we can always count on the bootloader
	 * setting the golden registers, then perhaps we don't need to
	 * care.
	 */

	mdp5_write(mdp5_kms, REG_MDP5_DISP_INTF_SEL, 0);
	mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(0), 0);
	mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(1), 0);
	mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(2), 0);
	mdp5_write(mdp5_kms, REG_MDP5_CTL_OP(3), 0);

out:
	pm_runtime_put_sync(dev->dev);

	return ret;
}