-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Drop the msm_connector base class, and special calls to base class methods from the encoder, and use instead drm_bridge. This allows for a cleaner division between the hdmi (and in future dsi) blocks, from the mdp block. Signed-off-by: Rob Clark <robdclark@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
- Loading branch information
Rob Clark
authored and
Dave Airlie
committed
Sep 2, 2013
1 parent
3b336ec
commit a3376e3
Showing
10 changed files
with
274 additions
and
260 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
/* | ||
* Copyright (C) 2013 Red Hat | ||
* Author: Rob Clark <robdclark@gmail.com> | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 as published by | ||
* the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
* more details. | ||
* | ||
* You should have received a copy of the GNU General Public License along with | ||
* this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include "hdmi.h" | ||
|
||
struct hdmi_bridge { | ||
struct drm_bridge base; | ||
|
||
struct hdmi *hdmi; | ||
|
||
unsigned long int pixclock; | ||
}; | ||
#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base) | ||
|
||
static void hdmi_bridge_destroy(struct drm_bridge *bridge) | ||
{ | ||
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | ||
hdmi_unreference(hdmi_bridge->hdmi); | ||
drm_bridge_cleanup(bridge); | ||
kfree(hdmi_bridge); | ||
} | ||
|
||
static void hdmi_bridge_pre_enable(struct drm_bridge *bridge) | ||
{ | ||
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | ||
struct hdmi *hdmi = hdmi_bridge->hdmi; | ||
struct hdmi_phy *phy = hdmi->phy; | ||
|
||
DBG("power up"); | ||
phy->funcs->powerup(phy, hdmi_bridge->pixclock); | ||
hdmi_set_mode(hdmi, true); | ||
} | ||
|
||
static void hdmi_bridge_enable(struct drm_bridge *bridge) | ||
{ | ||
} | ||
|
||
static void hdmi_bridge_disable(struct drm_bridge *bridge) | ||
{ | ||
} | ||
|
||
static void hdmi_bridge_post_disable(struct drm_bridge *bridge) | ||
{ | ||
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | ||
struct hdmi *hdmi = hdmi_bridge->hdmi; | ||
struct hdmi_phy *phy = hdmi->phy; | ||
|
||
DBG("power down"); | ||
hdmi_set_mode(hdmi, false); | ||
phy->funcs->powerdown(phy); | ||
} | ||
|
||
static void hdmi_bridge_mode_set(struct drm_bridge *bridge, | ||
struct drm_display_mode *mode, | ||
struct drm_display_mode *adjusted_mode) | ||
{ | ||
struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); | ||
struct hdmi *hdmi = hdmi_bridge->hdmi; | ||
int hstart, hend, vstart, vend; | ||
uint32_t frame_ctrl; | ||
|
||
mode = adjusted_mode; | ||
|
||
hdmi_bridge->pixclock = mode->clock * 1000; | ||
|
||
hdmi->hdmi_mode = drm_match_cea_mode(mode) > 1; | ||
|
||
hstart = mode->htotal - mode->hsync_start; | ||
hend = mode->htotal - mode->hsync_start + mode->hdisplay; | ||
|
||
vstart = mode->vtotal - mode->vsync_start - 1; | ||
vend = mode->vtotal - mode->vsync_start + mode->vdisplay - 1; | ||
|
||
DBG("htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d", | ||
mode->htotal, mode->vtotal, hstart, hend, vstart, vend); | ||
|
||
hdmi_write(hdmi, REG_HDMI_TOTAL, | ||
HDMI_TOTAL_H_TOTAL(mode->htotal - 1) | | ||
HDMI_TOTAL_V_TOTAL(mode->vtotal - 1)); | ||
|
||
hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC, | ||
HDMI_ACTIVE_HSYNC_START(hstart) | | ||
HDMI_ACTIVE_HSYNC_END(hend)); | ||
hdmi_write(hdmi, REG_HDMI_ACTIVE_VSYNC, | ||
HDMI_ACTIVE_VSYNC_START(vstart) | | ||
HDMI_ACTIVE_VSYNC_END(vend)); | ||
|
||
if (mode->flags & DRM_MODE_FLAG_INTERLACE) { | ||
hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2, | ||
HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal)); | ||
hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2, | ||
HDMI_VSYNC_ACTIVE_F2_START(vstart + 1) | | ||
HDMI_VSYNC_ACTIVE_F2_END(vend + 1)); | ||
} else { | ||
hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2, | ||
HDMI_VSYNC_TOTAL_F2_V_TOTAL(0)); | ||
hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2, | ||
HDMI_VSYNC_ACTIVE_F2_START(0) | | ||
HDMI_VSYNC_ACTIVE_F2_END(0)); | ||
} | ||
|
||
frame_ctrl = 0; | ||
if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
frame_ctrl |= HDMI_FRAME_CTRL_HSYNC_LOW; | ||
if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
frame_ctrl |= HDMI_FRAME_CTRL_VSYNC_LOW; | ||
if (mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN; | ||
DBG("frame_ctrl=%08x", frame_ctrl); | ||
hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl); | ||
|
||
// TODO until we have audio, this might be safest: | ||
if (hdmi->hdmi_mode) | ||
hdmi_write(hdmi, REG_HDMI_GC, HDMI_GC_MUTE); | ||
} | ||
|
||
static const struct drm_bridge_funcs hdmi_bridge_funcs = { | ||
.pre_enable = hdmi_bridge_pre_enable, | ||
.enable = hdmi_bridge_enable, | ||
.disable = hdmi_bridge_disable, | ||
.post_disable = hdmi_bridge_post_disable, | ||
.mode_set = hdmi_bridge_mode_set, | ||
.destroy = hdmi_bridge_destroy, | ||
}; | ||
|
||
|
||
/* initialize bridge */ | ||
struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi) | ||
{ | ||
struct drm_bridge *bridge = NULL; | ||
struct hdmi_bridge *hdmi_bridge; | ||
int ret; | ||
|
||
hdmi_bridge = kzalloc(sizeof(*hdmi_bridge), GFP_KERNEL); | ||
if (!hdmi_bridge) { | ||
ret = -ENOMEM; | ||
goto fail; | ||
} | ||
|
||
hdmi_bridge->hdmi = hdmi_reference(hdmi); | ||
|
||
bridge = &hdmi_bridge->base; | ||
|
||
drm_bridge_init(hdmi->dev, bridge, &hdmi_bridge_funcs); | ||
|
||
return bridge; | ||
|
||
fail: | ||
if (bridge) | ||
hdmi_bridge_destroy(bridge); | ||
|
||
return ERR_PTR(ret); | ||
} |
Oops, something went wrong.