linux/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2013 Red Hat
   4 * Author: Rob Clark <robdclark@gmail.com>
   5 */
   6
   7#include <drm/drm_crtc.h>
   8#include <drm/drm_probe_helper.h>
   9
  10#include "mdp4_kms.h"
  11
  12struct mdp4_dtv_encoder {
  13        struct drm_encoder base;
  14        struct clk *hdmi_clk;
  15        struct clk *mdp_clk;
  16        unsigned long int pixclock;
  17        bool enabled;
  18        uint32_t bsc;
  19};
  20#define to_mdp4_dtv_encoder(x) container_of(x, struct mdp4_dtv_encoder, base)
  21
  22static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
  23{
  24        struct msm_drm_private *priv = encoder->dev->dev_private;
  25        return to_mdp4_kms(to_mdp_kms(priv->kms));
  26}
  27
  28static void mdp4_dtv_encoder_destroy(struct drm_encoder *encoder)
  29{
  30        struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
  31        drm_encoder_cleanup(encoder);
  32        kfree(mdp4_dtv_encoder);
  33}
  34
  35static const struct drm_encoder_funcs mdp4_dtv_encoder_funcs = {
  36        .destroy = mdp4_dtv_encoder_destroy,
  37};
  38
  39static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder,
  40                struct drm_display_mode *mode,
  41                struct drm_display_mode *adjusted_mode)
  42{
  43        struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
  44        struct mdp4_kms *mdp4_kms = get_kms(encoder);
  45        uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
  46        uint32_t display_v_start, display_v_end;
  47        uint32_t hsync_start_x, hsync_end_x;
  48
  49        mode = adjusted_mode;
  50
  51        DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
  52
  53        mdp4_dtv_encoder->pixclock = mode->clock * 1000;
  54
  55        DBG("pixclock=%lu", mdp4_dtv_encoder->pixclock);
  56
  57        ctrl_pol = 0;
  58        if (mode->flags & DRM_MODE_FLAG_NHSYNC)
  59                ctrl_pol |= MDP4_DTV_CTRL_POLARITY_HSYNC_LOW;
  60        if (mode->flags & DRM_MODE_FLAG_NVSYNC)
  61                ctrl_pol |= MDP4_DTV_CTRL_POLARITY_VSYNC_LOW;
  62        /* probably need to get DATA_EN polarity from panel.. */
  63
  64        dtv_hsync_skew = 0;  /* get this from panel? */
  65
  66        hsync_start_x = (mode->htotal - mode->hsync_start);
  67        hsync_end_x = mode->htotal - (mode->hsync_start - mode->hdisplay) - 1;
  68
  69        vsync_period = mode->vtotal * mode->htotal;
  70        vsync_len = (mode->vsync_end - mode->vsync_start) * mode->htotal;
  71        display_v_start = (mode->vtotal - mode->vsync_start) * mode->htotal + dtv_hsync_skew;
  72        display_v_end = vsync_period - ((mode->vsync_start - mode->vdisplay) * mode->htotal) + dtv_hsync_skew - 1;
  73
  74        mdp4_write(mdp4_kms, REG_MDP4_DTV_HSYNC_CTRL,
  75                        MDP4_DTV_HSYNC_CTRL_PULSEW(mode->hsync_end - mode->hsync_start) |
  76                        MDP4_DTV_HSYNC_CTRL_PERIOD(mode->htotal));
  77        mdp4_write(mdp4_kms, REG_MDP4_DTV_VSYNC_PERIOD, vsync_period);
  78        mdp4_write(mdp4_kms, REG_MDP4_DTV_VSYNC_LEN, vsync_len);
  79        mdp4_write(mdp4_kms, REG_MDP4_DTV_DISPLAY_HCTRL,
  80                        MDP4_DTV_DISPLAY_HCTRL_START(hsync_start_x) |
  81                        MDP4_DTV_DISPLAY_HCTRL_END(hsync_end_x));
  82        mdp4_write(mdp4_kms, REG_MDP4_DTV_DISPLAY_VSTART, display_v_start);
  83        mdp4_write(mdp4_kms, REG_MDP4_DTV_DISPLAY_VEND, display_v_end);
  84        mdp4_write(mdp4_kms, REG_MDP4_DTV_BORDER_CLR, 0);
  85        mdp4_write(mdp4_kms, REG_MDP4_DTV_UNDERFLOW_CLR,
  86                        MDP4_DTV_UNDERFLOW_CLR_ENABLE_RECOVERY |
  87                        MDP4_DTV_UNDERFLOW_CLR_COLOR(0xff));
  88        mdp4_write(mdp4_kms, REG_MDP4_DTV_HSYNC_SKEW, dtv_hsync_skew);
  89        mdp4_write(mdp4_kms, REG_MDP4_DTV_CTRL_POLARITY, ctrl_pol);
  90        mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_HCTL,
  91                        MDP4_DTV_ACTIVE_HCTL_START(0) |
  92                        MDP4_DTV_ACTIVE_HCTL_END(0));
  93        mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VSTART, 0);
  94        mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VEND, 0);
  95}
  96
  97static void mdp4_dtv_encoder_disable(struct drm_encoder *encoder)
  98{
  99        struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
 100        struct mdp4_kms *mdp4_kms = get_kms(encoder);
 101
 102        if (WARN_ON(!mdp4_dtv_encoder->enabled))
 103                return;
 104
 105        mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0);
 106
 107        /*
 108         * Wait for a vsync so we know the ENABLE=0 latched before
 109         * the (connector) source of the vsync's gets disabled,
 110         * otherwise we end up in a funny state if we re-enable
 111         * before the disable latches, which results that some of
 112         * the settings changes for the new modeset (like new
 113         * scanout buffer) don't latch properly..
 114         */
 115        mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_EXTERNAL_VSYNC);
 116
 117        clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk);
 118        clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk);
 119
 120        mdp4_dtv_encoder->enabled = false;
 121}
 122
 123static void mdp4_dtv_encoder_enable(struct drm_encoder *encoder)
 124{
 125        struct drm_device *dev = encoder->dev;
 126        struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
 127        struct mdp4_kms *mdp4_kms = get_kms(encoder);
 128        unsigned long pc = mdp4_dtv_encoder->pixclock;
 129        int ret;
 130
 131        if (WARN_ON(mdp4_dtv_encoder->enabled))
 132                return;
 133
 134        mdp4_crtc_set_config(encoder->crtc,
 135                        MDP4_DMA_CONFIG_R_BPC(BPC8) |
 136                        MDP4_DMA_CONFIG_G_BPC(BPC8) |
 137                        MDP4_DMA_CONFIG_B_BPC(BPC8) |
 138                        MDP4_DMA_CONFIG_PACK(0x21));
 139        mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 1);
 140
 141        DBG("setting mdp_clk=%lu", pc);
 142
 143        ret = clk_set_rate(mdp4_dtv_encoder->mdp_clk, pc);
 144        if (ret)
 145                DRM_DEV_ERROR(dev->dev, "failed to set mdp_clk to %lu: %d\n",
 146                        pc, ret);
 147
 148        ret = clk_prepare_enable(mdp4_dtv_encoder->mdp_clk);
 149        if (ret)
 150                DRM_DEV_ERROR(dev->dev, "failed to enabled mdp_clk: %d\n", ret);
 151
 152        ret = clk_prepare_enable(mdp4_dtv_encoder->hdmi_clk);
 153        if (ret)
 154                DRM_DEV_ERROR(dev->dev, "failed to enable hdmi_clk: %d\n", ret);
 155
 156        mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 1);
 157
 158        mdp4_dtv_encoder->enabled = true;
 159}
 160
 161static const struct drm_encoder_helper_funcs mdp4_dtv_encoder_helper_funcs = {
 162        .mode_set = mdp4_dtv_encoder_mode_set,
 163        .enable = mdp4_dtv_encoder_enable,
 164        .disable = mdp4_dtv_encoder_disable,
 165};
 166
 167long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate)
 168{
 169        struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
 170        return clk_round_rate(mdp4_dtv_encoder->mdp_clk, rate);
 171}
 172
 173/* initialize encoder */
 174struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev)
 175{
 176        struct drm_encoder *encoder = NULL;
 177        struct mdp4_dtv_encoder *mdp4_dtv_encoder;
 178        int ret;
 179
 180        mdp4_dtv_encoder = kzalloc(sizeof(*mdp4_dtv_encoder), GFP_KERNEL);
 181        if (!mdp4_dtv_encoder) {
 182                ret = -ENOMEM;
 183                goto fail;
 184        }
 185
 186        encoder = &mdp4_dtv_encoder->base;
 187
 188        drm_encoder_init(dev, encoder, &mdp4_dtv_encoder_funcs,
 189                         DRM_MODE_ENCODER_TMDS, NULL);
 190        drm_encoder_helper_add(encoder, &mdp4_dtv_encoder_helper_funcs);
 191
 192        mdp4_dtv_encoder->hdmi_clk = devm_clk_get(dev->dev, "hdmi_clk");
 193        if (IS_ERR(mdp4_dtv_encoder->hdmi_clk)) {
 194                DRM_DEV_ERROR(dev->dev, "failed to get hdmi_clk\n");
 195                ret = PTR_ERR(mdp4_dtv_encoder->hdmi_clk);
 196                goto fail;
 197        }
 198
 199        mdp4_dtv_encoder->mdp_clk = devm_clk_get(dev->dev, "tv_clk");
 200        if (IS_ERR(mdp4_dtv_encoder->mdp_clk)) {
 201                DRM_DEV_ERROR(dev->dev, "failed to get tv_clk\n");
 202                ret = PTR_ERR(mdp4_dtv_encoder->mdp_clk);
 203                goto fail;
 204        }
 205
 206        return encoder;
 207
 208fail:
 209        if (encoder)
 210                mdp4_dtv_encoder_destroy(encoder);
 211
 212        return ERR_PTR(ret);
 213}
 214