linux/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
   3 * Copyright (C) 2013 Red Hat
   4 * Author: Rob Clark <robdclark@gmail.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License version 2 as published by
   8 * the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along with
  16 * this program.  If not, see <http://www.gnu.org/licenses/>.
  17 */
  18
  19#include "mdp5_kms.h"
  20
  21#include "drm_crtc.h"
  22#include "drm_crtc_helper.h"
  23
  24struct mdp5_encoder {
  25        struct drm_encoder base;
  26        struct mdp5_interface intf;
  27        spinlock_t intf_lock;   /* protect REG_MDP5_INTF_* registers */
  28        bool enabled;
  29        uint32_t bsc;
  30
  31        struct mdp5_ctl *ctl;
  32};
  33#define to_mdp5_encoder(x) container_of(x, struct mdp5_encoder, base)
  34
  35static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
  36{
  37        struct msm_drm_private *priv = encoder->dev->dev_private;
  38        return to_mdp5_kms(to_mdp_kms(priv->kms));
  39}
  40
  41#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
  42#include <mach/board.h>
  43#include <mach/msm_bus.h>
  44#include <mach/msm_bus_board.h>
  45#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val)            \
  46        {                                               \
  47                .src = MSM_BUS_MASTER_MDP_PORT0,        \
  48                .dst = MSM_BUS_SLAVE_EBI_CH0,           \
  49                .ab = (ab_val),                         \
  50                .ib = (ib_val),                         \
  51        }
  52
  53static struct msm_bus_vectors mdp_bus_vectors[] = {
  54        MDP_BUS_VECTOR_ENTRY(0, 0),
  55        MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000),
  56};
  57static struct msm_bus_paths mdp_bus_usecases[] = { {
  58                .num_paths = 1,
  59                .vectors = &mdp_bus_vectors[0],
  60}, {
  61                .num_paths = 1,
  62                .vectors = &mdp_bus_vectors[1],
  63} };
  64static struct msm_bus_scale_pdata mdp_bus_scale_table = {
  65        .usecase = mdp_bus_usecases,
  66        .num_usecases = ARRAY_SIZE(mdp_bus_usecases),
  67        .name = "mdss_mdp",
  68};
  69
  70static void bs_init(struct mdp5_encoder *mdp5_encoder)
  71{
  72        mdp5_encoder->bsc = msm_bus_scale_register_client(
  73                        &mdp_bus_scale_table);
  74        DBG("bus scale client: %08x", mdp5_encoder->bsc);
  75}
  76
  77static void bs_fini(struct mdp5_encoder *mdp5_encoder)
  78{
  79        if (mdp5_encoder->bsc) {
  80                msm_bus_scale_unregister_client(mdp5_encoder->bsc);
  81                mdp5_encoder->bsc = 0;
  82        }
  83}
  84
  85static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx)
  86{
  87        if (mdp5_encoder->bsc) {
  88                DBG("set bus scaling: %d", idx);
  89                /* HACK: scaling down, and then immediately back up
  90                 * seems to leave things broken (underflow).. so
  91                 * never disable:
  92                 */
  93                idx = 1;
  94                msm_bus_scale_client_update_request(mdp5_encoder->bsc, idx);
  95        }
  96}
  97#else
  98static void bs_init(struct mdp5_encoder *mdp5_encoder) {}
  99static void bs_fini(struct mdp5_encoder *mdp5_encoder) {}
 100static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx) {}
 101#endif
 102
 103static void mdp5_encoder_destroy(struct drm_encoder *encoder)
 104{
 105        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
 106        bs_fini(mdp5_encoder);
 107        drm_encoder_cleanup(encoder);
 108        kfree(mdp5_encoder);
 109}
 110
 111static const struct drm_encoder_funcs mdp5_encoder_funcs = {
 112        .destroy = mdp5_encoder_destroy,
 113};
 114
 115static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
 116                struct drm_display_mode *mode,
 117                struct drm_display_mode *adjusted_mode)
 118{
 119        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
 120        struct mdp5_kms *mdp5_kms = get_kms(encoder);
 121        struct drm_device *dev = encoder->dev;
 122        struct drm_connector *connector;
 123        int intf = mdp5_encoder->intf.num;
 124        uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
 125        uint32_t display_v_start, display_v_end;
 126        uint32_t hsync_start_x, hsync_end_x;
 127        uint32_t format = 0x2100;
 128        unsigned long flags;
 129
 130        mode = adjusted_mode;
 131
 132        DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
 133                        mode->base.id, mode->name,
 134                        mode->vrefresh, mode->clock,
 135                        mode->hdisplay, mode->hsync_start,
 136                        mode->hsync_end, mode->htotal,
 137                        mode->vdisplay, mode->vsync_start,
 138                        mode->vsync_end, mode->vtotal,
 139                        mode->type, mode->flags);
 140
 141        ctrl_pol = 0;
 142
 143        /* DSI controller cannot handle active-low sync signals. */
 144        if (mdp5_encoder->intf.type != INTF_DSI) {
 145                if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 146                        ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
 147                if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 148                        ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
 149        }
 150        /* probably need to get DATA_EN polarity from panel.. */
 151
 152        dtv_hsync_skew = 0;  /* get this from panel? */
 153
 154        /* Get color format from panel, default is 8bpc */
 155        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 156                if (connector->encoder == encoder) {
 157                        switch (connector->display_info.bpc) {
 158                        case 4:
 159                                format |= 0;
 160                                break;
 161                        case 5:
 162                                format |= 0x15;
 163                                break;
 164                        case 6:
 165                                format |= 0x2A;
 166                                break;
 167                        case 8:
 168                        default:
 169                                format |= 0x3F;
 170                                break;
 171                        }
 172                        break;
 173                }
 174        }
 175
 176        hsync_start_x = (mode->htotal - mode->hsync_start);
 177        hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
 178
 179        vsync_period = mode->vtotal * mode->htotal;
 180        vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
 181        display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew;
 182        display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1;
 183
 184        /*
 185         * For edp only:
 186         * DISPLAY_V_START = (VBP * HCYCLE) + HBP
 187         * DISPLAY_V_END = (VBP + VACTIVE) * HCYCLE - 1 - HFP
 188         */
 189        if (mdp5_encoder->intf.type == INTF_eDP) {
 190                display_v_start += mode->htotal - mode->hsync_start;
 191                display_v_end -= mode->hsync_start - mode->hdisplay;
 192        }
 193
 194        spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
 195
 196        mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_CTL(intf),
 197                        MDP5_INTF_HSYNC_CTL_PULSEW(mode->hsync_end - mode->hsync_start) |
 198                        MDP5_INTF_HSYNC_CTL_PERIOD(mode->htotal));
 199        mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_PERIOD_F0(intf), vsync_period);
 200        mdp5_write(mdp5_kms, REG_MDP5_INTF_VSYNC_LEN_F0(intf), vsync_len);
 201        mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_HCTL(intf),
 202                        MDP5_INTF_DISPLAY_HCTL_START(hsync_start_x) |
 203                        MDP5_INTF_DISPLAY_HCTL_END(hsync_end_x));
 204        mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VSTART_F0(intf), display_v_start);
 205        mdp5_write(mdp5_kms, REG_MDP5_INTF_DISPLAY_VEND_F0(intf), display_v_end);
 206        mdp5_write(mdp5_kms, REG_MDP5_INTF_BORDER_COLOR(intf), 0);
 207        mdp5_write(mdp5_kms, REG_MDP5_INTF_UNDERFLOW_COLOR(intf), 0xff);
 208        mdp5_write(mdp5_kms, REG_MDP5_INTF_HSYNC_SKEW(intf), dtv_hsync_skew);
 209        mdp5_write(mdp5_kms, REG_MDP5_INTF_POLARITY_CTL(intf), ctrl_pol);
 210        mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_HCTL(intf),
 211                        MDP5_INTF_ACTIVE_HCTL_START(0) |
 212                        MDP5_INTF_ACTIVE_HCTL_END(0));
 213        mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VSTART_F0(intf), 0);
 214        mdp5_write(mdp5_kms, REG_MDP5_INTF_ACTIVE_VEND_F0(intf), 0);
 215        mdp5_write(mdp5_kms, REG_MDP5_INTF_PANEL_FORMAT(intf), format);
 216        mdp5_write(mdp5_kms, REG_MDP5_INTF_FRAME_LINE_COUNT_EN(intf), 0x3);  /* frame+line? */
 217
 218        spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
 219
 220        mdp5_crtc_set_pipeline(encoder->crtc, &mdp5_encoder->intf,
 221                                mdp5_encoder->ctl);
 222}
 223
 224static void mdp5_encoder_disable(struct drm_encoder *encoder)
 225{
 226        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
 227        struct mdp5_kms *mdp5_kms = get_kms(encoder);
 228        struct mdp5_ctl *ctl = mdp5_encoder->ctl;
 229        int lm = mdp5_crtc_get_lm(encoder->crtc);
 230        struct mdp5_interface *intf = &mdp5_encoder->intf;
 231        int intfn = mdp5_encoder->intf.num;
 232        unsigned long flags;
 233
 234        if (WARN_ON(!mdp5_encoder->enabled))
 235                return;
 236
 237        mdp5_ctl_set_encoder_state(ctl, false);
 238
 239        spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
 240        mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 0);
 241        spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
 242        mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
 243
 244        /*
 245         * Wait for a vsync so we know the ENABLE=0 latched before
 246         * the (connector) source of the vsync's gets disabled,
 247         * otherwise we end up in a funny state if we re-enable
 248         * before the disable latches, which results that some of
 249         * the settings changes for the new modeset (like new
 250         * scanout buffer) don't latch properly..
 251         */
 252        mdp_irq_wait(&mdp5_kms->base, intf2vblank(lm, intf));
 253
 254        bs_set(mdp5_encoder, 0);
 255
 256        mdp5_encoder->enabled = false;
 257}
 258
 259static void mdp5_encoder_enable(struct drm_encoder *encoder)
 260{
 261        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
 262        struct mdp5_kms *mdp5_kms = get_kms(encoder);
 263        struct mdp5_ctl *ctl = mdp5_encoder->ctl;
 264        struct mdp5_interface *intf = &mdp5_encoder->intf;
 265        int intfn = mdp5_encoder->intf.num;
 266        unsigned long flags;
 267
 268        if (WARN_ON(mdp5_encoder->enabled))
 269                return;
 270
 271        bs_set(mdp5_encoder, 1);
 272        spin_lock_irqsave(&mdp5_encoder->intf_lock, flags);
 273        mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1);
 274        spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags);
 275        mdp5_ctl_commit(ctl, mdp_ctl_flush_mask_encoder(intf));
 276
 277        mdp5_ctl_set_encoder_state(ctl, true);
 278
 279        mdp5_encoder->enabled = true;
 280}
 281
 282static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = {
 283        .mode_set = mdp5_encoder_mode_set,
 284        .disable = mdp5_encoder_disable,
 285        .enable = mdp5_encoder_enable,
 286};
 287
 288int mdp5_encoder_get_linecount(struct drm_encoder *encoder)
 289{
 290        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
 291        struct mdp5_kms *mdp5_kms = get_kms(encoder);
 292        int intf = mdp5_encoder->intf.num;
 293
 294        return mdp5_read(mdp5_kms, REG_MDP5_INTF_LINE_COUNT(intf));
 295}
 296
 297u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder)
 298{
 299        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
 300        struct mdp5_kms *mdp5_kms = get_kms(encoder);
 301        int intf = mdp5_encoder->intf.num;
 302
 303        return mdp5_read(mdp5_kms, REG_MDP5_INTF_FRAME_COUNT(intf));
 304}
 305
 306int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
 307                                        struct drm_encoder *slave_encoder)
 308{
 309        struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
 310        struct mdp5_encoder *mdp5_slave_enc = to_mdp5_encoder(slave_encoder);
 311        struct mdp5_kms *mdp5_kms;
 312        int intf_num;
 313        u32 data = 0;
 314
 315        if (!encoder || !slave_encoder)
 316                return -EINVAL;
 317
 318        mdp5_kms = get_kms(encoder);
 319        intf_num = mdp5_encoder->intf.num;
 320
 321        /* Switch slave encoder's TimingGen Sync mode,
 322         * to use the master's enable signal for the slave encoder.
 323         */
 324        if (intf_num == 1)
 325                data |= MDP5_MDP_SPLIT_DPL_LOWER_INTF2_TG_SYNC;
 326        else if (intf_num == 2)
 327                data |= MDP5_MDP_SPLIT_DPL_LOWER_INTF1_TG_SYNC;
 328        else
 329                return -EINVAL;
 330
 331        /* Make sure clocks are on when connectors calling this function. */
 332        mdp5_enable(mdp5_kms);
 333        /* Dumb Panel, Sync mode */
 334        mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_UPPER(0), 0);
 335        mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_LOWER(0), data);
 336        mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_EN(0), 1);
 337
 338        mdp5_ctl_pair(mdp5_encoder->ctl, mdp5_slave_enc->ctl, true);
 339
 340        mdp5_disable(mdp5_kms);
 341
 342        return 0;
 343}
 344
 345/* initialize encoder */
 346struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
 347                        struct mdp5_interface *intf, struct mdp5_ctl *ctl)
 348{
 349        struct drm_encoder *encoder = NULL;
 350        struct mdp5_encoder *mdp5_encoder;
 351        int enc_type = (intf->type == INTF_DSI) ?
 352                DRM_MODE_ENCODER_DSI : DRM_MODE_ENCODER_TMDS;
 353        int ret;
 354
 355        mdp5_encoder = kzalloc(sizeof(*mdp5_encoder), GFP_KERNEL);
 356        if (!mdp5_encoder) {
 357                ret = -ENOMEM;
 358                goto fail;
 359        }
 360
 361        memcpy(&mdp5_encoder->intf, intf, sizeof(mdp5_encoder->intf));
 362        encoder = &mdp5_encoder->base;
 363        mdp5_encoder->ctl = ctl;
 364
 365        spin_lock_init(&mdp5_encoder->intf_lock);
 366
 367        drm_encoder_init(dev, encoder, &mdp5_encoder_funcs, enc_type, NULL);
 368
 369        drm_encoder_helper_add(encoder, &mdp5_encoder_helper_funcs);
 370
 371        bs_init(mdp5_encoder);
 372
 373        return encoder;
 374
 375fail:
 376        if (encoder)
 377                mdp5_encoder_destroy(encoder);
 378
 379        return ERR_PTR(ret);
 380}
 381