root/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fsl_dcu_drm_crtc_atomic_flush
  2. fsl_dcu_drm_crtc_atomic_disable
  3. fsl_dcu_drm_crtc_atomic_enable
  4. fsl_dcu_drm_crtc_mode_set_nofb
  5. fsl_dcu_drm_crtc_enable_vblank
  6. fsl_dcu_drm_crtc_disable_vblank
  7. fsl_dcu_drm_crtc_create

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright 2015 Freescale Semiconductor, Inc.
   4  *
   5  * Freescale DCU drm device driver
   6  */
   7 
   8 #include <linux/clk.h>
   9 #include <linux/regmap.h>
  10 
  11 #include <video/videomode.h>
  12 
  13 #include <drm/drm_atomic.h>
  14 #include <drm/drm_atomic_helper.h>
  15 #include <drm/drm_crtc.h>
  16 #include <drm/drm_probe_helper.h>
  17 #include <drm/drm_vblank.h>
  18 
  19 #include "fsl_dcu_drm_crtc.h"
  20 #include "fsl_dcu_drm_drv.h"
  21 #include "fsl_dcu_drm_plane.h"
  22 
  23 static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
  24                                           struct drm_crtc_state *old_crtc_state)
  25 {
  26         struct drm_device *dev = crtc->dev;
  27         struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
  28         struct drm_pending_vblank_event *event = crtc->state->event;
  29 
  30         regmap_write(fsl_dev->regmap,
  31                      DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
  32 
  33         if (event) {
  34                 crtc->state->event = NULL;
  35 
  36                 spin_lock_irq(&crtc->dev->event_lock);
  37                 if (drm_crtc_vblank_get(crtc) == 0)
  38                         drm_crtc_arm_vblank_event(crtc, event);
  39                 else
  40                         drm_crtc_send_vblank_event(crtc, event);
  41                 spin_unlock_irq(&crtc->dev->event_lock);
  42         }
  43 }
  44 
  45 static void fsl_dcu_drm_crtc_atomic_disable(struct drm_crtc *crtc,
  46                                         struct drm_crtc_state *old_crtc_state)
  47 {
  48         struct drm_device *dev = crtc->dev;
  49         struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
  50 
  51         /* always disable planes on the CRTC */
  52         drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, true);
  53 
  54         drm_crtc_vblank_off(crtc);
  55 
  56         regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
  57                            DCU_MODE_DCU_MODE_MASK,
  58                            DCU_MODE_DCU_MODE(DCU_MODE_OFF));
  59         regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
  60                      DCU_UPDATE_MODE_READREG);
  61         clk_disable_unprepare(fsl_dev->pix_clk);
  62 }
  63 
  64 static void fsl_dcu_drm_crtc_atomic_enable(struct drm_crtc *crtc,
  65                                            struct drm_crtc_state *old_state)
  66 {
  67         struct drm_device *dev = crtc->dev;
  68         struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
  69 
  70         clk_prepare_enable(fsl_dev->pix_clk);
  71         regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
  72                            DCU_MODE_DCU_MODE_MASK,
  73                            DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
  74         regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
  75                      DCU_UPDATE_MODE_READREG);
  76 
  77         drm_crtc_vblank_on(crtc);
  78 }
  79 
  80 static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
  81 {
  82         struct drm_device *dev = crtc->dev;
  83         struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
  84         struct drm_connector *con = &fsl_dev->connector.base;
  85         struct drm_display_mode *mode = &crtc->state->mode;
  86         unsigned int pol = 0;
  87         struct videomode vm;
  88 
  89         clk_set_rate(fsl_dev->pix_clk, mode->clock * 1000);
  90 
  91         drm_display_mode_to_videomode(mode, &vm);
  92 
  93         /* INV_PXCK as default (most display sample data on rising edge) */
  94         if (!(con->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE))
  95                 pol |= DCU_SYN_POL_INV_PXCK;
  96 
  97         if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
  98                 pol |= DCU_SYN_POL_INV_HS_LOW;
  99 
 100         if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
 101                 pol |= DCU_SYN_POL_INV_VS_LOW;
 102 
 103         regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
 104                      DCU_HSYN_PARA_BP(vm.hback_porch) |
 105                      DCU_HSYN_PARA_PW(vm.hsync_len) |
 106                      DCU_HSYN_PARA_FP(vm.hfront_porch));
 107         regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
 108                      DCU_VSYN_PARA_BP(vm.vback_porch) |
 109                      DCU_VSYN_PARA_PW(vm.vsync_len) |
 110                      DCU_VSYN_PARA_FP(vm.vfront_porch));
 111         regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
 112                      DCU_DISP_SIZE_DELTA_Y(vm.vactive) |
 113                      DCU_DISP_SIZE_DELTA_X(vm.hactive));
 114         regmap_write(fsl_dev->regmap, DCU_SYN_POL, pol);
 115         regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
 116                      DCU_BGND_G(0) | DCU_BGND_B(0));
 117         regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
 118                      DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
 119         regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
 120                      DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
 121                      DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
 122                      DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
 123         return;
 124 }
 125 
 126 static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
 127         .atomic_disable = fsl_dcu_drm_crtc_atomic_disable,
 128         .atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
 129         .atomic_enable = fsl_dcu_drm_crtc_atomic_enable,
 130         .mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
 131 };
 132 
 133 static int fsl_dcu_drm_crtc_enable_vblank(struct drm_crtc *crtc)
 134 {
 135         struct drm_device *dev = crtc->dev;
 136         struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
 137         unsigned int value;
 138 
 139         regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
 140         value &= ~DCU_INT_MASK_VBLANK;
 141         regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
 142 
 143         return 0;
 144 }
 145 
 146 static void fsl_dcu_drm_crtc_disable_vblank(struct drm_crtc *crtc)
 147 {
 148         struct drm_device *dev = crtc->dev;
 149         struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
 150         unsigned int value;
 151 
 152         regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
 153         value |= DCU_INT_MASK_VBLANK;
 154         regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
 155 }
 156 
 157 static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
 158         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 159         .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 160         .destroy = drm_crtc_cleanup,
 161         .page_flip = drm_atomic_helper_page_flip,
 162         .reset = drm_atomic_helper_crtc_reset,
 163         .set_config = drm_atomic_helper_set_config,
 164         .enable_vblank = fsl_dcu_drm_crtc_enable_vblank,
 165         .disable_vblank = fsl_dcu_drm_crtc_disable_vblank,
 166 };
 167 
 168 int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
 169 {
 170         struct drm_plane *primary;
 171         struct drm_crtc *crtc = &fsl_dev->crtc;
 172         int ret;
 173 
 174         fsl_dcu_drm_init_planes(fsl_dev->drm);
 175 
 176         primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm);
 177         if (!primary)
 178                 return -ENOMEM;
 179 
 180         ret = drm_crtc_init_with_planes(fsl_dev->drm, crtc, primary, NULL,
 181                                         &fsl_dcu_drm_crtc_funcs, NULL);
 182         if (ret) {
 183                 primary->funcs->destroy(primary);
 184                 return ret;
 185         }
 186 
 187         drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
 188 
 189         return 0;
 190 }

/* [<][>][^][v][top][bottom][index][help] */