drm/tegra: sor: Extract tegra_sor_mode_set()
The code to set a video mode is common to all types of outputs that the SOR can drive. Extract it into a separate function so that it can be shared. Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
Родитель
402f6bcd94
Коммит
2bd1dd399f
|
@ -718,6 +718,83 @@ static void tegra_sor_apply_config(struct tegra_sor *sor,
|
|||
tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS);
|
||||
}
|
||||
|
||||
static void tegra_sor_mode_set(struct tegra_sor *sor,
|
||||
const struct drm_display_mode *mode,
|
||||
const struct drm_display_info *info)
|
||||
{
|
||||
struct tegra_dc *dc = to_tegra_dc(sor->output.encoder.crtc);
|
||||
unsigned int vbe, vse, hbe, hse, vbs, hbs;
|
||||
u32 value;
|
||||
|
||||
value = tegra_sor_readl(sor, SOR_STATE1);
|
||||
value &= ~SOR_STATE_ASY_PIXELDEPTH_MASK;
|
||||
value &= ~SOR_STATE_ASY_CRC_MODE_MASK;
|
||||
value &= ~SOR_STATE_ASY_OWNER_MASK;
|
||||
|
||||
value |= SOR_STATE_ASY_CRC_MODE_COMPLETE |
|
||||
SOR_STATE_ASY_OWNER(dc->pipe + 1);
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
value &= ~SOR_STATE_ASY_HSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
|
||||
value |= SOR_STATE_ASY_HSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
value &= ~SOR_STATE_ASY_VSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
|
||||
value |= SOR_STATE_ASY_VSYNCPOL;
|
||||
|
||||
switch (info->bpc) {
|
||||
case 8:
|
||||
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444;
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
tegra_sor_writel(sor, value, SOR_STATE1);
|
||||
|
||||
/*
|
||||
* TODO: The video timing programming below doesn't seem to match the
|
||||
* register definitions.
|
||||
*/
|
||||
|
||||
value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe));
|
||||
|
||||
/* sync end = sync width - 1 */
|
||||
vse = mode->vsync_end - mode->vsync_start - 1;
|
||||
hse = mode->hsync_end - mode->hsync_start - 1;
|
||||
|
||||
value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe));
|
||||
|
||||
/* blank end = sync end + back porch */
|
||||
vbe = vse + (mode->vtotal - mode->vsync_end);
|
||||
hbe = hse + (mode->htotal - mode->hsync_end);
|
||||
|
||||
value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe));
|
||||
|
||||
/* blank start = blank end + active */
|
||||
vbs = vbe + mode->vdisplay;
|
||||
hbs = hbe + mode->hdisplay;
|
||||
|
||||
value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe));
|
||||
|
||||
/* XXX interlacing support */
|
||||
tegra_sor_writel(sor, 0x001, SOR_HEAD_STATE5(dc->pipe));
|
||||
}
|
||||
|
||||
static int tegra_sor_detach(struct tegra_sor *sor)
|
||||
{
|
||||
unsigned long value, timeout;
|
||||
|
@ -1250,14 +1327,17 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
|
|||
struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
|
||||
struct tegra_output *output = encoder_to_output(encoder);
|
||||
struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
|
||||
unsigned int vbe, vse, hbe, hse, vbs, hbs, i;
|
||||
struct tegra_sor *sor = to_sor(output);
|
||||
struct tegra_sor_config config;
|
||||
struct drm_display_info *info;
|
||||
struct drm_dp_link link;
|
||||
u8 rate, lanes;
|
||||
unsigned int i;
|
||||
int err = 0;
|
||||
u32 value;
|
||||
|
||||
info = &output->connector.display_info;
|
||||
|
||||
err = clk_prepare_enable(sor->clk);
|
||||
if (err < 0)
|
||||
dev_err(sor->dev, "failed to enable clock: %d\n", err);
|
||||
|
@ -1505,75 +1585,19 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
|
|||
if (err < 0)
|
||||
dev_err(sor->dev, "failed to power up SOR: %d\n", err);
|
||||
|
||||
/*
|
||||
* configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
|
||||
* raster, associate with display controller)
|
||||
*/
|
||||
value = SOR_STATE_ASY_PROTOCOL_DP_A |
|
||||
SOR_STATE_ASY_CRC_MODE_COMPLETE |
|
||||
SOR_STATE_ASY_OWNER(dc->pipe + 1);
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
value &= ~SOR_STATE_ASY_HSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
|
||||
value |= SOR_STATE_ASY_HSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
value &= ~SOR_STATE_ASY_VSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
|
||||
value |= SOR_STATE_ASY_VSYNCPOL;
|
||||
|
||||
switch (config.bits_per_pixel) {
|
||||
case 24:
|
||||
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
|
||||
break;
|
||||
|
||||
case 18:
|
||||
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444;
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
tegra_sor_writel(sor, value, SOR_STATE1);
|
||||
|
||||
/*
|
||||
* TODO: The video timing programming below doesn't seem to match the
|
||||
* register definitions.
|
||||
*/
|
||||
|
||||
value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe));
|
||||
|
||||
vse = mode->vsync_end - mode->vsync_start - 1;
|
||||
hse = mode->hsync_end - mode->hsync_start - 1;
|
||||
|
||||
value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe));
|
||||
|
||||
vbe = vse + (mode->vsync_start - mode->vdisplay);
|
||||
hbe = hse + (mode->hsync_start - mode->hdisplay);
|
||||
|
||||
value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe));
|
||||
|
||||
vbs = vbe + mode->vdisplay;
|
||||
hbs = hbe + mode->hdisplay;
|
||||
|
||||
value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe));
|
||||
|
||||
tegra_sor_writel(sor, 0x1, SOR_HEAD_STATE5(dc->pipe));
|
||||
|
||||
/* CSTM (LVDS, link A/B, upper) */
|
||||
value = SOR_CSTM_LVDS | SOR_CSTM_LINK_ACT_A | SOR_CSTM_LINK_ACT_B |
|
||||
SOR_CSTM_UPPER;
|
||||
tegra_sor_writel(sor, value, SOR_CSTM);
|
||||
|
||||
/* use DP-A protocol */
|
||||
value = tegra_sor_readl(sor, SOR_STATE1);
|
||||
value &= ~SOR_STATE_ASY_PROTOCOL_MASK;
|
||||
value |= SOR_STATE_ASY_PROTOCOL_DP_A;
|
||||
tegra_sor_writel(sor, value, SOR_STATE1);
|
||||
|
||||
tegra_sor_mode_set(sor, mode, info);
|
||||
|
||||
/* PWM setup */
|
||||
err = tegra_sor_setup_pwm(sor, 250);
|
||||
if (err < 0)
|
||||
|
@ -1789,11 +1813,11 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
|
|||
struct tegra_output *output = encoder_to_output(encoder);
|
||||
unsigned int h_ref_to_sync = 1, pulse_start, max_ac;
|
||||
struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
|
||||
unsigned int vbe, vse, hbe, hse, vbs, hbs, div;
|
||||
struct tegra_sor_hdmi_settings *settings;
|
||||
struct tegra_sor *sor = to_sor(output);
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_display_info *info;
|
||||
unsigned int div;
|
||||
u32 value;
|
||||
int err;
|
||||
|
||||
|
@ -2051,83 +2075,19 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
|
|||
if (err < 0)
|
||||
dev_err(sor->dev, "failed to power up SOR: %d\n", err);
|
||||
|
||||
/* configure mode */
|
||||
value = tegra_sor_readl(sor, SOR_STATE1);
|
||||
value &= ~SOR_STATE_ASY_PIXELDEPTH_MASK;
|
||||
value &= ~SOR_STATE_ASY_CRC_MODE_MASK;
|
||||
value &= ~SOR_STATE_ASY_OWNER_MASK;
|
||||
|
||||
value |= SOR_STATE_ASY_CRC_MODE_COMPLETE |
|
||||
SOR_STATE_ASY_OWNER(dc->pipe + 1);
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
value &= ~SOR_STATE_ASY_HSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
|
||||
value |= SOR_STATE_ASY_HSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
value &= ~SOR_STATE_ASY_VSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
|
||||
value |= SOR_STATE_ASY_VSYNCPOL;
|
||||
|
||||
switch (info->bpc) {
|
||||
case 8:
|
||||
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444;
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
tegra_sor_writel(sor, value, SOR_STATE1);
|
||||
|
||||
/* configure dynamic range of output */
|
||||
value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe));
|
||||
value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK;
|
||||
value &= ~SOR_HEAD_STATE_DYNRANGE_MASK;
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe));
|
||||
|
||||
/* configure colorspace */
|
||||
value = tegra_sor_readl(sor, SOR_HEAD_STATE0(dc->pipe));
|
||||
value &= ~SOR_HEAD_STATE_COLORSPACE_MASK;
|
||||
value |= SOR_HEAD_STATE_COLORSPACE_RGB;
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE0(dc->pipe));
|
||||
|
||||
/*
|
||||
* TODO: The video timing programming below doesn't seem to match the
|
||||
* register definitions.
|
||||
*/
|
||||
|
||||
value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE1(dc->pipe));
|
||||
|
||||
/* sync end = sync width - 1 */
|
||||
vse = mode->vsync_end - mode->vsync_start - 1;
|
||||
hse = mode->hsync_end - mode->hsync_start - 1;
|
||||
|
||||
value = ((vse & 0x7fff) << 16) | (hse & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE2(dc->pipe));
|
||||
|
||||
/* blank end = sync end + back porch */
|
||||
vbe = vse + (mode->vtotal - mode->vsync_end);
|
||||
hbe = hse + (mode->htotal - mode->hsync_end);
|
||||
|
||||
value = ((vbe & 0x7fff) << 16) | (hbe & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE3(dc->pipe));
|
||||
|
||||
/* blank start = blank end + active */
|
||||
vbs = vbe + mode->vdisplay;
|
||||
hbs = hbe + mode->hdisplay;
|
||||
|
||||
value = ((vbs & 0x7fff) << 16) | (hbs & 0x7fff);
|
||||
tegra_sor_writel(sor, value, SOR_HEAD_STATE4(dc->pipe));
|
||||
|
||||
tegra_sor_writel(sor, 0x1, SOR_HEAD_STATE5(dc->pipe));
|
||||
tegra_sor_mode_set(sor, mode, info);
|
||||
|
||||
tegra_sor_update(sor);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче