diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 153 |
1 files changed, 75 insertions, 78 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 7d66269ad998..06a719c104f4 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -100,14 +100,14 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc) * the upstream part of the video pipe. */ -static void omap_crtc_dss_start_update(struct omap_drm_private *priv, +void omap_crtc_dss_start_update(struct omap_drm_private *priv, enum omap_channel channel) { - priv->dispc_ops->mgr_enable(priv->dispc, channel, true); + dispc_mgr_enable(priv->dispc, channel, true); } /* Called only from the encoder enable/disable and suspend/resume handlers. */ -static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) +void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) { struct omap_crtc_state *omap_state = to_omap_crtc_state(crtc->state); struct drm_device *dev = crtc->dev; @@ -128,7 +128,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) } if (omap_crtc->pipe->output->type == OMAP_DISPLAY_TYPE_HDMI) { - priv->dispc_ops->mgr_enable(priv->dispc, channel, enable); + dispc_mgr_enable(priv->dispc, channel, enable); omap_crtc->enabled = enable; return; } @@ -141,9 +141,9 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) omap_crtc->ignore_digit_sync_lost = true; } - framedone_irq = priv->dispc_ops->mgr_get_framedone_irq(priv->dispc, + framedone_irq = dispc_mgr_get_framedone_irq(priv->dispc, channel); - vsync_irq = priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, channel); + vsync_irq = dispc_mgr_get_vsync_irq(priv->dispc, channel); if (enable) { wait = omap_irq_wait_init(dev, vsync_irq, 1); @@ -163,7 +163,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) wait = omap_irq_wait_init(dev, vsync_irq, 2); } - priv->dispc_ops->mgr_enable(priv->dispc, channel, enable); + dispc_mgr_enable(priv->dispc, channel, enable); omap_crtc->enabled = enable; ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); @@ -180,21 +180,19 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) } -static int omap_crtc_dss_enable(struct omap_drm_private *priv, - enum omap_channel channel) +int omap_crtc_dss_enable(struct omap_drm_private *priv, enum omap_channel channel) { struct drm_crtc *crtc = priv->channels[channel]->crtc; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - priv->dispc_ops->mgr_set_timings(priv->dispc, omap_crtc->channel, + dispc_mgr_set_timings(priv->dispc, omap_crtc->channel, &omap_crtc->vm); omap_crtc_set_enabled(&omap_crtc->base, true); return 0; } -static void omap_crtc_dss_disable(struct omap_drm_private *priv, - enum omap_channel channel) +void omap_crtc_dss_disable(struct omap_drm_private *priv, enum omap_channel channel) { struct drm_crtc *crtc = priv->channels[channel]->crtc; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); @@ -202,7 +200,7 @@ static void omap_crtc_dss_disable(struct omap_drm_private *priv, omap_crtc_set_enabled(&omap_crtc->base, false); } -static void omap_crtc_dss_set_timings(struct omap_drm_private *priv, +void omap_crtc_dss_set_timings(struct omap_drm_private *priv, enum omap_channel channel, const struct videomode *vm) { @@ -213,7 +211,7 @@ static void omap_crtc_dss_set_timings(struct omap_drm_private *priv, omap_crtc->vm = *vm; } -static void omap_crtc_dss_set_lcd_config(struct omap_drm_private *priv, +void omap_crtc_dss_set_lcd_config(struct omap_drm_private *priv, enum omap_channel channel, const struct dss_lcd_mgr_config *config) { @@ -221,11 +219,11 @@ static void omap_crtc_dss_set_lcd_config(struct omap_drm_private *priv, struct omap_crtc *omap_crtc = to_omap_crtc(crtc); DBG("%s", omap_crtc->name); - priv->dispc_ops->mgr_set_lcd_config(priv->dispc, omap_crtc->channel, + dispc_mgr_set_lcd_config(priv->dispc, omap_crtc->channel, config); } -static int omap_crtc_dss_register_framedone( +int omap_crtc_dss_register_framedone( struct omap_drm_private *priv, enum omap_channel channel, void (*handler)(void *), void *data) { @@ -244,7 +242,7 @@ static int omap_crtc_dss_register_framedone( return 0; } -static void omap_crtc_dss_unregister_framedone( +void omap_crtc_dss_unregister_framedone( struct omap_drm_private *priv, enum omap_channel channel, void (*handler)(void *), void *data) { @@ -261,16 +259,6 @@ static void omap_crtc_dss_unregister_framedone( omap_crtc->framedone_handler_data = NULL; } -static const struct dss_mgr_ops mgr_ops = { - .start_update = omap_crtc_dss_start_update, - .enable = omap_crtc_dss_enable, - .disable = omap_crtc_dss_disable, - .set_timings = omap_crtc_dss_set_timings, - .set_lcd_config = omap_crtc_dss_set_lcd_config, - .register_framedone_handler = omap_crtc_dss_register_framedone, - .unregister_framedone_handler = omap_crtc_dss_unregister_framedone, -}; - /* ----------------------------------------------------------------------------- * Setup, Flush and Page Flip */ @@ -300,7 +288,7 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc) * If the dispc is busy we're racing the flush operation. Try again on * the next vblank interrupt. */ - if (priv->dispc_ops->mgr_go_busy(priv->dispc, omap_crtc->channel)) { + if (dispc_mgr_go_busy(priv->dispc, omap_crtc->channel)) { spin_unlock(&crtc->dev->event_lock); return; } @@ -362,27 +350,14 @@ static void omap_crtc_manual_display_update(struct work_struct *data) { struct omap_crtc *omap_crtc = container_of(data, struct omap_crtc, update_work.work); - struct drm_display_mode *mode = &omap_crtc->pipe->crtc->mode; - struct omap_dss_device *dssdev = omap_crtc->pipe->output->next; + struct omap_dss_device *dssdev = omap_crtc->pipe->output; struct drm_device *dev = omap_crtc->base.dev; - const struct omap_dss_driver *dssdrv; int ret; - if (!dssdev) { - dev_err_once(dev->dev, "missing display dssdev!"); + if (!dssdev || !dssdev->dsi_ops || !dssdev->dsi_ops->update) return; - } - - dssdrv = dssdev->driver; - if (!dssdrv || !dssdrv->update) { - dev_err_once(dev->dev, "missing or incorrect dssdrv!"); - return; - } - - if (dssdrv->sync) - dssdrv->sync(dssdev); - ret = dssdrv->update(dssdev, 0, 0, mode->hdisplay, mode->vdisplay); + ret = dssdev->dsi_ops->update(dssdev); if (ret < 0) { spin_lock_irq(&dev->event_lock); omap_crtc->pending = false; @@ -391,6 +366,33 @@ static void omap_crtc_manual_display_update(struct work_struct *data) } } +static s16 omap_crtc_s31_32_to_s2_8(s64 coef) +{ + u64 sign_bit = 1ULL << 63; + u64 cbits = (u64)coef; + + s16 ret = clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x1ff); + + if (cbits & sign_bit) + ret = -ret; + + return ret; +} + +static void omap_crtc_cpr_coefs_from_ctm(const struct drm_color_ctm *ctm, + struct omap_dss_cpr_coefs *cpr) +{ + cpr->rr = omap_crtc_s31_32_to_s2_8(ctm->matrix[0]); + cpr->rg = omap_crtc_s31_32_to_s2_8(ctm->matrix[1]); + cpr->rb = omap_crtc_s31_32_to_s2_8(ctm->matrix[2]); + cpr->gr = omap_crtc_s31_32_to_s2_8(ctm->matrix[3]); + cpr->gg = omap_crtc_s31_32_to_s2_8(ctm->matrix[4]); + cpr->gb = omap_crtc_s31_32_to_s2_8(ctm->matrix[5]); + cpr->br = omap_crtc_s31_32_to_s2_8(ctm->matrix[6]); + cpr->bg = omap_crtc_s31_32_to_s2_8(ctm->matrix[7]); + cpr->bb = omap_crtc_s31_32_to_s2_8(ctm->matrix[8]); +} + static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc) { struct omap_drm_private *priv = crtc->dev->dev_private; @@ -402,9 +404,17 @@ static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc) info.default_color = 0x000000; info.trans_enabled = false; info.partial_alpha_enabled = false; - info.cpr_enable = false; - priv->dispc_ops->mgr_setup(priv->dispc, omap_crtc->channel, &info); + if (crtc->state->ctm) { + struct drm_color_ctm *ctm = crtc->state->ctm->data; + + info.cpr_enable = true; + omap_crtc_cpr_coefs_from_ctm(ctm, &info.cpr_coefs); + } else { + info.cpr_enable = false; + } + + dispc_mgr_setup(priv->dispc, omap_crtc->channel, &info); } /* ----------------------------------------------------------------------------- @@ -445,7 +455,7 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc, DBG("%s", omap_crtc->name); - priv->dispc_ops->runtime_get(priv->dispc); + dispc_runtime_get(priv->dispc); /* manual updated display will not trigger vsync irq */ if (omap_state->manually_updated) @@ -484,7 +494,7 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc, drm_crtc_vblank_off(crtc); - priv->dispc_ops->runtime_put(priv->dispc); + dispc_runtime_put(priv->dispc); } static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc, @@ -502,9 +512,8 @@ static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc, * valid DISPC mode. DSI will calculate and configure the * proper DISPC mode later. */ - if (omap_crtc->pipe->output->next == NULL || - omap_crtc->pipe->output->next->type != OMAP_DISPLAY_TYPE_DSI) { - r = priv->dispc_ops->mgr_check_timings(priv->dispc, + if (omap_crtc->pipe->output->type != OMAP_DISPLAY_TYPE_DSI) { + r = dispc_mgr_check_timings(priv->dispc, omap_crtc->channel, &vm); if (r) @@ -555,17 +564,16 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - struct omap_dss_device *display = omap_crtc->pipe->output->next; + struct omap_dss_device *dssdev = omap_crtc->pipe->output; - if (!display) + if (!dssdev || !dssdev->dsi_ops || !dssdev->dsi_ops->is_video_mode) return false; - if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { - DBG("detected manually updated display!"); - return true; - } + if (dssdev->dsi_ops->is_video_mode(dssdev)) + return false; - return false; + DBG("detected manually updated display!"); + return true; } static int omap_crtc_atomic_check(struct drm_crtc *crtc, @@ -575,8 +583,8 @@ static int omap_crtc_atomic_check(struct drm_crtc *crtc, crtc); struct drm_plane_state *pri_state; - if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) { - unsigned int length = crtc_state->gamma_lut->length / + if (crtc_state->color_mgmt_changed && crtc_state->degamma_lut) { + unsigned int length = crtc_state->degamma_lut->length / sizeof(struct drm_color_lut); if (length < 2) @@ -617,13 +625,13 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_color_lut *lut = NULL; unsigned int length = 0; - if (crtc->state->gamma_lut) { + if (crtc->state->degamma_lut) { lut = (struct drm_color_lut *) - crtc->state->gamma_lut->data; - length = crtc->state->gamma_lut->length / + crtc->state->degamma_lut->data; + length = crtc->state->degamma_lut->length / sizeof(*lut); } - priv->dispc_ops->mgr_set_gamma(priv->dispc, omap_crtc->channel, + dispc_mgr_set_gamma(priv->dispc, omap_crtc->channel, lut, length); } @@ -648,7 +656,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, WARN_ON(ret != 0); spin_lock_irq(&crtc->dev->event_lock); - priv->dispc_ops->mgr_go(priv->dispc, omap_crtc->channel); + dispc_mgr_go(priv->dispc, omap_crtc->channel); omap_crtc_arm_event(crtc); spin_unlock_irq(&crtc->dev->event_lock); } @@ -741,7 +749,6 @@ static const struct drm_crtc_funcs omap_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = omap_crtc_destroy, .page_flip = drm_atomic_helper_page_flip, - .gamma_set = drm_atomic_helper_legacy_gamma_set, .atomic_duplicate_state = omap_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, .atomic_set_property = omap_crtc_atomic_set_property, @@ -771,16 +778,6 @@ static const char *channel_names[] = { [OMAP_DSS_CHANNEL_LCD3] = "lcd3", }; -void omap_crtc_pre_init(struct omap_drm_private *priv) -{ - dss_install_mgr_ops(priv->dss, &mgr_ops, priv); -} - -void omap_crtc_pre_uninit(struct omap_drm_private *priv) -{ - dss_uninstall_mgr_ops(priv->dss); -} - /* initialize crtc */ struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct omap_drm_pipeline *pipe, @@ -839,10 +836,10 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, * extracted with dispc_mgr_gamma_size(). If it returns 0 * gamma table is not supported. */ - if (priv->dispc_ops->mgr_gamma_size(priv->dispc, channel)) { + if (dispc_mgr_gamma_size(priv->dispc, channel)) { unsigned int gamma_lut_size = 256; - drm_crtc_enable_color_mgmt(crtc, 0, false, gamma_lut_size); + drm_crtc_enable_color_mgmt(crtc, gamma_lut_size, true, 0); drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size); } |