mirror of
https://github.com/LIV2/LIV2-Xoom-GNU.git
synced 2025-12-06 00:12:52 +00:00
Qtouch driver by Lilsteve, nvidia tegrafb patch
This commit is contained in:
parent
cef3887d2b
commit
710904ebc2
@ -845,7 +845,7 @@ static int usbnet_probe(struct platform_device *pdev)
|
||||
{
|
||||
pr_info("usbnet_probe\n");
|
||||
/* do not register our function unless our platform device was registered */
|
||||
android_register_function(&usbnet_function);
|
||||
// android_register_function(&usbnet_function);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -187,7 +187,7 @@ u32 tegra_dc_incr_syncpt_max(struct tegra_dc *dc);
|
||||
void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, u32 val);
|
||||
|
||||
int tegra_dc_set_default_emc(struct tegra_dc *dc);
|
||||
int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n);
|
||||
//int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n);
|
||||
|
||||
/* tegra_dc_update_windows and tegra_dc_sync_windows do not support windows
|
||||
* with differenct dcs in one call
|
||||
|
||||
@ -37,8 +37,6 @@ void tegra_fb_unregister(struct tegra_fb_info *fb_info);
|
||||
void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info,
|
||||
struct fb_monspecs *specs,
|
||||
bool (*mode_filter)(struct fb_videomode *mode));
|
||||
/* called by display controller on suspend */
|
||||
void tegra_fb_suspend(struct tegra_fb_info *tegra_fb);
|
||||
#else
|
||||
static inline struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
|
||||
struct tegra_dc *dc,
|
||||
@ -57,9 +55,6 @@ static inline void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info,
|
||||
bool (*mode_filter)(struct fb_videomode *mode))
|
||||
{
|
||||
}
|
||||
static inline void tegra_fb_suspend(struct tegra_fb_info *tegra_fb)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2009 Google, Inc.
|
||||
* Copyright (C) 2009-2010 Motorola, Inc.
|
||||
* Copyright (C) 2011 Lilstevie
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
@ -896,8 +897,18 @@ static int do_touch_multi_msg(struct qtouch_ts_data *ts, struct qtm_object *obj,
|
||||
ts->finger_data[i].vector);
|
||||
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID,
|
||||
i);
|
||||
|
||||
input_report_abs(ts->input_dev, ABS_X, ts->finger_data[i].x_data);
|
||||
input_report_abs(ts->input_dev, ABS_Y, ts->finger_data[i].y_data);
|
||||
if(down == 1){
|
||||
input_report_key(ts->input_dev, BTN_TOUCH, 1);
|
||||
}else{
|
||||
input_report_key(ts->input_dev, BTN_TOUCH, 0);
|
||||
}
|
||||
|
||||
input_mt_sync(ts->input_dev);
|
||||
}
|
||||
|
||||
input_sync(ts->input_dev);
|
||||
|
||||
if (!down) {
|
||||
@ -1086,7 +1097,6 @@ static int qtouch_ts_register_input(struct qtouch_ts_data *ts)
|
||||
set_bit(EV_ABS, ts->input_dev->evbit);
|
||||
/* Legacy support for testing only */
|
||||
input_set_capability(ts->input_dev, EV_KEY, BTN_TOUCH);
|
||||
input_set_capability(ts->input_dev, EV_KEY, BTN_2);
|
||||
input_set_abs_params(ts->input_dev, ABS_X,
|
||||
ts->pdata->abs_min_x, ts->pdata->abs_max_x,
|
||||
ts->pdata->fuzz_x, 0);
|
||||
|
||||
@ -24,7 +24,9 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/usb/composite.h>
|
||||
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "u_serial.h"
|
||||
#include "gadget_chips.h"
|
||||
|
||||
@ -529,56 +529,6 @@ static unsigned int tegra_dc_find_max_bandwidth(struct tegra_dc_win *wins[],
|
||||
|
||||
/* 8 bits per byte (1 << 3) */
|
||||
#define BIT_TO_BYTE_SHIFT 3
|
||||
static unsigned long tegra_dc_get_emc_rate(struct tegra_dc_win *wins[], int n)
|
||||
{
|
||||
int i;
|
||||
unsigned int bw[TEGRA_FB_FLIP_N_WINDOWS];
|
||||
struct tegra_dc_win *w;
|
||||
struct tegra_dc *dc;
|
||||
unsigned int max;
|
||||
unsigned int ret;
|
||||
|
||||
dc = wins[0]->dc;
|
||||
|
||||
if (tegra_dc_has_multiple_dc())
|
||||
return tegra_dc_get_default_emc_clk_rate(dc);
|
||||
|
||||
BUG_ON(n > ARRAY_SIZE(bw));
|
||||
/*
|
||||
* Calculate peak EMC bandwidth for each enabled window =
|
||||
* pixel_clock * win_bpp * (use_v_filter ? 2 : 1)) * H_scale_factor *
|
||||
* (windows_tiling ? 2 : 1)
|
||||
*
|
||||
*
|
||||
* note:
|
||||
* (*) We use 2 tap V filter, so need double BW if use V filter
|
||||
* (*) Tiling mode on T30 and DDR3 requires double BW
|
||||
*/
|
||||
for (i = 0; w = wins[i], bw[i] = 0, i < n; i++) {
|
||||
if (!WIN_IS_ENABLED(w))
|
||||
continue;
|
||||
bw[i] = dc->mode.pclk *
|
||||
(tegra_dc_fmt_bpp(w->fmt) >> BIT_TO_BYTE_SHIFT) *
|
||||
(WIN_USE_V_FILTER(w) ? 2 : 1) /
|
||||
w->out_w * w->w *
|
||||
(WIN_IS_TILED(w) ? TILED_WINDOWS_BW_MULTIPLIER : 1);
|
||||
}
|
||||
|
||||
max = tegra_dc_find_max_bandwidth(wins, bw, n);
|
||||
/* multiply bandwidth by 2.5 assuming 40% memory efficiency */
|
||||
max = (max << 1) + (max >> 1);
|
||||
|
||||
ret = EMC_BW_TO_FREQ(max);
|
||||
|
||||
/*
|
||||
* If the calculated peak BW is bigger than board specified BW, then
|
||||
* either the above calculation is wrong, or board specified BW is
|
||||
* wrong.
|
||||
*/
|
||||
WARN_ON(ret > tegra_dc_get_default_emc_clk_rate(dc));
|
||||
|
||||
return ret;
|
||||
}
|
||||
#undef BIT_TO_BYTE_SHIFT
|
||||
|
||||
static void tegra_dc_change_emc(struct tegra_dc *dc)
|
||||
@ -608,45 +558,6 @@ static void tegra_dc_reduce_emc_worker(struct work_struct *work)
|
||||
mutex_unlock(&dc->lock);
|
||||
}
|
||||
|
||||
int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n)
|
||||
{
|
||||
unsigned long new_rate;
|
||||
struct tegra_dc *dc;
|
||||
|
||||
if (!use_dynamic_emc)
|
||||
return 0;
|
||||
|
||||
dc = windows[0]->dc;
|
||||
|
||||
mutex_lock(&dc->lock);
|
||||
|
||||
if (!dc->enabled) {
|
||||
mutex_unlock(&dc->lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* calculate the new rate based on this POST */
|
||||
new_rate = tegra_dc_get_emc_rate(windows, n);
|
||||
|
||||
dc->new_emc_clk_rate = new_rate;
|
||||
|
||||
/*
|
||||
* If we don't need set EMC immediately after a frame POST, we schedule
|
||||
* a work_queue to reduce EMC in the future. This work_queue task will
|
||||
* not be executed if the another POST comes before the idle time
|
||||
* expired.
|
||||
*/
|
||||
if (NEED_UPDATE_EMC_ON_EVERY_FRAME)
|
||||
tegra_dc_change_emc(dc);
|
||||
else
|
||||
schedule_delayed_work(&dc->reduce_emc_clk_work,
|
||||
msecs_to_jiffies(windows_idle_detection_time));
|
||||
|
||||
mutex_unlock(&dc->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_dc_set_default_emc(struct tegra_dc *dc)
|
||||
{
|
||||
/*
|
||||
@ -1570,7 +1481,6 @@ static int tegra_dc_suspend(struct nvhost_device *ndev, pm_message_t state)
|
||||
dc->out_ops->suspend(dc);
|
||||
|
||||
if (dc->enabled) {
|
||||
tegra_fb_suspend(dc->fb);
|
||||
_tegra_dc_disable(dc);
|
||||
|
||||
dc->suspended = true;
|
||||
|
||||
@ -51,75 +51,11 @@ struct tegra_fb_info {
|
||||
int xres;
|
||||
int yres;
|
||||
|
||||
atomic_t in_use;
|
||||
struct nvmap_client *user_nvmap;
|
||||
struct nvmap_client *fb_nvmap;
|
||||
|
||||
struct workqueue_struct *flip_wq;
|
||||
};
|
||||
|
||||
struct tegra_fb_flip_win {
|
||||
struct tegra_fb_windowattr attr;
|
||||
struct nvmap_handle_ref *handle;
|
||||
dma_addr_t phys_addr;
|
||||
};
|
||||
|
||||
struct tegra_fb_flip_data {
|
||||
struct work_struct work;
|
||||
struct tegra_fb_info *fb;
|
||||
struct tegra_fb_flip_win win[TEGRA_FB_FLIP_N_WINDOWS];
|
||||
u32 syncpt_max;
|
||||
};
|
||||
|
||||
/* palette array used by the fbcon */
|
||||
static u32 pseudo_palette[16];
|
||||
|
||||
static int tegra_fb_open(struct fb_info *info, int user)
|
||||
{
|
||||
struct tegra_fb_info *tegra_fb = info->par;
|
||||
|
||||
if (atomic_xchg(&tegra_fb->in_use, 1))
|
||||
return -EBUSY;
|
||||
|
||||
tegra_fb->user_nvmap = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_fb_release(struct fb_info *info, int user)
|
||||
{
|
||||
struct tegra_fb_info *tegra_fb = info->par;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
|
||||
flush_workqueue(tegra_fb->flip_wq);
|
||||
|
||||
if (tegra_fb->win->cur_handle) {
|
||||
nvmap_unpin(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle);
|
||||
nvmap_free(tegra_fb->fb_nvmap, tegra_fb->win->cur_handle);
|
||||
|
||||
tegra_fb->win->cur_handle = NULL;
|
||||
|
||||
tegra_fb->win->x = 0;
|
||||
tegra_fb->win->y = 0;
|
||||
tegra_fb->win->w = var->xres;
|
||||
tegra_fb->win->h = var->yres;
|
||||
tegra_fb->win->out_x = 0;
|
||||
tegra_fb->win->out_y = 0;
|
||||
tegra_fb->win->out_w = var->xres;
|
||||
tegra_fb->win->out_h = var->yres;
|
||||
tegra_fb->win->flags = TEGRA_WIN_FLAG_ENABLED;
|
||||
}
|
||||
|
||||
if (tegra_fb->user_nvmap) {
|
||||
nvmap_client_put(tegra_fb->user_nvmap);
|
||||
tegra_fb->user_nvmap = NULL;
|
||||
}
|
||||
|
||||
WARN_ON(!atomic_xchg(&tegra_fb->in_use, 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_fb_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
@ -250,7 +186,6 @@ static int tegra_fb_blank(int blank, struct fb_info *info)
|
||||
|
||||
case FB_BLANK_POWERDOWN:
|
||||
dev_dbg(&tegra_fb->ndev->dev, "blank\n");
|
||||
flush_workqueue(tegra_fb->flip_wq);
|
||||
tegra_dc_disable(tegra_fb->win->dc);
|
||||
return 0;
|
||||
|
||||
@ -259,12 +194,6 @@ static int tegra_fb_blank(int blank, struct fb_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
void tegra_fb_suspend(struct tegra_fb_info *tegra_fb)
|
||||
{
|
||||
flush_workqueue(tegra_fb->flip_wq);
|
||||
}
|
||||
|
||||
|
||||
static int tegra_fb_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
@ -287,7 +216,7 @@ static int tegra_fb_pan_display(struct fb_var_screeninfo *var,
|
||||
/* TODO: update virt_addr */
|
||||
|
||||
tegra_dc_set_default_emc(tegra_fb->win->dc);
|
||||
tegra_dc_set_dynamic_emc(&tegra_fb->win, 1);
|
||||
// tegra_dc_set_dynamic_emc(&tegra_fb->win, 1);
|
||||
tegra_dc_update_windows(&tegra_fb->win, 1);
|
||||
tegra_dc_sync_windows(&tegra_fb->win, 1);
|
||||
}
|
||||
@ -315,270 +244,13 @@ static void tegra_fb_imageblit(struct fb_info *info,
|
||||
|
||||
/* TODO: implement ALLOC, FREE, BLANK ioctls */
|
||||
|
||||
static int tegra_fb_set_nvmap_fd(struct tegra_fb_info *tegra_fb, int fd)
|
||||
{
|
||||
struct nvmap_client *nvmap = NULL;
|
||||
|
||||
if (fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
nvmap = nvmap_client_get_file(fd);
|
||||
if (IS_ERR(nvmap))
|
||||
return PTR_ERR(nvmap);
|
||||
|
||||
if (tegra_fb->user_nvmap)
|
||||
nvmap_client_put(tegra_fb->user_nvmap);
|
||||
|
||||
tegra_fb->user_nvmap = nvmap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_fb_pin_window(struct tegra_fb_info *tegra_fb,
|
||||
struct tegra_fb_flip_win *flip_win)
|
||||
{
|
||||
struct nvmap_handle_ref *win_dupe;
|
||||
struct nvmap_handle *win_handle;
|
||||
unsigned long buff_id = flip_win->attr.buff_id;
|
||||
|
||||
if (!buff_id)
|
||||
return 0;
|
||||
|
||||
win_handle = nvmap_get_handle_id(tegra_fb->user_nvmap, buff_id);
|
||||
if (win_handle == NULL) {
|
||||
dev_err(&tegra_fb->ndev->dev, "%s: flip invalid "
|
||||
"handle %08lx\n", current->comm, buff_id);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* duplicate the new framebuffer's handle into the fb driver's
|
||||
* nvmap context, to ensure that the handle won't be freed as
|
||||
* long as it is in-use by the fb driver */
|
||||
win_dupe = nvmap_duplicate_handle_id(tegra_fb->fb_nvmap, buff_id);
|
||||
nvmap_handle_put(win_handle);
|
||||
|
||||
if (IS_ERR(win_dupe)) {
|
||||
dev_err(&tegra_fb->ndev->dev, "couldn't duplicate handle\n");
|
||||
return PTR_ERR(win_dupe);
|
||||
}
|
||||
|
||||
flip_win->handle = win_dupe;
|
||||
|
||||
flip_win->phys_addr = nvmap_pin(tegra_fb->fb_nvmap, win_dupe);
|
||||
if (IS_ERR((void *)flip_win->phys_addr)) {
|
||||
dev_err(&tegra_fb->ndev->dev, "couldn't pin handle\n");
|
||||
nvmap_free(tegra_fb->fb_nvmap, win_dupe);
|
||||
return PTR_ERR((void *)flip_win->phys_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_fb_set_windowattr(struct tegra_fb_info *tegra_fb,
|
||||
struct tegra_dc_win *win,
|
||||
const struct tegra_fb_flip_win *flip_win)
|
||||
{
|
||||
if (flip_win->handle == NULL) {
|
||||
win->flags = 0;
|
||||
win->cur_handle = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
win->flags = TEGRA_WIN_FLAG_ENABLED;
|
||||
if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_PREMULT)
|
||||
win->flags |= TEGRA_WIN_FLAG_BLEND_PREMULT;
|
||||
else if (flip_win->attr.blend == TEGRA_FB_WIN_BLEND_COVERAGE)
|
||||
win->flags |= TEGRA_WIN_FLAG_BLEND_COVERAGE;
|
||||
if (flip_win->attr.flags & TEGRA_FB_WIN_FLAG_INVERT_H)
|
||||
win->flags |= TEGRA_WIN_FLAG_INVERT_H;
|
||||
if (flip_win->attr.flags & TEGRA_FB_WIN_FLAG_INVERT_V)
|
||||
win->flags |= TEGRA_WIN_FLAG_INVERT_V;
|
||||
if (flip_win->attr.flags & TEGRA_FB_WIN_FLAG_TILED)
|
||||
win->flags |= TEGRA_WIN_FLAG_TILED;
|
||||
|
||||
win->fmt = flip_win->attr.pixformat;
|
||||
win->x = flip_win->attr.x;
|
||||
win->y = flip_win->attr.y;
|
||||
win->w = flip_win->attr.w;
|
||||
win->h = flip_win->attr.h;
|
||||
win->out_x = flip_win->attr.out_x;
|
||||
win->out_y = flip_win->attr.out_y;
|
||||
win->out_w = flip_win->attr.out_w;
|
||||
win->out_h = flip_win->attr.out_h;
|
||||
win->z = flip_win->attr.z;
|
||||
win->cur_handle = flip_win->handle;
|
||||
|
||||
/* STOPSHIP verify that this won't read outside of the surface */
|
||||
win->phys_addr = flip_win->phys_addr + flip_win->attr.offset;
|
||||
win->offset_u = flip_win->attr.offset_u + flip_win->attr.offset;
|
||||
win->offset_v = flip_win->attr.offset_v + flip_win->attr.offset;
|
||||
win->stride = flip_win->attr.stride;
|
||||
win->stride_uv = flip_win->attr.stride_uv;
|
||||
|
||||
if ((s32)flip_win->attr.pre_syncpt_id >= 0) {
|
||||
nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt,
|
||||
flip_win->attr.pre_syncpt_id,
|
||||
flip_win->attr.pre_syncpt_val,
|
||||
msecs_to_jiffies(500));
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra_fb_flip_worker(struct work_struct *work)
|
||||
{
|
||||
struct tegra_fb_flip_data *data =
|
||||
container_of(work, struct tegra_fb_flip_data, work);
|
||||
struct tegra_fb_info *tegra_fb = data->fb;
|
||||
struct tegra_dc_win *win;
|
||||
struct tegra_dc_win *wins[TEGRA_FB_FLIP_N_WINDOWS];
|
||||
struct nvmap_handle_ref *unpin_handles[TEGRA_FB_FLIP_N_WINDOWS];
|
||||
int i, nr_win = 0, nr_unpin = 0;
|
||||
|
||||
data = container_of(work, struct tegra_fb_flip_data, work);
|
||||
|
||||
for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) {
|
||||
struct tegra_fb_flip_win *flip_win = &data->win[i];
|
||||
int idx = flip_win->attr.index;
|
||||
win = tegra_dc_get_window(tegra_fb->win->dc, idx);
|
||||
|
||||
if (!win)
|
||||
continue;
|
||||
|
||||
if (win->flags && win->cur_handle)
|
||||
unpin_handles[nr_unpin++] = win->cur_handle;
|
||||
|
||||
tegra_fb_set_windowattr(tegra_fb, win, &data->win[i]);
|
||||
|
||||
wins[nr_win++] = win;
|
||||
|
||||
#if 0
|
||||
if (flip_win->attr.pre_syncpt_id < 0)
|
||||
continue;
|
||||
printk("%08x %08x\n",
|
||||
flip_win->attr.pre_syncpt_id,
|
||||
flip_win->attr.pre_syncpt_val);
|
||||
|
||||
nvhost_syncpt_wait_timeout(&tegra_fb->ndev->host->syncpt,
|
||||
flip_win->attr.pre_syncpt_id,
|
||||
flip_win->attr.pre_syncpt_val,
|
||||
msecs_to_jiffies(500));
|
||||
#endif
|
||||
}
|
||||
|
||||
tegra_dc_set_dynamic_emc(wins, nr_win);
|
||||
tegra_dc_update_windows(wins, nr_win);
|
||||
/* TODO: implement swapinterval here */
|
||||
tegra_dc_sync_windows(wins, nr_win);
|
||||
|
||||
tegra_dc_incr_syncpt_min(tegra_fb->win->dc, data->syncpt_max);
|
||||
|
||||
/* unpin and deref previous front buffers */
|
||||
for (i = 0; i < nr_unpin; i++) {
|
||||
nvmap_unpin(tegra_fb->fb_nvmap, unpin_handles[i]);
|
||||
nvmap_free(tegra_fb->fb_nvmap, unpin_handles[i]);
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static int tegra_fb_flip(struct tegra_fb_info *tegra_fb,
|
||||
struct tegra_fb_flip_args *args)
|
||||
{
|
||||
struct tegra_fb_flip_data *data;
|
||||
struct tegra_fb_flip_win *flip_win;
|
||||
u32 syncpt_max;
|
||||
int i, err;
|
||||
|
||||
if (WARN_ON(!tegra_fb->user_nvmap))
|
||||
return -EFAULT;
|
||||
|
||||
if (WARN_ON(!tegra_fb->ndev))
|
||||
return -EFAULT;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (data == NULL) {
|
||||
dev_err(&tegra_fb->ndev->dev,
|
||||
"can't allocate memory for flip\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_WORK(&data->work, tegra_fb_flip_worker);
|
||||
data->fb = tegra_fb;
|
||||
|
||||
for (i = 0; i < TEGRA_FB_FLIP_N_WINDOWS; i++) {
|
||||
flip_win = &data->win[i];
|
||||
|
||||
memcpy(&flip_win->attr, &args->win[i], sizeof(flip_win->attr));
|
||||
|
||||
err = tegra_fb_pin_window(tegra_fb, flip_win);
|
||||
if (err < 0) {
|
||||
dev_err(&tegra_fb->ndev->dev,
|
||||
"error setting window attributes\n");
|
||||
goto surf_err;
|
||||
}
|
||||
}
|
||||
|
||||
syncpt_max = tegra_dc_incr_syncpt_max(tegra_fb->win->dc);
|
||||
data->syncpt_max = syncpt_max;
|
||||
|
||||
queue_work(tegra_fb->flip_wq, &data->work);
|
||||
|
||||
/*
|
||||
* Before the queued flip_wq get scheduled, we set the EMC clock to the
|
||||
* default value in order to do FLIP without glitch.
|
||||
*/
|
||||
tegra_dc_set_default_emc(tegra_fb->win->dc);
|
||||
|
||||
args->post_syncpt_val = syncpt_max;
|
||||
args->post_syncpt_id = tegra_dc_get_syncpt_id(tegra_fb->win->dc);
|
||||
|
||||
return 0;
|
||||
|
||||
surf_err:
|
||||
while (i--) {
|
||||
if (data->win[i].handle) {
|
||||
nvmap_unpin(tegra_fb->fb_nvmap,
|
||||
data->win[i].handle);
|
||||
nvmap_free(tegra_fb->fb_nvmap,
|
||||
data->win[i].handle);
|
||||
}
|
||||
}
|
||||
kfree(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* TODO: implement private window ioctls to set overlay x,y */
|
||||
|
||||
static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct tegra_fb_info *tegra_fb = info->par;
|
||||
struct tegra_fb_flip_args flip_args;
|
||||
struct tegra_fb_modedb modedb;
|
||||
struct fb_modelist *modelist;
|
||||
int i;
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
switch (cmd) {
|
||||
case FBIO_TEGRA_SET_NVMAP_FD:
|
||||
if (copy_from_user(&fd, (void __user *)arg, sizeof(fd)))
|
||||
return -EFAULT;
|
||||
|
||||
return tegra_fb_set_nvmap_fd(tegra_fb, fd);
|
||||
|
||||
case FBIO_TEGRA_FLIP:
|
||||
if (copy_from_user(&flip_args, (void __user *)arg, sizeof(flip_args)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = tegra_fb_flip(tegra_fb, &flip_args);
|
||||
|
||||
if (copy_to_user((void __user *)arg, &flip_args, sizeof(flip_args)))
|
||||
return -EFAULT;
|
||||
|
||||
return ret;
|
||||
|
||||
case FBIO_TEGRA_GET_MODEDB:
|
||||
if (copy_from_user(&modedb, (void __user *)arg, sizeof(modedb)))
|
||||
return -EFAULT;
|
||||
@ -612,8 +284,6 @@ static int tegra_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long
|
||||
|
||||
static struct fb_ops tegra_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_open = tegra_fb_open,
|
||||
.fb_release = tegra_fb_release,
|
||||
.fb_check_var = tegra_fb_check_var,
|
||||
.fb_set_par = tegra_fb_set_par,
|
||||
.fb_setcolreg = tegra_fb_setcolreg,
|
||||
@ -717,20 +387,6 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
|
||||
tegra_fb->fb_mem = fb_mem;
|
||||
tegra_fb->xres = fb_data->xres;
|
||||
tegra_fb->yres = fb_data->yres;
|
||||
tegra_fb->fb_nvmap = nvmap_create_client(nvmap_dev, "tegra-fb");
|
||||
if (!tegra_fb->fb_nvmap) {
|
||||
dev_err(&ndev->dev, "couldn't create nvmap client\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_free;
|
||||
}
|
||||
atomic_set(&tegra_fb->in_use, 0);
|
||||
|
||||
tegra_fb->flip_wq = create_singlethread_workqueue(dev_name(&ndev->dev));
|
||||
if (!tegra_fb->flip_wq) {
|
||||
dev_err(&ndev->dev, "couldn't create flip work-queue\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_delete_wq;
|
||||
}
|
||||
|
||||
if (fb_mem) {
|
||||
fb_size = resource_size(fb_mem);
|
||||
@ -739,7 +395,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
|
||||
if (!fb_base) {
|
||||
dev_err(&ndev->dev, "fb can't be mapped\n");
|
||||
ret = -EBUSY;
|
||||
goto err_put_client;
|
||||
goto err_free;
|
||||
}
|
||||
tegra_fb->valid = true;
|
||||
}
|
||||
@ -808,7 +464,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
|
||||
|
||||
if (fb_data->flags & TEGRA_FB_FLIP_ON_PROBE) {
|
||||
tegra_dc_set_default_emc(tegra_fb->win->dc);
|
||||
tegra_dc_set_dynamic_emc(&tegra_fb->win, 1);
|
||||
// tegra_dc_set_dynamic_emc(&tegra_fb->win, 1);
|
||||
tegra_dc_update_windows(&tegra_fb->win, 1);
|
||||
tegra_dc_sync_windows(&tegra_fb->win, 1);
|
||||
}
|
||||
@ -816,11 +472,8 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
|
||||
return tegra_fb;
|
||||
|
||||
err_iounmap_fb:
|
||||
if (fb_base)
|
||||
iounmap(fb_base);
|
||||
err_put_client:
|
||||
nvmap_client_put(tegra_fb->fb_nvmap);
|
||||
err_delete_wq:
|
||||
destroy_workqueue(tegra_fb->flip_wq);
|
||||
err_free:
|
||||
framebuffer_release(info);
|
||||
err:
|
||||
@ -831,19 +484,8 @@ void tegra_fb_unregister(struct tegra_fb_info *fb_info)
|
||||
{
|
||||
struct fb_info *info = fb_info->info;
|
||||
|
||||
if (fb_info->win->cur_handle) {
|
||||
nvmap_unpin(fb_info->fb_nvmap, fb_info->win->cur_handle);
|
||||
nvmap_free(fb_info->fb_nvmap, fb_info->win->cur_handle);
|
||||
}
|
||||
|
||||
if (fb_info->fb_nvmap)
|
||||
nvmap_client_put(fb_info->fb_nvmap);
|
||||
|
||||
unregister_framebuffer(info);
|
||||
|
||||
flush_workqueue(fb_info->flip_wq);
|
||||
destroy_workqueue(fb_info->flip_wq);
|
||||
|
||||
iounmap(info->screen_base);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
|
||||
@ -20,71 +20,11 @@
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/ioctl.h>
|
||||
|
||||
#define TEGRA_FB_WIN_FMT_P1 0
|
||||
#define TEGRA_FB_WIN_FMT_P2 1
|
||||
#define TEGRA_FB_WIN_FMT_P4 2
|
||||
#define TEGRA_FB_WIN_FMT_P8 3
|
||||
#define TEGRA_FB_WIN_FMT_B4G4R4A4 4
|
||||
#define TEGRA_FB_WIN_FMT_B5G5R5A 5
|
||||
#define TEGRA_FB_WIN_FMT_B5G6R5 6
|
||||
#define TEGRA_FB_WIN_FMT_AB5G5R5 7
|
||||
#define TEGRA_FB_WIN_FMT_B8G8R8A8 12
|
||||
#define TEGRA_FB_WIN_FMT_R8G8B8A8 13
|
||||
#define TEGRA_FB_WIN_FMT_B6x2G6x2R6x2A8 14
|
||||
#define TEGRA_FB_WIN_FMT_R6x2G6x2B6x2A8 15
|
||||
#define TEGRA_FB_WIN_FMT_YCbCr422 16
|
||||
#define TEGRA_FB_WIN_FMT_YUV422 17
|
||||
#define TEGRA_FB_WIN_FMT_YCbCr420P 18
|
||||
#define TEGRA_FB_WIN_FMT_YUV420P 19
|
||||
#define TEGRA_FB_WIN_FMT_YCbCr422P 20
|
||||
#define TEGRA_FB_WIN_FMT_YUV422P 21
|
||||
#define TEGRA_FB_WIN_FMT_YCbCr422R 22
|
||||
#define TEGRA_FB_WIN_FMT_YUV422R 23
|
||||
#define TEGRA_FB_WIN_FMT_YCbCr422RA 24
|
||||
#define TEGRA_FB_WIN_FMT_YUV422RA 25
|
||||
|
||||
#define TEGRA_FB_WIN_BLEND_NONE 0
|
||||
#define TEGRA_FB_WIN_BLEND_PREMULT 1
|
||||
#define TEGRA_FB_WIN_BLEND_COVERAGE 2
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
#define TEGRA_FB_WIN_FLAG_INVERT_H (1 << 0)
|
||||
#define TEGRA_FB_WIN_FLAG_INVERT_V (1 << 1)
|
||||
#define TEGRA_FB_WIN_FLAG_TILED (1 << 2)
|
||||
|
||||
/* set index to -1 to ignore window data */
|
||||
struct tegra_fb_windowattr {
|
||||
__s32 index;
|
||||
__u32 buff_id;
|
||||
__u32 flags;
|
||||
__u32 blend;
|
||||
__u32 offset;
|
||||
__u32 offset_u;
|
||||
__u32 offset_v;
|
||||
__u32 stride;
|
||||
__u32 stride_uv;
|
||||
__u32 pixformat;
|
||||
__u32 x;
|
||||
__u32 y;
|
||||
__u32 w;
|
||||
__u32 h;
|
||||
__u32 out_x;
|
||||
__u32 out_y;
|
||||
__u32 out_w;
|
||||
__u32 out_h;
|
||||
__u32 z;
|
||||
__u32 pre_syncpt_id;
|
||||
__u32 pre_syncpt_val;
|
||||
};
|
||||
|
||||
#define TEGRA_FB_FLIP_N_WINDOWS 3
|
||||
|
||||
struct tegra_fb_flip_args {
|
||||
struct tegra_fb_windowattr win[TEGRA_FB_FLIP_N_WINDOWS];
|
||||
__u32 post_syncpt_id;
|
||||
__u32 post_syncpt_val;
|
||||
};
|
||||
|
||||
struct tegra_fb_modedb {
|
||||
struct fb_var_screeninfo *modedb;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user