mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-23 11:04:44 +08:00
- remove deprecated stih416 chip functionnalities
- fix issues met around gdp panes - fix STI driver unbind procedure - DVI/HDMI mode is automatically detected - allow fps statisitics resetting -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYnX00AAoJENMx8KsF0f19GScP/RsSL8+Qo5N9Ru+gMUDsBMS/ 587xtU8I6y2o3r1Mb4/WxFaTI9Rf3rlosFFtF42loFKbnTiTOihXnGAlQ+hcEnn9 YyCxdBaLz/CF0FDN1kTE0Rq01qR2+PTiKJcxzOr3WcjVVmYsWl0QyoAcCSsnm1/k pSvJe0QaHxsLeC/iPgQBsEaLYlQWAhOZ/Yco+Rym6x36PHDCmDJfw+Njjbp3Bjnq yq6tP/uNQg3SQLCLsJdlGgN4FvLrTzlC32REU1t5NfLKhQngXNL/bnjw/xg/U/wN 3XIGE1YGunEc4i2Su/sPBv0NzVXlj4umW3qqKmu+5uXN3IidNXDTSdSK1MfaVn5q n4A9IKOo3QSzG4IFzgW5yxJc03fFw4sU3seILRmORELLqjUUSmqmwTZhwl9Zq363 TVZ0h0Ku8aeLVUGhWs4J8Y9Ec40CVpQmSScogsP2Syi/Ac7QkqJIHv68s8IEL0xX FTStehIraGIco3QtRl8CbCSCEVuAjI+16REYs6h7vRLVce7PCLnfoR22KmMPj6p9 X5Wt3xuU+dZhP5xgVSEyXARvM4TtFVLrtstC8MlJwPGUSR76aTnsaxiXIsHVTVAh 6M/syyDSVN6OswMPAixw9/dALZWXBhQLMyANpG2jTgZIAjmGLmCSg7LkUa149nWZ pG+O8mdNVpREz97WgZZV =I/dF -----END PGP SIGNATURE----- Merge tag 'sti-drm-next-2017-02-10' of https://github.com/vinceab/linux into drm-next - remove deprecated stih416 chip functionnalities - fix issues met around gdp panes - fix STI driver unbind procedure - DVI/HDMI mode is automatically detected - allow fps statisitics resetting * tag 'sti-drm-next-2017-02-10' of https://github.com/vinceab/linux: drm/sti: debug fps reset drm/sti: hdmi: automatically check DVI/HDMI mode drm/sti: unbind all components while driver cleanup drm/sti: do not post GDP command if no update drm/sti: do not set gdp pixel clock rate if mode is not set drm/sti: enable gdp pixel clock in atomic_update drm/sti: remove deprecated legacy vtg slave drm/sti: remove deprecated sink_term config drm/sti: do not check hw scaling if mode is not set drm/sti: Fix up crtc_state->event handling drm/sti: use atomic_helper for commit
This commit is contained in:
commit
1e9d996645
@ -134,21 +134,6 @@ sti_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
|||||||
sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
|
sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sti_crtc_atomic_begin(struct drm_crtc *crtc,
|
|
||||||
struct drm_crtc_state *old_crtc_state)
|
|
||||||
{
|
|
||||||
struct sti_mixer *mixer = to_sti_mixer(crtc);
|
|
||||||
|
|
||||||
if (crtc->state->event) {
|
|
||||||
crtc->state->event->pipe = drm_crtc_index(crtc);
|
|
||||||
|
|
||||||
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
|
||||||
|
|
||||||
mixer->pending_event = crtc->state->event;
|
|
||||||
crtc->state->event = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
|
static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||||
struct drm_crtc_state *old_crtc_state)
|
struct drm_crtc_state *old_crtc_state)
|
||||||
{
|
{
|
||||||
@ -156,6 +141,8 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||||||
struct sti_mixer *mixer = to_sti_mixer(crtc);
|
struct sti_mixer *mixer = to_sti_mixer(crtc);
|
||||||
struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
|
struct sti_compositor *compo = dev_get_drvdata(mixer->dev);
|
||||||
struct drm_plane *p;
|
struct drm_plane *p;
|
||||||
|
struct drm_pending_vblank_event *event;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("\n");
|
DRM_DEBUG_DRIVER("\n");
|
||||||
|
|
||||||
@ -220,13 +207,24 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event = crtc->state->event;
|
||||||
|
if (event) {
|
||||||
|
crtc->state->event = NULL;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
||||||
|
if (drm_crtc_vblank_get(crtc) == 0)
|
||||||
|
drm_crtc_arm_vblank_event(crtc, event);
|
||||||
|
else
|
||||||
|
drm_crtc_send_vblank_event(crtc, event);
|
||||||
|
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
|
static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
|
||||||
.enable = sti_crtc_enable,
|
.enable = sti_crtc_enable,
|
||||||
.disable = sti_crtc_disabling,
|
.disable = sti_crtc_disabling,
|
||||||
.mode_set_nofb = sti_crtc_mode_set_nofb,
|
.mode_set_nofb = sti_crtc_mode_set_nofb,
|
||||||
.atomic_begin = sti_crtc_atomic_begin,
|
|
||||||
.atomic_flush = sti_crtc_atomic_flush,
|
.atomic_flush = sti_crtc_atomic_flush,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -250,7 +248,6 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,
|
|||||||
struct sti_compositor *compo;
|
struct sti_compositor *compo;
|
||||||
struct drm_crtc *crtc = data;
|
struct drm_crtc *crtc = data;
|
||||||
struct sti_mixer *mixer;
|
struct sti_mixer *mixer;
|
||||||
unsigned long flags;
|
|
||||||
struct sti_private *priv;
|
struct sti_private *priv;
|
||||||
unsigned int pipe;
|
unsigned int pipe;
|
||||||
|
|
||||||
@ -267,14 +264,6 @@ int sti_crtc_vblank_cb(struct notifier_block *nb,
|
|||||||
|
|
||||||
drm_crtc_handle_vblank(crtc);
|
drm_crtc_handle_vblank(crtc);
|
||||||
|
|
||||||
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
|
||||||
if (mixer->pending_event) {
|
|
||||||
drm_crtc_send_vblank_event(crtc, mixer->pending_event);
|
|
||||||
drm_crtc_vblank_put(crtc);
|
|
||||||
mixer->pending_event = NULL;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
|
||||||
|
|
||||||
if (mixer->status == STI_MIXER_DISABLING) {
|
if (mixer->status == STI_MIXER_DISABLING) {
|
||||||
struct drm_plane *p;
|
struct drm_plane *p;
|
||||||
|
|
||||||
@ -317,19 +306,12 @@ void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe)
|
|||||||
struct sti_private *priv = drm_dev->dev_private;
|
struct sti_private *priv = drm_dev->dev_private;
|
||||||
struct sti_compositor *compo = priv->compo;
|
struct sti_compositor *compo = priv->compo;
|
||||||
struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe];
|
struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe];
|
||||||
struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc;
|
|
||||||
struct sti_vtg *vtg = compo->vtg[pipe];
|
struct sti_vtg *vtg = compo->vtg[pipe];
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("\n");
|
DRM_DEBUG_DRIVER("\n");
|
||||||
|
|
||||||
if (sti_vtg_unregister_client(vtg, vtg_vblank_nb))
|
if (sti_vtg_unregister_client(vtg, vtg_vblank_nb))
|
||||||
DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
|
DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n");
|
||||||
|
|
||||||
/* free the resources of the pending requests */
|
|
||||||
if (compo->mixer[pipe]->pending_event) {
|
|
||||||
drm_crtc_vblank_put(crtc);
|
|
||||||
compo->mixer[pipe]->pending_event = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sti_crtc_late_register(struct drm_crtc *crtc)
|
static int sti_crtc_late_register(struct drm_crtc *crtc)
|
||||||
|
@ -58,7 +58,9 @@ static int sti_drm_fps_set(void *data, u64 val)
|
|||||||
list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
|
list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) {
|
||||||
struct sti_plane *plane = to_sti_plane(p);
|
struct sti_plane *plane = to_sti_plane(p);
|
||||||
|
|
||||||
|
memset(&plane->fps_info, 0, sizeof(plane->fps_info));
|
||||||
plane->fps_info.output = (val >> i) & 1;
|
plane->fps_info.output = (val >> i) & 1;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,50 +117,13 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sti_atomic_schedule(struct sti_private *private,
|
static void sti_drm_dbg_cleanup(struct drm_minor *minor)
|
||||||
struct drm_atomic_state *state)
|
|
||||||
{
|
{
|
||||||
private->commit.state = state;
|
drm_debugfs_remove_files(sti_drm_dbg_list,
|
||||||
schedule_work(&private->commit.work);
|
ARRAY_SIZE(sti_drm_dbg_list), minor);
|
||||||
}
|
|
||||||
|
|
||||||
static void sti_atomic_complete(struct sti_private *private,
|
drm_debugfs_remove_files((struct drm_info_list *)&sti_drm_fps_fops,
|
||||||
struct drm_atomic_state *state)
|
1, minor);
|
||||||
{
|
|
||||||
struct drm_device *drm = private->drm_dev;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Everything below can be run asynchronously without the need to grab
|
|
||||||
* any modeset locks at all under one condition: It must be guaranteed
|
|
||||||
* that the asynchronous work has either been cancelled (if the driver
|
|
||||||
* supports it, which at least requires that the framebuffers get
|
|
||||||
* cleaned up with drm_atomic_helper_cleanup_planes()) or completed
|
|
||||||
* before the new state gets committed on the software side with
|
|
||||||
* drm_atomic_helper_swap_state().
|
|
||||||
*
|
|
||||||
* This scheme allows new atomic state updates to be prepared and
|
|
||||||
* checked in parallel to the asynchronous completion of the previous
|
|
||||||
* update. Which is important since compositors need to figure out the
|
|
||||||
* composition of the next frame right after having submitted the
|
|
||||||
* current layout.
|
|
||||||
*/
|
|
||||||
|
|
||||||
drm_atomic_helper_commit_modeset_disables(drm, state);
|
|
||||||
drm_atomic_helper_commit_planes(drm, state, 0);
|
|
||||||
drm_atomic_helper_commit_modeset_enables(drm, state);
|
|
||||||
|
|
||||||
drm_atomic_helper_wait_for_vblanks(drm, state);
|
|
||||||
|
|
||||||
drm_atomic_helper_cleanup_planes(drm, state);
|
|
||||||
drm_atomic_state_put(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sti_atomic_work(struct work_struct *work)
|
|
||||||
{
|
|
||||||
struct sti_private *private = container_of(work,
|
|
||||||
struct sti_private, commit.work);
|
|
||||||
|
|
||||||
sti_atomic_complete(private, private->commit.state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sti_atomic_check(struct drm_device *dev,
|
static int sti_atomic_check(struct drm_device *dev,
|
||||||
@ -181,38 +146,6 @@ static int sti_atomic_check(struct drm_device *dev,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sti_atomic_commit(struct drm_device *drm,
|
|
||||||
struct drm_atomic_state *state, bool nonblock)
|
|
||||||
{
|
|
||||||
struct sti_private *private = drm->dev_private;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = drm_atomic_helper_prepare_planes(drm, state);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
/* serialize outstanding nonblocking commits */
|
|
||||||
mutex_lock(&private->commit.lock);
|
|
||||||
flush_work(&private->commit.work);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the point of no return - everything below never fails except
|
|
||||||
* when the hw goes bonghits. Which means we can commit the new state on
|
|
||||||
* the software side now.
|
|
||||||
*/
|
|
||||||
|
|
||||||
drm_atomic_helper_swap_state(state, true);
|
|
||||||
|
|
||||||
drm_atomic_state_get(state);
|
|
||||||
if (nonblock)
|
|
||||||
sti_atomic_schedule(private, state);
|
|
||||||
else
|
|
||||||
sti_atomic_complete(private, state);
|
|
||||||
|
|
||||||
mutex_unlock(&private->commit.lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sti_output_poll_changed(struct drm_device *ddev)
|
static void sti_output_poll_changed(struct drm_device *ddev)
|
||||||
{
|
{
|
||||||
struct sti_private *private = ddev->dev_private;
|
struct sti_private *private = ddev->dev_private;
|
||||||
@ -224,7 +157,7 @@ static const struct drm_mode_config_funcs sti_mode_config_funcs = {
|
|||||||
.fb_create = drm_fb_cma_create,
|
.fb_create = drm_fb_cma_create,
|
||||||
.output_poll_changed = sti_output_poll_changed,
|
.output_poll_changed = sti_output_poll_changed,
|
||||||
.atomic_check = sti_atomic_check,
|
.atomic_check = sti_atomic_check,
|
||||||
.atomic_commit = sti_atomic_commit,
|
.atomic_commit = drm_atomic_helper_commit,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sti_mode_config_init(struct drm_device *dev)
|
static void sti_mode_config_init(struct drm_device *dev)
|
||||||
@ -304,9 +237,6 @@ static int sti_init(struct drm_device *ddev)
|
|||||||
dev_set_drvdata(ddev->dev, ddev);
|
dev_set_drvdata(ddev->dev, ddev);
|
||||||
private->drm_dev = ddev;
|
private->drm_dev = ddev;
|
||||||
|
|
||||||
mutex_init(&private->commit.lock);
|
|
||||||
INIT_WORK(&private->commit.work, sti_atomic_work);
|
|
||||||
|
|
||||||
drm_mode_config_init(ddev);
|
drm_mode_config_init(ddev);
|
||||||
|
|
||||||
sti_mode_config_init(ddev);
|
sti_mode_config_init(ddev);
|
||||||
@ -327,6 +257,7 @@ static void sti_cleanup(struct drm_device *ddev)
|
|||||||
|
|
||||||
drm_kms_helper_poll_fini(ddev);
|
drm_kms_helper_poll_fini(ddev);
|
||||||
drm_vblank_cleanup(ddev);
|
drm_vblank_cleanup(ddev);
|
||||||
|
component_unbind_all(ddev->dev, ddev);
|
||||||
kfree(private);
|
kfree(private);
|
||||||
ddev->dev_private = NULL;
|
ddev->dev_private = NULL;
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,6 @@ struct sti_private {
|
|||||||
struct drm_property *plane_zorder_property;
|
struct drm_property *plane_zorder_property;
|
||||||
struct drm_device *drm_dev;
|
struct drm_device *drm_dev;
|
||||||
struct drm_fbdev_cma *fbdev;
|
struct drm_fbdev_cma *fbdev;
|
||||||
|
|
||||||
struct {
|
|
||||||
struct drm_atomic_state *state;
|
|
||||||
struct work_struct work;
|
|
||||||
struct mutex lock;
|
|
||||||
} commit;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct platform_driver sti_tvout_driver;
|
extern struct platform_driver sti_tvout_driver;
|
||||||
|
@ -610,7 +610,6 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane,
|
|||||||
struct sti_plane *plane = to_sti_plane(drm_plane);
|
struct sti_plane *plane = to_sti_plane(drm_plane);
|
||||||
struct sti_gdp *gdp = to_sti_gdp(plane);
|
struct sti_gdp *gdp = to_sti_gdp(plane);
|
||||||
struct drm_crtc *crtc = state->crtc;
|
struct drm_crtc *crtc = state->crtc;
|
||||||
struct sti_compositor *compo = dev_get_drvdata(gdp->dev);
|
|
||||||
struct drm_framebuffer *fb = state->fb;
|
struct drm_framebuffer *fb = state->fb;
|
||||||
struct drm_crtc_state *crtc_state;
|
struct drm_crtc_state *crtc_state;
|
||||||
struct sti_mixer *mixer;
|
struct sti_mixer *mixer;
|
||||||
@ -648,45 +647,30 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gdp->vtg) {
|
/* Set gdp clock */
|
||||||
/* Register gdp callback */
|
if (mode->clock && gdp->clk_pix) {
|
||||||
gdp->vtg = compo->vtg[mixer->id];
|
struct clk *clkp;
|
||||||
if (sti_vtg_register_client(gdp->vtg,
|
int rate = mode->clock * 1000;
|
||||||
&gdp->vtg_field_nb, crtc)) {
|
int res;
|
||||||
DRM_ERROR("Cannot register VTG notifier\n");
|
|
||||||
|
/*
|
||||||
|
* According to the mixer used, the gdp pixel clock
|
||||||
|
* should have a different parent clock.
|
||||||
|
*/
|
||||||
|
if (mixer->id == STI_MIXER_MAIN)
|
||||||
|
clkp = gdp->clk_main_parent;
|
||||||
|
else
|
||||||
|
clkp = gdp->clk_aux_parent;
|
||||||
|
|
||||||
|
if (clkp)
|
||||||
|
clk_set_parent(gdp->clk_pix, clkp);
|
||||||
|
|
||||||
|
res = clk_set_rate(gdp->clk_pix, rate);
|
||||||
|
if (res < 0) {
|
||||||
|
DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
|
||||||
|
rate);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set and enable gdp clock */
|
|
||||||
if (gdp->clk_pix) {
|
|
||||||
struct clk *clkp;
|
|
||||||
int rate = mode->clock * 1000;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* According to the mixer used, the gdp pixel clock
|
|
||||||
* should have a different parent clock.
|
|
||||||
*/
|
|
||||||
if (mixer->id == STI_MIXER_MAIN)
|
|
||||||
clkp = gdp->clk_main_parent;
|
|
||||||
else
|
|
||||||
clkp = gdp->clk_aux_parent;
|
|
||||||
|
|
||||||
if (clkp)
|
|
||||||
clk_set_parent(gdp->clk_pix, clkp);
|
|
||||||
|
|
||||||
res = clk_set_rate(gdp->clk_pix, rate);
|
|
||||||
if (res < 0) {
|
|
||||||
DRM_ERROR("Cannot set rate (%dHz) for gdp\n",
|
|
||||||
rate);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clk_prepare_enable(gdp->clk_pix)) {
|
|
||||||
DRM_ERROR("Failed to prepare/enable gdp\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
|
DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
|
||||||
@ -724,6 +708,31 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
|
|||||||
if (!crtc || !fb)
|
if (!crtc || !fb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ((oldstate->fb == state->fb) &&
|
||||||
|
(oldstate->crtc_x == state->crtc_x) &&
|
||||||
|
(oldstate->crtc_y == state->crtc_y) &&
|
||||||
|
(oldstate->crtc_w == state->crtc_w) &&
|
||||||
|
(oldstate->crtc_h == state->crtc_h) &&
|
||||||
|
(oldstate->src_x == state->src_x) &&
|
||||||
|
(oldstate->src_y == state->src_y) &&
|
||||||
|
(oldstate->src_w == state->src_w) &&
|
||||||
|
(oldstate->src_h == state->src_h)) {
|
||||||
|
/* No change since last update, do not post cmd */
|
||||||
|
DRM_DEBUG_DRIVER("No change, not posting cmd\n");
|
||||||
|
plane->status = STI_PLANE_UPDATED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gdp->vtg) {
|
||||||
|
struct sti_compositor *compo = dev_get_drvdata(gdp->dev);
|
||||||
|
struct sti_mixer *mixer = to_sti_mixer(crtc);
|
||||||
|
|
||||||
|
/* Register gdp callback */
|
||||||
|
gdp->vtg = compo->vtg[mixer->id];
|
||||||
|
sti_vtg_register_client(gdp->vtg, &gdp->vtg_field_nb, crtc);
|
||||||
|
clk_prepare_enable(gdp->clk_pix);
|
||||||
|
}
|
||||||
|
|
||||||
mode = &crtc->mode;
|
mode = &crtc->mode;
|
||||||
dst_x = state->crtc_x;
|
dst_x = state->crtc_x;
|
||||||
dst_y = state->crtc_y;
|
dst_y = state->crtc_y;
|
||||||
|
@ -95,7 +95,6 @@
|
|||||||
#define HDMI_CFG_HDCP_EN BIT(2)
|
#define HDMI_CFG_HDCP_EN BIT(2)
|
||||||
#define HDMI_CFG_ESS_NOT_OESS BIT(3)
|
#define HDMI_CFG_ESS_NOT_OESS BIT(3)
|
||||||
#define HDMI_CFG_H_SYNC_POL_NEG BIT(4)
|
#define HDMI_CFG_H_SYNC_POL_NEG BIT(4)
|
||||||
#define HDMI_CFG_SINK_TERM_DET_EN BIT(5)
|
|
||||||
#define HDMI_CFG_V_SYNC_POL_NEG BIT(6)
|
#define HDMI_CFG_V_SYNC_POL_NEG BIT(6)
|
||||||
#define HDMI_CFG_422_EN BIT(8)
|
#define HDMI_CFG_422_EN BIT(8)
|
||||||
#define HDMI_CFG_FIFO_OVERRUN_CLR BIT(12)
|
#define HDMI_CFG_FIFO_OVERRUN_CLR BIT(12)
|
||||||
@ -159,7 +158,6 @@ struct sti_hdmi_connector {
|
|||||||
struct drm_encoder *encoder;
|
struct drm_encoder *encoder;
|
||||||
struct sti_hdmi *hdmi;
|
struct sti_hdmi *hdmi;
|
||||||
struct drm_property *colorspace_property;
|
struct drm_property *colorspace_property;
|
||||||
struct drm_property *hdmi_mode_property;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define to_sti_hdmi_connector(x) \
|
#define to_sti_hdmi_connector(x) \
|
||||||
@ -266,12 +264,9 @@ static void hdmi_config(struct sti_hdmi *hdmi)
|
|||||||
|
|
||||||
/* Select encryption type and the framing mode */
|
/* Select encryption type and the framing mode */
|
||||||
conf |= HDMI_CFG_ESS_NOT_OESS;
|
conf |= HDMI_CFG_ESS_NOT_OESS;
|
||||||
if (hdmi->hdmi_mode == HDMI_MODE_HDMI)
|
if (hdmi->hdmi_monitor)
|
||||||
conf |= HDMI_CFG_HDMI_NOT_DVI;
|
conf |= HDMI_CFG_HDMI_NOT_DVI;
|
||||||
|
|
||||||
/* Enable sink term detection */
|
|
||||||
conf |= HDMI_CFG_SINK_TERM_DET_EN;
|
|
||||||
|
|
||||||
/* Set Hsync polarity */
|
/* Set Hsync polarity */
|
||||||
if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) {
|
if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) {
|
||||||
DRM_DEBUG_DRIVER("H Sync Negative\n");
|
DRM_DEBUG_DRIVER("H Sync Negative\n");
|
||||||
@ -607,9 +602,6 @@ static void hdmi_dbg_cfg(struct seq_file *s, int val)
|
|||||||
tmp = val & HDMI_CFG_ESS_NOT_OESS;
|
tmp = val & HDMI_CFG_ESS_NOT_OESS;
|
||||||
DBGFS_PRINT_STR("HDCP mode:", tmp ? "ESS enable" : "OESS enable");
|
DBGFS_PRINT_STR("HDCP mode:", tmp ? "ESS enable" : "OESS enable");
|
||||||
seq_puts(s, "\t\t\t\t\t");
|
seq_puts(s, "\t\t\t\t\t");
|
||||||
tmp = val & HDMI_CFG_SINK_TERM_DET_EN;
|
|
||||||
DBGFS_PRINT_STR("Sink term detection:", tmp ? "enable" : "disable");
|
|
||||||
seq_puts(s, "\t\t\t\t\t");
|
|
||||||
tmp = val & HDMI_CFG_H_SYNC_POL_NEG;
|
tmp = val & HDMI_CFG_H_SYNC_POL_NEG;
|
||||||
DBGFS_PRINT_STR("Hsync polarity:", tmp ? "inverted" : "normal");
|
DBGFS_PRINT_STR("Hsync polarity:", tmp ? "inverted" : "normal");
|
||||||
seq_puts(s, "\t\t\t\t\t");
|
seq_puts(s, "\t\t\t\t\t");
|
||||||
@ -977,6 +969,11 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
|
|||||||
if (!edid)
|
if (!edid)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid);
|
||||||
|
DRM_DEBUG_KMS("%s : %dx%d cm\n",
|
||||||
|
(hdmi->hdmi_monitor ? "hdmi monitor" : "dvi monitor"),
|
||||||
|
edid->width_cm, edid->height_cm);
|
||||||
|
|
||||||
count = drm_add_edid_modes(connector, edid);
|
count = drm_add_edid_modes(connector, edid);
|
||||||
drm_mode_connector_update_edid_property(connector, edid);
|
drm_mode_connector_update_edid_property(connector, edid);
|
||||||
drm_edid_to_eld(connector, edid);
|
drm_edid_to_eld(connector, edid);
|
||||||
@ -1060,19 +1057,6 @@ static void sti_hdmi_connector_init_property(struct drm_device *drm_dev,
|
|||||||
}
|
}
|
||||||
hdmi_connector->colorspace_property = prop;
|
hdmi_connector->colorspace_property = prop;
|
||||||
drm_object_attach_property(&connector->base, prop, hdmi->colorspace);
|
drm_object_attach_property(&connector->base, prop, hdmi->colorspace);
|
||||||
|
|
||||||
/* hdmi_mode property */
|
|
||||||
hdmi->hdmi_mode = DEFAULT_HDMI_MODE;
|
|
||||||
prop = drm_property_create_enum(drm_dev, 0, "hdmi_mode",
|
|
||||||
hdmi_mode_names,
|
|
||||||
ARRAY_SIZE(hdmi_mode_names));
|
|
||||||
if (!prop) {
|
|
||||||
DRM_ERROR("fails to create colorspace property\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hdmi_connector->hdmi_mode_property = prop;
|
|
||||||
drm_object_attach_property(&connector->base, prop, hdmi->hdmi_mode);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1090,11 +1074,6 @@ sti_hdmi_connector_set_property(struct drm_connector *connector,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property == hdmi_connector->hdmi_mode_property) {
|
|
||||||
hdmi->hdmi_mode = val;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DRM_ERROR("failed to set hdmi connector property\n");
|
DRM_ERROR("failed to set hdmi connector property\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1114,11 +1093,6 @@ sti_hdmi_connector_get_property(struct drm_connector *connector,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property == hdmi_connector->hdmi_mode_property) {
|
|
||||||
*val = hdmi->hdmi_mode;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DRM_ERROR("failed to get hdmi connector property\n");
|
DRM_ERROR("failed to get hdmi connector property\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -30,19 +30,6 @@ struct hdmi_audio_params {
|
|||||||
struct hdmi_audio_infoframe cea;
|
struct hdmi_audio_infoframe cea;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* values for the framing mode property */
|
|
||||||
enum sti_hdmi_modes {
|
|
||||||
HDMI_MODE_HDMI,
|
|
||||||
HDMI_MODE_DVI,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct drm_prop_enum_list hdmi_mode_names[] = {
|
|
||||||
{ HDMI_MODE_HDMI, "hdmi" },
|
|
||||||
{ HDMI_MODE_DVI, "dvi" },
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEFAULT_HDMI_MODE HDMI_MODE_HDMI
|
|
||||||
|
|
||||||
static const struct drm_prop_enum_list colorspace_mode_names[] = {
|
static const struct drm_prop_enum_list colorspace_mode_names[] = {
|
||||||
{ HDMI_COLORSPACE_RGB, "rgb" },
|
{ HDMI_COLORSPACE_RGB, "rgb" },
|
||||||
{ HDMI_COLORSPACE_YUV422, "yuv422" },
|
{ HDMI_COLORSPACE_YUV422, "yuv422" },
|
||||||
@ -73,7 +60,7 @@ static const struct drm_prop_enum_list colorspace_mode_names[] = {
|
|||||||
* @reset: reset control of the hdmi phy
|
* @reset: reset control of the hdmi phy
|
||||||
* @ddc_adapt: i2c ddc adapter
|
* @ddc_adapt: i2c ddc adapter
|
||||||
* @colorspace: current colorspace selected
|
* @colorspace: current colorspace selected
|
||||||
* @hdmi_mode: select framing for HDMI or DVI
|
* @hdmi_monitor: true if HDMI monitor detected else DVI monitor assumed
|
||||||
* @audio_pdev: ASoC hdmi-codec platform device
|
* @audio_pdev: ASoC hdmi-codec platform device
|
||||||
* @audio: hdmi audio parameters.
|
* @audio: hdmi audio parameters.
|
||||||
* @drm_connector: hdmi connector
|
* @drm_connector: hdmi connector
|
||||||
@ -98,7 +85,7 @@ struct sti_hdmi {
|
|||||||
struct reset_control *reset;
|
struct reset_control *reset;
|
||||||
struct i2c_adapter *ddc_adapt;
|
struct i2c_adapter *ddc_adapt;
|
||||||
enum hdmi_colorspace colorspace;
|
enum hdmi_colorspace colorspace;
|
||||||
enum sti_hdmi_modes hdmi_mode;
|
bool hdmi_monitor;
|
||||||
struct platform_device *audio_pdev;
|
struct platform_device *audio_pdev;
|
||||||
struct hdmi_audio_params audio;
|
struct hdmi_audio_params audio;
|
||||||
struct drm_connector *drm_connector;
|
struct drm_connector *drm_connector;
|
||||||
|
@ -1037,9 +1037,9 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane,
|
|||||||
src_w = state->src_w >> 16;
|
src_w = state->src_w >> 16;
|
||||||
src_h = state->src_h >> 16;
|
src_h = state->src_h >> 16;
|
||||||
|
|
||||||
if (!sti_hqvdp_check_hw_scaling(hqvdp, mode,
|
if (mode->clock && !sti_hqvdp_check_hw_scaling(hqvdp, mode,
|
||||||
src_w, src_h,
|
src_w, src_h,
|
||||||
dst_w, dst_h)) {
|
dst_w, dst_h)) {
|
||||||
DRM_ERROR("Scaling beyond HW capabilities\n");
|
DRM_ERROR("Scaling beyond HW capabilities\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ enum sti_mixer_status {
|
|||||||
* @regs: mixer registers
|
* @regs: mixer registers
|
||||||
* @id: id of the mixer
|
* @id: id of the mixer
|
||||||
* @drm_crtc: crtc object link to the mixer
|
* @drm_crtc: crtc object link to the mixer
|
||||||
* @pending_event: set if a flip event is pending on crtc
|
|
||||||
* @status: to know the status of the mixer
|
* @status: to know the status of the mixer
|
||||||
*/
|
*/
|
||||||
struct sti_mixer {
|
struct sti_mixer {
|
||||||
@ -36,7 +35,6 @@ struct sti_mixer {
|
|||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
int id;
|
int id;
|
||||||
struct drm_crtc drm_crtc;
|
struct drm_crtc drm_crtc;
|
||||||
struct drm_pending_vblank_event *pending_event;
|
|
||||||
enum sti_mixer_status status;
|
enum sti_mixer_status status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "sti_vtg.h"
|
#include "sti_vtg.h"
|
||||||
|
|
||||||
#define VTG_MODE_MASTER 0
|
#define VTG_MODE_MASTER 0
|
||||||
#define VTG_MODE_SLAVE_BY_EXT0 1
|
|
||||||
|
|
||||||
/* registers offset */
|
/* registers offset */
|
||||||
#define VTG_MODE 0x0000
|
#define VTG_MODE 0x0000
|
||||||
@ -132,7 +131,6 @@ struct sti_vtg_sync_params {
|
|||||||
* @irq_status: store the IRQ status value
|
* @irq_status: store the IRQ status value
|
||||||
* @notifier_list: notifier callback
|
* @notifier_list: notifier callback
|
||||||
* @crtc: the CRTC for vblank event
|
* @crtc: the CRTC for vblank event
|
||||||
* @slave: slave vtg
|
|
||||||
* @link: List node to link the structure in lookup list
|
* @link: List node to link the structure in lookup list
|
||||||
*/
|
*/
|
||||||
struct sti_vtg {
|
struct sti_vtg {
|
||||||
@ -144,7 +142,6 @@ struct sti_vtg {
|
|||||||
u32 irq_status;
|
u32 irq_status;
|
||||||
struct raw_notifier_head notifier_list;
|
struct raw_notifier_head notifier_list;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
struct sti_vtg *slave;
|
|
||||||
struct list_head link;
|
struct list_head link;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -166,10 +163,6 @@ struct sti_vtg *of_vtg_find(struct device_node *np)
|
|||||||
|
|
||||||
static void vtg_reset(struct sti_vtg *vtg)
|
static void vtg_reset(struct sti_vtg *vtg)
|
||||||
{
|
{
|
||||||
/* reset slave and then master */
|
|
||||||
if (vtg->slave)
|
|
||||||
vtg_reset(vtg->slave);
|
|
||||||
|
|
||||||
writel(1, vtg->regs + VTG_DRST_AUTOC);
|
writel(1, vtg->regs + VTG_DRST_AUTOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,10 +252,6 @@ static void vtg_set_mode(struct sti_vtg *vtg,
|
|||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (vtg->slave)
|
|
||||||
vtg_set_mode(vtg->slave, VTG_MODE_SLAVE_BY_EXT0,
|
|
||||||
vtg->sync_params, mode);
|
|
||||||
|
|
||||||
/* Set the number of clock cycles per line */
|
/* Set the number of clock cycles per line */
|
||||||
writel(mode->htotal, vtg->regs + VTG_CLKLN);
|
writel(mode->htotal, vtg->regs + VTG_CLKLN);
|
||||||
|
|
||||||
@ -318,11 +307,7 @@ void sti_vtg_set_config(struct sti_vtg *vtg,
|
|||||||
|
|
||||||
vtg_reset(vtg);
|
vtg_reset(vtg);
|
||||||
|
|
||||||
/* enable irq for the vtg vblank synchro */
|
vtg_enable_irq(vtg);
|
||||||
if (vtg->slave)
|
|
||||||
vtg_enable_irq(vtg->slave);
|
|
||||||
else
|
|
||||||
vtg_enable_irq(vtg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -365,18 +350,12 @@ u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x)
|
|||||||
int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
|
int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb,
|
||||||
struct drm_crtc *crtc)
|
struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
if (vtg->slave)
|
|
||||||
return sti_vtg_register_client(vtg->slave, nb, crtc);
|
|
||||||
|
|
||||||
vtg->crtc = crtc;
|
vtg->crtc = crtc;
|
||||||
return raw_notifier_chain_register(&vtg->notifier_list, nb);
|
return raw_notifier_chain_register(&vtg->notifier_list, nb);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
|
int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb)
|
||||||
{
|
{
|
||||||
if (vtg->slave)
|
|
||||||
return sti_vtg_unregister_client(vtg->slave, nb);
|
|
||||||
|
|
||||||
return raw_notifier_chain_unregister(&vtg->notifier_list, nb);
|
return raw_notifier_chain_unregister(&vtg->notifier_list, nb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,29 +413,20 @@ static int vtg_probe(struct platform_device *pdev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
np = of_parse_phandle(pdev->dev.of_node, "st,slave", 0);
|
vtg->irq = platform_get_irq(pdev, 0);
|
||||||
if (np) {
|
if (vtg->irq < 0) {
|
||||||
vtg->slave = of_vtg_find(np);
|
DRM_ERROR("Failed to get VTG interrupt\n");
|
||||||
of_node_put(np);
|
return vtg->irq;
|
||||||
|
}
|
||||||
|
|
||||||
if (!vtg->slave)
|
RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list);
|
||||||
return -EPROBE_DEFER;
|
|
||||||
} else {
|
|
||||||
vtg->irq = platform_get_irq(pdev, 0);
|
|
||||||
if (vtg->irq < 0) {
|
|
||||||
DRM_ERROR("Failed to get VTG interrupt\n");
|
|
||||||
return vtg->irq;
|
|
||||||
}
|
|
||||||
|
|
||||||
RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list);
|
ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq,
|
||||||
|
vtg_irq_thread, IRQF_ONESHOT,
|
||||||
ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq,
|
dev_name(dev), vtg);
|
||||||
vtg_irq_thread, IRQF_ONESHOT,
|
if (ret < 0) {
|
||||||
dev_name(dev), vtg);
|
DRM_ERROR("Failed to register VTG interrupt\n");
|
||||||
if (ret < 0) {
|
return ret;
|
||||||
DRM_ERROR("Failed to register VTG interrupt\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vtg_register(vtg);
|
vtg_register(vtg);
|
||||||
|
Loading…
Reference in New Issue
Block a user