Skip to content

Commit

Permalink
Merge branch 'for-next' of http://git.agner.ch/git/linux-drm-fsl-dcu
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Dave Airlie committed Feb 26, 2016
2 parents 0041ee4 + f76b987 commit 44ab404
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 208 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
140 changes: 54 additions & 86 deletions drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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,
DCU_UPDATE_MODE_READREG);
if (ret)
dev_err(fsl_dev->dev, "Enable CRTC failed\n");
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_DCU_MODE_MASK,
DCU_MODE_DCU_MODE(DCU_MODE_OFF));
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG);
}

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,
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,
DCU_UPDATE_MODE_READREG);
if (ret)
dev_err(fsl_dev->dev, "Enable CRTC failed\n");
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_DCU_MODE_MASK,
DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG);
}

static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
Expand All @@ -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);
Expand All @@ -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,
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,
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,
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) |
DCU_BGND_G(0) | DCU_BGND_B(0));
if (ret)
goto set_failed;
ret = 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,
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,
DCU_UPDATE_MODE_READREG);
if (ret)
goto set_failed;
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));
regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
DCU_VSYN_PARA_BP(vbp) |
DCU_VSYN_PARA_PW(vsw) |
DCU_VSYN_PARA_FP(vfp));
regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
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));
regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
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));
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG);
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 = {
Expand Down Expand Up @@ -174,37 +148,31 @@ 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);

if (!strcmp(fsl_dev->soc->name, "ls1021a"))
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,
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,
DCU_UPDATE_MODE_READREG);
if (ret)
goto init_failed;
regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
DCU_MODE_DCU_MODE_MASK,
DCU_MODE_DCU_MODE(DCU_MODE_OFF));
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG);

return 0;
init_failed:
dev_err(fsl_dev->dev, "init DCU register failed\n");
return ret;
}
65 changes: 27 additions & 38 deletions drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
DCU_UPDATE_MODE_READREG);
if (ret)
dev_err(dev->dev, "set DCU_UPDATE_MODE failed\n");
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);

return ret;
}
Expand Down Expand Up @@ -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,
DCU_UPDATE_MODE_READREG);
if (ret)
dev_err(dev->dev, "set DCU_UPDATE_MODE failed\n");
regmap_write(fsl_dev->regmap, DCU_INT_STATUS, int_status);
regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
DCU_UPDATE_MODE_READREG);

return IRQ_HANDLED;
}
Expand All @@ -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;
}

Expand All @@ -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 = {
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
24 changes: 20 additions & 4 deletions drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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

0 comments on commit 44ab404

Please sign in to comment.