提交 72d45a76 编写于 作者: D Dave Airlie

Merge tag 'omapdrm-4.14-fixes' of...

Merge tag 'omapdrm-4.14-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux into drm-next

omapdrm fixes for 4.14

* fix compilation when compiling omapfb driver
* WA for OMAP3 endless sync lost issue
* WA for OMAP5 DSI PLL issue
* fix analog TV out modecheck

* tag 'omapdrm-4.14-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux:
  ARM: OMAP2+: fix missing variable declaration
  drm/omap: work-around for omap3 display enable
  drm/omap: fix i886 work-around
  drm/omap: fix analog tv-out modecheck
......@@ -172,6 +172,7 @@ static int __init omapdss_init_fbdev(void)
.set_min_bus_tput = omap_dss_set_min_bus_tput,
};
struct device_node *node;
int r;
board_data.version = omap_display_get_version();
if (board_data.version == OMAPDSS_VER_UNKNOWN) {
......
......@@ -185,6 +185,9 @@ struct dss_pll_hw {
bool has_freqsel;
bool has_selfreqdco;
bool has_refsel;
/* DRA7 errata i886: use high N & M to avoid jitter */
bool errata_i886;
};
struct dss_pll {
......
......@@ -215,8 +215,8 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
dss_pll_calc_func func, void *data)
{
const struct dss_pll_hw *hw = pll->hw;
int n, n_min, n_max;
int m, m_min, m_max;
int n, n_start, n_stop, n_inc;
int m, m_start, m_stop, m_inc;
unsigned long fint, clkdco;
unsigned long pll_hw_max;
unsigned long fint_hw_min, fint_hw_max;
......@@ -226,22 +226,33 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
fint_hw_min = hw->fint_min;
fint_hw_max = hw->fint_max;
n_min = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
n_max = min((unsigned)(clkin / fint_hw_min), hw->n_max);
n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max);
n_inc = 1;
if (hw->errata_i886) {
swap(n_start, n_stop);
n_inc = -1;
}
pll_max = pll_max ? pll_max : ULONG_MAX;
/* Try to find high N & M to avoid jitter (DRA7 errata i886) */
for (n = n_max; n >= n_min; --n) {
for (n = n_start; n != n_stop; n += n_inc) {
fint = clkin / n;
m_min = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
m_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
1ul);
m_max = min3((unsigned)(pll_max / fint / 2),
m_stop = min3((unsigned)(pll_max / fint / 2),
(unsigned)(pll_hw_max / fint / 2),
hw->m_max);
m_inc = 1;
if (hw->errata_i886) {
swap(m_start, m_stop);
m_inc = -1;
}
for (m = m_max; m >= m_min; --m) {
for (m = m_start; m != m_stop; m += m_inc) {
clkdco = 2 * m * fint;
if (func(n, m, fint, clkdco, data))
......
......@@ -263,6 +263,12 @@ static const struct venc_config venc_config_pal_bdghi = {
.fid_ext_start_y__fid_ext_offset_y = 0x01380005,
};
enum venc_videomode {
VENC_MODE_UNKNOWN,
VENC_MODE_PAL,
VENC_MODE_NTSC,
};
static const struct videomode omap_dss_pal_vm = {
.hactive = 720,
.vactive = 574,
......@@ -297,6 +303,24 @@ static const struct videomode omap_dss_ntsc_vm = {
DISPLAY_FLAGS_SYNC_NEGEDGE,
};
static enum venc_videomode venc_get_videomode(const struct videomode *vm)
{
if (!(vm->flags & DISPLAY_FLAGS_INTERLACED))
return VENC_MODE_UNKNOWN;
if (vm->pixelclock == omap_dss_pal_vm.pixelclock &&
vm->hactive == omap_dss_pal_vm.hactive &&
vm->vactive == omap_dss_pal_vm.vactive)
return VENC_MODE_PAL;
if (vm->pixelclock == omap_dss_ntsc_vm.pixelclock &&
vm->hactive == omap_dss_ntsc_vm.hactive &&
vm->vactive == omap_dss_ntsc_vm.vactive)
return VENC_MODE_NTSC;
return VENC_MODE_UNKNOWN;
}
static struct {
struct platform_device *pdev;
void __iomem *base;
......@@ -423,14 +447,14 @@ static void venc_runtime_put(void)
static const struct venc_config *venc_timings_to_config(struct videomode *vm)
{
if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0)
switch (venc_get_videomode(vm)) {
default:
WARN_ON_ONCE(1);
case VENC_MODE_PAL:
return &venc_config_pal_trm;
if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0)
case VENC_MODE_NTSC:
return &venc_config_ntsc_trm;
BUG();
return NULL;
}
}
static int venc_power_on(struct omap_dss_device *dssdev)
......@@ -541,15 +565,28 @@ static void venc_display_disable(struct omap_dss_device *dssdev)
static void venc_set_timings(struct omap_dss_device *dssdev,
struct videomode *vm)
{
struct videomode actual_vm;
DSSDBG("venc_set_timings\n");
mutex_lock(&venc.venc_lock);
switch (venc_get_videomode(vm)) {
default:
WARN_ON_ONCE(1);
case VENC_MODE_PAL:
actual_vm = omap_dss_pal_vm;
break;
case VENC_MODE_NTSC:
actual_vm = omap_dss_ntsc_vm;
break;
}
/* Reset WSS data when the TV standard changes. */
if (memcmp(&venc.vm, vm, sizeof(*vm)))
if (memcmp(&venc.vm, &actual_vm, sizeof(actual_vm)))
venc.wss_data = 0;
venc.vm = *vm;
venc.vm = actual_vm;
dispc_set_tv_pclk(13500000);
......@@ -561,13 +598,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
{
DSSDBG("venc_check_timings\n");
if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0)
switch (venc_get_videomode(vm)) {
case VENC_MODE_PAL:
case VENC_MODE_NTSC:
return 0;
if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0)
return 0;
return -EINVAL;
default:
return -EINVAL;
}
}
static void venc_get_timings(struct omap_dss_device *dssdev,
......
......@@ -130,6 +130,8 @@ static const struct dss_pll_hw dss_dra7_video_pll_hw = {
.mX_lsb[3] = 5,
.has_refsel = true,
.errata_i886 = true,
};
struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id,
......
......@@ -84,23 +84,36 @@ static void omap_atomic_commit_tail(struct drm_atomic_state *old_state)
/* Apply the atomic update. */
drm_atomic_helper_commit_modeset_disables(dev, old_state);
/* With the current dss dispc implementation we have to enable
* the new modeset before we can commit planes. The dispc ovl
* configuration relies on the video mode configuration been
* written into the HW when the ovl configuration is
* calculated.
*
* This approach is not ideal because after a mode change the
* plane update is executed only after the first vblank
* interrupt. The dispc implementation should be fixed so that
* it is able use uncommitted drm state information.
*/
drm_atomic_helper_commit_modeset_enables(dev, old_state);
omap_atomic_wait_for_completion(dev, old_state);
drm_atomic_helper_commit_planes(dev, old_state, 0);
drm_atomic_helper_commit_hw_done(old_state);
if (priv->omaprev != 0x3430) {
/* With the current dss dispc implementation we have to enable
* the new modeset before we can commit planes. The dispc ovl
* configuration relies on the video mode configuration been
* written into the HW when the ovl configuration is
* calculated.
*
* This approach is not ideal because after a mode change the
* plane update is executed only after the first vblank
* interrupt. The dispc implementation should be fixed so that
* it is able use uncommitted drm state information.
*/
drm_atomic_helper_commit_modeset_enables(dev, old_state);
omap_atomic_wait_for_completion(dev, old_state);
drm_atomic_helper_commit_planes(dev, old_state, 0);
drm_atomic_helper_commit_hw_done(old_state);
} else {
/*
* OMAP3 DSS seems to have issues with the work-around above,
* resulting in endless sync losts if a crtc is enabled without
* a plane. For now, skip the WA for OMAP3.
*/
drm_atomic_helper_commit_planes(dev, old_state, 0);
drm_atomic_helper_commit_modeset_enables(dev, old_state);
drm_atomic_helper_commit_hw_done(old_state);
}
/*
* Wait for completion of the page flips to ensure that old buffers
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册