linux/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2013 Red Hat
   3 * Author: Rob Clark <robdclark@gmail.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of the GNU General Public License version 2 as published by
   7 * the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program.  If not, see <http://www.gnu.org/licenses/>.
  16 */
  17
  18#ifndef __MDP4_KMS_H__
  19#define __MDP4_KMS_H__
  20
  21#include <drm/drm_panel.h>
  22
  23#include "msm_drv.h"
  24#include "msm_kms.h"
  25#include "disp/mdp_kms.h"
  26#include "mdp4.xml.h"
  27
  28struct device_node;
  29
  30struct mdp4_kms {
  31        struct mdp_kms base;
  32
  33        struct drm_device *dev;
  34
  35        int rev;
  36
  37        void __iomem *mmio;
  38
  39        struct regulator *vdd;
  40
  41        struct clk *clk;
  42        struct clk *pclk;
  43        struct clk *lut_clk;
  44        struct clk *axi_clk;
  45
  46        struct mdp_irq error_handler;
  47
  48        bool rpm_enabled;
  49
  50        /* empty/blank cursor bo to use when cursor is "disabled" */
  51        struct drm_gem_object *blank_cursor_bo;
  52        uint64_t blank_cursor_iova;
  53};
  54#define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base)
  55
  56/* platform config data (ie. from DT, or pdata) */
  57struct mdp4_platform_config {
  58        struct iommu_domain *iommu;
  59        uint32_t max_clk;
  60};
  61
  62static inline void mdp4_write(struct mdp4_kms *mdp4_kms, u32 reg, u32 data)
  63{
  64        msm_writel(data, mdp4_kms->mmio + reg);
  65}
  66
  67static inline u32 mdp4_read(struct mdp4_kms *mdp4_kms, u32 reg)
  68{
  69        return msm_readl(mdp4_kms->mmio + reg);
  70}
  71
  72static inline uint32_t pipe2flush(enum mdp4_pipe pipe)
  73{
  74        switch (pipe) {
  75        case VG1:      return MDP4_OVERLAY_FLUSH_VG1;
  76        case VG2:      return MDP4_OVERLAY_FLUSH_VG2;
  77        case RGB1:     return MDP4_OVERLAY_FLUSH_RGB1;
  78        case RGB2:     return MDP4_OVERLAY_FLUSH_RGB2;
  79        default:       return 0;
  80        }
  81}
  82
  83static inline uint32_t ovlp2flush(int ovlp)
  84{
  85        switch (ovlp) {
  86        case 0:        return MDP4_OVERLAY_FLUSH_OVLP0;
  87        case 1:        return MDP4_OVERLAY_FLUSH_OVLP1;
  88        default:       return 0;
  89        }
  90}
  91
  92static inline uint32_t dma2irq(enum mdp4_dma dma)
  93{
  94        switch (dma) {
  95        case DMA_P:    return MDP4_IRQ_DMA_P_DONE;
  96        case DMA_S:    return MDP4_IRQ_DMA_S_DONE;
  97        case DMA_E:    return MDP4_IRQ_DMA_E_DONE;
  98        default:       return 0;
  99        }
 100}
 101
 102static inline uint32_t dma2err(enum mdp4_dma dma)
 103{
 104        switch (dma) {
 105        case DMA_P:    return MDP4_IRQ_PRIMARY_INTF_UDERRUN;
 106        case DMA_S:    return 0;  // ???
 107        case DMA_E:    return MDP4_IRQ_EXTERNAL_INTF_UDERRUN;
 108        default:       return 0;
 109        }
 110}
 111
 112static inline uint32_t mixercfg(uint32_t mixer_cfg, int mixer,
 113                enum mdp4_pipe pipe, enum mdp_mixer_stage_id stage)
 114{
 115        switch (pipe) {
 116        case VG1:
 117                mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE0__MASK |
 118                                MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1);
 119                mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE0(stage) |
 120                        COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE0_MIXER1);
 121                break;
 122        case VG2:
 123                mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE1__MASK |
 124                                MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1);
 125                mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE1(stage) |
 126                        COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE1_MIXER1);
 127                break;
 128        case RGB1:
 129                mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE2__MASK |
 130                                MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1);
 131                mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE2(stage) |
 132                        COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE2_MIXER1);
 133                break;
 134        case RGB2:
 135                mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE3__MASK |
 136                                MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1);
 137                mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE3(stage) |
 138                        COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE3_MIXER1);
 139                break;
 140        case RGB3:
 141                mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE4__MASK |
 142                                MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1);
 143                mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE4(stage) |
 144                        COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE4_MIXER1);
 145                break;
 146        case VG3:
 147                mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE5__MASK |
 148                                MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1);
 149                mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE5(stage) |
 150                        COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE5_MIXER1);
 151                break;
 152        case VG4:
 153                mixer_cfg &= ~(MDP4_LAYERMIXER_IN_CFG_PIPE6__MASK |
 154                                MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1);
 155                mixer_cfg |= MDP4_LAYERMIXER_IN_CFG_PIPE6(stage) |
 156                        COND(mixer == 1, MDP4_LAYERMIXER_IN_CFG_PIPE6_MIXER1);
 157                break;
 158        default:
 159                WARN(1, "invalid pipe");
 160                break;
 161        }
 162
 163        return mixer_cfg;
 164}
 165
 166int mdp4_disable(struct mdp4_kms *mdp4_kms);
 167int mdp4_enable(struct mdp4_kms *mdp4_kms);
 168
 169void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
 170                uint32_t old_irqmask);
 171void mdp4_irq_preinstall(struct msm_kms *kms);
 172int mdp4_irq_postinstall(struct msm_kms *kms);
 173void mdp4_irq_uninstall(struct msm_kms *kms);
 174irqreturn_t mdp4_irq(struct msm_kms *kms);
 175int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
 176void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
 177
 178static inline uint32_t mdp4_pipe_caps(enum mdp4_pipe pipe)
 179{
 180        switch (pipe) {
 181        case VG1:
 182        case VG2:
 183        case VG3:
 184        case VG4:
 185                return MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
 186                                MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC;
 187        case RGB1:
 188        case RGB2:
 189        case RGB3:
 190                return MDP_PIPE_CAP_SCALE;
 191        default:
 192                return 0;
 193        }
 194}
 195
 196enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane);
 197struct drm_plane *mdp4_plane_init(struct drm_device *dev,
 198                enum mdp4_pipe pipe_id, bool private_plane);
 199
 200uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc);
 201void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config);
 202void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer);
 203void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc);
 204struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
 205                struct drm_plane *plane, int id, int ovlp_id,
 206                enum mdp4_dma dma_id);
 207
 208long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate);
 209struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev);
 210
 211long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate);
 212struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
 213                struct device_node *panel_node);
 214
 215struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev,
 216                struct device_node *panel_node, struct drm_encoder *encoder);
 217
 218#ifdef CONFIG_DRM_MSM_DSI
 219struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev);
 220#else
 221static inline struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev)
 222{
 223        return ERR_PTR(-ENODEV);
 224}
 225#endif
 226
 227#ifdef CONFIG_COMMON_CLK
 228struct clk *mpd4_lvds_pll_init(struct drm_device *dev);
 229#else
 230static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev)
 231{
 232        return ERR_PTR(-ENODEV);
 233}
 234#endif
 235
 236#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 237/* bus scaling data is associated with extra pointless platform devices,
 238 * "dtv", etc.. this is a bit of a hack, but we need a way for encoders
 239 * to find their pdata to make the bus-scaling stuff work.
 240 */
 241static inline void *mdp4_find_pdata(const char *devname)
 242{
 243        struct device *dev;
 244        dev = bus_find_device_by_name(&platform_bus_type, NULL, devname);
 245        return dev ? dev->platform_data : NULL;
 246}
 247#endif
 248
 249#endif /* __MDP4_KMS_H__ */
 250