Commit 72d45a76 authored by Dave Airlie's avatar 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
parents cfcfb65a d1bbc823
...@@ -172,6 +172,7 @@ static int __init omapdss_init_fbdev(void) ...@@ -172,6 +172,7 @@ static int __init omapdss_init_fbdev(void)
.set_min_bus_tput = omap_dss_set_min_bus_tput, .set_min_bus_tput = omap_dss_set_min_bus_tput,
}; };
struct device_node *node; struct device_node *node;
int r;
board_data.version = omap_display_get_version(); board_data.version = omap_display_get_version();
if (board_data.version == OMAPDSS_VER_UNKNOWN) { if (board_data.version == OMAPDSS_VER_UNKNOWN) {
......
...@@ -185,6 +185,9 @@ struct dss_pll_hw { ...@@ -185,6 +185,9 @@ struct dss_pll_hw {
bool has_freqsel; bool has_freqsel;
bool has_selfreqdco; bool has_selfreqdco;
bool has_refsel; bool has_refsel;
/* DRA7 errata i886: use high N & M to avoid jitter */
bool errata_i886;
}; };
struct dss_pll { struct dss_pll {
......
...@@ -215,8 +215,8 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin, ...@@ -215,8 +215,8 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
dss_pll_calc_func func, void *data) dss_pll_calc_func func, void *data)
{ {
const struct dss_pll_hw *hw = pll->hw; const struct dss_pll_hw *hw = pll->hw;
int n, n_min, n_max; int n, n_start, n_stop, n_inc;
int m, m_min, m_max; int m, m_start, m_stop, m_inc;
unsigned long fint, clkdco; unsigned long fint, clkdco;
unsigned long pll_hw_max; unsigned long pll_hw_max;
unsigned long fint_hw_min, fint_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, ...@@ -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_min = hw->fint_min;
fint_hw_max = hw->fint_max; fint_hw_max = hw->fint_max;
n_min = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
n_max = min((unsigned)(clkin / fint_hw_min), hw->n_max); 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; pll_max = pll_max ? pll_max : ULONG_MAX;
/* Try to find high N & M to avoid jitter (DRA7 errata i886) */ for (n = n_start; n != n_stop; n += n_inc) {
for (n = n_max; n >= n_min; --n) {
fint = clkin / n; 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); 1ul);
m_max = min3((unsigned)(pll_max / fint / 2), m_stop = min3((unsigned)(pll_max / fint / 2),
(unsigned)(pll_hw_max / fint / 2), (unsigned)(pll_hw_max / fint / 2),
hw->m_max); 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; clkdco = 2 * m * fint;
if (func(n, m, fint, clkdco, data)) if (func(n, m, fint, clkdco, data))
......
...@@ -263,6 +263,12 @@ static const struct venc_config venc_config_pal_bdghi = { ...@@ -263,6 +263,12 @@ static const struct venc_config venc_config_pal_bdghi = {
.fid_ext_start_y__fid_ext_offset_y = 0x01380005, .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 = { static const struct videomode omap_dss_pal_vm = {
.hactive = 720, .hactive = 720,
.vactive = 574, .vactive = 574,
...@@ -297,6 +303,24 @@ static const struct videomode omap_dss_ntsc_vm = { ...@@ -297,6 +303,24 @@ static const struct videomode omap_dss_ntsc_vm = {
DISPLAY_FLAGS_SYNC_NEGEDGE, 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 { static struct {
struct platform_device *pdev; struct platform_device *pdev;
void __iomem *base; void __iomem *base;
...@@ -423,14 +447,14 @@ static void venc_runtime_put(void) ...@@ -423,14 +447,14 @@ static void venc_runtime_put(void)
static const struct venc_config *venc_timings_to_config(struct videomode *vm) 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; return &venc_config_pal_trm;
case VENC_MODE_NTSC:
if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0)
return &venc_config_ntsc_trm; return &venc_config_ntsc_trm;
}
BUG();
return NULL;
} }
static int venc_power_on(struct omap_dss_device *dssdev) static int venc_power_on(struct omap_dss_device *dssdev)
...@@ -541,15 +565,28 @@ static void venc_display_disable(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, static void venc_set_timings(struct omap_dss_device *dssdev,
struct videomode *vm) struct videomode *vm)
{ {
struct videomode actual_vm;
DSSDBG("venc_set_timings\n"); DSSDBG("venc_set_timings\n");
mutex_lock(&venc.venc_lock); 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. */ /* 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.wss_data = 0;
venc.vm = *vm; venc.vm = actual_vm;
dispc_set_tv_pclk(13500000); dispc_set_tv_pclk(13500000);
...@@ -561,13 +598,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev, ...@@ -561,13 +598,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
{ {
DSSDBG("venc_check_timings\n"); 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; return 0;
default:
if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0) return -EINVAL;
return 0; }
return -EINVAL;
} }
static void venc_get_timings(struct omap_dss_device *dssdev, 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 = { ...@@ -130,6 +130,8 @@ static const struct dss_pll_hw dss_dra7_video_pll_hw = {
.mX_lsb[3] = 5, .mX_lsb[3] = 5,
.has_refsel = true, .has_refsel = true,
.errata_i886 = true,
}; };
struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id, 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) ...@@ -84,23 +84,36 @@ static void omap_atomic_commit_tail(struct drm_atomic_state *old_state)
/* Apply the atomic update. */ /* Apply the atomic update. */
drm_atomic_helper_commit_modeset_disables(dev, old_state); drm_atomic_helper_commit_modeset_disables(dev, old_state);
/* With the current dss dispc implementation we have to enable if (priv->omaprev != 0x3430) {
* the new modeset before we can commit planes. The dispc ovl /* With the current dss dispc implementation we have to enable
* configuration relies on the video mode configuration been * the new modeset before we can commit planes. The dispc ovl
* written into the HW when the ovl configuration is * configuration relies on the video mode configuration been
* calculated. * 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 * This approach is not ideal because after a mode change the
* interrupt. The dispc implementation should be fixed so that * plane update is executed only after the first vblank
* it is able use uncommitted drm state information. * 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_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_planes(dev, old_state, 0);
drm_atomic_helper_commit_hw_done(old_state);
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 * Wait for completion of the page flips to ensure that old buffers
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment