linux/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
<<
>>
Prefs
   1/*
   2 * Copyright 2015 Freescale Semiconductor, Inc.
   3 *
   4 * Freescale DCU drm device driver
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 */
  11
  12#include <linux/clk.h>
  13#include <linux/regmap.h>
  14
  15#include <drm/drmP.h>
  16#include <drm/drm_atomic.h>
  17#include <drm/drm_atomic_helper.h>
  18#include <drm/drm_crtc.h>
  19#include <drm/drm_crtc_helper.h>
  20
  21#include "fsl_dcu_drm_crtc.h"
  22#include "fsl_dcu_drm_drv.h"
  23#include "fsl_dcu_drm_plane.h"
  24
  25static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc,
  26                                          struct drm_crtc_state *old_crtc_state)
  27{
  28}
  29
  30static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
  31                                         struct drm_crtc_state *state)
  32{
  33        return 0;
  34}
  35
  36static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
  37                                          struct drm_crtc_state *old_crtc_state)
  38{
  39}
  40
  41static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
  42{
  43        struct drm_device *dev = crtc->dev;
  44        struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
  45
  46        regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
  47                           DCU_MODE_DCU_MODE_MASK,
  48                           DCU_MODE_DCU_MODE(DCU_MODE_OFF));
  49        regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
  50                     DCU_UPDATE_MODE_READREG);
  51}
  52
  53static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)
  54{
  55        struct drm_device *dev = crtc->dev;
  56        struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
  57
  58        regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
  59                           DCU_MODE_DCU_MODE_MASK,
  60                           DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
  61        regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
  62                     DCU_UPDATE_MODE_READREG);
  63}
  64
  65static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
  66{
  67        struct drm_device *dev = crtc->dev;
  68        struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
  69        struct drm_display_mode *mode = &crtc->state->mode;
  70        unsigned int hbp, hfp, hsw, vbp, vfp, vsw, div, index, pol = 0;
  71        unsigned long dcuclk;
  72
  73        index = drm_crtc_index(crtc);
  74        dcuclk = clk_get_rate(fsl_dev->clk);
  75        div = dcuclk / mode->clock / 1000;
  76
  77        /* Configure timings: */
  78        hbp = mode->htotal - mode->hsync_end;
  79        hfp = mode->hsync_start - mode->hdisplay;
  80        hsw = mode->hsync_end - mode->hsync_start;
  81        vbp = mode->vtotal - mode->vsync_end;
  82        vfp = mode->vsync_start - mode->vdisplay;
  83        vsw = mode->vsync_end - mode->vsync_start;
  84
  85        if (mode->flags & DRM_MODE_FLAG_NHSYNC)
  86                pol |= DCU_SYN_POL_INV_HS_LOW;
  87
  88        if (mode->flags & DRM_MODE_FLAG_NVSYNC)
  89                pol |= DCU_SYN_POL_INV_VS_LOW;
  90
  91        regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
  92                     DCU_HSYN_PARA_BP(hbp) |
  93                     DCU_HSYN_PARA_PW(hsw) |
  94                     DCU_HSYN_PARA_FP(hfp));
  95        regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
  96                     DCU_VSYN_PARA_BP(vbp) |
  97                     DCU_VSYN_PARA_PW(vsw) |
  98                     DCU_VSYN_PARA_FP(vfp));
  99        regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
 100                     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
 101                     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
 102        regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
 103        regmap_write(fsl_dev->regmap, DCU_SYN_POL, pol);
 104        regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
 105                     DCU_BGND_G(0) | DCU_BGND_B(0));
 106        regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
 107                     DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
 108        regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
 109                     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
 110                     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
 111                     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
 112        regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
 113                     DCU_UPDATE_MODE_READREG);
 114        return;
 115}
 116
 117static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
 118        .atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
 119        .atomic_check = fsl_dcu_drm_crtc_atomic_check,
 120        .atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
 121        .disable = fsl_dcu_drm_disable_crtc,
 122        .enable = fsl_dcu_drm_crtc_enable,
 123        .mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
 124};
 125
 126static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
 127        .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 128        .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 129        .destroy = drm_crtc_cleanup,
 130        .page_flip = drm_atomic_helper_page_flip,
 131        .reset = drm_atomic_helper_crtc_reset,
 132        .set_config = drm_atomic_helper_set_config,
 133};
 134
 135int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
 136{
 137        struct drm_plane *primary;
 138        struct drm_crtc *crtc = &fsl_dev->crtc;
 139        unsigned int i, j, reg_num;
 140        int ret;
 141
 142        primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm);
 143        if (!primary)
 144                return -ENOMEM;
 145
 146        ret = drm_crtc_init_with_planes(fsl_dev->drm, crtc, primary, NULL,
 147                                        &fsl_dcu_drm_crtc_funcs, NULL);
 148        if (ret) {
 149                primary->funcs->destroy(primary);
 150                return ret;
 151        }
 152
 153        drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
 154
 155        if (!strcmp(fsl_dev->soc->name, "ls1021a"))
 156                reg_num = LS1021A_LAYER_REG_NUM;
 157        else
 158                reg_num = VF610_LAYER_REG_NUM;
 159        for (i = 0; i < fsl_dev->soc->total_layer; i++) {
 160                for (j = 1; j <= reg_num; j++)
 161                        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
 162        }
 163        regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
 164                           DCU_MODE_DCU_MODE_MASK,
 165                           DCU_MODE_DCU_MODE(DCU_MODE_OFF));
 166        regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
 167                     DCU_UPDATE_MODE_READREG);
 168
 169        return 0;
 170}
 171