summaryrefslogtreecommitdiff
path: root/drivers/video/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra')
-rw-r--r--drivers/video/tegra/dc/dc.c6
-rw-r--r--drivers/video/tegra/dc/dc_priv.h6
-rw-r--r--drivers/video/tegra/dc/ext/dev.c32
-rw-r--r--drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h2
-rw-r--r--drivers/video/tegra/dc/hdmi.c13
-rw-r--r--drivers/video/tegra/dc/mode.c285
-rw-r--r--drivers/video/tegra/dc/nvhdcp.c2
-rw-r--r--drivers/video/tegra/dc/window.c15
-rw-r--r--drivers/video/tegra/fb.c343
-rw-r--r--drivers/video/tegra/host/bus_client.c3
-rw-r--r--drivers/video/tegra/host/nvhost_acm.c2
-rw-r--r--drivers/video/tegra/host/nvhost_syncpt.c3
-rw-r--r--drivers/video/tegra/nvmap/nvmap.c6
-rw-r--r--drivers/video/tegra/nvmap/nvmap_dev.c3
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c3
15 files changed, 589 insertions, 135 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index bfd916e0e16e..d4c3f8bc9a49 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -1067,9 +1067,11 @@ static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status)
queue_work(system_freezable_wq, &dc->vblank_work);
if (status & FRAME_END_INT) {
+#ifndef CONFIG_ANDROID
struct timespec tm = CURRENT_TIME;
dc->frame_end_timestamp = timespec_to_ns(&tm);
wake_up(&dc->timestamp_wq);
+#endif /* !CONFIG_ANDROID */
/* Mark the frame_end as complete. */
if (!completion_done(&dc->frame_end_complete))
@@ -1079,6 +1081,7 @@ static void tegra_dc_continuous_irq(struct tegra_dc *dc, unsigned long status)
}
}
+#ifndef CONFIG_ANDROID
/* XXX: Not sure if we limit look ahead to 1 frame */
bool tegra_dc_is_within_n_vsync(struct tegra_dc *dc, s64 ts)
{
@@ -1094,6 +1097,7 @@ bool tegra_dc_does_vsync_separate(struct tegra_dc *dc, s64 new_ts, s64 old_ts)
!= div_s64((old_ts - dc->frame_end_timestamp),
dc->frametime_ns)));
}
+#endif /* !CONFIG_ANDROID */
#endif
static irqreturn_t tegra_dc_irq(int irq, void *ptr)
@@ -1781,7 +1785,9 @@ static int tegra_dc_probe(struct nvhost_device *ndev,
mutex_init(&dc->one_shot_lock);
init_completion(&dc->frame_end_complete);
init_waitqueue_head(&dc->wq);
+#ifndef CONFIG_ANDROID
init_waitqueue_head(&dc->timestamp_wq);
+#endif /* !CONFIG_ANDROID */
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
INIT_WORK(&dc->reset_work, tegra_dc_reset_worker);
#endif
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index 75c3a2a29658..e91071f70ddc 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -113,14 +113,18 @@ struct tegra_dc {
void *out_data;
struct tegra_dc_mode mode;
+#ifndef CONFIG_ANDROID
s64 frametime_ns;
+#endif /* !CONFIG_ANDROID */
struct tegra_dc_win windows[DC_N_WINDOWS];
struct tegra_dc_blend blend;
int n_windows;
wait_queue_head_t wq;
+#ifndef CONFIG_ANDROID
wait_queue_head_t timestamp_wq;
+#endif /* !CONFIG_ANDROID */
struct mutex lock;
struct mutex one_shot_lock;
@@ -165,7 +169,9 @@ struct tegra_dc {
struct delayed_work underflow_work;
u32 one_shot_delay_ms;
struct delayed_work one_shot_work;
+#ifndef CONFIG_ANDROID
s64 frame_end_timestamp;
+#endif /* !CONFIG_ANDROID */
};
#define print_mode_info(dc, mode) do { \
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index 88273e26c51c..37a6d9bd3f80 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -56,7 +56,9 @@ struct tegra_dc_ext_flip_data {
struct tegra_dc_ext *ext;
struct work_struct work;
struct tegra_dc_ext_flip_win win[DC_N_WINDOWS];
+#ifndef CONFIG_ANDROID
struct list_head timestamp_node;
+#endif /* !CONFIG_ANDROID */
};
int tegra_dc_ext_get_num_outputs(void)
@@ -208,7 +210,9 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
{
int err = 0;
struct tegra_dc_ext_win *ext_win = &ext->win[win->idx];
+#ifndef CONFIG_ANDROID
s64 timestamp_ns;
+#endif /* !CONFIG_ANDROID */
if (flip_win->handle[TEGRA_DC_Y] == NULL) {
win->flags = 0;
@@ -272,6 +276,7 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
msecs_to_jiffies(500), NULL);
}
+#ifndef CONFIG_ANDROID
#ifndef CONFIG_TEGRA_SIMULATION_PLATFORM
timestamp_ns = timespec_to_ns(&flip_win->attr.timestamp);
@@ -286,9 +291,12 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
}
#endif
return err;
+#else /* !CONFIG_ANDROID */
+ return 0;
+#endif /* !CONFIG_ANDROID */
}
-static void (*flip_callback)(void);
+static int (*flip_callback)(void);
static spinlock_t flip_callback_lock;
static bool init_tegra_dc_flip_callback_called;
@@ -301,7 +309,7 @@ static int __init init_tegra_dc_flip_callback(void)
pure_initcall(init_tegra_dc_flip_callback);
-int tegra_dc_set_flip_callback(void (*callback)(void))
+int tegra_dc_set_flip_callback(int (*callback)(void))
{
WARN_ON(!init_tegra_dc_flip_callback_called);
@@ -337,11 +345,14 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
for (i = 0; i < DC_N_WINDOWS; i++) {
struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
- int j = 0, index = flip_win->attr.index;
+ int index = flip_win->attr.index;
struct tegra_dc_win *win;
struct tegra_dc_ext_win *ext_win;
+#ifndef CONFIG_ANDROID
+ int j = 0;
struct tegra_dc_ext_flip_data *temp = NULL;
s64 head_timestamp = 0;
+#endif /* !CONFIG_ANDROID */
if (index < 0)
continue;
@@ -353,6 +364,7 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
(flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_CURSOR))
skip_flip = true;
+#ifndef CONFIG_ANDROID
mutex_lock(&ext_win->queue_lock);
list_for_each_entry(temp, &ext_win->timestamp_queue,
timestamp_node) {
@@ -377,6 +389,7 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
if (!list_empty(&ext_win->timestamp_queue))
list_del(&data->timestamp_node);
mutex_unlock(&ext_win->queue_lock);
+#endif /* !CONFIG_ANDROID */
if (win->flags & TEGRA_WIN_FLAG_ENABLED) {
int j;
@@ -409,6 +422,9 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
flip_callback();
spin_unlock(&flip_callback_lock);
}
+#ifdef CONFIG_ANDROID
+ }
+#endif /* CONFIG_ANDROID */
for (i = 0; i < DC_N_WINDOWS; i++) {
struct tegra_dc_ext_flip_win *flip_win = &data->win[i];
@@ -420,7 +436,9 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work)
tegra_dc_incr_syncpt_min(ext->dc, index,
flip_win->syncpt_max);
}
+#ifndef CONFIG_ANDROID
}
+#endif /* !CONFIG_ANDROID */
/* unpin and deref previous front buffers */
for (i = 0; i < nr_unpin; i++) {
@@ -531,7 +549,9 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
struct tegra_dc_ext_flip_data *data;
int work_index = -1;
int i, ret = 0;
+#ifndef CONFIG_ANDROID
bool has_timestamp = false;
+#endif /* !CONFIG_ANDROID */
#ifdef CONFIG_ANDROID
int index_check[DC_N_WINDOWS] = {0, };
@@ -572,8 +592,10 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
int index = args->win[i].index;
memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr));
+#ifndef CONFIG_ANDROID
if (timespec_to_ns(&flip_win->attr.timestamp))
has_timestamp = true;
+#endif /* !CONFIG_ANDROID */
if (index < 0)
continue;
@@ -648,11 +670,13 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
ret = -EINVAL;
goto unlock;
}
+#ifndef CONFIG_ANDROID
if (has_timestamp) {
mutex_lock(&ext->win[work_index].queue_lock);
list_add_tail(&data->timestamp_node, &ext->win[work_index].timestamp_queue);
mutex_unlock(&ext->win[work_index].queue_lock);
}
+#endif /* !CONFIG_ANDROID */
queue_work(ext->win[work_index].flip_wq, &data->work);
unlock_windows_for_flip(user, args);
@@ -993,8 +1017,10 @@ static int tegra_dc_ext_setup_windows(struct tegra_dc_ext *ext)
}
mutex_init(&win->lock);
+#ifndef CONFIG_ANDROID
mutex_init(&win->queue_lock);
INIT_LIST_HEAD(&win->timestamp_queue);
+#endif /* !CONFIG_ANDROID */
}
return 0;
diff --git a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
index ef7361d1d933..7238e95e59db 100644
--- a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
+++ b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
@@ -59,9 +59,11 @@ struct tegra_dc_ext_win {
atomic_t nr_pending_flips;
+#ifndef CONFIG_ANDROID
struct mutex queue_lock;
struct list_head timestamp_queue;
+#endif /* !CONFIG_ANDROID */
};
struct tegra_dc_ext {
diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c
index 55d9163d4faf..225d48ab15ee 100644
--- a/drivers/video/tegra/dc/hdmi.c
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -1258,6 +1258,9 @@ static bool tegra_dc_hdmi_valid_asp_ratio(const struct tegra_dc *dc,
int m_aspratio = 0;
int s_aspratio = 0;
+ if (!mode->yres)
+ return false;
+
/* To check the aspect upto two decimal digits, calculate in % */
m_aspratio = (mode->xres*100 / mode->yres);
@@ -1345,7 +1348,8 @@ void tegra_dc_hdmi_detect_config(struct tegra_dc *dc,
hdmi->dvi = !(specs->misc & FB_MISC_HDMI);
- tegra_fb_update_monspecs(dc->fb, specs, tegra_dc_hdmi_mode_filter);
+ if (dc->fb != NULL)
+ tegra_fb_update_monspecs(dc->fb, specs, tegra_dc_hdmi_mode_filter);
#ifdef CONFIG_SWITCH
hdmi->hpd_switch.state = 0;
switch_set_state(&hdmi->hpd_switch, 1);
@@ -1413,11 +1417,18 @@ static bool tegra_dc_hdmi_detect(struct tegra_dc *dc)
struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
struct fb_monspecs specs;
int err;
+ int cnt = 0;
if (!tegra_dc_hdmi_hpd(dc))
goto fail;
err = tegra_edid_get_monspecs(hdmi->edid, &specs);
+ /* retry, maybe hdmi detect is not debounced or the monitor needs some time */
+ while ( (err < 0) && (cnt++ < 4) ) {
+ dev_err(&dc->ndev->dev, "error reading edid, trying again in 500ms\n");
+ msleep(500);
+ err = tegra_edid_get_monspecs(hdmi->edid, &specs);
+ }
if (err < 0) {
if (dc->out->n_modes)
tegra_dc_enable(dc);
diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c
index 3a95f2e7ab0e..f5cd4fb0cdea 100644
--- a/drivers/video/tegra/dc/mode.c
+++ b/drivers/video/tegra/dc/mode.c
@@ -26,6 +26,179 @@
#include "dc_reg.h"
#include "dc_priv.h"
+const struct fb_videomode tegra_modes[] = {
+ /* EDT 5.7" ET070080DH or TouchRevolution Fusion 7" */
+ {
+ .name = "800x480",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 30807,
+ .left_margin = 128,
+ .right_margin = 64,
+ .upper_margin = 22,
+ .lower_margin = 20,
+ .hsync_len = 64,
+ .vsync_len = 3,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ /* TouchRevolution Fusion 10" aka Chunghwa Picture Tubes
+ * CLAA100NC05 10.1 inch 1024x600 single channel LVDS panel
+ */
+ {
+ .name = "1024x600",
+ .refresh = 60,
+ .xres = 1024,
+ .yres = 600,
+ .pixclock = KHZ2PICOS(48000),
+ .left_margin = 104,
+ .right_margin = 43,
+ .upper_margin = 24,
+ .lower_margin = 20,
+ .hsync_len = 5,
+ .vsync_len = 5,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .flag = FB_FLAG_RATIO_16_9,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ {
+ /* 1366x768 */
+ .refresh = 60,
+ .xres = 1366,
+ .yres = 768,
+ .pixclock = KHZ2PICOS(72072),
+ .hsync_len = 58, /* h_sync_width */
+ .vsync_len = 4, /* v_sync_width */
+ .left_margin = 58, /* h_back_porch */
+ .upper_margin = 4, /* v_back_porch */
+ .right_margin = 58, /* h_front_porch */
+ .lower_margin = 4, /* v_front_porch */
+ .vmode = FB_VMODE_NONINTERLACED,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ },
+ {
+ /* 1680x1050p 59.94/60hz */
+ .refresh = 60,
+ .xres = 1680,
+ .yres = 1050,
+ .pixclock = KHZ2PICOS(147140),
+ .hsync_len = 184, /* h_sync_width */
+ .vsync_len = 3, /* v_sync_width */
+ .left_margin = 288, /* h_back_porch */
+ .upper_margin = 33, /* v_back_porch */
+ .right_margin = 104, /* h_front_porch */
+ .lower_margin = 1, /* v_front_porch */
+ .vmode = FB_VMODE_NONINTERLACED,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ },
+ {
+ /* 1920x1080p 59.94/60hz CVT */
+ .refresh = 60,
+ .xres = 1920,
+ .yres = 1080,
+ .pixclock = KHZ2PICOS(148500),
+ .hsync_len = 44, /* h_sync_width */
+ .vsync_len = 5, /* v_sync_width */
+ .left_margin = 148, /* h_back_porch */
+ .upper_margin = 36, /* v_back_porch */
+ .right_margin = 88, /* h_front_porch */
+ .lower_margin = 4, /* v_front_porch */
+ .vmode = FB_VMODE_NONINTERLACED,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ },
+ {
+ /* 1920x1200p 60hz */
+ .refresh = 60,
+ .xres = 1920,
+ .yres = 1200,
+ .pixclock = KHZ2PICOS(154000),
+ .hsync_len = 32, /* h_sync_width */
+ .vsync_len = 6, /* v_sync_width */
+ .left_margin = 80, /* h_back_porch */
+ .upper_margin = 26, /* v_back_porch */
+ .right_margin = 48, /* h_front_porch */
+ .lower_margin = 3, /* v_front_porch */
+ .vmode = FB_VMODE_NONINTERLACED,
+ .sync = 0,
+ },
+ /* Portrait modes */
+ {
+ .name = "480x640",
+ .refresh = 60,
+ .xres = 480,
+ .yres = 640,
+ .pixclock = 55555,
+ .left_margin = 20,
+ .right_margin = 8,
+ .upper_margin = 7,
+ .lower_margin = 8,
+ .hsync_len = 4,
+ .vsync_len = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ {
+ .name = "540x960",
+ .refresh = 60,
+ .xres = 540,
+ .yres = 960,
+ .pixclock = 100000,
+ .left_margin = 32,
+ .right_margin = 32,
+ .upper_margin = 1,
+ .lower_margin = 2,
+ .hsync_len = 16,
+ .vsync_len = 1,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+ {
+ .name = "720x1280",
+ .refresh = 60,
+ .xres = 720,
+ .yres = 1280,
+ .pixclock = 16282,
+ .left_margin = 100,
+ .right_margin = 4,
+ .upper_margin = 14,
+ .lower_margin = 4,
+ .hsync_len = 4,
+ .vsync_len = 4,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+ },
+};
+
+/* try to find best matching mode using our modes, VESA and CEA modes from
+ * modedb
+ */
+int tegra_fb_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+ const char* option, unsigned int default_bpp)
+{
+ int out;
+
+ out = fb_find_mode(var, info, option, tegra_modes,
+ ARRAY_SIZE(tegra_modes), NULL, default_bpp);
+
+ /* Only accept this mode if we found a reasonable match (resolution) */
+ if (out == 1 || out == 2)
+ return out;
+
+ out = fb_find_mode(&info->var, info, option,
+ cea_modes, CEA_MODEDB_SIZE, NULL, default_bpp);
+
+ /* Check if we found a full match */
+ if (out == 1 || out == 2)
+ return out;
+
+ return fb_find_mode(&info->var, info, option,
+ vesa_modes, VESA_MODEDB_SIZE, NULL, default_bpp);
+}
+EXPORT_SYMBOL(tegra_fb_find_mode);
+
+
/* return non-zero if constraint is violated */
static int calc_h_ref_to_sync(const struct tegra_dc_mode *mode, int *href)
{
@@ -137,6 +310,7 @@ static bool check_ref_to_sync(struct tegra_dc_mode *mode)
return true;
}
+#ifndef CONFIG_ANDROID
static s64 calc_frametime_ns(const struct tegra_dc_mode *m)
{
long h_total, v_total;
@@ -147,6 +321,7 @@ static s64 calc_frametime_ns(const struct tegra_dc_mode *m)
return (!m->pclk) ? 0 : (s64)(div_s64(((s64)h_total * v_total *
1000000000ULL), m->pclk));
}
+#endif /* !CONFIG_ANDROID */
/* return in 1000ths of a Hertz */
int tegra_dc_calc_refresh(const struct tegra_dc_mode *m)
@@ -270,21 +445,108 @@ int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode)
{
memcpy(&dc->mode, mode, sizeof(dc->mode));
+ dev_info(&dc->ndev->dev, "using mode %dx%d pclk=%d href=%d vref=%d\n",
+ mode->h_active, mode->v_active, mode->pclk,
+ mode->h_ref_to_sync, mode->v_ref_to_sync
+ );
+
if (dc->out->type == TEGRA_DC_OUT_RGB)
panel_sync_rate = tegra_dc_calc_refresh(mode);
else if (dc->out->type == TEGRA_DC_OUT_DSI)
panel_sync_rate = dc->out->dsi->rated_refresh_rate * 1000;
print_mode(dc, mode, __func__);
+#ifndef CONFIG_ANDROID
dc->frametime_ns = calc_frametime_ns(mode);
+#endif /* !CONFIG_ANDROID */
return 0;
}
EXPORT_SYMBOL(tegra_dc_set_mode);
+int tegra_dc_var_to_dc_mode(struct tegra_dc *dc, struct fb_var_screeninfo *var,
+ struct tegra_dc_mode *mode)
+{
+ bool stereo_mode = false;
+ int err;
+
+ if (!var->pixclock)
+ return -EINVAL;
+
+ mode->pclk = PICOS2KHZ(var->pixclock) * 1000;
+ mode->h_sync_width = var->hsync_len;
+ mode->v_sync_width = var->vsync_len;
+ mode->h_back_porch = var->left_margin;
+ mode->v_back_porch = var->upper_margin;
+ mode->h_active = var->xres;
+ mode->v_active = var->yres;
+ mode->h_front_porch = var->right_margin;
+ mode->v_front_porch = var->lower_margin;
+ mode->stereo_mode = stereo_mode;
+
+ /*
+ * HACK:
+ * If v_front_porch is only 1, we would violate Constraint 5/6
+ * in this case, increase front porch by 1
+ */
+ if (mode->v_front_porch <= 1)
+ mode->v_front_porch = 2;
+
+
+ if (dc->out->type == TEGRA_DC_OUT_HDMI) {
+ /* HDMI controller requires h_ref=1, v_ref=1 */
+ mode->h_ref_to_sync = 1;
+ mode->v_ref_to_sync = 1;
+ } else {
+ /* Calculate ref_to_sync signals */
+ err = calc_ref_to_sync(mode);
+ if (err) {
+ dev_err(&dc->ndev->dev, "display timing ref_to_sync"
+ "calculation failed with code %d\n", err);
+ return -EINVAL;
+ }
+ dev_info(&dc->ndev->dev, "Calculated sync href=%d vref=%d\n",
+ mode->h_ref_to_sync, mode->v_ref_to_sync);
+ }
+ if (!check_ref_to_sync(mode)) {
+ dev_err(&dc->ndev->dev,
+ "display timing doesn't meet restrictions.\n");
+ return -EINVAL;
+ }
+
+#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
+ /* Double the pixel clock and update v_active only for
+ * frame packed mode */
+ if (mode->stereo_mode) {
+ mode->pclk *= 2;
+ /* total v_active = yres*2 + activespace */
+ mode->v_active = var->yres * 2 +
+ var->vsync_len +
+ var->upper_margin +
+ var->lower_margin;
+ }
+#endif
+
+ mode->flags = 0;
+
+ if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+ mode->flags |= TEGRA_DC_MODE_FLAG_NEG_H_SYNC;
+
+ if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+ mode->flags |= TEGRA_DC_MODE_FLAG_NEG_V_SYNC;
+
+ return 0;
+}
+EXPORT_SYMBOL(tegra_dc_var_to_dc_mode);
+
+/*
+ * This method is only used by sysfs interface
+ * /sys/devices/tegradc.1/nvdps
+ */
int tegra_dc_set_fb_mode(struct tegra_dc *dc,
const struct fb_videomode *fbmode, bool stereo_mode)
{
+ int err;
struct tegra_dc_mode mode;
if (!fbmode->pixclock)
@@ -305,17 +567,28 @@ int tegra_dc_set_fb_mode(struct tegra_dc *dc,
mode.h_ref_to_sync = 1;
mode.v_ref_to_sync = 1;
} else {
- calc_ref_to_sync(&mode);
+ /*
+ * HACK:
+ * If v_front_porch is only 1, we would violate Constraint 5/6
+ * in this case, increase front porch by 1
+ */
+ if (mode.v_front_porch <= 1)
+ mode.v_front_porch = 2;
+
+ err = calc_ref_to_sync(&mode);
+ if (err) {
+ dev_err(&dc->ndev->dev, "display timing ref_to_sync"
+ "calculation failed with code %d\n", err);
+ return -EINVAL;
+ }
+ dev_info(&dc->ndev->dev, "Calculated sync href=%d vref=%d\n",
+ mode.h_ref_to_sync, mode.v_ref_to_sync);
}
if (!check_ref_to_sync(&mode)) {
dev_err(&dc->ndev->dev,
- "Display timing doesn't meet restrictions.\n");
+ "display timing doesn't meet restrictions.\n");
return -EINVAL;
}
- dev_info(&dc->ndev->dev, "Using mode %dx%d pclk=%d href=%d vref=%d\n",
- mode.h_active, mode.v_active, mode.pclk,
- mode.h_ref_to_sync, mode.v_ref_to_sync
- );
#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
/* Double the pixel clock and update v_active only for
diff --git a/drivers/video/tegra/dc/nvhdcp.c b/drivers/video/tegra/dc/nvhdcp.c
index 3566e2bd33b5..8489ebf69719 100644
--- a/drivers/video/tegra/dc/nvhdcp.c
+++ b/drivers/video/tegra/dc/nvhdcp.c
@@ -760,7 +760,7 @@ static int get_repeater_info(struct tegra_nvhdcp *nvhdcp)
{
int e, retries;
u8 b_caps;
- u16 b_status;
+ u16 b_status = 0;
nvhdcp_vdbg("repeater found:fetching repeater info\n");
diff --git a/drivers/video/tegra/dc/window.c b/drivers/video/tegra/dc/window.c
index cd91fab428ed..af18564f45b9 100644
--- a/drivers/video/tegra/dc/window.c
+++ b/drivers/video/tegra/dc/window.c
@@ -24,7 +24,9 @@
#include "dc_priv.h"
static int no_vsync;
+#ifndef CONFIG_ANDROID
static atomic_t frame_end_ref = ATOMIC_INIT(0);
+#endif /* !CONFIG_ANDROID */
module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
@@ -41,6 +43,7 @@ static bool tegra_dc_windows_are_clean(struct tegra_dc_win *windows[],
return true;
}
+#ifndef CONFIG_ANDROID
int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
{
tegra_dc_writel(dc, FRAME_END_INT, DC_CMD_INT_STATUS);
@@ -51,6 +54,7 @@ int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
tegra_dc_mask_interrupt(dc, FRAME_END_INT);
return 0;
}
+#endif /* !CONFIG_ANDROID */
static int get_topmost_window(u32 *depths, unsigned long *wins)
{
@@ -418,9 +422,14 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
} else {
clear_bit(V_BLANK_FLIP, &dc->vblank_ref_count);
- tegra_dc_mask_interrupt(dc, V_BLANK_INT | ALL_UF_INT);
+ tegra_dc_mask_interrupt(dc,
+#ifndef CONFIG_ANDROID
+ V_BLANK_INT | ALL_UF_INT);
if (!atomic_read(&frame_end_ref))
tegra_dc_mask_interrupt(dc, FRAME_END_INT);
+#else /* !CONFIG_ANDROID */
+ FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
+#endif /* !CONFIG_ANDROID */
}
if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
@@ -470,7 +479,11 @@ void tegra_dc_trigger_windows(struct tegra_dc *dc)
if (!dirty) {
if (!(dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+#ifndef CONFIG_ANDROID
&& !atomic_read(&frame_end_ref))
+#else /* !CONFIG_ANDROID */
+ )
+#endif /* !CONFIG_ANDROID */
tegra_dc_mask_interrupt(dc, FRAME_END_INT);
}
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c
index f69048f62cc2..b7aa066751fc 100644
--- a/drivers/video/tegra/fb.c
+++ b/drivers/video/tegra/fb.c
@@ -55,9 +55,6 @@ struct tegra_fb_info {
bool valid;
struct resource *fb_mem;
-
- int xres;
- int yres;
};
/* palette array used by the fbcon */
@@ -75,10 +72,18 @@ static int tegra_fb_check_var(struct fb_var_screeninfo *var,
info->screen_size)
return -EINVAL;
+ fb_var_to_videomode(&mode, var);
+
+#if defined(CONFIG_MACH_APALIS_T30) || defined(CONFIG_MACH_COLIBRI_T20) || \
+defined(CONFIG_MACH_COLIBRI_T30)
+ /* Hack: avoid 24 Hz mode in X resulting in no display at all */
+ if (mode.refresh < 50)
+ return -EINVAL;
+#endif /* CONFIG_MACH_APALIS_T30 | CONFIG_MACH_COLIBRI_T20 |
+ CONFIG_MACH_COLIBRI_T30 */
+
/* Apply mode filter for HDMI only -LVDS supports only fix mode */
if (ops && ops->mode_filter) {
-
- fb_var_to_videomode(&mode, var);
if (!ops->mode_filter(dc, &mode))
return -EINVAL;
@@ -87,8 +92,35 @@ static int tegra_fb_check_var(struct fb_var_screeninfo *var,
}
/* Double yres_virtual to allow double buffering through pan_display */
+ var->xres_virtual = var->xres;
var->yres_virtual = var->yres * 2;
+ /* we only support RGB ordering for now */
+ switch (var->bits_per_pixel) {
+ case 32:
+ case 24:
+ var->bits_per_pixel = 32;
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 16;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ break;
+ case 16:
+ default:
+ var->bits_per_pixel = 16;
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ break;
+ }
+
return 0;
}
@@ -97,103 +129,61 @@ static int tegra_fb_set_par(struct fb_info *info)
struct tegra_fb_info *tegra_fb = info->par;
struct fb_var_screeninfo *var = &info->var;
struct tegra_dc *dc = tegra_fb->win->dc;
+ int err;
- if (var->bits_per_pixel) {
- /* we only support RGB ordering for now */
- switch (var->bits_per_pixel) {
- case 32:
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 16;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- tegra_fb->win->fmt = TEGRA_WIN_FMT_R8G8B8A8;
- break;
- case 16:
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- tegra_fb->win->fmt = TEGRA_WIN_FMT_B5G6R5;
- break;
-
- default:
- return -EINVAL;
- }
- /* if line_length unset, then pad the stride */
- info->fix.line_length = var->xres * var->bits_per_pixel / 8;
- info->fix.line_length = round_up(info->fix.line_length,
- TEGRA_LINEAR_PITCH_ALIGNMENT);
- tegra_fb->win->stride = info->fix.line_length;
- tegra_fb->win->stride_uv = 0;
- tegra_fb->win->phys_addr_u = 0;
- tegra_fb->win->phys_addr_v = 0;
- }
-
- if (var->pixclock) {
- bool stereo;
- unsigned old_len = 0;
- struct fb_videomode m;
- struct fb_videomode *old_mode = NULL;
-
- fb_var_to_videomode(&m, var);
+ struct tegra_dc_mode mode;
- /* Load framebuffer info with new mode details*/
- old_mode = info->mode;
- old_len = info->fix.line_length;
-
- info->mode = (struct fb_videomode *)
- fb_find_nearest_mode(&m, &info->modelist);
- if (!info->mode) {
- dev_warn(&tegra_fb->ndev->dev, "can't match video mode\n");
- info->mode = old_mode;
- return -EINVAL;
- }
+ /* This is usually altered to 16/32 by tegra_fb_check_var
+ * above which is called before this function
+ */
+ switch (var->bits_per_pixel) {
+ case 32:
+ tegra_fb->win->fmt = TEGRA_WIN_FMT_R8G8B8A8;
+ break;
+ case 16:
+ tegra_fb->win->fmt = TEGRA_WIN_FMT_B5G6R5;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
- /* Update fix line_length and window stride as per new mode */
- info->fix.line_length = var->xres * var->bits_per_pixel / 8;
- info->fix.line_length = round_up(info->fix.line_length,
- TEGRA_LINEAR_PITCH_ALIGNMENT);
- tegra_fb->win->stride = info->fix.line_length;
+ /* if line_length unset, then pad the stride */
+ info->fix.line_length = var->xres * var->bits_per_pixel / 8;
+ info->fix.line_length = round_up(info->fix.line_length,
+ TEGRA_LINEAR_PITCH_ALIGNMENT);
+ tegra_fb->win->stride = info->fix.line_length;
+ tegra_fb->win->stride_uv = 0;
+ tegra_fb->win->phys_addr_u = 0;
+ tegra_fb->win->phys_addr_v = 0;
+
+ tegra_fb->win->w.full = dfixed_const(var->xres);
+ tegra_fb->win->h.full = dfixed_const(var->yres);
+ tegra_fb->win->out_w = var->xres;
+ tegra_fb->win->out_h = var->yres;
+
+ dev_info(&tegra_fb->ndev->dev, "switching framebuffer to %dx%d\n",
+ var->xres, var->yres);
+
+ err = tegra_dc_var_to_dc_mode(dc, var, &mode);
+ if (err) {
+ dev_warn(&tegra_fb->ndev->dev, "could not convert var %d\n", err);
+ return -EINVAL;
+ }
- /*
- * only enable stereo if the mode supports it and
- * client requests it
- */
- stereo = !!(var->vmode & info->mode->vmode &
-#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT
- FB_VMODE_STEREO_FRAME_PACK);
-#else
- FB_VMODE_STEREO_LEFT_RIGHT);
-#endif
+ err = tegra_dc_set_mode(dc, &mode);
+ if (err) {
+ dev_warn(&tegra_fb->ndev->dev, "could not set dc mode %d\n", err);
+ return -EINVAL;
+ }
- /* Configure DC with new mode */
- if (tegra_dc_set_fb_mode(dc, info->mode, stereo)) {
- /* Error while configuring DC, fallback to old mode */
- dev_warn(&tegra_fb->ndev->dev, "can't configure dc with mode %ux%u\n",
- info->mode->xres, info->mode->yres);
- info->mode = old_mode;
- info->fix.line_length = old_len;
- tegra_fb->win->stride = old_len;
- return -EINVAL;
- }
+ /* Reflect changes on HW */
+ if (dc->enabled)
+ tegra_dc_disable(dc);
+ tegra_dc_enable(dc);
- /* Reflect mode chnage on DC HW */
- if (dc->enabled)
- tegra_dc_disable(dc);
- tegra_dc_enable(dc);
+ return err;
- tegra_fb->win->w.full = dfixed_const(info->mode->xres);
- tegra_fb->win->h.full = dfixed_const(info->mode->yres);
- tegra_fb->win->out_w = info->mode->xres;
- tegra_fb->win->out_h = info->mode->yres;
- }
- return 0;
}
static int tegra_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -417,6 +407,9 @@ static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long
}
int tegra_fb_get_mode(struct tegra_dc *dc) {
+ /* Avoid error when reading sysfs */
+ if (dc->fb->info->mode == NULL)
+ return 0;
return dc->fb->info->mode->refresh;
}
@@ -532,13 +525,11 @@ void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info,
/* Prepare a mode db */
for (i = 0; i < specs->modedb_len; i++) {
if (info->fbops->fb_check_var) {
- struct fb_videomode m;
-
/* Call mode filter to check mode */
fb_videomode_to_var(&var, &specs->modedb[i]);
if (!(info->fbops->fb_check_var(&var, info))) {
- fb_var_to_videomode(&m, &var);
- fb_add_videomode(&m,
+ fb_var_to_videomode(&specs->modedb[i], &var);
+ fb_add_videomode(&specs->modedb[i],
&fb_info->info->modelist);
/* EDID stds recommend first detailed mode
to be applied as default,but if first mode
@@ -584,6 +575,106 @@ void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info,
mutex_unlock(&fb_info->info->lock);
}
+struct tegra_dc_out_pin dc_out_pins[4];
+
+
+static int parse_opt(struct tegra_dc_out *out, char *this_opt)
+{
+ if (!strncmp(this_opt, "hsync:", 6)) {
+ if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
+ out->out_pins[TEGRA_DC_OUT_PIN_H_SYNC].pol =
+ TEGRA_DC_OUT_PIN_POL_LOW;
+ } else {
+ out->out_pins[TEGRA_DC_OUT_PIN_H_SYNC].pol =
+ TEGRA_DC_OUT_PIN_POL_HIGH;
+ }
+ return 0;
+ } else if (!strncmp(this_opt, "vsync:", 6)) {
+ if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
+ out->out_pins[TEGRA_DC_OUT_PIN_V_SYNC].pol =
+ TEGRA_DC_OUT_PIN_POL_LOW;
+ } else {
+ out->out_pins[TEGRA_DC_OUT_PIN_V_SYNC].pol =
+ TEGRA_DC_OUT_PIN_POL_HIGH;
+ }
+ return 0;
+ } else if (!strncmp(this_opt, "outputen:", 9)) {
+ if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
+ out->out_pins[TEGRA_DC_OUT_PIN_DATA_ENABLE].pol =
+ TEGRA_DC_OUT_PIN_POL_LOW;
+ } else {
+ out->out_pins[TEGRA_DC_OUT_PIN_DATA_ENABLE].pol =
+ TEGRA_DC_OUT_PIN_POL_HIGH;
+ }
+ return 0;
+ } else if (!strncmp(this_opt, "pixclockpol:", 12)) {
+ if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
+ out->out_pins[TEGRA_DC_OUT_PIN_PIXEL_CLOCK].pol =
+ TEGRA_DC_OUT_PIN_POL_LOW;
+ } else {
+ out->out_pins[TEGRA_DC_OUT_PIN_PIXEL_CLOCK].pol =
+ TEGRA_DC_OUT_PIN_POL_HIGH;
+ }
+ return 0;
+ }
+
+ return -1;
+}
+
+static void tegra_dc_copy_pin_modes(struct tegra_dc_out *out)
+{
+ int i;
+ struct tegra_dc_out_pin *def = out->out_pins;
+ int n_out_pins_default = out->n_out_pins;
+
+ /* Allocate memory for dynamic output pin configuration... */
+ out->n_out_pins = 4;
+ out->out_pins = kmalloc(sizeof(struct tegra_dc_out_pin) * out->n_out_pins,
+ GFP_KERNEL);
+
+ /* ...set fallback values, we use the pin enum as array index... */
+ out->out_pins[TEGRA_DC_OUT_PIN_DATA_ENABLE].name = TEGRA_DC_OUT_PIN_DATA_ENABLE;
+ out->out_pins[TEGRA_DC_OUT_PIN_DATA_ENABLE].pol = TEGRA_DC_OUT_PIN_POL_HIGH;
+ out->out_pins[TEGRA_DC_OUT_PIN_H_SYNC].name = TEGRA_DC_OUT_PIN_H_SYNC;
+ out->out_pins[TEGRA_DC_OUT_PIN_H_SYNC].pol = TEGRA_DC_OUT_PIN_POL_LOW;
+ out->out_pins[TEGRA_DC_OUT_PIN_V_SYNC].name = TEGRA_DC_OUT_PIN_V_SYNC;
+ out->out_pins[TEGRA_DC_OUT_PIN_V_SYNC].pol = TEGRA_DC_OUT_PIN_POL_LOW;
+ out->out_pins[TEGRA_DC_OUT_PIN_PIXEL_CLOCK].name = TEGRA_DC_OUT_PIN_PIXEL_CLOCK;
+ out->out_pins[TEGRA_DC_OUT_PIN_PIXEL_CLOCK].pol = TEGRA_DC_OUT_PIN_POL_LOW;
+
+ /* ... and copy the static default config from platform data */
+ for (i = 0; i < n_out_pins_default; i++)
+ out->out_pins[def[i].name].pol = def[i].pol;
+}
+
+static int tegra_parse_options(struct tegra_dc_out *out, struct fb_info *info,
+ char *option)
+{
+ char *this_opt;
+
+ /* This off option works perfectly for framebuffer
+ * device, however the tegra binary driver somehow
+ * has troubles to handle a missing fb0
+ * (then, dc1 gets remapped to fb0, which seems
+ * to be an issue for the binary driver)...
+ */
+ if (!strcmp(option, "off"))
+ return -ENODEV;
+
+ while ((this_opt = strsep(&option, ",")) != NULL) {
+ /* Parse driver specific arguments for RGB output */
+ if (out->type == TEGRA_DC_OUT_RGB) {
+ if (parse_opt(out, this_opt) == 0)
+ continue;
+ }
+
+ /* No valid driver specific argument, has to be mode */
+ if (!tegra_fb_find_mode(&info->var, info, this_opt, 16))
+ return -EINVAL;
+ }
+ return 0;
+}
+
struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
struct tegra_dc *dc,
struct tegra_fb_data *fb_data,
@@ -597,6 +688,9 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
unsigned long fb_phys = 0;
int ret = 0;
unsigned stride;
+ char *param_option = NULL;
+ char *option = NULL;
+ char driver[10];
win = tegra_dc_get_window(dc, fb_data->win);
if (!win) {
@@ -615,8 +709,6 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
tegra_fb->win = win;
tegra_fb->ndev = ndev;
tegra_fb->fb_mem = fb_mem;
- tegra_fb->xres = fb_data->xres;
- tegra_fb->yres = fb_data->yres;
if (fb_mem) {
fb_size = resource_size(fb_mem);
@@ -653,6 +745,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
info->var.xres_virtual = fb_data->xres;
info->var.yres_virtual = fb_data->yres * 2;
info->var.bits_per_pixel = fb_data->bits_per_pixel;
+
info->var.activate = FB_ACTIVATE_VBL;
info->var.height = tegra_dc_get_out_height(dc);
info->var.width = tegra_dc_get_out_width(dc);
@@ -665,11 +758,11 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
info->var.vsync_len = 0;
info->var.vmode = FB_VMODE_NONINTERLACED;
+ /* window settings */
win->x.full = dfixed_const(0);
win->y.full = dfixed_const(0);
win->w.full = dfixed_const(fb_data->xres);
win->h.full = dfixed_const(fb_data->yres);
- /* TODO: set to output res dc */
win->out_x = 0;
win->out_y = 0;
win->out_w = fb_data->xres;
@@ -683,6 +776,32 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
win->stride_uv = 0;
win->flags = TEGRA_WIN_FLAG_ENABLED;
+ /* Set/copy default pin modes, if output is RGB... */
+ if (dc->out->type == TEGRA_DC_OUT_RGB)
+ tegra_dc_copy_pin_modes(dc->out);
+
+ /* try to use kernel cmd line specified mode */
+ sprintf(driver, "tegrafb%d", ndev->id);
+ fb_get_options(driver, &param_option);
+ if (param_option != NULL) {
+ option = param_option;
+ dev_info(&ndev->dev, "use cmd options for %s: %s\n",
+ driver, option);
+ } else {
+ option = dc->out->default_mode;
+ dev_info(&ndev->dev, "use default mode for %s: %s\n",
+ driver, option);
+ }
+
+ if (option != NULL) {
+ ret = tegra_parse_options(dc->out, info, option);
+ if (ret < 0)
+ goto err_iounmap_fb;
+ }
+
+ /* Activate current settings (tegra_fb_find_mode has call
+ * tegra_fb_check_var already)
+ */
if (fb_mem)
tegra_fb_set_par(info);
@@ -701,26 +820,6 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
tegra_dc_sync_windows(&tegra_fb->win, 1);
}
- if (dc->mode.pclk > 1000) {
- struct tegra_dc_mode *mode = &dc->mode;
- struct fb_videomode vmode;
-
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
- info->var.pixclock = KHZ2PICOS(mode->rated_pclk / 1000);
- else
- info->var.pixclock = KHZ2PICOS(mode->pclk / 1000);
- info->var.left_margin = mode->h_back_porch;
- info->var.right_margin = mode->h_front_porch;
- info->var.upper_margin = mode->v_back_porch;
- info->var.lower_margin = mode->v_front_porch;
- info->var.hsync_len = mode->h_sync_width;
- info->var.vsync_len = mode->v_sync_width;
-
- /* Keep info->var consistent with info->modelist. */
- fb_var_to_videomode(&vmode, &info->var);
- fb_add_videomode(&vmode, &info->modelist);
- }
-
return tegra_fb;
err_iounmap_fb:
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index 4614689ec37c..2b92a62cc0bc 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -611,6 +611,7 @@ fail:
nvhost_free_channel(ch);
return err;
}
+EXPORT_SYMBOL(nvhost_client_device_init);
int nvhost_client_device_suspend(struct nvhost_device *dev)
{
@@ -658,6 +659,7 @@ fail:
return -ENXIO;
}
+EXPORT_SYMBOL(nvhost_client_device_get_resources);
void nvhost_client_device_put_resources(struct nvhost_device *dev)
{
@@ -670,3 +672,4 @@ void nvhost_client_device_put_resources(struct nvhost_device *dev)
release_mem_region(r->start, resource_size(r));
}
+EXPORT_SYMBOL(nvhost_client_device_put_resources);
diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c
index 5bde55ad2ff5..f22c91ac03f1 100644
--- a/drivers/video/tegra/host/nvhost_acm.c
+++ b/drivers/video/tegra/host/nvhost_acm.c
@@ -639,8 +639,10 @@ void nvhost_module_busy_ext(struct nvhost_device *dev)
{
nvhost_module_busy(dev);
}
+EXPORT_SYMBOL(nvhost_module_busy_ext);
void nvhost_module_idle_ext(struct nvhost_device *dev)
{
nvhost_module_idle(dev);
}
+EXPORT_SYMBOL(nvhost_module_idle_ext);
diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c
index 38c28ca116e7..de3e04f65cdd 100644
--- a/drivers/video/tegra/host/nvhost_syncpt.c
+++ b/drivers/video/tegra/host/nvhost_syncpt.c
@@ -493,12 +493,14 @@ void nvhost_syncpt_cpu_incr_ext(struct nvhost_device *dev, u32 id)
struct nvhost_syncpt *sp = &(nvhost_get_host(dev)->syncpt);
nvhost_syncpt_cpu_incr(sp, id);
}
+EXPORT_SYMBOL(nvhost_syncpt_cpu_incr_ext);
u32 nvhost_syncpt_read_ext(struct nvhost_device *dev, u32 id)
{
struct nvhost_syncpt *sp = &(nvhost_get_host(dev)->syncpt);
return nvhost_syncpt_read(sp, id);
}
+EXPORT_SYMBOL(nvhost_syncpt_read_ext);
int nvhost_syncpt_wait_timeout_ext(struct nvhost_device *dev, u32 id, u32 thresh,
u32 timeout, u32 *value)
@@ -506,3 +508,4 @@ int nvhost_syncpt_wait_timeout_ext(struct nvhost_device *dev, u32 id, u32 thresh
struct nvhost_syncpt *sp = &(nvhost_get_host(dev)->syncpt);
return nvhost_syncpt_wait_timeout(sp, id, thresh, timeout, value);
}
+EXPORT_SYMBOL(nvhost_syncpt_wait_timeout_ext);
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c
index 19b821d41284..e66ca982f2f3 100644
--- a/drivers/video/tegra/nvmap/nvmap.c
+++ b/drivers/video/tegra/nvmap/nvmap.c
@@ -387,6 +387,7 @@ phys_addr_t nvmap_pin(struct nvmap_client *client,
return ret ?: phys;
}
+EXPORT_SYMBOL(nvmap_pin);
phys_addr_t nvmap_handle_address(struct nvmap_client *c, unsigned long id)
{
@@ -413,6 +414,7 @@ void nvmap_unpin(struct nvmap_client *client, struct nvmap_handle_ref *ref)
if (handle_unpin(client, ref->handle, false))
wake_up(&client->share->pin_wait);
}
+EXPORT_SYMBOL(nvmap_unpin);
void nvmap_unpin_handles(struct nvmap_client *client,
struct nvmap_handle **h, int nr)
@@ -501,6 +503,7 @@ void *nvmap_mmap(struct nvmap_handle_ref *ref)
* nvmap_handle_put will be called by unmapping this address */
return p;
}
+EXPORT_SYMBOL(nvmap_mmap);
void nvmap_munmap(struct nvmap_handle_ref *ref, void *addr)
{
@@ -523,6 +526,7 @@ void nvmap_munmap(struct nvmap_handle_ref *ref, void *addr)
}
nvmap_handle_put(h);
}
+EXPORT_SYMBOL(nvmap_munmap);
struct nvmap_handle_ref *nvmap_alloc(struct nvmap_client *client, size_t size,
size_t align, unsigned int flags,
@@ -550,6 +554,7 @@ struct nvmap_handle_ref *nvmap_alloc(struct nvmap_client *client, size_t size,
return r;
}
+EXPORT_SYMBOL(nvmap_alloc);
/* allocates memory with specifed iovm_start address. */
struct nvmap_handle_ref *nvmap_alloc_iovm(struct nvmap_client *client,
@@ -605,6 +610,7 @@ void nvmap_free(struct nvmap_client *client, struct nvmap_handle_ref *r)
nvmap_free_handle_id(client, nvmap_ref_to_id(r));
}
+EXPORT_SYMBOL(nvmap_free);
int nvmap_mark_global(struct nvmap_client *client, struct nvmap_handle_ref *r)
{
diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c
index 3b0db14f16ca..3ea7bd2ea797 100644
--- a/drivers/video/tegra/nvmap/nvmap_dev.c
+++ b/drivers/video/tegra/nvmap/nvmap_dev.c
@@ -87,6 +87,7 @@ struct nvmap_device {
};
struct nvmap_device *nvmap_dev;
+EXPORT_SYMBOL(nvmap_dev);
static struct backing_dev_info nvmap_bdi = {
.ra_pages = 0,
@@ -670,6 +671,7 @@ struct nvmap_client *nvmap_create_client(struct nvmap_device *dev,
spin_unlock(&dev->clients_lock);
return client;
}
+EXPORT_SYMBOL(nvmap_create_client);
static void destroy_client(struct nvmap_client *client)
{
@@ -756,6 +758,7 @@ void nvmap_client_put(struct nvmap_client *client)
if (!atomic_dec_return(&client->count))
destroy_client(client);
}
+EXPORT_SYMBOL(nvmap_client_put);
static int nvmap_open(struct inode *inode, struct file *filp)
{
diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c
index 4b7760b22190..c1add8383e83 100644
--- a/drivers/video/tegra/nvmap/nvmap_handle.c
+++ b/drivers/video/tegra/nvmap/nvmap_handle.c
@@ -572,9 +572,10 @@ static int handle_page_alloc(struct nvmap_client *client,
#ifdef CONFIG_NVMAP_PAGE_POOLS
struct nvmap_page_pool *pool = NULL;
struct nvmap_share *share = nvmap_get_share_from_dev(h->dev);
+ unsigned long paddr;
#endif
gfp_t gfp = GFP_NVMAP;
- unsigned long kaddr, paddr;
+ unsigned long kaddr;
pte_t **pte = NULL;
if (h->userflags & NVMAP_HANDLE_ZEROED_PAGES) {