Skip to content

Commit

Permalink
Merge tag 'fbdev-4.1' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/tomba/linux

Pull fbdev updates from Tomi Valkeinen:
 "Small fixes and improvements to various fbdev drivers"

* tag 'fbdev-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux: (24 commits)
  omapdss: extend pm notifier to handle hibernation
  OMAPDSS: Correct video ports description file path in DT binding doc
  OMAPDSS: disable VT switch
  fbdev: sh_mobile_lcdc: Fix destruction of uninitialized mutex
  video: fbdev: sh_mobile_lcdcfb: Fix ROP3 sysfs attribute parsing
  fbdev: pm3fb: cleanup some confusing indenting
  hyperv: hyperv_fb: match wait_for_completion_timeout return type
  video: fbdev: use msecs_to_jiffies for time conversions
  fbdev: via/via_clock: fix sparse warning
  video: fbdev: make of_device_id array const
  fbdev: sm501fb: use memset_io
  OMAPDSS: workaround for MFLAG + NV12 issue
  OMAPDSS: Add support for MFLAG
  OMAPDSS: setup default fifo thresholds
  OMAPDSS: DISPC: lock access to DISPC_CONTROL & DISPC_CONFIG
  OMAPDSS: DISPC: fix div by zero issue in overlay scaling
  OMAPDSS: DISPC: change sync_pclk_edge default value
  OMAPDSS: change signal_level & signal_edge enum values
  OMAPDSS: DISPC: explicit handling for sync and de levels
  OMAPDSS: DISPC: remove OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES
  ...
  • Loading branch information
torvalds committed Apr 20, 2015
2 parents 14aa024 + 6b75b54 commit bf2ae5d
Show file tree
Hide file tree
Showing 26 changed files with 193 additions and 50 deletions.
4 changes: 2 additions & 2 deletions Documentation/devicetree/bindings/video/ti,omap-dss.txt
Expand Up @@ -25,8 +25,8 @@ Video Ports
-----------

The DSS Core and the encoders have video port outputs. The structure of the
video ports is described in Documentation/devicetree/bindings/video/video-
ports.txt, and the properties for the ports and endpoints for each encoder are
video ports is described in Documentation/devicetree/bindings/graph.txt,
and the properties for the ports and endpoints for each encoder are
described in the SoC's DSS binding documentation.

The video ports are used to describe the connections to external hardware, like
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/omapdrm/omap_connector.c
Expand Up @@ -102,7 +102,7 @@ void copy_timings_drm_to_omap(struct omap_video_timings *timings,

timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
}

static enum drm_connector_status omap_connector_detect(
Expand Down
6 changes: 4 additions & 2 deletions drivers/video/fbdev/hyperv_fb.c
Expand Up @@ -415,7 +415,8 @@ static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver)
struct fb_info *info = hv_get_drvdata(hdev);
struct hvfb_par *par = info->par;
struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
int t, ret = 0;
int ret = 0;
unsigned long t;

memset(msg, 0, sizeof(struct synthvid_msg));
msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST;
Expand Down Expand Up @@ -488,7 +489,8 @@ static int synthvid_send_config(struct hv_device *hdev)
struct fb_info *info = hv_get_drvdata(hdev);
struct hvfb_par *par = info->par;
struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf;
int t, ret = 0;
int ret = 0;
unsigned long t;

/* Send VRAM location */
memset(msg, 0, sizeof(struct synthvid_msg));
Expand Down
2 changes: 1 addition & 1 deletion drivers/video/fbdev/imxfb.c
Expand Up @@ -183,7 +183,7 @@ static struct platform_device_id imxfb_devtype[] = {
};
MODULE_DEVICE_TABLE(platform, imxfb_devtype);

static struct of_device_id imxfb_of_dev_id[] = {
static const struct of_device_id imxfb_of_dev_id[] = {
{
.compatible = "fsl,imx1-fb",
.data = &imxfb_devtype[IMX1_FB],
Expand Down
2 changes: 1 addition & 1 deletion drivers/video/fbdev/omap2/displays-new/connector-dvi.c
Expand Up @@ -37,7 +37,7 @@ static const struct omap_video_timings dvic_default_timings = {
.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
};

struct panel_drv_data {
Expand Down
11 changes: 11 additions & 0 deletions drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
Expand Up @@ -114,12 +114,21 @@ static void tfp410_disable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
}

static void tfp410_fix_timings(struct omap_video_timings *timings)
{
timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
}

static void tfp410_set_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;

tfp410_fix_timings(timings);

ddata->timings = *timings;
dssdev->panel.timings = *timings;

Expand All @@ -140,6 +149,8 @@ static int tfp410_check_timings(struct omap_dss_device *dssdev,
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;

tfp410_fix_timings(timings);

return in->ops.dpi->check_timings(in, timings);
}

Expand Down
Expand Up @@ -37,7 +37,7 @@ static struct omap_video_timings lb035q02_timings = {
.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
};

struct panel_drv_data {
Expand Down
Expand Up @@ -54,7 +54,7 @@ static const struct omap_video_timings sharp_ls_timings = {
.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
};

#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
Expand Down
Expand Up @@ -108,7 +108,7 @@ static const struct omap_video_timings acx565akm_panel_timings = {

.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
};

#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
Expand Down
Expand Up @@ -58,7 +58,7 @@ static struct omap_video_timings td028ttec1_panel_timings = {

.data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
};

#define JBT_COMMAND 0x000
Expand Down
Expand Up @@ -91,7 +91,7 @@ static const struct omap_video_timings tpo_td043_timings = {
.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
.data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
};

#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
Expand Down
4 changes: 4 additions & 0 deletions drivers/video/fbdev/omap2/dss/core.c
Expand Up @@ -179,10 +179,14 @@ static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)

switch (v) {
case PM_SUSPEND_PREPARE:
case PM_HIBERNATION_PREPARE:
case PM_RESTORE_PREPARE:
DSSDBG("suspending displays\n");
return dss_suspend_all_devices();

case PM_POST_SUSPEND:
case PM_POST_HIBERNATION:
case PM_POST_RESTORE:
DSSDBG("resuming displays\n");
return dss_resume_all_devices();

Expand Down
147 changes: 135 additions & 12 deletions drivers/video/fbdev/omap2/dss/dispc.c
Expand Up @@ -123,6 +123,9 @@ static struct {

struct regmap *syscon_pol;
u32 syscon_pol_offset;

/* DISPC_CONTROL & DISPC_CONFIG lock*/
spinlock_t control_lock;
} dispc;

enum omap_color_component {
Expand Down Expand Up @@ -261,7 +264,16 @@ static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld)
static void mgr_fld_write(enum omap_channel channel,
enum mgr_reg_fields regfld, int val) {
const struct dispc_reg_field rfld = mgr_desc[channel].reg_desc[regfld];
const bool need_lock = rfld.reg == DISPC_CONTROL || rfld.reg == DISPC_CONFIG;
unsigned long flags;

if (need_lock)
spin_lock_irqsave(&dispc.control_lock, flags);

REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);

if (need_lock)
spin_unlock_irqrestore(&dispc.control_lock, flags);
}

#define SR(reg) \
Expand Down Expand Up @@ -1126,6 +1138,7 @@ static void dispc_init_fifos(void)
int fifo;
u8 start, end;
u32 unit;
int i;

unit = dss_feat_get_buffer_size_unit();

Expand Down Expand Up @@ -1165,6 +1178,20 @@ static void dispc_init_fifos(void)
dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
}

/*
* Setup default fifo thresholds.
*/
for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
u32 low, high;
const bool use_fifomerge = false;
const bool manual_update = false;

dispc_ovl_compute_fifo_thresholds(i, &low, &high,
use_fifomerge, manual_update);

dispc_ovl_set_fifo_threshold(i, low, high);
}
}

static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
Expand Down Expand Up @@ -1278,6 +1305,63 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
}
EXPORT_SYMBOL(dispc_ovl_compute_fifo_thresholds);

static void dispc_ovl_set_mflag(enum omap_plane plane, bool enable)
{
int bit;

if (plane == OMAP_DSS_GFX)
bit = 14;
else
bit = 23;

REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
}

static void dispc_ovl_set_mflag_threshold(enum omap_plane plane,
int low, int high)
{
dispc_write_reg(DISPC_OVL_MFLAG_THRESHOLD(plane),
FLD_VAL(high, 31, 16) | FLD_VAL(low, 15, 0));
}

static void dispc_init_mflag(void)
{
int i;

/*
* HACK: NV12 color format and MFLAG seem to have problems working
* together: using two displays, and having an NV12 overlay on one of
* the displays will cause underflows/synclosts when MFLAG_CTRL=2.
* Changing MFLAG thresholds and PRELOAD to certain values seem to
* remove the errors, but there doesn't seem to be a clear logic on
* which values work and which not.
*
* As a work-around, set force MFLAG to always on.
*/
dispc_write_reg(DISPC_GLOBAL_MFLAG_ATTRIBUTE,
(1 << 0) | /* MFLAG_CTRL = force always on */
(0 << 2)); /* MFLAG_START = disable */

for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
u32 size = dispc_ovl_get_fifo_size(i);
u32 unit = dss_feat_get_buffer_size_unit();
u32 low, high;

dispc_ovl_set_mflag(i, true);

/*
* Simulation team suggests below thesholds:
* HT = fifosize * 5 / 8;
* LT = fifosize * 4 / 8;
*/

low = size * 4 / 8 / unit;
high = size * 5 / 8 / unit;

dispc_ovl_set_mflag_threshold(i, low, high);
}
}

static void dispc_ovl_set_fir(enum omap_plane plane,
int hinc, int vinc,
enum omap_color_component color_comp)
Expand Down Expand Up @@ -2322,6 +2406,11 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
if (width == out_width && height == out_height)
return 0;

if (pclk == 0 || mgr_timings->pixelclock == 0) {
DSSERR("cannot calculate scaling settings: pclk is zero\n");
return -EINVAL;
}

if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
return -EINVAL;

Expand Down Expand Up @@ -2441,7 +2530,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
unsigned long pclk = dispc_plane_pclk_rate(plane);
unsigned long lclk = dispc_plane_lclk_rate(plane);

if (paddr == 0)
if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER)
return -EINVAL;

out_width = out_width == 0 ? width : out_width;
Expand Down Expand Up @@ -2915,7 +3004,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,

{
u32 timing_h, timing_v, l;
bool onoff, rf, ipc;
bool onoff, rf, ipc, vs, hs, de;

timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
Expand All @@ -2927,29 +3016,58 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
dispc_write_reg(DISPC_TIMING_V(channel), timing_v);

switch (vsync_level) {
case OMAPDSS_SIG_ACTIVE_LOW:
vs = true;
break;
case OMAPDSS_SIG_ACTIVE_HIGH:
vs = false;
break;
default:
BUG();
}

switch (hsync_level) {
case OMAPDSS_SIG_ACTIVE_LOW:
hs = true;
break;
case OMAPDSS_SIG_ACTIVE_HIGH:
hs = false;
break;
default:
BUG();
}

switch (de_level) {
case OMAPDSS_SIG_ACTIVE_LOW:
de = true;
break;
case OMAPDSS_SIG_ACTIVE_HIGH:
de = false;
break;
default:
BUG();
}

switch (data_pclk_edge) {
case OMAPDSS_DRIVE_SIG_RISING_EDGE:
ipc = false;
break;
case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
ipc = true;
break;
case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
default:
BUG();
}

/* always use the 'rf' setting */
onoff = true;

switch (sync_pclk_edge) {
case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
onoff = false;
rf = false;
break;
case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
onoff = true;
rf = false;
break;
case OMAPDSS_DRIVE_SIG_RISING_EDGE:
onoff = true;
rf = true;
break;
default:
Expand All @@ -2958,10 +3076,10 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,

l = FLD_VAL(onoff, 17, 17) |
FLD_VAL(rf, 16, 16) |
FLD_VAL(de_level, 15, 15) |
FLD_VAL(de, 15, 15) |
FLD_VAL(ipc, 14, 14) |
FLD_VAL(hsync_level, 13, 13) |
FLD_VAL(vsync_level, 12, 12);
FLD_VAL(hs, 13, 13) |
FLD_VAL(vs, 12, 12);

dispc_write_reg(DISPC_POL_FREQ(channel), l);

Expand Down Expand Up @@ -3569,6 +3687,9 @@ static void _omap_dispc_initial_config(void)

if (dispc.feat->mstandby_workaround)
REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0);

if (dss_has_feature(FEAT_MFLAG))
dispc_init_mflag();
}

static const struct dispc_features omap24xx_dispc_feats __initconst = {
Expand Down Expand Up @@ -3770,6 +3891,8 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)

dispc.pdev = pdev;

spin_lock_init(&dispc.control_lock);

r = dispc_init_features(dispc.pdev);
if (r)
return r;
Expand Down

0 comments on commit bf2ae5d

Please sign in to comment.