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

Commit 44ab4042 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu into drm-next

As previously discussed, this is my first pull request for the DCU DRM
driver along with the change in MAINTAINERS.
https://lkml.org/lkml/2016/1/7/26

The pull contains some code cleanup changes (e.g. removing all error
handling for the regmap calls) and several fixes.

* 'for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu:
  drm/fsl-dcu: fix register initialization
  drm/fsl-dcu: use mode flags for hsync/vsync polarity
  drm/fsl-dcu: fix alpha blending
  drm/fsl-dcu: mask all interrupts on initialization
  drm/fsl-dcu: handle initialization errors properly
  drm/fsl-dcu: avoid memory leak on errors
  drm/fsl-dcu: remove regmap return value checks
  drm/fsl-dcu: specify volatile registers
  drm: fsl-dcu: Fix no fb check bug
  MAINTAINERS: update for Freescale DCU DRM driver
parents 0041ee4d f76b9873
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3764,7 +3764,7 @@ F: include/drm/exynos*
F:	include/uapi/drm/exynos*

DRM DRIVERS FOR FREESCALE DCU
M:	Jianwei Wang <jianwei.wang.chn@gmail.com>
M:	Stefan Agner <stefan@agner.ch>
M:	Alison Wang <alison.wang@freescale.com>
L:	dri-devel@lists.freedesktop.org
S:	Supported
+54 −86
Original line number Diff line number Diff line
@@ -42,34 +42,24 @@ static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
{
	struct drm_device *dev = crtc->dev;
	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
	int ret;

	ret = regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
			   DCU_MODE_DCU_MODE_MASK,
			   DCU_MODE_DCU_MODE(DCU_MODE_OFF));
	if (ret)
		dev_err(fsl_dev->dev, "Disable CRTC failed\n");
	ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
		     DCU_UPDATE_MODE_READREG);
	if (ret)
		dev_err(fsl_dev->dev, "Enable CRTC failed\n");
}

static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)
{
	struct drm_device *dev = crtc->dev;
	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
	int ret;

	ret = regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
			   DCU_MODE_DCU_MODE_MASK,
			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
	if (ret)
		dev_err(fsl_dev->dev, "Enable CRTC failed\n");
	ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
		     DCU_UPDATE_MODE_READREG);
	if (ret)
		dev_err(fsl_dev->dev, "Enable CRTC failed\n");
}

static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -84,9 +74,8 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
	struct drm_device *dev = crtc->dev;
	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
	struct drm_display_mode *mode = &crtc->state->mode;
	unsigned int hbp, hfp, hsw, vbp, vfp, vsw, div, index;
	unsigned int hbp, hfp, hsw, vbp, vfp, vsw, div, index, pol = 0;
	unsigned long dcuclk;
	int ret;

	index = drm_crtc_index(crtc);
	dcuclk = clk_get_rate(fsl_dev->clk);
@@ -100,51 +89,36 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
	vfp = mode->vsync_start - mode->vdisplay;
	vsw = mode->vsync_end - mode->vsync_start;

	ret = regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
		pol |= DCU_SYN_POL_INV_HS_LOW;

	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
		pol |= DCU_SYN_POL_INV_VS_LOW;

	regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
		     DCU_HSYN_PARA_BP(hbp) |
		     DCU_HSYN_PARA_PW(hsw) |
		     DCU_HSYN_PARA_FP(hfp));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
	regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
		     DCU_VSYN_PARA_BP(vbp) |
		     DCU_VSYN_PARA_PW(vsw) |
		     DCU_VSYN_PARA_FP(vfp));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_SYN_POL,
			   DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
	regmap_write(fsl_dev->regmap, DCU_SYN_POL, pol);
	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
		     DCU_BGND_G(0) | DCU_BGND_B(0));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
	regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
		     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
	regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
	if (ret)
		goto set_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
		     DCU_UPDATE_MODE_READREG);
	if (ret)
		goto set_failed;
	return;
set_failed:
	dev_err(dev->dev, "set DCU register failed\n");
}

static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
@@ -174,10 +148,15 @@ int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
	int ret;

	primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm);
	if (!primary)
		return -ENOMEM;

	ret = drm_crtc_init_with_planes(fsl_dev->drm, crtc, primary, NULL,
					&fsl_dcu_drm_crtc_funcs, NULL);
	if (ret < 0)
	if (ret) {
		primary->funcs->destroy(primary);
		return ret;
	}

	drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);

@@ -185,26 +164,15 @@ int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
		reg_num = LS1021A_LAYER_REG_NUM;
	else
		reg_num = VF610_LAYER_REG_NUM;
	for (i = 0; i <= fsl_dev->soc->total_layer; i++) {
		for (j = 0; j < reg_num; j++) {
			ret = regmap_write(fsl_dev->regmap,
					   DCU_CTRLDESCLN(i, j), 0);
			if (ret)
				goto init_failed;
	for (i = 0; i < fsl_dev->soc->total_layer; i++) {
		for (j = 1; j <= reg_num; j++)
			regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
	}
	}
	ret = regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
			   DCU_MODE_DCU_MODE_MASK,
			   DCU_MODE_DCU_MODE(DCU_MODE_OFF));
	if (ret)
		goto init_failed;
	ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
		     DCU_UPDATE_MODE_READREG);
	if (ret)
		goto init_failed;

	return 0;
init_failed:
	dev_err(fsl_dev->dev, "init DCU register failed\n");
	return ret;
}
+27 −38
Original line number Diff line number Diff line
@@ -28,37 +28,36 @@
#include "fsl_dcu_drm_crtc.h"
#include "fsl_dcu_drm_drv.h"

static bool fsl_dcu_drm_is_volatile_reg(struct device *dev, unsigned int reg)
{
	if (reg == DCU_INT_STATUS || reg == DCU_UPDATE_MODE)
		return true;

	return false;
}

static const struct regmap_config fsl_dcu_regmap_config = {
	.reg_bits = 32,
	.reg_stride = 4,
	.val_bits = 32,
	.cache_type = REGCACHE_RBTREE,

	.volatile_reg = fsl_dcu_drm_is_volatile_reg,
};

static int fsl_dcu_drm_irq_init(struct drm_device *dev)
{
	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
	unsigned int value;
	int ret;

	ret = drm_irq_install(dev, fsl_dev->irq);
	if (ret < 0)
		dev_err(dev->dev, "failed to install IRQ handler\n");

	ret = regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0);
	if (ret)
		dev_err(dev->dev, "set DCU_INT_STATUS failed\n");
	ret = regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
	if (ret)
		dev_err(dev->dev, "read DCU_INT_MASK failed\n");
	value &= DCU_INT_MASK_VBLANK;
	ret = regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
	if (ret)
		dev_err(dev->dev, "set DCU_INT_MASK failed\n");
	ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
	regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0);
	regmap_write(fsl_dev->regmap, DCU_INT_MASK, ~0);
	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
		     DCU_UPDATE_MODE_READREG);
	if (ret)
		dev_err(dev->dev, "set DCU_UPDATE_MODE failed\n");

	return ret;
}
@@ -120,18 +119,17 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
	int ret;

	ret = regmap_read(fsl_dev->regmap, DCU_INT_STATUS, &int_status);
	if (ret)
		dev_err(dev->dev, "set DCU_INT_STATUS failed\n");
	if (ret) {
		dev_err(dev->dev, "read DCU_INT_STATUS failed\n");
		return IRQ_NONE;
	}

	if (int_status & DCU_INT_STATUS_VBLANK)
		drm_handle_vblank(dev, 0);

	ret = regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0xffffffff);
	if (ret)
		dev_err(dev->dev, "set DCU_INT_STATUS failed\n");
	ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
	regmap_write(fsl_dev->regmap, DCU_INT_STATUS, int_status);
	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
		     DCU_UPDATE_MODE_READREG);
	if (ret)
		dev_err(dev->dev, "set DCU_UPDATE_MODE failed\n");

	return IRQ_HANDLED;
}
@@ -140,15 +138,11 @@ static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
{
	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
	unsigned int value;
	int ret;

	ret = regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
	if (ret)
		dev_err(dev->dev, "read DCU_INT_MASK failed\n");
	regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
	value &= ~DCU_INT_MASK_VBLANK;
	ret = regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
	if (ret)
		dev_err(dev->dev, "set DCU_INT_MASK failed\n");
	regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);

	return 0;
}

@@ -157,15 +151,10 @@ static void fsl_dcu_drm_disable_vblank(struct drm_device *dev,
{
	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
	unsigned int value;
	int ret;

	ret = regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
	if (ret)
		dev_err(dev->dev, "read DCU_INT_MASK failed\n");
	regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
	value |= DCU_INT_MASK_VBLANK;
	ret = regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
	if (ret)
		dev_err(dev->dev, "set DCU_INT_MASK failed\n");
	regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
}

static const struct file_operations fsl_dcu_drm_fops = {
+3 −1
Original line number Diff line number Diff line
@@ -133,7 +133,9 @@
#define DCU_LAYER_RLE_EN		BIT(15)
#define DCU_LAYER_LUOFFS(x)		((x) << 4)
#define DCU_LAYER_BB_ON			BIT(2)
#define DCU_LAYER_AB(x)			(x)
#define DCU_LAYER_AB_NONE		0
#define DCU_LAYER_AB_CHROMA_KEYING	1
#define DCU_LAYER_AB_WHOLE_FRAME	2

#define DCU_LAYER_CKMAX_R(x)		((x) << 16)
#define DCU_LAYER_CKMAX_G(x)		((x) << 8)
+20 −4
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {

int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
{
	int ret;

	drm_mode_config_init(fsl_dev->drm);

	fsl_dev->drm->mode_config.min_width = 0;
@@ -33,11 +35,25 @@ int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
	fsl_dev->drm->mode_config.max_height = 2047;
	fsl_dev->drm->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;

	drm_kms_helper_poll_init(fsl_dev->drm);
	fsl_dcu_drm_crtc_create(fsl_dev);
	fsl_dcu_drm_encoder_create(fsl_dev, &fsl_dev->crtc);
	fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
	ret = fsl_dcu_drm_crtc_create(fsl_dev);
	if (ret)
		return ret;

	ret = fsl_dcu_drm_encoder_create(fsl_dev, &fsl_dev->crtc);
	if (ret)
		goto fail_encoder;

	ret = fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
	if (ret)
		goto fail_connector;

	drm_mode_config_reset(fsl_dev->drm);
	drm_kms_helper_poll_init(fsl_dev->drm);

	return 0;
fail_encoder:
	fsl_dev->crtc.funcs->destroy(&fsl_dev->crtc);
fail_connector:
	fsl_dev->encoder.funcs->destroy(&fsl_dev->encoder);
	return ret;
}
Loading