Commit 537d8478 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://gitorious.org/linux-omap-dss2/linux

* 'for-linus' of git://gitorious.org/linux-omap-dss2/linux: (64 commits)
  OMAP: DSS2: OMAPFB: add support for FBIO_WAITFORVSYNC
  OMAP: DSS2: Replace strncmp() with sysfs_streq() in overlay_manager_store()
  OMAP: DSS2: Fix error path in omap_dsi_update()
  OMAP: DSS2: TDO35S: fix video signaling
  OMAP: DSS2: OMAPFB: Fix invalid bpp for PAL and NTSC modes
  OMAP: DSS2: OMAPFB: Fix probe error path
  OMAP3EVM: Replace vdvi regulator supply with vdds_dsi
  OMAP: DSS2: Remove extra return statement
  OMAP: DSS2: adjust YUV overlay width to be even
  OMAP: DSS2: OMAPFB: Fix sysfs mirror input check
  OMAP: DSS2: OMAPFB: Remove redundant color register range check
  OMAP: DSS2: OMAPFB: Remove redundant rotate range check
  OMAP: DSS2: OMAPFB: Check fb2display() return value
  OMAP: DSS2: Taal: Optimize enable_te, rotate, mirror when value unchanged
  OMAP: DSS2: DSI: detect unsupported update requests
  OMAP: DSS2: DSI: increase FIFO low threshold
  OMAP: DSS2: DSI: Add error IRQ mask for DSI complexIO
  OMAP: DSS2: DSI: Remove BTA after set_max_rx_packet_size
  OMAP: DSS2: change manual update scaling setup
  OMAP: DSS2: DSI: use BTA to end the frame transfer
  ...
parents d71048e2 ece350d3
...@@ -514,14 +514,11 @@ static struct regulator_init_data omap3_evm_vdac = { ...@@ -514,14 +514,11 @@ static struct regulator_init_data omap3_evm_vdac = {
}; };
/* VPLL2 for digital video outputs */ /* VPLL2 for digital video outputs */
static struct regulator_consumer_supply omap3_evm_vpll2_supply = { static struct regulator_consumer_supply omap3_evm_vpll2_supply =
.supply = "vdvi", REGULATOR_SUPPLY("vdds_dsi", "omapdss");
.dev = &omap3_evm_lcd_device.dev,
};
static struct regulator_init_data omap3_evm_vpll2 = { static struct regulator_init_data omap3_evm_vpll2 = {
.constraints = { .constraints = {
.name = "VDVI",
.min_uV = 1800000, .min_uV = 1800000,
.max_uV = 1800000, .max_uV = 1800000,
.apply_uV = true, .apply_uV = true,
......
...@@ -238,7 +238,7 @@ int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param); ...@@ -238,7 +238,7 @@ int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param);
int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len); int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen); int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data); int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data);
int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data); int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2);
int dsi_vc_set_max_rx_packet_size(int channel, u16 len); int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
int dsi_vc_send_null(int channel); int dsi_vc_send_null(int channel);
int dsi_vc_send_bta_sync(int channel); int dsi_vc_send_bta_sync(int channel);
...@@ -277,8 +277,8 @@ struct omap_video_timings { ...@@ -277,8 +277,8 @@ struct omap_video_timings {
* identify the mode, and does not actually use the configs * identify the mode, and does not actually use the configs
* itself. However, the configs should be something that * itself. However, the configs should be something that
* a normal monitor can also show */ * a normal monitor can also show */
const extern struct omap_video_timings omap_dss_pal_timings; extern const struct omap_video_timings omap_dss_pal_timings;
const extern struct omap_video_timings omap_dss_ntsc_timings; extern const struct omap_video_timings omap_dss_ntsc_timings;
#endif #endif
struct omap_overlay_info { struct omap_overlay_info {
...@@ -560,7 +560,8 @@ void omapdss_dsi_vc_enable_hs(int channel, bool enable); ...@@ -560,7 +560,8 @@ void omapdss_dsi_vc_enable_hs(int channel, bool enable);
int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable); int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
int omap_dsi_prepare_update(struct omap_dss_device *dssdev, int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
u16 *x, u16 *y, u16 *w, u16 *h); u16 *x, u16 *y, u16 *w, u16 *h,
bool enlarge_update_area);
int omap_dsi_update(struct omap_dss_device *dssdev, int omap_dsi_update(struct omap_dss_device *dssdev,
int channel, int channel,
u16 x, u16 y, u16 w, u16 h, u16 x, u16 y, u16 w, u16 h,
......
#ifndef __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H
#define __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H
#include "display.h"
/**
* struct nokia_dsi_panel_data - Nokia DSI panel driver configuration
* @name: panel name
* @use_ext_te: use external TE
* @ext_te_gpio: external TE GPIO
* @use_esd_check: perform ESD checks
* @max_backlight_level: maximum backlight level
* @set_backlight: pointer to backlight set function
* @get_backlight: pointer to backlight get function
*/
struct nokia_dsi_panel_data {
const char *name;
int reset_gpio;
bool use_ext_te;
int ext_te_gpio;
bool use_esd_check;
int max_backlight_level;
int (*set_backlight)(struct omap_dss_device *dssdev, int level);
int (*get_backlight)(struct omap_dss_device *dssdev);
};
#endif /* __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H */
This diff is collapsed.
...@@ -73,8 +73,12 @@ static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev) ...@@ -73,8 +73,12 @@ static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev) static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev)
{ {
dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | dssdev->panel.config = OMAP_DSS_LCD_TFT |
OMAP_DSS_LCD_IHS; OMAP_DSS_LCD_IVS |
OMAP_DSS_LCD_IHS |
OMAP_DSS_LCD_IPC |
OMAP_DSS_LCD_ONOFF;
dssdev->panel.timings = toppoly_tdo_panel_timings; dssdev->panel.timings = toppoly_tdo_panel_timings;
return 0; return 0;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/hardirq.h>
#include <plat/sram.h> #include <plat/sram.h>
#include <plat/clock.h> #include <plat/clock.h>
...@@ -335,7 +336,7 @@ void dispc_save_context(void) ...@@ -335,7 +336,7 @@ void dispc_save_context(void)
void dispc_restore_context(void) void dispc_restore_context(void)
{ {
RR(SYSCONFIG); RR(SYSCONFIG);
RR(IRQENABLE); /*RR(IRQENABLE);*/
/*RR(CONTROL);*/ /*RR(CONTROL);*/
RR(CONFIG); RR(CONFIG);
RR(DEFAULT_COLOR0); RR(DEFAULT_COLOR0);
...@@ -472,6 +473,15 @@ void dispc_restore_context(void) ...@@ -472,6 +473,15 @@ void dispc_restore_context(void)
/* enable last, because LCD & DIGIT enable are here */ /* enable last, because LCD & DIGIT enable are here */
RR(CONTROL); RR(CONTROL);
/* clear spurious SYNC_LOST_DIGIT interrupts */
dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
/*
* enable last so IRQs won't trigger before
* the context is fully restored
*/
RR(IRQENABLE);
} }
#undef SR #undef SR
...@@ -3019,7 +3029,7 @@ void dispc_fake_vsync_irq(void) ...@@ -3019,7 +3029,7 @@ void dispc_fake_vsync_irq(void)
u32 irqstatus = DISPC_IRQ_VSYNC; u32 irqstatus = DISPC_IRQ_VSYNC;
int i; int i;
local_irq_disable(); WARN_ON(!in_interrupt());
for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
struct omap_dispc_isr_data *isr_data; struct omap_dispc_isr_data *isr_data;
...@@ -3031,8 +3041,6 @@ void dispc_fake_vsync_irq(void) ...@@ -3031,8 +3041,6 @@ void dispc_fake_vsync_irq(void)
if (isr_data->mask & irqstatus) if (isr_data->mask & irqstatus)
isr_data->isr(isr_data->arg, irqstatus); isr_data->isr(isr_data->arg, irqstatus);
} }
local_irq_enable();
} }
#endif #endif
......
...@@ -82,6 +82,9 @@ static ssize_t display_upd_mode_store(struct device *dev, ...@@ -82,6 +82,9 @@ static ssize_t display_upd_mode_store(struct device *dev,
int val, r; int val, r;
enum omap_dss_update_mode mode; enum omap_dss_update_mode mode;
if (!dssdev->driver->set_update_mode)
return -EINVAL;
val = simple_strtoul(buf, NULL, 10); val = simple_strtoul(buf, NULL, 10);
switch (val) { switch (val) {
...@@ -343,7 +346,6 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) ...@@ -343,7 +346,6 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
case OMAP_DISPLAY_TYPE_VENC: case OMAP_DISPLAY_TYPE_VENC:
case OMAP_DISPLAY_TYPE_SDI: case OMAP_DISPLAY_TYPE_SDI:
return 24; return 24;
return 24;
default: default:
BUG(); BUG();
} }
......
This diff is collapsed.
...@@ -265,6 +265,9 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src) ...@@ -265,6 +265,9 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
if (clk_src == DSS_SRC_DSI1_PLL_FCLK)
dsi_wait_dsi1_pll_active();
REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */
dss.dispc_clk_source = clk_src; dss.dispc_clk_source = clk_src;
...@@ -279,6 +282,9 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) ...@@ -279,6 +282,9 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
if (clk_src == DSS_SRC_DSI2_PLL_FCLK)
dsi_wait_dsi2_pll_active();
REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
dss.dsi_clk_source = clk_src; dss.dsi_clk_source = clk_src;
......
...@@ -199,7 +199,8 @@ int dss_init_overlay_managers(struct platform_device *pdev); ...@@ -199,7 +199,8 @@ int dss_init_overlay_managers(struct platform_device *pdev);
void dss_uninit_overlay_managers(struct platform_device *pdev); void dss_uninit_overlay_managers(struct platform_device *pdev);
int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
void dss_setup_partial_planes(struct omap_dss_device *dssdev, void dss_setup_partial_planes(struct omap_dss_device *dssdev,
u16 *x, u16 *y, u16 *w, u16 *h); u16 *x, u16 *y, u16 *w, u16 *h,
bool enlarge_update_area);
void dss_start_update(struct omap_dss_device *dssdev); void dss_start_update(struct omap_dss_device *dssdev);
/* overlay */ /* overlay */
...@@ -281,6 +282,8 @@ void dsi_pll_uninit(void); ...@@ -281,6 +282,8 @@ void dsi_pll_uninit(void);
void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
u32 fifo_size, enum omap_burst_size *burst_size, u32 fifo_size, enum omap_burst_size *burst_size,
u32 *fifo_low, u32 *fifo_high); u32 *fifo_low, u32 *fifo_high);
void dsi_wait_dsi1_pll_active(void);
void dsi_wait_dsi2_pll_active(void);
#else #else
static inline int dsi_init(struct platform_device *pdev) static inline int dsi_init(struct platform_device *pdev)
{ {
...@@ -289,6 +292,12 @@ static inline int dsi_init(struct platform_device *pdev) ...@@ -289,6 +292,12 @@ static inline int dsi_init(struct platform_device *pdev)
static inline void dsi_exit(void) static inline void dsi_exit(void)
{ {
} }
static inline void dsi_wait_dsi1_pll_active(void)
{
}
static inline void dsi_wait_dsi2_pll_active(void)
{
}
#endif #endif
/* DPI */ /* DPI */
......
...@@ -440,6 +440,10 @@ struct manager_cache_data { ...@@ -440,6 +440,10 @@ struct manager_cache_data {
/* manual update region */ /* manual update region */
u16 x, y, w, h; u16 x, y, w, h;
/* enlarge the update area if the update area contains scaled
* overlays */
bool enlarge_update_area;
}; };
static struct { static struct {
...@@ -525,7 +529,7 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) ...@@ -525,7 +529,7 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
int i; int i;
struct omap_dss_device *dssdev = mgr->device; struct omap_dss_device *dssdev = mgr->device;
if (!dssdev) if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return 0; return 0;
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
...@@ -596,11 +600,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) ...@@ -596,11 +600,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
int r; int r;
int i; int i;
if (!ovl->manager || !ovl->manager->device) if (!ovl->manager)
return 0; return 0;
dssdev = ovl->manager->device; dssdev = ovl->manager->device;
if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
return 0;
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
channel = OMAP_DSS_CHANNEL_DIGIT; channel = OMAP_DSS_CHANNEL_DIGIT;
...@@ -718,6 +725,7 @@ static int configure_overlay(enum omap_plane plane) ...@@ -718,6 +725,7 @@ static int configure_overlay(enum omap_plane plane)
u16 x, y, w, h; u16 x, y, w, h;
u32 paddr; u32 paddr;
int r; int r;
u16 orig_w, orig_h, orig_outw, orig_outh;
DSSDBGF("%d", plane); DSSDBGF("%d", plane);
...@@ -738,8 +746,16 @@ static int configure_overlay(enum omap_plane plane) ...@@ -738,8 +746,16 @@ static int configure_overlay(enum omap_plane plane)
outh = c->out_height == 0 ? c->height : c->out_height; outh = c->out_height == 0 ? c->height : c->out_height;
paddr = c->paddr; paddr = c->paddr;
orig_w = w;
orig_h = h;
orig_outw = outw;
orig_outh = outh;
if (c->manual_update && mc->do_manual_update) { if (c->manual_update && mc->do_manual_update) {
unsigned bpp; unsigned bpp;
unsigned scale_x_m = w, scale_x_d = outw;
unsigned scale_y_m = h, scale_y_d = outh;
/* If the overlay is outside the update region, disable it */ /* If the overlay is outside the update region, disable it */
if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
x, y, outw, outh)) { x, y, outw, outh)) {
...@@ -770,38 +786,47 @@ static int configure_overlay(enum omap_plane plane) ...@@ -770,38 +786,47 @@ static int configure_overlay(enum omap_plane plane)
BUG(); BUG();
} }
if (dispc_is_overlay_scaled(c)) { if (mc->x > c->pos_x) {
/* If the overlay is scaled, the update area has x = 0;
* already been enlarged to cover the whole overlay. We outw -= (mc->x - c->pos_x);
* only need to adjust x/y here */ paddr += (mc->x - c->pos_x) *
x = c->pos_x - mc->x; scale_x_m / scale_x_d * bpp / 8;
y = c->pos_y - mc->y;
} else { } else {
if (mc->x > c->pos_x) { x = c->pos_x - mc->x;
x = 0; }
w -= (mc->x - c->pos_x);
paddr += (mc->x - c->pos_x) * bpp / 8;
} else {
x = c->pos_x - mc->x;
}
if (mc->y > c->pos_y) {
y = 0;
h -= (mc->y - c->pos_y);
paddr += (mc->y - c->pos_y) * c->screen_width *
bpp / 8;
} else {
y = c->pos_y - mc->y;
}
if (mc->w < (x+w))
w -= (x+w) - (mc->w);
if (mc->h < (y+h)) if (mc->y > c->pos_y) {
h -= (y+h) - (mc->h); y = 0;
outh -= (mc->y - c->pos_y);
paddr += (mc->y - c->pos_y) *
scale_y_m / scale_y_d *
c->screen_width * bpp / 8;
} else {
y = c->pos_y - mc->y;
}
outw = w; if (mc->w < (x + outw))
outh = h; outw -= (x + outw) - (mc->w);
if (mc->h < (y + outh))
outh -= (y + outh) - (mc->h);
w = w * outw / orig_outw;
h = h * outh / orig_outh;
/* YUV mode overlay's input width has to be even and the
* algorithm above may adjust the width to be odd.
*
* Here we adjust the width if needed, preferring to increase
* the width if the original width was bigger.
*/
if ((w & 1) &&
(c->color_mode == OMAP_DSS_COLOR_YUV2 ||
c->color_mode == OMAP_DSS_COLOR_UYVY)) {
if (orig_w > w)
w += 1;
else
w -= 1;
} }
} }
...@@ -960,7 +985,7 @@ static void make_even(u16 *x, u16 *w) ...@@ -960,7 +985,7 @@ static void make_even(u16 *x, u16 *w)
/* Configure dispc for partial update. Return possibly modified update /* Configure dispc for partial update. Return possibly modified update
* area */ * area */
void dss_setup_partial_planes(struct omap_dss_device *dssdev, void dss_setup_partial_planes(struct omap_dss_device *dssdev,
u16 *xi, u16 *yi, u16 *wi, u16 *hi) u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
{ {
struct overlay_cache_data *oc; struct overlay_cache_data *oc;
struct manager_cache_data *mc; struct manager_cache_data *mc;
...@@ -969,6 +994,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev, ...@@ -969,6 +994,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
int i; int i;
u16 x, y, w, h; u16 x, y, w, h;
unsigned long flags; unsigned long flags;
bool area_changed;
x = *xi; x = *xi;
y = *yi; y = *yi;
...@@ -989,73 +1015,91 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev, ...@@ -989,73 +1015,91 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
spin_lock_irqsave(&dss_cache.lock, flags); spin_lock_irqsave(&dss_cache.lock, flags);
/* We need to show the whole overlay if it is scaled. So look for /*
* those, and make the update area larger if found. * Execute the outer loop until the inner loop has completed
* Also mark the overlay cache dirty */ * once without increasing the update area. This will ensure that
for (i = 0; i < num_ovls; ++i) { * all scaled overlays end up completely within the update area.
unsigned x1, y1, x2, y2; */
unsigned outw, outh; do {
area_changed = false;
oc = &dss_cache.overlay_cache[i]; /* We need to show the whole overlay if it is scaled. So look
* for those, and make the update area larger if found.
* Also mark the overlay cache dirty */
for (i = 0; i < num_ovls; ++i) {
unsigned x1, y1, x2, y2;
unsigned outw, outh;
if (oc->channel != mgr->id) oc = &dss_cache.overlay_cache[i];
continue;
oc->dirty = true; if (oc->channel != mgr->id)
continue;
if (!oc->enabled) oc->dirty = true;
continue;
if (!dispc_is_overlay_scaled(oc)) if (!enlarge_update_area)
continue; continue;
outw = oc->out_width == 0 ? oc->width : oc->out_width; if (!oc->enabled)
outh = oc->out_height == 0 ? oc->height : oc->out_height; continue;
/* is the overlay outside the update region? */ if (!dispc_is_overlay_scaled(oc))
if (!rectangle_intersects(x, y, w, h, continue;
oc->pos_x, oc->pos_y,
outw, outh))
continue;
/* if the overlay totally inside the update region? */ outw = oc->out_width == 0 ?
if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh, oc->width : oc->out_width;
x, y, w, h)) outh = oc->out_height == 0 ?
continue; oc->height : oc->out_height;
/* is the overlay outside the update region? */
if (!rectangle_intersects(x, y, w, h,
oc->pos_x, oc->pos_y,
outw, outh))
continue;
if (x > oc->pos_x) /* if the overlay totally inside the update region? */
x1 = oc->pos_x; if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh,
else x, y, w, h))
x1 = x; continue;
if (y > oc->pos_y) if (x > oc->pos_x)
y1 = oc->pos_y; x1 = oc->pos_x;
else else
y1 = y; x1 = x;
if ((x + w) < (oc->pos_x + outw)) if (y > oc->pos_y)
x2 = oc->pos_x + outw; y1 = oc->pos_y;
else else
x2 = x + w; y1 = y;
if ((y + h) < (oc->pos_y + outh)) if ((x + w) < (oc->pos_x + outw))
y2 = oc->pos_y + outh; x2 = oc->pos_x + outw;
else else
y2 = y + h; x2 = x + w;
x = x1; if ((y + h) < (oc->pos_y + outh))
y = y1; y2 = oc->pos_y + outh;
w = x2 - x1; else
h = y2 - y1; y2 = y + h;
make_even(&x, &w); x = x1;
y = y1;
w = x2 - x1;
h = y2 - y1;
DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", make_even(&x, &w);
DSSDBG("changing upd area due to ovl(%d) "
"scaling %d,%d %dx%d\n",
i, x, y, w, h); i, x, y, w, h);
}
area_changed = true;
}
} while (area_changed);
mc = &dss_cache.manager_cache[mgr->id]; mc = &dss_cache.manager_cache[mgr->id];
mc->do_manual_update = true; mc->do_manual_update = true;
mc->enlarge_update_area = enlarge_update_area;
mc->x = x; mc->x = x;
mc->y = y; mc->y = y;
mc->w = w; mc->w = w;
......
...@@ -65,7 +65,7 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, ...@@ -65,7 +65,7 @@ static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
mgr = omap_dss_get_overlay_manager(i); mgr = omap_dss_get_overlay_manager(i);
if (strncmp(buf, mgr->name, len) == 0) if (sysfs_streq(buf, mgr->name))
break; break;
mgr = NULL; mgr = NULL;
......
...@@ -886,7 +886,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, ...@@ -886,7 +886,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
return -EINVAL; return -EINVAL;
if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
dss_setup_partial_planes(dssdev, x, y, w, h); dss_setup_partial_planes(dssdev, x, y, w, h, true);
dispc_set_lcd_size(*w, *h); dispc_set_lcd_size(*w, *h);
} }
......
...@@ -34,12 +34,37 @@ ...@@ -34,12 +34,37 @@
#include "omapfb.h" #include "omapfb.h"
static u8 get_mem_idx(struct omapfb_info *ofbi)
{
if (ofbi->id == ofbi->region->id)
return 0;
return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
}
static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
u8 mem_idx)
{
struct omapfb2_device *fbdev = ofbi->fbdev;
if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
mem_idx &= OMAPFB_MEM_IDX_MASK;
else
mem_idx = ofbi->id;
if (mem_idx >= fbdev->num_fbs)
return NULL;
return &fbdev->regions[mem_idx];
}
static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
{ {
struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev; struct omapfb2_device *fbdev = ofbi->fbdev;
struct omap_overlay *ovl; struct omap_overlay *ovl;
struct omap_overlay_info info; struct omap_overlay_info old_info;
struct omapfb2_mem_region *old_rg, *new_rg;
int r = 0; int r = 0;
DBG("omapfb_setup_plane\n"); DBG("omapfb_setup_plane\n");
...@@ -52,36 +77,106 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) ...@@ -52,36 +77,106 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
/* XXX uses only the first overlay */ /* XXX uses only the first overlay */
ovl = ofbi->overlays[0]; ovl = ofbi->overlays[0];
if (pi->enabled && !ofbi->region.size) { old_rg = ofbi->region;
new_rg = get_mem_region(ofbi, pi->mem_idx);
if (!new_rg) {
r = -EINVAL;
goto out;
}
/* Take the locks in a specific order to keep lockdep happy */
if (old_rg->id < new_rg->id) {
omapfb_get_mem_region(old_rg);
omapfb_get_mem_region(new_rg);
} else if (new_rg->id < old_rg->id) {
omapfb_get_mem_region(new_rg);
omapfb_get_mem_region(old_rg);
} else
omapfb_get_mem_region(old_rg);
if (pi->enabled && !new_rg->size) {
/* /*
* This plane's memory was freed, can't enable it * This plane's memory was freed, can't enable it
* until it's reallocated. * until it's reallocated.
*/ */
r = -EINVAL; r = -EINVAL;
goto out; goto put_mem;
} }
ovl->get_overlay_info(ovl, &info); ovl->get_overlay_info(ovl, &old_info);
info.pos_x = pi->pos_x; if (old_rg != new_rg) {
info.pos_y = pi->pos_y; ofbi->region = new_rg;
info.out_width = pi->out_width; set_fb_fix(fbi);
info.out_height = pi->out_height; }
info.enabled = pi->enabled;
r = ovl->set_overlay_info(ovl, &info); if (pi->enabled) {
if (r) struct omap_overlay_info info;
goto out;
if (ovl->manager) { r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
r = ovl->manager->apply(ovl->manager); pi->out_width, pi->out_height);
if (r) if (r)
goto out; goto undo;
ovl->get_overlay_info(ovl, &info);
if (!info.enabled) {
info.enabled = pi->enabled;
r = ovl->set_overlay_info(ovl, &info);
if (r)
goto undo;
}
} else {
struct omap_overlay_info info;
ovl->get_overlay_info(ovl, &info);
info.enabled = pi->enabled;
info.pos_x = pi->pos_x;
info.pos_y = pi->pos_y;
info.out_width = pi->out_width;
info.out_height = pi->out_height;
r = ovl->set_overlay_info(ovl, &info);
if (r)
goto undo;
} }
out: if (ovl->manager)
if (r) ovl->manager->apply(ovl->manager);
dev_err(fbdev->dev, "setup_plane failed\n");
/* Release the locks in a specific order to keep lockdep happy */
if (old_rg->id > new_rg->id) {
omapfb_put_mem_region(old_rg);
omapfb_put_mem_region(new_rg);
} else if (new_rg->id > old_rg->id) {
omapfb_put_mem_region(new_rg);
omapfb_put_mem_region(old_rg);
} else
omapfb_put_mem_region(old_rg);
return 0;
undo:
if (old_rg != new_rg) {
ofbi->region = old_rg;
set_fb_fix(fbi);
}
ovl->set_overlay_info(ovl, &old_info);
put_mem:
/* Release the locks in a specific order to keep lockdep happy */
if (old_rg->id > new_rg->id) {
omapfb_put_mem_region(old_rg);
omapfb_put_mem_region(new_rg);
} else if (new_rg->id > old_rg->id) {
omapfb_put_mem_region(new_rg);
omapfb_put_mem_region(old_rg);
} else
omapfb_put_mem_region(old_rg);
out:
dev_err(fbdev->dev, "setup_plane failed\n");
return r; return r;
} }
...@@ -92,8 +187,8 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) ...@@ -92,8 +187,8 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
if (ofbi->num_overlays != 1) { if (ofbi->num_overlays != 1) {
memset(pi, 0, sizeof(*pi)); memset(pi, 0, sizeof(*pi));
} else { } else {
struct omap_overlay_info *ovli;
struct omap_overlay *ovl; struct omap_overlay *ovl;
struct omap_overlay_info *ovli;
ovl = ofbi->overlays[0]; ovl = ofbi->overlays[0];
ovli = &ovl->info; ovli = &ovl->info;
...@@ -103,6 +198,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) ...@@ -103,6 +198,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
pi->enabled = ovli->enabled; pi->enabled = ovli->enabled;
pi->channel_out = 0; /* xxx */ pi->channel_out = 0; /* xxx */
pi->mirror = 0; pi->mirror = 0;
pi->mem_idx = get_mem_idx(ofbi);
pi->out_width = ovli->out_width; pi->out_width = ovli->out_width;
pi->out_height = ovli->out_height; pi->out_height = ovli->out_height;
} }
...@@ -115,7 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) ...@@ -115,7 +211,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev; struct omapfb2_device *fbdev = ofbi->fbdev;
struct omapfb2_mem_region *rg; struct omapfb2_mem_region *rg;
int r, i; int r = 0, i;
size_t size; size_t size;
if (mi->type > OMAPFB_MEMTYPE_MAX) if (mi->type > OMAPFB_MEMTYPE_MAX)
...@@ -123,22 +219,44 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) ...@@ -123,22 +219,44 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
size = PAGE_ALIGN(mi->size); size = PAGE_ALIGN(mi->size);
rg = &ofbi->region; rg = ofbi->region;
for (i = 0; i < ofbi->num_overlays; i++) { down_write_nested(&rg->lock, rg->id);
if (ofbi->overlays[i]->info.enabled) atomic_inc(&rg->lock_count);
return -EBUSY;
if (atomic_read(&rg->map_count)) {
r = -EBUSY;
goto out;
}
for (i = 0; i < fbdev->num_fbs; i++) {
struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
int j;
if (ofbi2->region != rg)
continue;
for (j = 0; j < ofbi2->num_overlays; j++) {
if (ofbi2->overlays[j]->info.enabled) {
r = -EBUSY;
goto out;
}
}
} }
if (rg->size != size || rg->type != mi->type) { if (rg->size != size || rg->type != mi->type) {
r = omapfb_realloc_fbmem(fbi, size, mi->type); r = omapfb_realloc_fbmem(fbi, size, mi->type);
if (r) { if (r) {
dev_err(fbdev->dev, "realloc fbmem failed\n"); dev_err(fbdev->dev, "realloc fbmem failed\n");
return r; goto out;
} }
} }
return 0; out:
atomic_dec(&rg->lock_count);
up_write(&rg->lock);
return r;
} }
static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
...@@ -146,12 +264,14 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) ...@@ -146,12 +264,14 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_mem_region *rg; struct omapfb2_mem_region *rg;
rg = &ofbi->region; rg = omapfb_get_mem_region(ofbi->region);
memset(mi, 0, sizeof(*mi)); memset(mi, 0, sizeof(*mi));
mi->size = rg->size; mi->size = rg->size;
mi->type = rg->type; mi->type = rg->type;
omapfb_put_mem_region(rg);
return 0; return 0;
} }
...@@ -490,6 +610,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) ...@@ -490,6 +610,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
struct omapfb_vram_info vram_info; struct omapfb_vram_info vram_info;
struct omapfb_tearsync_info tearsync_info; struct omapfb_tearsync_info tearsync_info;
struct omapfb_display_info display_info; struct omapfb_display_info display_info;
u32 crt;
} p; } p;
int r = 0; int r = 0;
...@@ -648,6 +769,17 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) ...@@ -648,6 +769,17 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
r = -EFAULT; r = -EFAULT;
break; break;
case FBIO_WAITFORVSYNC:
if (get_user(p.crt, (__u32 __user *)arg)) {
r = -EFAULT;
break;
}
if (p.crt != 0) {
r = -ENODEV;
break;
}
/* FALLTHROUGH */
case OMAPFB_WAITFORVSYNC: case OMAPFB_WAITFORVSYNC:
DBG("ioctl WAITFORVSYNC\n"); DBG("ioctl WAITFORVSYNC\n");
if (!display) { if (!display) {
...@@ -738,7 +870,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) ...@@ -738,7 +870,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
break; break;
} }
if (!display->driver->enable_te) { if (!display || !display->driver->enable_te) {
r = -ENODEV; r = -ENODEV;
break; break;
} }
......
This diff is collapsed.
...@@ -49,6 +49,7 @@ static ssize_t store_rotate_type(struct device *dev, ...@@ -49,6 +49,7 @@ static ssize_t store_rotate_type(struct device *dev,
{ {
struct fb_info *fbi = dev_get_drvdata(dev); struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_mem_region *rg;
enum omap_dss_rotation_type rot_type; enum omap_dss_rotation_type rot_type;
int r; int r;
...@@ -64,9 +65,11 @@ static ssize_t store_rotate_type(struct device *dev, ...@@ -64,9 +65,11 @@ static ssize_t store_rotate_type(struct device *dev,
if (rot_type == ofbi->rotation_type) if (rot_type == ofbi->rotation_type)
goto out; goto out;
if (ofbi->region.size) { rg = omapfb_get_mem_region(ofbi->region);
if (rg->size) {
r = -EBUSY; r = -EBUSY;
goto out; goto put_region;
} }
ofbi->rotation_type = rot_type; ofbi->rotation_type = rot_type;
...@@ -75,6 +78,8 @@ static ssize_t store_rotate_type(struct device *dev, ...@@ -75,6 +78,8 @@ static ssize_t store_rotate_type(struct device *dev,
* Since the VRAM for this FB is not allocated at the moment we don't * Since the VRAM for this FB is not allocated at the moment we don't
* need to do any further parameter checking at this point. * need to do any further parameter checking at this point.
*/ */
put_region:
omapfb_put_mem_region(rg);
out: out:
unlock_fb_info(fbi); unlock_fb_info(fbi);
...@@ -97,7 +102,7 @@ static ssize_t store_mirror(struct device *dev, ...@@ -97,7 +102,7 @@ static ssize_t store_mirror(struct device *dev,
{ {
struct fb_info *fbi = dev_get_drvdata(dev); struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb_info *ofbi = FB2OFB(fbi);
bool mirror; unsigned long mirror;
int r; int r;
struct fb_var_screeninfo new_var; struct fb_var_screeninfo new_var;
...@@ -111,6 +116,8 @@ static ssize_t store_mirror(struct device *dev, ...@@ -111,6 +116,8 @@ static ssize_t store_mirror(struct device *dev,
ofbi->mirror = mirror; ofbi->mirror = mirror;
omapfb_get_mem_region(ofbi->region);
memcpy(&new_var, &fbi->var, sizeof(new_var)); memcpy(&new_var, &fbi->var, sizeof(new_var));
r = check_fb_var(fbi, &new_var); r = check_fb_var(fbi, &new_var);
if (r) if (r)
...@@ -125,6 +132,8 @@ static ssize_t store_mirror(struct device *dev, ...@@ -125,6 +132,8 @@ static ssize_t store_mirror(struct device *dev,
r = count; r = count;
out: out:
omapfb_put_mem_region(ofbi->region);
unlock_fb_info(fbi); unlock_fb_info(fbi);
return r; return r;
...@@ -263,11 +272,15 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, ...@@ -263,11 +272,15 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
DBG("detaching %d\n", ofbi->overlays[i]->id); DBG("detaching %d\n", ofbi->overlays[i]->id);
omapfb_get_mem_region(ofbi->region);
omapfb_overlay_enable(ovl, 0); omapfb_overlay_enable(ovl, 0);
if (ovl->manager) if (ovl->manager)
ovl->manager->apply(ovl->manager); ovl->manager->apply(ovl->manager);
omapfb_put_mem_region(ofbi->region);
for (t = i + 1; t < ofbi->num_overlays; t++) { for (t = i + 1; t < ofbi->num_overlays; t++) {
ofbi->rotation[t-1] = ofbi->rotation[t]; ofbi->rotation[t-1] = ofbi->rotation[t];
ofbi->overlays[t-1] = ofbi->overlays[t]; ofbi->overlays[t-1] = ofbi->overlays[t];
...@@ -300,7 +313,12 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, ...@@ -300,7 +313,12 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
} }
if (added) { if (added) {
omapfb_get_mem_region(ofbi->region);
r = omapfb_apply_changes(fbi, 0); r = omapfb_apply_changes(fbi, 0);
omapfb_put_mem_region(ofbi->region);
if (r) if (r)
goto out; goto out;
} }
...@@ -388,7 +406,12 @@ static ssize_t store_overlays_rotate(struct device *dev, ...@@ -388,7 +406,12 @@ static ssize_t store_overlays_rotate(struct device *dev,
for (i = 0; i < num_ovls; ++i) for (i = 0; i < num_ovls; ++i)
ofbi->rotation[i] = rotation[i]; ofbi->rotation[i] = rotation[i];
omapfb_get_mem_region(ofbi->region);
r = omapfb_apply_changes(fbi, 0); r = omapfb_apply_changes(fbi, 0);
omapfb_put_mem_region(ofbi->region);
if (r) if (r)
goto out; goto out;
...@@ -408,7 +431,7 @@ static ssize_t show_size(struct device *dev, ...@@ -408,7 +431,7 @@ static ssize_t show_size(struct device *dev,
struct fb_info *fbi = dev_get_drvdata(dev); struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb_info *ofbi = FB2OFB(fbi);
return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size); return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
} }
static ssize_t store_size(struct device *dev, struct device_attribute *attr, static ssize_t store_size(struct device *dev, struct device_attribute *attr,
...@@ -416,6 +439,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, ...@@ -416,6 +439,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
{ {
struct fb_info *fbi = dev_get_drvdata(dev); struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omapfb2_mem_region *rg;
unsigned long size; unsigned long size;
int r; int r;
int i; int i;
...@@ -425,15 +450,33 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, ...@@ -425,15 +450,33 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
if (!lock_fb_info(fbi)) if (!lock_fb_info(fbi))
return -ENODEV; return -ENODEV;
for (i = 0; i < ofbi->num_overlays; i++) { rg = ofbi->region;
if (ofbi->overlays[i]->info.enabled) {
r = -EBUSY; down_write_nested(&rg->lock, rg->id);
goto out; atomic_inc(&rg->lock_count);
if (atomic_read(&rg->map_count)) {
r = -EBUSY;
goto out;
}
for (i = 0; i < fbdev->num_fbs; i++) {
struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
int j;
if (ofbi2->region != rg)
continue;
for (j = 0; j < ofbi2->num_overlays; j++) {
if (ofbi2->overlays[j]->info.enabled) {
r = -EBUSY;
goto out;
}
} }
} }
if (size != ofbi->region.size) { if (size != ofbi->region->size) {
r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type); r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
if (r) { if (r) {
dev_err(dev, "realloc fbmem failed\n"); dev_err(dev, "realloc fbmem failed\n");
goto out; goto out;
...@@ -442,6 +485,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, ...@@ -442,6 +485,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
r = count; r = count;
out: out:
atomic_dec(&rg->lock_count);
up_write(&rg->lock);
unlock_fb_info(fbi); unlock_fb_info(fbi);
return r; return r;
...@@ -453,7 +499,7 @@ static ssize_t show_phys(struct device *dev, ...@@ -453,7 +499,7 @@ static ssize_t show_phys(struct device *dev,
struct fb_info *fbi = dev_get_drvdata(dev); struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb_info *ofbi = FB2OFB(fbi);
return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr); return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
} }
static ssize_t show_virt(struct device *dev, static ssize_t show_virt(struct device *dev,
...@@ -462,7 +508,7 @@ static ssize_t show_virt(struct device *dev, ...@@ -462,7 +508,7 @@ static ssize_t show_virt(struct device *dev,
struct fb_info *fbi = dev_get_drvdata(dev); struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi); struct omapfb_info *ofbi = FB2OFB(fbi);
return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr); return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
} }
static struct device_attribute omapfb_attrs[] = { static struct device_attribute omapfb_attrs[] = {
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#define DEBUG #define DEBUG
#endif #endif
#include <linux/rwsem.h>
#include <plat/display.h> #include <plat/display.h>
#ifdef DEBUG #ifdef DEBUG
...@@ -44,6 +46,7 @@ extern unsigned int omapfb_debug; ...@@ -44,6 +46,7 @@ extern unsigned int omapfb_debug;
#define OMAPFB_MAX_OVL_PER_FB 3 #define OMAPFB_MAX_OVL_PER_FB 3
struct omapfb2_mem_region { struct omapfb2_mem_region {
int id;
u32 paddr; u32 paddr;
void __iomem *vaddr; void __iomem *vaddr;
struct vrfb vrfb; struct vrfb vrfb;
...@@ -51,13 +54,15 @@ struct omapfb2_mem_region { ...@@ -51,13 +54,15 @@ struct omapfb2_mem_region {
u8 type; /* OMAPFB_PLANE_MEM_* */ u8 type; /* OMAPFB_PLANE_MEM_* */
bool alloc; /* allocated by the driver */ bool alloc; /* allocated by the driver */
bool map; /* kernel mapped by the driver */ bool map; /* kernel mapped by the driver */
atomic_t map_count;
struct rw_semaphore lock;
atomic_t lock_count;
}; };
/* appended to fb_info */ /* appended to fb_info */
struct omapfb_info { struct omapfb_info {
int id; int id;
struct omapfb2_mem_region region; struct omapfb2_mem_region *region;
atomic_t map_count;
int num_overlays; int num_overlays;
struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
struct omapfb2_device *fbdev; struct omapfb2_device *fbdev;
...@@ -76,6 +81,7 @@ struct omapfb2_device { ...@@ -76,6 +81,7 @@ struct omapfb2_device {
unsigned num_fbs; unsigned num_fbs;
struct fb_info *fbs[10]; struct fb_info *fbs[10];
struct omapfb2_mem_region regions[10];
unsigned num_displays; unsigned num_displays;
struct omap_dss_device *displays[10]; struct omap_dss_device *displays[10];
...@@ -117,6 +123,9 @@ int omapfb_update_window(struct fb_info *fbi, ...@@ -117,6 +123,9 @@ int omapfb_update_window(struct fb_info *fbi,
int dss_mode_to_fb_mode(enum omap_color_mode dssmode, int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
struct fb_var_screeninfo *var); struct fb_var_screeninfo *var);
int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
u16 posx, u16 posy, u16 outw, u16 outh);
/* find the display connected to this fb, if any */ /* find the display connected to this fb, if any */
static inline struct omap_dss_device *fb2display(struct fb_info *fbi) static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
{ {
...@@ -148,8 +157,24 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl, ...@@ -148,8 +157,24 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
struct omap_overlay_info info; struct omap_overlay_info info;
ovl->get_overlay_info(ovl, &info); ovl->get_overlay_info(ovl, &info);
if (info.enabled == enable)
return 0;
info.enabled = enable; info.enabled = enable;
return ovl->set_overlay_info(ovl, &info); return ovl->set_overlay_info(ovl, &info);
} }
static inline struct omapfb2_mem_region *
omapfb_get_mem_region(struct omapfb2_mem_region *rg)
{
down_read_nested(&rg->lock, rg->id);
atomic_inc(&rg->lock_count);
return rg;
}
static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
{
atomic_dec(&rg->lock_count);
up_read(&rg->lock);
}
#endif #endif
...@@ -85,6 +85,9 @@ ...@@ -85,6 +85,9 @@
#define OMAPFB_MEMTYPE_SRAM 1 #define OMAPFB_MEMTYPE_SRAM 1
#define OMAPFB_MEMTYPE_MAX 1 #define OMAPFB_MEMTYPE_MAX 1
#define OMAPFB_MEM_IDX_ENABLED 0x80
#define OMAPFB_MEM_IDX_MASK 0x7f
enum omapfb_color_format { enum omapfb_color_format {
OMAPFB_COLOR_RGB565 = 0, OMAPFB_COLOR_RGB565 = 0,
OMAPFB_COLOR_YUV422, OMAPFB_COLOR_YUV422,
...@@ -136,7 +139,7 @@ struct omapfb_plane_info { ...@@ -136,7 +139,7 @@ struct omapfb_plane_info {
__u8 enabled; __u8 enabled;
__u8 channel_out; __u8 channel_out;
__u8 mirror; __u8 mirror;
__u8 reserved1; __u8 mem_idx;
__u32 out_width; __u32 out_width;
__u32 out_height; __u32 out_height;
__u32 reserved2[12]; __u32 reserved2[12];
......
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