|
@@ -33,9 +33,9 @@
|
|
#include <linux/delay.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/hardirq.h>
|
|
#include <linux/hardirq.h>
|
|
-#include <linux/interrupt.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/pm_runtime.h>
|
|
|
|
+#include <linux/sizes.h>
|
|
|
|
|
|
#include <video/omapdss.h>
|
|
#include <video/omapdss.h>
|
|
|
|
|
|
@@ -46,21 +46,6 @@
|
|
/* DISPC */
|
|
/* DISPC */
|
|
#define DISPC_SZ_REGS SZ_4K
|
|
#define DISPC_SZ_REGS SZ_4K
|
|
|
|
|
|
-#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
|
|
|
|
- DISPC_IRQ_OCP_ERR | \
|
|
|
|
- DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
|
|
|
|
- DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
|
|
|
|
- DISPC_IRQ_SYNC_LOST | \
|
|
|
|
- DISPC_IRQ_SYNC_LOST_DIGIT)
|
|
|
|
-
|
|
|
|
-#define DISPC_MAX_NR_ISRS 8
|
|
|
|
-
|
|
|
|
-struct omap_dispc_isr_data {
|
|
|
|
- omap_dispc_isr_t isr;
|
|
|
|
- void *arg;
|
|
|
|
- u32 mask;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
enum omap_burst_size {
|
|
enum omap_burst_size {
|
|
BURST_SIZE_X2 = 0,
|
|
BURST_SIZE_X2 = 0,
|
|
BURST_SIZE_X4 = 1,
|
|
BURST_SIZE_X4 = 1,
|
|
@@ -73,12 +58,6 @@ enum omap_burst_size {
|
|
#define REG_FLD_MOD(idx, val, start, end) \
|
|
#define REG_FLD_MOD(idx, val, start, end) \
|
|
dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
|
|
dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
|
|
|
|
|
|
-struct dispc_irq_stats {
|
|
|
|
- unsigned long last_reset;
|
|
|
|
- unsigned irq_count;
|
|
|
|
- unsigned irqs[32];
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
struct dispc_features {
|
|
struct dispc_features {
|
|
u8 sw_start;
|
|
u8 sw_start;
|
|
u8 fp_start;
|
|
u8 fp_start;
|
|
@@ -86,19 +65,26 @@ struct dispc_features {
|
|
u16 sw_max;
|
|
u16 sw_max;
|
|
u16 vp_max;
|
|
u16 vp_max;
|
|
u16 hp_max;
|
|
u16 hp_max;
|
|
- int (*calc_scaling) (enum omap_plane plane,
|
|
|
|
|
|
+ u8 mgr_width_start;
|
|
|
|
+ u8 mgr_height_start;
|
|
|
|
+ u16 mgr_width_max;
|
|
|
|
+ u16 mgr_height_max;
|
|
|
|
+ int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
|
|
const struct omap_video_timings *mgr_timings,
|
|
const struct omap_video_timings *mgr_timings,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
enum omap_color_mode color_mode, bool *five_taps,
|
|
enum omap_color_mode color_mode, bool *five_taps,
|
|
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
|
|
int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
|
|
u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
|
|
u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
|
|
- unsigned long (*calc_core_clk) (enum omap_plane plane,
|
|
|
|
|
|
+ unsigned long (*calc_core_clk) (unsigned long pclk,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
bool mem_to_mem);
|
|
bool mem_to_mem);
|
|
u8 num_fifos;
|
|
u8 num_fifos;
|
|
|
|
|
|
/* swap GFX & WB fifos */
|
|
/* swap GFX & WB fifos */
|
|
bool gfx_fifo_workaround:1;
|
|
bool gfx_fifo_workaround:1;
|
|
|
|
+
|
|
|
|
+ /* no DISPC_IRQ_FRAMEDONETV on this SoC */
|
|
|
|
+ bool no_framedone_tv:1;
|
|
};
|
|
};
|
|
|
|
|
|
#define DISPC_MAX_NR_FIFOS 5
|
|
#define DISPC_MAX_NR_FIFOS 5
|
|
@@ -110,27 +96,15 @@ static struct {
|
|
int ctx_loss_cnt;
|
|
int ctx_loss_cnt;
|
|
|
|
|
|
int irq;
|
|
int irq;
|
|
- struct clk *dss_clk;
|
|
|
|
|
|
|
|
u32 fifo_size[DISPC_MAX_NR_FIFOS];
|
|
u32 fifo_size[DISPC_MAX_NR_FIFOS];
|
|
/* maps which plane is using a fifo. fifo-id -> plane-id */
|
|
/* maps which plane is using a fifo. fifo-id -> plane-id */
|
|
int fifo_assignment[DISPC_MAX_NR_FIFOS];
|
|
int fifo_assignment[DISPC_MAX_NR_FIFOS];
|
|
|
|
|
|
- spinlock_t irq_lock;
|
|
|
|
- u32 irq_error_mask;
|
|
|
|
- struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
|
|
|
|
- u32 error_irqs;
|
|
|
|
- struct work_struct error_work;
|
|
|
|
-
|
|
|
|
bool ctx_valid;
|
|
bool ctx_valid;
|
|
u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
|
|
u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
|
|
|
|
|
|
const struct dispc_features *feat;
|
|
const struct dispc_features *feat;
|
|
-
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
- spinlock_t irq_stats_lock;
|
|
|
|
- struct dispc_irq_stats irq_stats;
|
|
|
|
-#endif
|
|
|
|
} dispc;
|
|
} dispc;
|
|
|
|
|
|
enum omap_color_component {
|
|
enum omap_color_component {
|
|
@@ -186,7 +160,7 @@ static const struct {
|
|
[OMAP_DSS_CHANNEL_DIGIT] = {
|
|
[OMAP_DSS_CHANNEL_DIGIT] = {
|
|
.name = "DIGIT",
|
|
.name = "DIGIT",
|
|
.vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
|
|
.vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
|
|
- .framedone_irq = 0,
|
|
|
|
|
|
+ .framedone_irq = DISPC_IRQ_FRAMEDONETV,
|
|
.sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT,
|
|
.sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT,
|
|
.reg_desc = {
|
|
.reg_desc = {
|
|
[DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 },
|
|
[DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 },
|
|
@@ -241,7 +215,6 @@ struct color_conv_coef {
|
|
int full_range;
|
|
int full_range;
|
|
};
|
|
};
|
|
|
|
|
|
-static void _omap_dispc_set_irqs(void);
|
|
|
|
static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
|
|
static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
|
|
static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
|
|
static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
|
|
|
|
|
|
@@ -374,7 +347,7 @@ static void dispc_save_context(void)
|
|
if (dss_has_feature(FEAT_CORE_CLK_DIV))
|
|
if (dss_has_feature(FEAT_CORE_CLK_DIV))
|
|
SR(DIVISOR);
|
|
SR(DIVISOR);
|
|
|
|
|
|
- dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev);
|
|
|
|
|
|
+ dispc.ctx_loss_cnt = dss_get_ctx_loss_count();
|
|
dispc.ctx_valid = true;
|
|
dispc.ctx_valid = true;
|
|
|
|
|
|
DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
|
|
DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
|
|
@@ -389,7 +362,7 @@ static void dispc_restore_context(void)
|
|
if (!dispc.ctx_valid)
|
|
if (!dispc.ctx_valid)
|
|
return;
|
|
return;
|
|
|
|
|
|
- ctx = dss_get_ctx_loss_count(&dispc.pdev->dev);
|
|
|
|
|
|
+ ctx = dss_get_ctx_loss_count();
|
|
|
|
|
|
if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
|
|
if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
|
|
return;
|
|
return;
|
|
@@ -496,7 +469,7 @@ static void dispc_restore_context(void)
|
|
if (dss_has_feature(FEAT_MGR_LCD3))
|
|
if (dss_has_feature(FEAT_MGR_LCD3))
|
|
RR(CONTROL3);
|
|
RR(CONTROL3);
|
|
/* clear spurious SYNC_LOST_DIGIT interrupts */
|
|
/* clear spurious SYNC_LOST_DIGIT interrupts */
|
|
- dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
|
|
|
|
|
|
+ dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT);
|
|
|
|
|
|
/*
|
|
/*
|
|
* enable last so IRQs won't trigger before
|
|
* enable last so IRQs won't trigger before
|
|
@@ -520,6 +493,7 @@ int dispc_runtime_get(void)
|
|
WARN_ON(r < 0);
|
|
WARN_ON(r < 0);
|
|
return r < 0 ? r : 0;
|
|
return r < 0 ? r : 0;
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_runtime_get);
|
|
|
|
|
|
void dispc_runtime_put(void)
|
|
void dispc_runtime_put(void)
|
|
{
|
|
{
|
|
@@ -530,16 +504,28 @@ void dispc_runtime_put(void)
|
|
r = pm_runtime_put_sync(&dispc.pdev->dev);
|
|
r = pm_runtime_put_sync(&dispc.pdev->dev);
|
|
WARN_ON(r < 0 && r != -ENOSYS);
|
|
WARN_ON(r < 0 && r != -ENOSYS);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_runtime_put);
|
|
|
|
|
|
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
|
|
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
|
|
{
|
|
{
|
|
return mgr_desc[channel].vsync_irq;
|
|
return mgr_desc[channel].vsync_irq;
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
|
|
|
|
|
|
u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
|
|
u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
|
|
{
|
|
{
|
|
|
|
+ if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
return mgr_desc[channel].framedone_irq;
|
|
return mgr_desc[channel].framedone_irq;
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
|
|
|
|
+
|
|
|
|
+u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel)
|
|
|
|
+{
|
|
|
|
+ return mgr_desc[channel].sync_lost_irq;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
|
|
|
|
|
|
u32 dispc_wb_get_framedone_irq(void)
|
|
u32 dispc_wb_get_framedone_irq(void)
|
|
{
|
|
{
|
|
@@ -550,28 +536,18 @@ bool dispc_mgr_go_busy(enum omap_channel channel)
|
|
{
|
|
{
|
|
return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
|
|
return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_go_busy);
|
|
|
|
|
|
void dispc_mgr_go(enum omap_channel channel)
|
|
void dispc_mgr_go(enum omap_channel channel)
|
|
{
|
|
{
|
|
- bool enable_bit, go_bit;
|
|
|
|
-
|
|
|
|
- /* if the channel is not enabled, we don't need GO */
|
|
|
|
- enable_bit = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE) == 1;
|
|
|
|
-
|
|
|
|
- if (!enable_bit)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- go_bit = mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
|
|
|
|
-
|
|
|
|
- if (go_bit) {
|
|
|
|
- DSSERR("GO bit not down for channel %d\n", channel);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ WARN_ON(dispc_mgr_is_enabled(channel) == false);
|
|
|
|
+ WARN_ON(dispc_mgr_go_busy(channel));
|
|
|
|
|
|
DSSDBG("GO %s\n", mgr_desc[channel].name);
|
|
DSSDBG("GO %s\n", mgr_desc[channel].name);
|
|
|
|
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_go);
|
|
|
|
|
|
bool dispc_wb_go_busy(void)
|
|
bool dispc_wb_go_busy(void)
|
|
{
|
|
{
|
|
@@ -975,6 +951,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
|
|
}
|
|
}
|
|
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
|
|
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_ovl_set_channel_out);
|
|
|
|
|
|
static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
|
|
static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
|
|
{
|
|
{
|
|
@@ -1040,7 +1017,7 @@ static void dispc_configure_burst_sizes(void)
|
|
const int burst_size = BURST_SIZE_X8;
|
|
const int burst_size = BURST_SIZE_X8;
|
|
|
|
|
|
/* Configure burst size always to maximum size */
|
|
/* Configure burst size always to maximum size */
|
|
- for (i = 0; i < omap_dss_get_num_overlays(); ++i)
|
|
|
|
|
|
+ for (i = 0; i < dss_feat_get_num_ovls(); ++i)
|
|
dispc_ovl_set_burst_size(i, burst_size);
|
|
dispc_ovl_set_burst_size(i, burst_size);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1074,7 +1051,7 @@ static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
|
|
}
|
|
}
|
|
|
|
|
|
static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
|
|
static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
|
|
- struct omap_dss_cpr_coefs *coefs)
|
|
|
|
|
|
+ const struct omap_dss_cpr_coefs *coefs)
|
|
{
|
|
{
|
|
u32 coef_r, coef_g, coef_b;
|
|
u32 coef_r, coef_g, coef_b;
|
|
|
|
|
|
@@ -1122,7 +1099,9 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
|
|
{
|
|
{
|
|
u32 val;
|
|
u32 val;
|
|
|
|
|
|
- val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
|
|
|
|
|
|
+ val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) |
|
|
|
|
+ FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
|
|
|
|
+
|
|
dispc_write_reg(DISPC_SIZE_MGR(channel), val);
|
|
dispc_write_reg(DISPC_SIZE_MGR(channel), val);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1244,7 +1223,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
|
|
|
|
|
|
if (use_fifomerge) {
|
|
if (use_fifomerge) {
|
|
total_fifo_size = 0;
|
|
total_fifo_size = 0;
|
|
- for (i = 0; i < omap_dss_get_num_overlays(); ++i)
|
|
|
|
|
|
+ for (i = 0; i < dss_feat_get_num_ovls(); ++i)
|
|
total_fifo_size += dispc_ovl_get_fifo_size(i);
|
|
total_fifo_size += dispc_ovl_get_fifo_size(i);
|
|
} else {
|
|
} else {
|
|
total_fifo_size = ovl_fifo_size;
|
|
total_fifo_size = ovl_fifo_size;
|
|
@@ -1989,16 +1968,14 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
|
|
* This function is used to avoid synclosts in OMAP3, because of some
|
|
* This function is used to avoid synclosts in OMAP3, because of some
|
|
* undocumented horizontal position and timing related limitations.
|
|
* undocumented horizontal position and timing related limitations.
|
|
*/
|
|
*/
|
|
-static int check_horiz_timing_omap3(enum omap_plane plane,
|
|
|
|
|
|
+static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
|
|
const struct omap_video_timings *t, u16 pos_x,
|
|
const struct omap_video_timings *t, u16 pos_x,
|
|
u16 width, u16 height, u16 out_width, u16 out_height)
|
|
u16 width, u16 height, u16 out_width, u16 out_height)
|
|
{
|
|
{
|
|
- int DS = DIV_ROUND_UP(height, out_height);
|
|
|
|
|
|
+ const int ds = DIV_ROUND_UP(height, out_height);
|
|
unsigned long nonactive;
|
|
unsigned long nonactive;
|
|
static const u8 limits[3] = { 8, 10, 20 };
|
|
static const u8 limits[3] = { 8, 10, 20 };
|
|
u64 val, blank;
|
|
u64 val, blank;
|
|
- unsigned long pclk = dispc_plane_pclk_rate(plane);
|
|
|
|
- unsigned long lclk = dispc_plane_lclk_rate(plane);
|
|
|
|
int i;
|
|
int i;
|
|
|
|
|
|
nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
|
|
nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
|
|
@@ -2020,8 +1997,8 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
|
|
*/
|
|
*/
|
|
val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
|
|
val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
|
|
DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
|
|
DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
|
|
- val, max(0, DS - 2) * width);
|
|
|
|
- if (val < max(0, DS - 2) * width)
|
|
|
|
|
|
+ val, max(0, ds - 2) * width);
|
|
|
|
+ if (val < max(0, ds - 2) * width)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2031,21 +2008,20 @@ static int check_horiz_timing_omap3(enum omap_plane plane,
|
|
*/
|
|
*/
|
|
val = div_u64((u64)nonactive * lclk, pclk);
|
|
val = div_u64((u64)nonactive * lclk, pclk);
|
|
DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n",
|
|
DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n",
|
|
- val, max(0, DS - 1) * width);
|
|
|
|
- if (val < max(0, DS - 1) * width)
|
|
|
|
|
|
+ val, max(0, ds - 1) * width);
|
|
|
|
+ if (val < max(0, ds - 1) * width)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
|
|
|
|
|
|
+static unsigned long calc_core_clk_five_taps(unsigned long pclk,
|
|
const struct omap_video_timings *mgr_timings, u16 width,
|
|
const struct omap_video_timings *mgr_timings, u16 width,
|
|
u16 height, u16 out_width, u16 out_height,
|
|
u16 height, u16 out_width, u16 out_height,
|
|
enum omap_color_mode color_mode)
|
|
enum omap_color_mode color_mode)
|
|
{
|
|
{
|
|
u32 core_clk = 0;
|
|
u32 core_clk = 0;
|
|
u64 tmp;
|
|
u64 tmp;
|
|
- unsigned long pclk = dispc_plane_pclk_rate(plane);
|
|
|
|
|
|
|
|
if (height <= out_height && width <= out_width)
|
|
if (height <= out_height && width <= out_width)
|
|
return (unsigned long) pclk;
|
|
return (unsigned long) pclk;
|
|
@@ -2079,22 +2055,19 @@ static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
|
|
return core_clk;
|
|
return core_clk;
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
|
|
|
|
|
|
+static unsigned long calc_core_clk_24xx(unsigned long pclk, u16 width,
|
|
u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
|
|
u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
|
|
{
|
|
{
|
|
- unsigned long pclk = dispc_plane_pclk_rate(plane);
|
|
|
|
-
|
|
|
|
if (height > out_height && width > out_width)
|
|
if (height > out_height && width > out_width)
|
|
return pclk * 4;
|
|
return pclk * 4;
|
|
else
|
|
else
|
|
return pclk * 2;
|
|
return pclk * 2;
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
|
|
|
|
|
|
+static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
|
|
u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
|
|
u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
|
|
{
|
|
{
|
|
unsigned int hf, vf;
|
|
unsigned int hf, vf;
|
|
- unsigned long pclk = dispc_plane_pclk_rate(plane);
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
* FIXME how to determine the 'A' factor
|
|
* FIXME how to determine the 'A' factor
|
|
@@ -2117,11 +2090,9 @@ static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
|
|
return pclk * vf * hf;
|
|
return pclk * vf * hf;
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
|
|
|
|
|
|
+static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width,
|
|
u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
|
|
u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
|
|
{
|
|
{
|
|
- unsigned long pclk;
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* If the overlay/writeback is in mem to mem mode, there are no
|
|
* If the overlay/writeback is in mem to mem mode, there are no
|
|
* downscaling limitations with respect to pixel clock, return 1 as
|
|
* downscaling limitations with respect to pixel clock, return 1 as
|
|
@@ -2131,15 +2102,13 @@ static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
|
|
if (mem_to_mem)
|
|
if (mem_to_mem)
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
- pclk = dispc_plane_pclk_rate(plane);
|
|
|
|
-
|
|
|
|
if (width > out_width)
|
|
if (width > out_width)
|
|
return DIV_ROUND_UP(pclk, out_width) * width;
|
|
return DIV_ROUND_UP(pclk, out_width) * width;
|
|
else
|
|
else
|
|
return pclk;
|
|
return pclk;
|
|
}
|
|
}
|
|
|
|
|
|
-static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
|
|
|
|
|
|
+static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
|
|
const struct omap_video_timings *mgr_timings,
|
|
const struct omap_video_timings *mgr_timings,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
enum omap_color_mode color_mode, bool *five_taps,
|
|
enum omap_color_mode color_mode, bool *five_taps,
|
|
@@ -2157,7 +2126,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
|
|
do {
|
|
do {
|
|
in_height = DIV_ROUND_UP(height, *decim_y);
|
|
in_height = DIV_ROUND_UP(height, *decim_y);
|
|
in_width = DIV_ROUND_UP(width, *decim_x);
|
|
in_width = DIV_ROUND_UP(width, *decim_x);
|
|
- *core_clk = dispc.feat->calc_core_clk(plane, in_width,
|
|
|
|
|
|
+ *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
|
|
in_height, out_width, out_height, mem_to_mem);
|
|
in_height, out_width, out_height, mem_to_mem);
|
|
error = (in_width > maxsinglelinewidth || !*core_clk ||
|
|
error = (in_width > maxsinglelinewidth || !*core_clk ||
|
|
*core_clk > dispc_core_clk_rate());
|
|
*core_clk > dispc_core_clk_rate());
|
|
@@ -2180,7 +2149,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
|
|
|
|
|
|
+static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
|
|
const struct omap_video_timings *mgr_timings,
|
|
const struct omap_video_timings *mgr_timings,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
enum omap_color_mode color_mode, bool *five_taps,
|
|
enum omap_color_mode color_mode, bool *five_taps,
|
|
@@ -2196,10 +2165,10 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
|
|
do {
|
|
do {
|
|
in_height = DIV_ROUND_UP(height, *decim_y);
|
|
in_height = DIV_ROUND_UP(height, *decim_y);
|
|
in_width = DIV_ROUND_UP(width, *decim_x);
|
|
in_width = DIV_ROUND_UP(width, *decim_x);
|
|
- *core_clk = calc_core_clk_five_taps(plane, mgr_timings,
|
|
|
|
|
|
+ *core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
|
|
in_width, in_height, out_width, out_height, color_mode);
|
|
in_width, in_height, out_width, out_height, color_mode);
|
|
|
|
|
|
- error = check_horiz_timing_omap3(plane, mgr_timings,
|
|
|
|
|
|
+ error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
|
|
pos_x, in_width, in_height, out_width,
|
|
pos_x, in_width, in_height, out_width,
|
|
out_height);
|
|
out_height);
|
|
|
|
|
|
@@ -2208,7 +2177,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
|
|
in_height < out_height * 2)
|
|
in_height < out_height * 2)
|
|
*five_taps = false;
|
|
*five_taps = false;
|
|
if (!*five_taps)
|
|
if (!*five_taps)
|
|
- *core_clk = dispc.feat->calc_core_clk(plane, in_width,
|
|
|
|
|
|
+ *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
|
|
in_height, out_width, out_height,
|
|
in_height, out_width, out_height,
|
|
mem_to_mem);
|
|
mem_to_mem);
|
|
|
|
|
|
@@ -2227,8 +2196,8 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
|
|
}
|
|
}
|
|
} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
|
|
} while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
|
|
|
|
|
|
- if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
|
|
|
|
- out_width, out_height)){
|
|
|
|
|
|
+ if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
|
|
|
|
+ height, out_width, out_height)){
|
|
DSSERR("horizontal timing too tight\n");
|
|
DSSERR("horizontal timing too tight\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
@@ -2246,7 +2215,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
|
|
|
|
|
|
+static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
|
|
const struct omap_video_timings *mgr_timings,
|
|
const struct omap_video_timings *mgr_timings,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
enum omap_color_mode color_mode, bool *five_taps,
|
|
enum omap_color_mode color_mode, bool *five_taps,
|
|
@@ -2258,14 +2227,14 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
|
|
u16 in_height = DIV_ROUND_UP(height, *decim_y);
|
|
u16 in_height = DIV_ROUND_UP(height, *decim_y);
|
|
const int maxsinglelinewidth =
|
|
const int maxsinglelinewidth =
|
|
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
|
|
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
|
|
- unsigned long pclk = dispc_plane_pclk_rate(plane);
|
|
|
|
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
|
|
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
|
|
|
|
|
|
- if (mem_to_mem)
|
|
|
|
- in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
|
|
|
|
- else
|
|
|
|
|
|
+ if (mem_to_mem) {
|
|
|
|
+ in_width_max = out_width * maxdownscale;
|
|
|
|
+ } else {
|
|
in_width_max = dispc_core_clk_rate() /
|
|
in_width_max = dispc_core_clk_rate() /
|
|
DIV_ROUND_UP(pclk, out_width);
|
|
DIV_ROUND_UP(pclk, out_width);
|
|
|
|
+ }
|
|
|
|
|
|
*decim_x = DIV_ROUND_UP(width, in_width_max);
|
|
*decim_x = DIV_ROUND_UP(width, in_width_max);
|
|
|
|
|
|
@@ -2283,12 +2252,12 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
|
|
|
|
|
|
+ *core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height,
|
|
out_width, out_height, mem_to_mem);
|
|
out_width, out_height, mem_to_mem);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|
|
|
|
|
+static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
|
|
enum omap_overlay_caps caps,
|
|
enum omap_overlay_caps caps,
|
|
const struct omap_video_timings *mgr_timings,
|
|
const struct omap_video_timings *mgr_timings,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
u16 width, u16 height, u16 out_width, u16 out_height,
|
|
@@ -2307,9 +2276,14 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|
if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
|
|
if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- *x_predecim = max_decim_limit;
|
|
|
|
- *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
|
|
|
|
- dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;
|
|
|
|
|
|
+ if (mem_to_mem) {
|
|
|
|
+ *x_predecim = *y_predecim = 1;
|
|
|
|
+ } else {
|
|
|
|
+ *x_predecim = max_decim_limit;
|
|
|
|
+ *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
|
|
|
|
+ dss_has_feature(FEAT_BURST_2D)) ?
|
|
|
|
+ 2 : max_decim_limit;
|
|
|
|
+ }
|
|
|
|
|
|
if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
|
|
if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
|
|
color_mode == OMAP_DSS_COLOR_CLUT2 ||
|
|
color_mode == OMAP_DSS_COLOR_CLUT2 ||
|
|
@@ -2330,7 +2304,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|
if (decim_y > *y_predecim || out_height > height * 8)
|
|
if (decim_y > *y_predecim || out_height > height * 8)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
|
|
|
|
|
|
+ ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
|
|
out_width, out_height, color_mode, five_taps,
|
|
out_width, out_height, color_mode, five_taps,
|
|
x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
|
|
x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
|
|
mem_to_mem);
|
|
mem_to_mem);
|
|
@@ -2353,6 +2327,47 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
|
|
|
|
+ const struct omap_overlay_info *oi,
|
|
|
|
+ const struct omap_video_timings *timings,
|
|
|
|
+ int *x_predecim, int *y_predecim)
|
|
|
|
+{
|
|
|
|
+ enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
|
|
|
|
+ bool five_taps = true;
|
|
|
|
+ bool fieldmode = 0;
|
|
|
|
+ u16 in_height = oi->height;
|
|
|
|
+ u16 in_width = oi->width;
|
|
|
|
+ bool ilace = timings->interlace;
|
|
|
|
+ u16 out_width, out_height;
|
|
|
|
+ int pos_x = oi->pos_x;
|
|
|
|
+ unsigned long pclk = dispc_mgr_pclk_rate(channel);
|
|
|
|
+ unsigned long lclk = dispc_mgr_lclk_rate(channel);
|
|
|
|
+
|
|
|
|
+ out_width = oi->out_width == 0 ? oi->width : oi->out_width;
|
|
|
|
+ out_height = oi->out_height == 0 ? oi->height : oi->out_height;
|
|
|
|
+
|
|
|
|
+ if (ilace && oi->height == out_height)
|
|
|
|
+ fieldmode = 1;
|
|
|
|
+
|
|
|
|
+ if (ilace) {
|
|
|
|
+ if (fieldmode)
|
|
|
|
+ in_height /= 2;
|
|
|
|
+ out_height /= 2;
|
|
|
|
+
|
|
|
|
+ DSSDBG("adjusting for ilace: height %d, out_height %d\n",
|
|
|
|
+ in_height, out_height);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!dss_feat_color_mode_supported(plane, oi->color_mode))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
|
|
|
|
+ in_height, out_width, out_height, oi->color_mode,
|
|
|
|
+ &five_taps, x_predecim, y_predecim, pos_x,
|
|
|
|
+ oi->rotation_type, false);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(dispc_ovl_check);
|
|
|
|
+
|
|
static int dispc_ovl_setup_common(enum omap_plane plane,
|
|
static int dispc_ovl_setup_common(enum omap_plane plane,
|
|
enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
|
|
enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
|
|
u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
|
|
u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
|
|
@@ -2368,12 +2383,14 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
|
|
unsigned offset0, offset1;
|
|
unsigned offset0, offset1;
|
|
s32 row_inc;
|
|
s32 row_inc;
|
|
s32 pix_inc;
|
|
s32 pix_inc;
|
|
- u16 frame_height = height;
|
|
|
|
|
|
+ u16 frame_width, frame_height;
|
|
unsigned int field_offset = 0;
|
|
unsigned int field_offset = 0;
|
|
u16 in_height = height;
|
|
u16 in_height = height;
|
|
u16 in_width = width;
|
|
u16 in_width = width;
|
|
int x_predecim = 1, y_predecim = 1;
|
|
int x_predecim = 1, y_predecim = 1;
|
|
bool ilace = mgr_timings->interlace;
|
|
bool ilace = mgr_timings->interlace;
|
|
|
|
+ unsigned long pclk = dispc_plane_pclk_rate(plane);
|
|
|
|
+ unsigned long lclk = dispc_plane_lclk_rate(plane);
|
|
|
|
|
|
if (paddr == 0)
|
|
if (paddr == 0)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -2398,7 +2415,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
|
|
if (!dss_feat_color_mode_supported(plane, color_mode))
|
|
if (!dss_feat_color_mode_supported(plane, color_mode))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
|
|
|
|
|
|
+ r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width,
|
|
in_height, out_width, out_height, color_mode,
|
|
in_height, out_width, out_height, color_mode,
|
|
&five_taps, &x_predecim, &y_predecim, pos_x,
|
|
&five_taps, &x_predecim, &y_predecim, pos_x,
|
|
rotation_type, mem_to_mem);
|
|
rotation_type, mem_to_mem);
|
|
@@ -2436,20 +2453,28 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
|
|
row_inc = 0;
|
|
row_inc = 0;
|
|
pix_inc = 0;
|
|
pix_inc = 0;
|
|
|
|
|
|
|
|
+ if (plane == OMAP_DSS_WB) {
|
|
|
|
+ frame_width = out_width;
|
|
|
|
+ frame_height = out_height;
|
|
|
|
+ } else {
|
|
|
|
+ frame_width = in_width;
|
|
|
|
+ frame_height = height;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (rotation_type == OMAP_DSS_ROT_TILER)
|
|
if (rotation_type == OMAP_DSS_ROT_TILER)
|
|
- calc_tiler_rotation_offset(screen_width, in_width,
|
|
|
|
|
|
+ calc_tiler_rotation_offset(screen_width, frame_width,
|
|
color_mode, fieldmode, field_offset,
|
|
color_mode, fieldmode, field_offset,
|
|
&offset0, &offset1, &row_inc, &pix_inc,
|
|
&offset0, &offset1, &row_inc, &pix_inc,
|
|
x_predecim, y_predecim);
|
|
x_predecim, y_predecim);
|
|
else if (rotation_type == OMAP_DSS_ROT_DMA)
|
|
else if (rotation_type == OMAP_DSS_ROT_DMA)
|
|
- calc_dma_rotation_offset(rotation, mirror,
|
|
|
|
- screen_width, in_width, frame_height,
|
|
|
|
|
|
+ calc_dma_rotation_offset(rotation, mirror, screen_width,
|
|
|
|
+ frame_width, frame_height,
|
|
color_mode, fieldmode, field_offset,
|
|
color_mode, fieldmode, field_offset,
|
|
&offset0, &offset1, &row_inc, &pix_inc,
|
|
&offset0, &offset1, &row_inc, &pix_inc,
|
|
x_predecim, y_predecim);
|
|
x_predecim, y_predecim);
|
|
else
|
|
else
|
|
calc_vrfb_rotation_offset(rotation, mirror,
|
|
calc_vrfb_rotation_offset(rotation, mirror,
|
|
- screen_width, in_width, frame_height,
|
|
|
|
|
|
+ screen_width, frame_width, frame_height,
|
|
color_mode, fieldmode, field_offset,
|
|
color_mode, fieldmode, field_offset,
|
|
&offset0, &offset1, &row_inc, &pix_inc,
|
|
&offset0, &offset1, &row_inc, &pix_inc,
|
|
x_predecim, y_predecim);
|
|
x_predecim, y_predecim);
|
|
@@ -2503,7 +2528,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
|
|
bool mem_to_mem)
|
|
bool mem_to_mem)
|
|
{
|
|
{
|
|
int r;
|
|
int r;
|
|
- struct omap_overlay *ovl = omap_dss_get_overlay(plane);
|
|
|
|
|
|
+ enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
|
|
enum omap_channel channel;
|
|
enum omap_channel channel;
|
|
|
|
|
|
channel = dispc_ovl_get_channel_out(plane);
|
|
channel = dispc_ovl_get_channel_out(plane);
|
|
@@ -2514,7 +2539,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
|
|
oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
|
|
oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
|
|
oi->color_mode, oi->rotation, oi->mirror, channel, replication);
|
|
oi->color_mode, oi->rotation, oi->mirror, channel, replication);
|
|
|
|
|
|
- r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
|
|
|
|
|
|
+ r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr,
|
|
oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
|
|
oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
|
|
oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
|
|
oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
|
|
oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
|
|
oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
|
|
@@ -2522,6 +2547,7 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
|
|
|
|
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_ovl_setup);
|
|
|
|
|
|
int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
|
|
int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
|
|
bool mem_to_mem, const struct omap_video_timings *mgr_timings)
|
|
bool mem_to_mem, const struct omap_video_timings *mgr_timings)
|
|
@@ -2582,192 +2608,39 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable)
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_ovl_enable);
|
|
|
|
|
|
-static void dispc_disable_isr(void *data, u32 mask)
|
|
|
|
|
|
+bool dispc_ovl_enabled(enum omap_plane plane)
|
|
{
|
|
{
|
|
- struct completion *compl = data;
|
|
|
|
- complete(compl);
|
|
|
|
|
|
+ return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_ovl_enabled);
|
|
|
|
|
|
-static void _enable_lcd_out(enum omap_channel channel, bool enable)
|
|
|
|
|
|
+void dispc_mgr_enable(enum omap_channel channel, bool enable)
|
|
{
|
|
{
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable);
|
|
/* flush posted write */
|
|
/* flush posted write */
|
|
mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
|
|
mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
|
|
}
|
|
}
|
|
-
|
|
|
|
-static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
|
|
|
|
-{
|
|
|
|
- struct completion frame_done_completion;
|
|
|
|
- bool is_on;
|
|
|
|
- int r;
|
|
|
|
- u32 irq;
|
|
|
|
-
|
|
|
|
- /* When we disable LCD output, we need to wait until frame is done.
|
|
|
|
- * Otherwise the DSS is still working, and turning off the clocks
|
|
|
|
- * prevents DSS from going to OFF mode */
|
|
|
|
- is_on = mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
|
|
|
|
-
|
|
|
|
- irq = mgr_desc[channel].framedone_irq;
|
|
|
|
-
|
|
|
|
- if (!enable && is_on) {
|
|
|
|
- init_completion(&frame_done_completion);
|
|
|
|
-
|
|
|
|
- r = omap_dispc_register_isr(dispc_disable_isr,
|
|
|
|
- &frame_done_completion, irq);
|
|
|
|
-
|
|
|
|
- if (r)
|
|
|
|
- DSSERR("failed to register FRAMEDONE isr\n");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- _enable_lcd_out(channel, enable);
|
|
|
|
-
|
|
|
|
- if (!enable && is_on) {
|
|
|
|
- if (!wait_for_completion_timeout(&frame_done_completion,
|
|
|
|
- msecs_to_jiffies(100)))
|
|
|
|
- DSSERR("timeout waiting for FRAME DONE\n");
|
|
|
|
-
|
|
|
|
- r = omap_dispc_unregister_isr(dispc_disable_isr,
|
|
|
|
- &frame_done_completion, irq);
|
|
|
|
-
|
|
|
|
- if (r)
|
|
|
|
- DSSERR("failed to unregister FRAMEDONE isr\n");
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void _enable_digit_out(bool enable)
|
|
|
|
-{
|
|
|
|
- REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
|
|
|
|
- /* flush posted write */
|
|
|
|
- dispc_read_reg(DISPC_CONTROL);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void dispc_mgr_enable_digit_out(bool enable)
|
|
|
|
-{
|
|
|
|
- struct completion frame_done_completion;
|
|
|
|
- enum dss_hdmi_venc_clk_source_select src;
|
|
|
|
- int r, i;
|
|
|
|
- u32 irq_mask;
|
|
|
|
- int num_irqs;
|
|
|
|
-
|
|
|
|
- if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- src = dss_get_hdmi_venc_clk_source();
|
|
|
|
-
|
|
|
|
- if (enable) {
|
|
|
|
- unsigned long flags;
|
|
|
|
- /* When we enable digit output, we'll get an extra digit
|
|
|
|
- * sync lost interrupt, that we need to ignore */
|
|
|
|
- spin_lock_irqsave(&dispc.irq_lock, flags);
|
|
|
|
- dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
|
|
|
|
- _omap_dispc_set_irqs();
|
|
|
|
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* When we disable digit output, we need to wait until fields are done.
|
|
|
|
- * Otherwise the DSS is still working, and turning off the clocks
|
|
|
|
- * prevents DSS from going to OFF mode. And when enabling, we need to
|
|
|
|
- * wait for the extra sync losts */
|
|
|
|
- init_completion(&frame_done_completion);
|
|
|
|
-
|
|
|
|
- if (src == DSS_HDMI_M_PCLK && enable == false) {
|
|
|
|
- irq_mask = DISPC_IRQ_FRAMEDONETV;
|
|
|
|
- num_irqs = 1;
|
|
|
|
- } else {
|
|
|
|
- irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
|
|
|
|
- /* XXX I understand from TRM that we should only wait for the
|
|
|
|
- * current field to complete. But it seems we have to wait for
|
|
|
|
- * both fields */
|
|
|
|
- num_irqs = 2;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
|
|
|
|
- irq_mask);
|
|
|
|
- if (r)
|
|
|
|
- DSSERR("failed to register %x isr\n", irq_mask);
|
|
|
|
-
|
|
|
|
- _enable_digit_out(enable);
|
|
|
|
-
|
|
|
|
- for (i = 0; i < num_irqs; ++i) {
|
|
|
|
- if (!wait_for_completion_timeout(&frame_done_completion,
|
|
|
|
- msecs_to_jiffies(100)))
|
|
|
|
- DSSERR("timeout waiting for digit out to %s\n",
|
|
|
|
- enable ? "start" : "stop");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion,
|
|
|
|
- irq_mask);
|
|
|
|
- if (r)
|
|
|
|
- DSSERR("failed to unregister %x isr\n", irq_mask);
|
|
|
|
-
|
|
|
|
- if (enable) {
|
|
|
|
- unsigned long flags;
|
|
|
|
- spin_lock_irqsave(&dispc.irq_lock, flags);
|
|
|
|
- dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT;
|
|
|
|
- dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
|
|
|
|
- _omap_dispc_set_irqs();
|
|
|
|
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_enable);
|
|
|
|
|
|
bool dispc_mgr_is_enabled(enum omap_channel channel)
|
|
bool dispc_mgr_is_enabled(enum omap_channel channel)
|
|
{
|
|
{
|
|
return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
|
|
return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
|
|
}
|
|
}
|
|
-
|
|
|
|
-void dispc_mgr_enable(enum omap_channel channel, bool enable)
|
|
|
|
-{
|
|
|
|
- if (dss_mgr_is_lcd(channel))
|
|
|
|
- dispc_mgr_enable_lcd_out(channel, enable);
|
|
|
|
- else if (channel == OMAP_DSS_CHANNEL_DIGIT)
|
|
|
|
- dispc_mgr_enable_digit_out(enable);
|
|
|
|
- else
|
|
|
|
- BUG();
|
|
|
|
-}
|
|
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_is_enabled);
|
|
|
|
|
|
void dispc_wb_enable(bool enable)
|
|
void dispc_wb_enable(bool enable)
|
|
{
|
|
{
|
|
- enum omap_plane plane = OMAP_DSS_WB;
|
|
|
|
- struct completion frame_done_completion;
|
|
|
|
- bool is_on;
|
|
|
|
- int r;
|
|
|
|
- u32 irq;
|
|
|
|
-
|
|
|
|
- is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
|
|
|
|
- irq = DISPC_IRQ_FRAMEDONEWB;
|
|
|
|
-
|
|
|
|
- if (!enable && is_on) {
|
|
|
|
- init_completion(&frame_done_completion);
|
|
|
|
-
|
|
|
|
- r = omap_dispc_register_isr(dispc_disable_isr,
|
|
|
|
- &frame_done_completion, irq);
|
|
|
|
- if (r)
|
|
|
|
- DSSERR("failed to register FRAMEDONEWB isr\n");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
|
|
|
|
-
|
|
|
|
- if (!enable && is_on) {
|
|
|
|
- if (!wait_for_completion_timeout(&frame_done_completion,
|
|
|
|
- msecs_to_jiffies(100)))
|
|
|
|
- DSSERR("timeout waiting for FRAMEDONEWB\n");
|
|
|
|
-
|
|
|
|
- r = omap_dispc_unregister_isr(dispc_disable_isr,
|
|
|
|
- &frame_done_completion, irq);
|
|
|
|
- if (r)
|
|
|
|
- DSSERR("failed to unregister FRAMEDONEWB isr\n");
|
|
|
|
- }
|
|
|
|
|
|
+ dispc_ovl_enable(OMAP_DSS_WB, enable);
|
|
}
|
|
}
|
|
|
|
|
|
bool dispc_wb_is_enabled(void)
|
|
bool dispc_wb_is_enabled(void)
|
|
{
|
|
{
|
|
- enum omap_plane plane = OMAP_DSS_WB;
|
|
|
|
-
|
|
|
|
- return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
|
|
|
|
|
|
+ return dispc_ovl_enabled(OMAP_DSS_WB);
|
|
}
|
|
}
|
|
|
|
|
|
-void dispc_lcd_enable_signal_polarity(bool act_high)
|
|
|
|
|
|
+static void dispc_lcd_enable_signal_polarity(bool act_high)
|
|
{
|
|
{
|
|
if (!dss_has_feature(FEAT_LCDENABLEPOL))
|
|
if (!dss_has_feature(FEAT_LCDENABLEPOL))
|
|
return;
|
|
return;
|
|
@@ -2791,13 +2664,13 @@ void dispc_pck_free_enable(bool enable)
|
|
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
|
|
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
|
|
}
|
|
}
|
|
|
|
|
|
-void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
|
|
|
|
|
|
+static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable)
|
|
{
|
|
{
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
|
|
|
|
|
|
+static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel)
|
|
{
|
|
{
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1);
|
|
}
|
|
}
|
|
@@ -2840,7 +2713,7 @@ static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
|
|
}
|
|
}
|
|
|
|
|
|
void dispc_mgr_setup(enum omap_channel channel,
|
|
void dispc_mgr_setup(enum omap_channel channel,
|
|
- struct omap_overlay_manager_info *info)
|
|
|
|
|
|
+ const struct omap_overlay_manager_info *info)
|
|
{
|
|
{
|
|
dispc_mgr_set_default_color(channel, info->default_color);
|
|
dispc_mgr_set_default_color(channel, info->default_color);
|
|
dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
|
|
dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
|
|
@@ -2852,8 +2725,9 @@ void dispc_mgr_setup(enum omap_channel channel,
|
|
dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
|
|
dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_setup);
|
|
|
|
|
|
-void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
|
|
|
|
|
|
+static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
|
|
{
|
|
{
|
|
int code;
|
|
int code;
|
|
|
|
|
|
@@ -2878,7 +2752,7 @@ void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code);
|
|
}
|
|
}
|
|
|
|
|
|
-void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
|
|
|
|
|
|
+static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
|
|
{
|
|
{
|
|
u32 l;
|
|
u32 l;
|
|
int gpout0, gpout1;
|
|
int gpout0, gpout1;
|
|
@@ -2907,15 +2781,33 @@ void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode)
|
|
dispc_write_reg(DISPC_CONTROL, l);
|
|
dispc_write_reg(DISPC_CONTROL, l);
|
|
}
|
|
}
|
|
|
|
|
|
-void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
|
|
|
|
|
|
+static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
|
|
{
|
|
{
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
|
|
mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void dispc_mgr_set_lcd_config(enum omap_channel channel,
|
|
|
|
+ const struct dss_lcd_mgr_config *config)
|
|
|
|
+{
|
|
|
|
+ dispc_mgr_set_io_pad_mode(config->io_pad_mode);
|
|
|
|
+
|
|
|
|
+ dispc_mgr_enable_stallmode(channel, config->stallmode);
|
|
|
|
+ dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
|
|
|
|
+
|
|
|
|
+ dispc_mgr_set_clock_div(channel, &config->clock_info);
|
|
|
|
+
|
|
|
|
+ dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
|
|
|
|
+
|
|
|
|
+ dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
|
|
|
|
+
|
|
|
|
+ dispc_mgr_set_lcd_type_tft(channel);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
|
|
|
|
+
|
|
static bool _dispc_mgr_size_ok(u16 width, u16 height)
|
|
static bool _dispc_mgr_size_ok(u16 width, u16 height)
|
|
{
|
|
{
|
|
- return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) &&
|
|
|
|
- height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT);
|
|
|
|
|
|
+ return width <= dispc.feat->mgr_width_max &&
|
|
|
|
+ height <= dispc.feat->mgr_height_max;
|
|
}
|
|
}
|
|
|
|
|
|
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
|
|
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
|
|
@@ -3010,7 +2902,7 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
|
|
|
|
|
|
/* change name to mode? */
|
|
/* change name to mode? */
|
|
void dispc_mgr_set_timings(enum omap_channel channel,
|
|
void dispc_mgr_set_timings(enum omap_channel channel,
|
|
- struct omap_video_timings *timings)
|
|
|
|
|
|
+ const struct omap_video_timings *timings)
|
|
{
|
|
{
|
|
unsigned xtot, ytot;
|
|
unsigned xtot, ytot;
|
|
unsigned long ht, vt;
|
|
unsigned long ht, vt;
|
|
@@ -3049,6 +2941,7 @@ void dispc_mgr_set_timings(enum omap_channel channel,
|
|
|
|
|
|
dispc_mgr_set_size(channel, t.x_res, t.y_res);
|
|
dispc_mgr_set_size(channel, t.x_res, t.y_res);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_mgr_set_timings);
|
|
|
|
|
|
static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
|
|
static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
|
|
u16 pck_div)
|
|
u16 pck_div)
|
|
@@ -3076,7 +2969,7 @@ unsigned long dispc_fclk_rate(void)
|
|
|
|
|
|
switch (dss_get_dispc_clk_source()) {
|
|
switch (dss_get_dispc_clk_source()) {
|
|
case OMAP_DSS_CLK_SRC_FCK:
|
|
case OMAP_DSS_CLK_SRC_FCK:
|
|
- r = clk_get_rate(dispc.dss_clk);
|
|
|
|
|
|
+ r = dss_get_dispc_clk_rate();
|
|
break;
|
|
break;
|
|
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
|
|
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
|
|
dsidev = dsi_get_dsidev_from_id(0);
|
|
dsidev = dsi_get_dsidev_from_id(0);
|
|
@@ -3101,28 +2994,32 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
|
|
unsigned long r;
|
|
unsigned long r;
|
|
u32 l;
|
|
u32 l;
|
|
|
|
|
|
- l = dispc_read_reg(DISPC_DIVISORo(channel));
|
|
|
|
|
|
+ if (dss_mgr_is_lcd(channel)) {
|
|
|
|
+ l = dispc_read_reg(DISPC_DIVISORo(channel));
|
|
|
|
|
|
- lcd = FLD_GET(l, 23, 16);
|
|
|
|
|
|
+ lcd = FLD_GET(l, 23, 16);
|
|
|
|
|
|
- switch (dss_get_lcd_clk_source(channel)) {
|
|
|
|
- case OMAP_DSS_CLK_SRC_FCK:
|
|
|
|
- r = clk_get_rate(dispc.dss_clk);
|
|
|
|
- break;
|
|
|
|
- case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
|
|
|
|
- dsidev = dsi_get_dsidev_from_id(0);
|
|
|
|
- r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
|
|
|
|
- break;
|
|
|
|
- case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
|
|
|
|
- dsidev = dsi_get_dsidev_from_id(1);
|
|
|
|
- r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- BUG();
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ switch (dss_get_lcd_clk_source(channel)) {
|
|
|
|
+ case OMAP_DSS_CLK_SRC_FCK:
|
|
|
|
+ r = dss_get_dispc_clk_rate();
|
|
|
|
+ break;
|
|
|
|
+ case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
|
|
|
|
+ dsidev = dsi_get_dsidev_from_id(0);
|
|
|
|
+ r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
|
|
|
|
+ break;
|
|
|
|
+ case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
|
|
|
|
+ dsidev = dsi_get_dsidev_from_id(1);
|
|
|
|
+ r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ BUG();
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
|
|
- return r / lcd;
|
|
|
|
|
|
+ return r / lcd;
|
|
|
|
+ } else {
|
|
|
|
+ return dispc_fclk_rate();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
|
|
unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
|
|
@@ -3172,21 +3069,28 @@ unsigned long dispc_core_clk_rate(void)
|
|
|
|
|
|
static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
|
|
static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
|
|
{
|
|
{
|
|
- enum omap_channel channel = dispc_ovl_get_channel_out(plane);
|
|
|
|
|
|
+ enum omap_channel channel;
|
|
|
|
+
|
|
|
|
+ if (plane == OMAP_DSS_WB)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ channel = dispc_ovl_get_channel_out(plane);
|
|
|
|
|
|
return dispc_mgr_pclk_rate(channel);
|
|
return dispc_mgr_pclk_rate(channel);
|
|
}
|
|
}
|
|
|
|
|
|
static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
|
|
static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
|
|
{
|
|
{
|
|
- enum omap_channel channel = dispc_ovl_get_channel_out(plane);
|
|
|
|
|
|
+ enum omap_channel channel;
|
|
|
|
|
|
- if (dss_mgr_is_lcd(channel))
|
|
|
|
- return dispc_mgr_lclk_rate(channel);
|
|
|
|
- else
|
|
|
|
- return dispc_fclk_rate();
|
|
|
|
|
|
+ if (plane == OMAP_DSS_WB)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ channel = dispc_ovl_get_channel_out(plane);
|
|
|
|
|
|
|
|
+ return dispc_mgr_lclk_rate(channel);
|
|
}
|
|
}
|
|
|
|
+
|
|
static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
|
|
static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
|
|
{
|
|
{
|
|
int lcd, pcd;
|
|
int lcd, pcd;
|
|
@@ -3244,64 +3148,6 @@ void dispc_dump_clocks(struct seq_file *s)
|
|
dispc_runtime_put();
|
|
dispc_runtime_put();
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
-void dispc_dump_irqs(struct seq_file *s)
|
|
|
|
-{
|
|
|
|
- unsigned long flags;
|
|
|
|
- struct dispc_irq_stats stats;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&dispc.irq_stats_lock, flags);
|
|
|
|
-
|
|
|
|
- stats = dispc.irq_stats;
|
|
|
|
- memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
|
|
|
|
- dispc.irq_stats.last_reset = jiffies;
|
|
|
|
-
|
|
|
|
- spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
|
|
|
|
-
|
|
|
|
- seq_printf(s, "period %u ms\n",
|
|
|
|
- jiffies_to_msecs(jiffies - stats.last_reset));
|
|
|
|
-
|
|
|
|
- seq_printf(s, "irqs %d\n", stats.irq_count);
|
|
|
|
-#define PIS(x) \
|
|
|
|
- seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
|
|
|
|
-
|
|
|
|
- PIS(FRAMEDONE);
|
|
|
|
- PIS(VSYNC);
|
|
|
|
- PIS(EVSYNC_EVEN);
|
|
|
|
- PIS(EVSYNC_ODD);
|
|
|
|
- PIS(ACBIAS_COUNT_STAT);
|
|
|
|
- PIS(PROG_LINE_NUM);
|
|
|
|
- PIS(GFX_FIFO_UNDERFLOW);
|
|
|
|
- PIS(GFX_END_WIN);
|
|
|
|
- PIS(PAL_GAMMA_MASK);
|
|
|
|
- PIS(OCP_ERR);
|
|
|
|
- PIS(VID1_FIFO_UNDERFLOW);
|
|
|
|
- PIS(VID1_END_WIN);
|
|
|
|
- PIS(VID2_FIFO_UNDERFLOW);
|
|
|
|
- PIS(VID2_END_WIN);
|
|
|
|
- if (dss_feat_get_num_ovls() > 3) {
|
|
|
|
- PIS(VID3_FIFO_UNDERFLOW);
|
|
|
|
- PIS(VID3_END_WIN);
|
|
|
|
- }
|
|
|
|
- PIS(SYNC_LOST);
|
|
|
|
- PIS(SYNC_LOST_DIGIT);
|
|
|
|
- PIS(WAKEUP);
|
|
|
|
- if (dss_has_feature(FEAT_MGR_LCD2)) {
|
|
|
|
- PIS(FRAMEDONE2);
|
|
|
|
- PIS(VSYNC2);
|
|
|
|
- PIS(ACBIAS_COUNT_STAT2);
|
|
|
|
- PIS(SYNC_LOST2);
|
|
|
|
- }
|
|
|
|
- if (dss_has_feature(FEAT_MGR_LCD3)) {
|
|
|
|
- PIS(FRAMEDONE3);
|
|
|
|
- PIS(VSYNC3);
|
|
|
|
- PIS(ACBIAS_COUNT_STAT3);
|
|
|
|
- PIS(SYNC_LOST3);
|
|
|
|
- }
|
|
|
|
-#undef PIS
|
|
|
|
-}
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
static void dispc_dump_regs(struct seq_file *s)
|
|
static void dispc_dump_regs(struct seq_file *s)
|
|
{
|
|
{
|
|
int i, j;
|
|
int i, j;
|
|
@@ -3351,7 +3197,7 @@ static void dispc_dump_regs(struct seq_file *s)
|
|
|
|
|
|
#define DISPC_REG(i, name) name(i)
|
|
#define DISPC_REG(i, name) name(i)
|
|
#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
|
|
#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
|
|
- 48 - strlen(#r) - strlen(p_names[i]), " ", \
|
|
|
|
|
|
+ (int)(48 - strlen(#r) - strlen(p_names[i])), " ", \
|
|
dispc_read_reg(DISPC_REG(i, r)))
|
|
dispc_read_reg(DISPC_REG(i, r)))
|
|
|
|
|
|
p_names = mgr_names;
|
|
p_names = mgr_names;
|
|
@@ -3428,7 +3274,7 @@ static void dispc_dump_regs(struct seq_file *s)
|
|
#define DISPC_REG(plane, name, i) name(plane, i)
|
|
#define DISPC_REG(plane, name, i) name(plane, i)
|
|
#define DUMPREG(plane, name, i) \
|
|
#define DUMPREG(plane, name, i) \
|
|
seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
|
|
seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \
|
|
- 46 - strlen(#name) - strlen(p_names[plane]), " ", \
|
|
|
|
|
|
+ (int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \
|
|
dispc_read_reg(DISPC_REG(plane, name, i)))
|
|
dispc_read_reg(DISPC_REG(plane, name, i)))
|
|
|
|
|
|
/* Video pipeline coefficient registers */
|
|
/* Video pipeline coefficient registers */
|
|
@@ -3531,7 +3377,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
|
|
}
|
|
}
|
|
|
|
|
|
void dispc_mgr_set_clock_div(enum omap_channel channel,
|
|
void dispc_mgr_set_clock_div(enum omap_channel channel,
|
|
- struct dispc_clock_info *cinfo)
|
|
|
|
|
|
+ const struct dispc_clock_info *cinfo)
|
|
{
|
|
{
|
|
DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
|
|
DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
|
|
DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
|
|
DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
|
|
@@ -3555,403 +3401,34 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/* dispc.irq_lock has to be locked by the caller */
|
|
|
|
-static void _omap_dispc_set_irqs(void)
|
|
|
|
|
|
+u32 dispc_read_irqstatus(void)
|
|
{
|
|
{
|
|
- u32 mask;
|
|
|
|
- u32 old_mask;
|
|
|
|
- int i;
|
|
|
|
- struct omap_dispc_isr_data *isr_data;
|
|
|
|
-
|
|
|
|
- mask = dispc.irq_error_mask;
|
|
|
|
-
|
|
|
|
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
|
|
|
|
- isr_data = &dispc.registered_isr[i];
|
|
|
|
-
|
|
|
|
- if (isr_data->isr == NULL)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- mask |= isr_data->mask;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- old_mask = dispc_read_reg(DISPC_IRQENABLE);
|
|
|
|
- /* clear the irqstatus for newly enabled irqs */
|
|
|
|
- dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
|
|
|
|
-
|
|
|
|
- dispc_write_reg(DISPC_IRQENABLE, mask);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
|
|
|
|
-{
|
|
|
|
- int i;
|
|
|
|
- int ret;
|
|
|
|
- unsigned long flags;
|
|
|
|
- struct omap_dispc_isr_data *isr_data;
|
|
|
|
-
|
|
|
|
- if (isr == NULL)
|
|
|
|
- return -EINVAL;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&dispc.irq_lock, flags);
|
|
|
|
-
|
|
|
|
- /* check for duplicate entry */
|
|
|
|
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
|
|
|
|
- isr_data = &dispc.registered_isr[i];
|
|
|
|
- if (isr_data->isr == isr && isr_data->arg == arg &&
|
|
|
|
- isr_data->mask == mask) {
|
|
|
|
- ret = -EINVAL;
|
|
|
|
- goto err;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- isr_data = NULL;
|
|
|
|
- ret = -EBUSY;
|
|
|
|
-
|
|
|
|
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
|
|
|
|
- isr_data = &dispc.registered_isr[i];
|
|
|
|
-
|
|
|
|
- if (isr_data->isr != NULL)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- isr_data->isr = isr;
|
|
|
|
- isr_data->arg = arg;
|
|
|
|
- isr_data->mask = mask;
|
|
|
|
- ret = 0;
|
|
|
|
-
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (ret)
|
|
|
|
- goto err;
|
|
|
|
-
|
|
|
|
- _omap_dispc_set_irqs();
|
|
|
|
-
|
|
|
|
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-err:
|
|
|
|
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-EXPORT_SYMBOL(omap_dispc_register_isr);
|
|
|
|
-
|
|
|
|
-int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
|
|
|
|
-{
|
|
|
|
- int i;
|
|
|
|
- unsigned long flags;
|
|
|
|
- int ret = -EINVAL;
|
|
|
|
- struct omap_dispc_isr_data *isr_data;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&dispc.irq_lock, flags);
|
|
|
|
-
|
|
|
|
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
|
|
|
|
- isr_data = &dispc.registered_isr[i];
|
|
|
|
- if (isr_data->isr != isr || isr_data->arg != arg ||
|
|
|
|
- isr_data->mask != mask)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- /* found the correct isr */
|
|
|
|
-
|
|
|
|
- isr_data->isr = NULL;
|
|
|
|
- isr_data->arg = NULL;
|
|
|
|
- isr_data->mask = 0;
|
|
|
|
-
|
|
|
|
- ret = 0;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (ret == 0)
|
|
|
|
- _omap_dispc_set_irqs();
|
|
|
|
-
|
|
|
|
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-EXPORT_SYMBOL(omap_dispc_unregister_isr);
|
|
|
|
-
|
|
|
|
-#ifdef DEBUG
|
|
|
|
-static void print_irq_status(u32 status)
|
|
|
|
-{
|
|
|
|
- if ((status & dispc.irq_error_mask) == 0)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
|
|
|
|
-
|
|
|
|
-#define PIS(x) \
|
|
|
|
- if (status & DISPC_IRQ_##x) \
|
|
|
|
- printk(#x " ");
|
|
|
|
- PIS(GFX_FIFO_UNDERFLOW);
|
|
|
|
- PIS(OCP_ERR);
|
|
|
|
- PIS(VID1_FIFO_UNDERFLOW);
|
|
|
|
- PIS(VID2_FIFO_UNDERFLOW);
|
|
|
|
- if (dss_feat_get_num_ovls() > 3)
|
|
|
|
- PIS(VID3_FIFO_UNDERFLOW);
|
|
|
|
- PIS(SYNC_LOST);
|
|
|
|
- PIS(SYNC_LOST_DIGIT);
|
|
|
|
- if (dss_has_feature(FEAT_MGR_LCD2))
|
|
|
|
- PIS(SYNC_LOST2);
|
|
|
|
- if (dss_has_feature(FEAT_MGR_LCD3))
|
|
|
|
- PIS(SYNC_LOST3);
|
|
|
|
-#undef PIS
|
|
|
|
-
|
|
|
|
- printk("\n");
|
|
|
|
-}
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-/* Called from dss.c. Note that we don't touch clocks here,
|
|
|
|
- * but we presume they are on because we got an IRQ. However,
|
|
|
|
- * an irq handler may turn the clocks off, so we may not have
|
|
|
|
- * clock later in the function. */
|
|
|
|
-static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
|
|
|
|
-{
|
|
|
|
- int i;
|
|
|
|
- u32 irqstatus, irqenable;
|
|
|
|
- u32 handledirqs = 0;
|
|
|
|
- u32 unhandled_errors;
|
|
|
|
- struct omap_dispc_isr_data *isr_data;
|
|
|
|
- struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
|
|
|
|
-
|
|
|
|
- spin_lock(&dispc.irq_lock);
|
|
|
|
-
|
|
|
|
- irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
|
|
|
|
- irqenable = dispc_read_reg(DISPC_IRQENABLE);
|
|
|
|
-
|
|
|
|
- /* IRQ is not for us */
|
|
|
|
- if (!(irqstatus & irqenable)) {
|
|
|
|
- spin_unlock(&dispc.irq_lock);
|
|
|
|
- return IRQ_NONE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
- spin_lock(&dispc.irq_stats_lock);
|
|
|
|
- dispc.irq_stats.irq_count++;
|
|
|
|
- dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
|
|
|
|
- spin_unlock(&dispc.irq_stats_lock);
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-#ifdef DEBUG
|
|
|
|
- if (dss_debug)
|
|
|
|
- print_irq_status(irqstatus);
|
|
|
|
-#endif
|
|
|
|
- /* Ack the interrupt. Do it here before clocks are possibly turned
|
|
|
|
- * off */
|
|
|
|
- dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
|
|
|
|
- /* flush posted write */
|
|
|
|
- dispc_read_reg(DISPC_IRQSTATUS);
|
|
|
|
-
|
|
|
|
- /* make a copy and unlock, so that isrs can unregister
|
|
|
|
- * themselves */
|
|
|
|
- memcpy(registered_isr, dispc.registered_isr,
|
|
|
|
- sizeof(registered_isr));
|
|
|
|
-
|
|
|
|
- spin_unlock(&dispc.irq_lock);
|
|
|
|
-
|
|
|
|
- for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
|
|
|
|
- isr_data = ®istered_isr[i];
|
|
|
|
-
|
|
|
|
- if (!isr_data->isr)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- if (isr_data->mask & irqstatus) {
|
|
|
|
- isr_data->isr(isr_data->arg, irqstatus);
|
|
|
|
- handledirqs |= isr_data->mask;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- spin_lock(&dispc.irq_lock);
|
|
|
|
-
|
|
|
|
- unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
|
|
|
|
-
|
|
|
|
- if (unhandled_errors) {
|
|
|
|
- dispc.error_irqs |= unhandled_errors;
|
|
|
|
-
|
|
|
|
- dispc.irq_error_mask &= ~unhandled_errors;
|
|
|
|
- _omap_dispc_set_irqs();
|
|
|
|
-
|
|
|
|
- schedule_work(&dispc.error_work);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- spin_unlock(&dispc.irq_lock);
|
|
|
|
-
|
|
|
|
- return IRQ_HANDLED;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void dispc_error_worker(struct work_struct *work)
|
|
|
|
-{
|
|
|
|
- int i;
|
|
|
|
- u32 errors;
|
|
|
|
- unsigned long flags;
|
|
|
|
- static const unsigned fifo_underflow_bits[] = {
|
|
|
|
- DISPC_IRQ_GFX_FIFO_UNDERFLOW,
|
|
|
|
- DISPC_IRQ_VID1_FIFO_UNDERFLOW,
|
|
|
|
- DISPC_IRQ_VID2_FIFO_UNDERFLOW,
|
|
|
|
- DISPC_IRQ_VID3_FIFO_UNDERFLOW,
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&dispc.irq_lock, flags);
|
|
|
|
- errors = dispc.error_irqs;
|
|
|
|
- dispc.error_irqs = 0;
|
|
|
|
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
|
|
|
|
-
|
|
|
|
- dispc_runtime_get();
|
|
|
|
-
|
|
|
|
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
|
|
|
|
- struct omap_overlay *ovl;
|
|
|
|
- unsigned bit;
|
|
|
|
-
|
|
|
|
- ovl = omap_dss_get_overlay(i);
|
|
|
|
- bit = fifo_underflow_bits[i];
|
|
|
|
-
|
|
|
|
- if (bit & errors) {
|
|
|
|
- DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
|
|
|
|
- ovl->name);
|
|
|
|
- dispc_ovl_enable(ovl->id, false);
|
|
|
|
- dispc_mgr_go(ovl->manager->id);
|
|
|
|
- msleep(50);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
|
|
|
- struct omap_overlay_manager *mgr;
|
|
|
|
- unsigned bit;
|
|
|
|
-
|
|
|
|
- mgr = omap_dss_get_overlay_manager(i);
|
|
|
|
- bit = mgr_desc[i].sync_lost_irq;
|
|
|
|
-
|
|
|
|
- if (bit & errors) {
|
|
|
|
- struct omap_dss_device *dssdev = mgr->get_device(mgr);
|
|
|
|
- bool enable;
|
|
|
|
-
|
|
|
|
- DSSERR("SYNC_LOST on channel %s, restarting the output "
|
|
|
|
- "with video overlays disabled\n",
|
|
|
|
- mgr->name);
|
|
|
|
-
|
|
|
|
- enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
|
|
|
|
- dssdev->driver->disable(dssdev);
|
|
|
|
-
|
|
|
|
- for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
|
|
|
|
- struct omap_overlay *ovl;
|
|
|
|
- ovl = omap_dss_get_overlay(i);
|
|
|
|
-
|
|
|
|
- if (ovl->id != OMAP_DSS_GFX &&
|
|
|
|
- ovl->manager == mgr)
|
|
|
|
- dispc_ovl_enable(ovl->id, false);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- dispc_mgr_go(mgr->id);
|
|
|
|
- msleep(50);
|
|
|
|
-
|
|
|
|
- if (enable)
|
|
|
|
- dssdev->driver->enable(dssdev);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (errors & DISPC_IRQ_OCP_ERR) {
|
|
|
|
- DSSERR("OCP_ERR\n");
|
|
|
|
- for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
|
|
|
- struct omap_overlay_manager *mgr;
|
|
|
|
- struct omap_dss_device *dssdev;
|
|
|
|
-
|
|
|
|
- mgr = omap_dss_get_overlay_manager(i);
|
|
|
|
- dssdev = mgr->get_device(mgr);
|
|
|
|
-
|
|
|
|
- if (dssdev && dssdev->driver)
|
|
|
|
- dssdev->driver->disable(dssdev);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&dispc.irq_lock, flags);
|
|
|
|
- dispc.irq_error_mask |= errors;
|
|
|
|
- _omap_dispc_set_irqs();
|
|
|
|
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
|
|
|
|
-
|
|
|
|
- dispc_runtime_put();
|
|
|
|
|
|
+ return dispc_read_reg(DISPC_IRQSTATUS);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_read_irqstatus);
|
|
|
|
|
|
-int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
|
|
|
|
|
|
+void dispc_clear_irqstatus(u32 mask)
|
|
{
|
|
{
|
|
- void dispc_irq_wait_handler(void *data, u32 mask)
|
|
|
|
- {
|
|
|
|
- complete((struct completion *)data);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- int r;
|
|
|
|
- DECLARE_COMPLETION_ONSTACK(completion);
|
|
|
|
-
|
|
|
|
- r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
|
|
|
|
- irqmask);
|
|
|
|
-
|
|
|
|
- if (r)
|
|
|
|
- return r;
|
|
|
|
-
|
|
|
|
- timeout = wait_for_completion_timeout(&completion, timeout);
|
|
|
|
-
|
|
|
|
- omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
|
|
|
|
-
|
|
|
|
- if (timeout == 0)
|
|
|
|
- return -ETIMEDOUT;
|
|
|
|
-
|
|
|
|
- if (timeout == -ERESTARTSYS)
|
|
|
|
- return -ERESTARTSYS;
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
|
|
+ dispc_write_reg(DISPC_IRQSTATUS, mask);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_clear_irqstatus);
|
|
|
|
|
|
-int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
|
|
|
|
- unsigned long timeout)
|
|
|
|
|
|
+u32 dispc_read_irqenable(void)
|
|
{
|
|
{
|
|
- void dispc_irq_wait_handler(void *data, u32 mask)
|
|
|
|
- {
|
|
|
|
- complete((struct completion *)data);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- int r;
|
|
|
|
- DECLARE_COMPLETION_ONSTACK(completion);
|
|
|
|
-
|
|
|
|
- r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
|
|
|
|
- irqmask);
|
|
|
|
-
|
|
|
|
- if (r)
|
|
|
|
- return r;
|
|
|
|
-
|
|
|
|
- timeout = wait_for_completion_interruptible_timeout(&completion,
|
|
|
|
- timeout);
|
|
|
|
-
|
|
|
|
- omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
|
|
|
|
-
|
|
|
|
- if (timeout == 0)
|
|
|
|
- return -ETIMEDOUT;
|
|
|
|
-
|
|
|
|
- if (timeout == -ERESTARTSYS)
|
|
|
|
- return -ERESTARTSYS;
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
|
|
+ return dispc_read_reg(DISPC_IRQENABLE);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_read_irqenable);
|
|
|
|
|
|
-static void _omap_dispc_initialize_irq(void)
|
|
|
|
|
|
+void dispc_write_irqenable(u32 mask)
|
|
{
|
|
{
|
|
- unsigned long flags;
|
|
|
|
-
|
|
|
|
- spin_lock_irqsave(&dispc.irq_lock, flags);
|
|
|
|
-
|
|
|
|
- memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
|
|
|
|
-
|
|
|
|
- dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
|
|
|
|
- if (dss_has_feature(FEAT_MGR_LCD2))
|
|
|
|
- dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
|
|
|
|
- if (dss_has_feature(FEAT_MGR_LCD3))
|
|
|
|
- dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
|
|
|
|
- if (dss_feat_get_num_ovls() > 3)
|
|
|
|
- dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
|
|
|
|
-
|
|
|
|
- /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
|
|
|
|
- * so clear it */
|
|
|
|
- dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
|
|
|
|
|
|
+ u32 old_mask = dispc_read_reg(DISPC_IRQENABLE);
|
|
|
|
|
|
- _omap_dispc_set_irqs();
|
|
|
|
|
|
+ /* clear the irqstatus for newly enabled irqs */
|
|
|
|
+ dispc_clear_irqstatus((mask ^ old_mask) & mask);
|
|
|
|
|
|
- spin_unlock_irqrestore(&dispc.irq_lock, flags);
|
|
|
|
|
|
+ dispc_write_reg(DISPC_IRQENABLE, mask);
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL(dispc_write_irqenable);
|
|
|
|
|
|
void dispc_enable_sidle(void)
|
|
void dispc_enable_sidle(void)
|
|
{
|
|
{
|
|
@@ -3998,9 +3475,14 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = {
|
|
.sw_max = 64,
|
|
.sw_max = 64,
|
|
.vp_max = 255,
|
|
.vp_max = 255,
|
|
.hp_max = 256,
|
|
.hp_max = 256,
|
|
|
|
+ .mgr_width_start = 10,
|
|
|
|
+ .mgr_height_start = 26,
|
|
|
|
+ .mgr_width_max = 2048,
|
|
|
|
+ .mgr_height_max = 2048,
|
|
.calc_scaling = dispc_ovl_calc_scaling_24xx,
|
|
.calc_scaling = dispc_ovl_calc_scaling_24xx,
|
|
.calc_core_clk = calc_core_clk_24xx,
|
|
.calc_core_clk = calc_core_clk_24xx,
|
|
.num_fifos = 3,
|
|
.num_fifos = 3,
|
|
|
|
+ .no_framedone_tv = true,
|
|
};
|
|
};
|
|
|
|
|
|
static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
|
|
static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
|
|
@@ -4010,9 +3492,14 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
|
|
.sw_max = 64,
|
|
.sw_max = 64,
|
|
.vp_max = 255,
|
|
.vp_max = 255,
|
|
.hp_max = 256,
|
|
.hp_max = 256,
|
|
|
|
+ .mgr_width_start = 10,
|
|
|
|
+ .mgr_height_start = 26,
|
|
|
|
+ .mgr_width_max = 2048,
|
|
|
|
+ .mgr_height_max = 2048,
|
|
.calc_scaling = dispc_ovl_calc_scaling_34xx,
|
|
.calc_scaling = dispc_ovl_calc_scaling_34xx,
|
|
.calc_core_clk = calc_core_clk_34xx,
|
|
.calc_core_clk = calc_core_clk_34xx,
|
|
.num_fifos = 3,
|
|
.num_fifos = 3,
|
|
|
|
+ .no_framedone_tv = true,
|
|
};
|
|
};
|
|
|
|
|
|
static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
|
|
static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
|
|
@@ -4022,9 +3509,14 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
|
|
.sw_max = 256,
|
|
.sw_max = 256,
|
|
.vp_max = 4095,
|
|
.vp_max = 4095,
|
|
.hp_max = 4096,
|
|
.hp_max = 4096,
|
|
|
|
+ .mgr_width_start = 10,
|
|
|
|
+ .mgr_height_start = 26,
|
|
|
|
+ .mgr_width_max = 2048,
|
|
|
|
+ .mgr_height_max = 2048,
|
|
.calc_scaling = dispc_ovl_calc_scaling_34xx,
|
|
.calc_scaling = dispc_ovl_calc_scaling_34xx,
|
|
.calc_core_clk = calc_core_clk_34xx,
|
|
.calc_core_clk = calc_core_clk_34xx,
|
|
.num_fifos = 3,
|
|
.num_fifos = 3,
|
|
|
|
+ .no_framedone_tv = true,
|
|
};
|
|
};
|
|
|
|
|
|
static const struct dispc_features omap44xx_dispc_feats __initconst = {
|
|
static const struct dispc_features omap44xx_dispc_feats __initconst = {
|
|
@@ -4034,6 +3526,27 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
|
|
.sw_max = 256,
|
|
.sw_max = 256,
|
|
.vp_max = 4095,
|
|
.vp_max = 4095,
|
|
.hp_max = 4096,
|
|
.hp_max = 4096,
|
|
|
|
+ .mgr_width_start = 10,
|
|
|
|
+ .mgr_height_start = 26,
|
|
|
|
+ .mgr_width_max = 2048,
|
|
|
|
+ .mgr_height_max = 2048,
|
|
|
|
+ .calc_scaling = dispc_ovl_calc_scaling_44xx,
|
|
|
|
+ .calc_core_clk = calc_core_clk_44xx,
|
|
|
|
+ .num_fifos = 5,
|
|
|
|
+ .gfx_fifo_workaround = true,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static const struct dispc_features omap54xx_dispc_feats __initconst = {
|
|
|
|
+ .sw_start = 7,
|
|
|
|
+ .fp_start = 19,
|
|
|
|
+ .bp_start = 31,
|
|
|
|
+ .sw_max = 256,
|
|
|
|
+ .vp_max = 4095,
|
|
|
|
+ .hp_max = 4096,
|
|
|
|
+ .mgr_width_start = 11,
|
|
|
|
+ .mgr_height_start = 27,
|
|
|
|
+ .mgr_width_max = 4096,
|
|
|
|
+ .mgr_height_max = 4096,
|
|
.calc_scaling = dispc_ovl_calc_scaling_44xx,
|
|
.calc_scaling = dispc_ovl_calc_scaling_44xx,
|
|
.calc_core_clk = calc_core_clk_44xx,
|
|
.calc_core_clk = calc_core_clk_44xx,
|
|
.num_fifos = 5,
|
|
.num_fifos = 5,
|
|
@@ -4042,7 +3555,6 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
|
|
|
|
|
|
static int __init dispc_init_features(struct platform_device *pdev)
|
|
static int __init dispc_init_features(struct platform_device *pdev)
|
|
{
|
|
{
|
|
- struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
|
|
|
const struct dispc_features *src;
|
|
const struct dispc_features *src;
|
|
struct dispc_features *dst;
|
|
struct dispc_features *dst;
|
|
|
|
|
|
@@ -4052,7 +3564,7 @@ static int __init dispc_init_features(struct platform_device *pdev)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
|
|
- switch (pdata->version) {
|
|
|
|
|
|
+ switch (omapdss_get_version()) {
|
|
case OMAPDSS_VER_OMAP24xx:
|
|
case OMAPDSS_VER_OMAP24xx:
|
|
src = &omap24xx_dispc_feats;
|
|
src = &omap24xx_dispc_feats;
|
|
break;
|
|
break;
|
|
@@ -4074,7 +3586,7 @@ static int __init dispc_init_features(struct platform_device *pdev)
|
|
break;
|
|
break;
|
|
|
|
|
|
case OMAPDSS_VER_OMAP5:
|
|
case OMAPDSS_VER_OMAP5:
|
|
- src = &omap44xx_dispc_feats;
|
|
|
|
|
|
+ src = &omap54xx_dispc_feats;
|
|
break;
|
|
break;
|
|
|
|
|
|
default:
|
|
default:
|
|
@@ -4087,13 +3599,25 @@ static int __init dispc_init_features(struct platform_device *pdev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int dispc_request_irq(irq_handler_t handler, void *dev_id)
|
|
|
|
+{
|
|
|
|
+ return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler,
|
|
|
|
+ IRQF_SHARED, "OMAP DISPC", dev_id);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(dispc_request_irq);
|
|
|
|
+
|
|
|
|
+void dispc_free_irq(void *dev_id)
|
|
|
|
+{
|
|
|
|
+ devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(dispc_free_irq);
|
|
|
|
+
|
|
/* DISPC HW IP initialisation */
|
|
/* DISPC HW IP initialisation */
|
|
static int __init omap_dispchw_probe(struct platform_device *pdev)
|
|
static int __init omap_dispchw_probe(struct platform_device *pdev)
|
|
{
|
|
{
|
|
u32 rev;
|
|
u32 rev;
|
|
int r = 0;
|
|
int r = 0;
|
|
struct resource *dispc_mem;
|
|
struct resource *dispc_mem;
|
|
- struct clk *clk;
|
|
|
|
|
|
|
|
dispc.pdev = pdev;
|
|
dispc.pdev = pdev;
|
|
|
|
|
|
@@ -4101,15 +3625,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
|
|
if (r)
|
|
if (r)
|
|
return r;
|
|
return r;
|
|
|
|
|
|
- spin_lock_init(&dispc.irq_lock);
|
|
|
|
-
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
- spin_lock_init(&dispc.irq_stats_lock);
|
|
|
|
- dispc.irq_stats.last_reset = jiffies;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- INIT_WORK(&dispc.error_work, dispc_error_worker);
|
|
|
|
-
|
|
|
|
dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
|
|
dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
|
|
if (!dispc_mem) {
|
|
if (!dispc_mem) {
|
|
DSSERR("can't get IORESOURCE_MEM DISPC\n");
|
|
DSSERR("can't get IORESOURCE_MEM DISPC\n");
|
|
@@ -4129,22 +3644,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
}
|
|
}
|
|
|
|
|
|
- r = devm_request_irq(&pdev->dev, dispc.irq, omap_dispc_irq_handler,
|
|
|
|
- IRQF_SHARED, "OMAP DISPC", dispc.pdev);
|
|
|
|
- if (r < 0) {
|
|
|
|
- DSSERR("request_irq failed\n");
|
|
|
|
- return r;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- clk = clk_get(&pdev->dev, "fck");
|
|
|
|
- if (IS_ERR(clk)) {
|
|
|
|
- DSSERR("can't get fck\n");
|
|
|
|
- r = PTR_ERR(clk);
|
|
|
|
- return r;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- dispc.dss_clk = clk;
|
|
|
|
-
|
|
|
|
pm_runtime_enable(&pdev->dev);
|
|
pm_runtime_enable(&pdev->dev);
|
|
|
|
|
|
r = dispc_runtime_get();
|
|
r = dispc_runtime_get();
|
|
@@ -4153,8 +3652,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
|
|
|
|
|
|
_omap_dispc_initial_config();
|
|
_omap_dispc_initial_config();
|
|
|
|
|
|
- _omap_dispc_initialize_irq();
|
|
|
|
-
|
|
|
|
rev = dispc_read_reg(DISPC_REVISION);
|
|
rev = dispc_read_reg(DISPC_REVISION);
|
|
dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
|
|
dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
|
|
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
|
|
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
|
|
@@ -4163,14 +3660,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
|
|
|
|
|
|
dss_debugfs_create_file("dispc", dispc_dump_regs);
|
|
dss_debugfs_create_file("dispc", dispc_dump_regs);
|
|
|
|
|
|
-#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
|
|
|
- dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
|
|
|
|
-#endif
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
err_runtime_get:
|
|
err_runtime_get:
|
|
pm_runtime_disable(&pdev->dev);
|
|
pm_runtime_disable(&pdev->dev);
|
|
- clk_put(dispc.dss_clk);
|
|
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4178,8 +3671,6 @@ static int __exit omap_dispchw_remove(struct platform_device *pdev)
|
|
{
|
|
{
|
|
pm_runtime_disable(&pdev->dev);
|
|
pm_runtime_disable(&pdev->dev);
|
|
|
|
|
|
- clk_put(dispc.dss_clk);
|
|
|
|
-
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|